X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fstructure%2FSGWeakReferenced.hxx;h=3bb70ffa6e541178db502667f7de71bc4ab99097;hb=5c9f5361bda56dddad8068d8e45dc08584440d70;hp=f5fd34c9a47476f8add67c792470b25118b39b72;hpb=6eff167a280a8fec682a75f392f3412656142a53;p=simgear.git diff --git a/simgear/structure/SGWeakReferenced.hxx b/simgear/structure/SGWeakReferenced.hxx index f5fd34c9..3bb70ffa 100644 --- a/simgear/structure/SGWeakReferenced.hxx +++ b/simgear/structure/SGWeakReferenced.hxx @@ -21,6 +21,9 @@ #include "SGReferenced.hxx" #include "SGSharedPtr.hxx" +#include +#include + #ifdef _MSC_VER # pragma warning(push) // C4355: 'this' : used in base member initializer list @@ -30,7 +33,18 @@ template class SGWeakPtr; +class SGVirtualWeakReferenced; +/** + * Base class for all reference counted SimGear objects supporting weak + * references, not incrementing the reference count. + * + * Classes derived from this one are meant to be managed with the SGSharedPtr + * and SGWeakPtr classes. + * + * If the class hierarchy contains virtual base classes use + * SGVirtualWeakReferenced instead. + */ class SGWeakReferenced { public: /// The object backref and the reference count for this object need to be @@ -57,11 +71,11 @@ public: /// The usual operations on weak pointers. /// The interface should stay the same then what we have in Referenced. static unsigned get(const SGWeakReferenced* ref) - { if (ref) return ++(ref->mWeakData->mRefcount); else return 0u; } + { if (ref) return ++(ref->mWeakData->mRefcount); else return 0; } static unsigned put(const SGWeakReferenced* ref) - { if (ref) return --(ref->mWeakData->mRefcount); else return ~0u; } + { if (ref) return --(ref->mWeakData->mRefcount); else return 0; } static unsigned count(const SGWeakReferenced* ref) - { if (ref) return ref->mWeakData->mRefcount; else return 0u; } + { if (ref) return ref->mWeakData->mRefcount; else return 0; } private: /// Support for weak references, not increasing the reference count @@ -89,7 +103,7 @@ private: } while (!mRefcount.compareAndExchange(count, count + 1)); // We know that as long as the refcount is not zero, the pointer still // points to valid data. So it is safe to work on it. - return static_cast(mWeakReferenced); + return up_cast(mWeakReferenced); } SGAtomic mRefcount; @@ -99,6 +113,27 @@ private: WeakData(void); WeakData(const WeakData&); WeakData& operator=(const WeakData&); + + /// Upcast in a class hierarchy with a virtual base class + template + static + typename boost::enable_if< + boost::is_base_of, + T* + >::type + up_cast(SGWeakReferenced* ptr); + + /// Upcast in a non-virtual class hierarchy + template + static + typename boost::disable_if< + boost::is_base_of, + T* + >::type + up_cast(SGWeakReferenced* ptr) + { + return static_cast(ptr); + } }; SGSharedPtr mWeakData; @@ -107,6 +142,56 @@ private: friend class SGWeakPtr; }; +/** + * Base class for all reference counted SimGear objects with virtual base + * classes, supporting weak references. + * + * Classes derived from this one are meant to be managed with the SGSharedPtr + * and SGWeakPtr classes. + * + * @code{cpp} + * + * class Base1: + * public virtual SGVirtualWeakReferenced + * {}; + * + * class Base2: + * public virtual SGVirtualWeakReferenced + * {}; + * + * class Derived: + * public Base1, + * public Base2 + * {}; + * + * SGSharedPtr ptr( new Derived() ); + * SGWeakPtr weak_ptr( ptr ); + * SGSharedPtr ptr1( weak_ptr.lock() ); + * SGSharedPtr ptr2( weak_ptr.lock() ); + * + * @endcode + */ +class SGVirtualWeakReferenced: + public SGWeakReferenced +{ + public: + virtual ~SGVirtualWeakReferenced() {} +}; + +/// Upcast in a class hierarchy with a virtual base class +// We (clang) need the definition of SGVirtualWeakReferenced for the static_cast +template +typename boost::enable_if< + boost::is_base_of, + T* +>::type +SGWeakReferenced::WeakData::up_cast(SGWeakReferenced* ptr) +{ + // First get the virtual base class, which then can be used to further + // upcast. + return dynamic_cast(static_cast(ptr)); +} + #ifdef _MSC_VER # pragma warning(pop) #endif