I need to better understand our css::uno::Reference

Stephan Bergmann sbergman at redhat.com
Mon Jun 23 04:07:14 PDT 2014


On 06/18/2014 10:58 PM, Lionel Elie Mamane wrote:
> On Wed, Jun 18, 2014 at 05:04:02PM +0200, Stephan Bergmann wrote:
>> Short answer (from just browsing the top of FOO.patch):  Use
>> css::uno::Reference<X> only for (C++ classes representing) UNO interfaces,
>> and use rtl::Reference<C> for C++ classes implementing UNO objects.
>
> Aha. This works. If you feel like explaining the C++-technical reason
> behind why we need different Reference implementations for the two
> cases... Feel free.

As C++ UNO for largely historic reasons does not use virtual 
inheritance, a css::uno::Reference for a multiple-inheritance interface 
type like css.uri.XVndSunStarExpandUrlReference (deriving from both 
css.uri.XUriReference and css.uri.XVndSunStarExpandUrl, each in turn 
deriving from css.uno.XInterface) faces a problem.  The Reference ctor 
has a pointer pInterface to css::uri::XVndSunStarExpandUrlReference and 
needs to call css::uno::XInterface::acquire through it.  But 
css::uno::XInterface is an ambiguous base class of 
css::uri::XVndSunStarExpandUrlReference, so calling 
pInterface->acquire() will not compile.

The trick is that we know that all compilers lay out the vtables in 
roughly the same way:  No matter how many types a given type X derives 
from, a pointer to X points to a vtable containing function pointers for 
X's first base (if any) followed by function pointers for X's own 
members (if any).  So as long as X represents any UNO interface type, 
the css::uno::Reference<X> ctor can do that dirty trick of 
reinterpret-casting pInterface to css::uno::XInterface* and calling 
acquire through that reinterpret-casted pointer and be sure it hits a 
vtable slot that calls the object's implementation of acquire (without 
needing adjustment of the this pointer).  All to allow for a single 
generic implementation of the css::uno::Reference<X> ctor that compiles 
fine regardless of X.

Now, if you break the assumption that X represents a UNO interface type, 
that reinterpret_cast trick potentially breaks down. 
connectivity::odbc::OResult derives from comphelper::OBaseMutex, 
connectivity::IResultSetHelper, OResultSet_BASE (aka 
cppu::WeakComponentImplHelper12 through which it derives from the 
various UNO interface types it implements), etc., in that order, so the 
vtable layout differs from that of a UNO interface type, and starts with 
vtables for comphelper::OBaseMutex and connectivity::IResultSetHelper. 
And the slot the reinterpret_cast hack mis-computes happens to be the 
slot for connectivity::IResultSetHelper::getDriverPos.

An alternative solution for the dilemma of a generic css::uno:Reference 
implementation could be to let cppumaker emit additional type-trait 
information how to cast between XInterface and any emitted interface 
type, and use that in the generic css::uno::Reference implementation. 
That could probably make a "bad" css::uno::Reference of an 
implementation class either silently do the right thing or cause a 
compilation error.

> I assume I can mix-and-match both, they will use the same (shared)
> counters for reference counting?

Yes, both css::uno::Reference<T> and rtl::Reference<T> rely on T's 
acquire and release functions.

> I see there is no rtl::WeakReference, and no automatic conversion from
> rtl::Reference to css::uno::(Weak)Reference; oh well, I can add
> ".get()" here and there.

Yes, use .get() for that.  (Theoretically, there could be implicit 
conversion between css::uno::Reference and rtl::Reference, but nobody 
ever bothered to add it.  Or there was a catch I momentarily can't 
remember.)

Stephan


More information about the LibreOffice mailing list