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
_______________________________________________
LibreOffice mailing list
LibreOffice@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/libreoffice

Reply via email to