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