From 9975c751a7a4986b1d1d1b1a546e37dc371e06f4 Mon Sep 17 00:00:00 2001 From: Thomas Geymayer Date: Thu, 8 May 2014 00:19:36 +0200 Subject: [PATCH] Add support for using SGWeakPtr with virtual base classes. - Add SGVirtualWeakReferenced to be used as base class for reference counted objects supporting weak references and virtual base classes. - Modify SGWeakPtr to copy with SGVirtualWeakReferenced objects. --- simgear/structure/SGReferenced.hxx | 4 +- simgear/structure/SGSharedPtr.hxx | 6 +- simgear/structure/SGWeakPtr.hxx | 4 ++ simgear/structure/SGWeakReferenced.hxx | 78 +++++++++++++++++++++++++- 4 files changed, 87 insertions(+), 5 deletions(-) diff --git a/simgear/structure/SGReferenced.hxx b/simgear/structure/SGReferenced.hxx index 6a3038f3..69788b3f 100644 --- a/simgear/structure/SGReferenced.hxx +++ b/simgear/structure/SGReferenced.hxx @@ -26,7 +26,9 @@ /// Base class for all reference counted SimGear objects /// Classes derived from this one are meant to be managed with /// the SGSharedPtr class. -/// For more info see @SGSharedPtr. +/// +/// For more info see SGSharedPtr. For using weak references see +/// SGWeakReferenced. class SGReferenced { public: diff --git a/simgear/structure/SGSharedPtr.hxx b/simgear/structure/SGSharedPtr.hxx index aedd8463..87497b8e 100644 --- a/simgear/structure/SGSharedPtr.hxx +++ b/simgear/structure/SGSharedPtr.hxx @@ -24,6 +24,9 @@ #include "SGReferenced.hxx" #include +template +class SGWeakPtr; + /// This class is a pointer proxy doing reference counting on the object /// it is pointing to. /// The SGSharedPtr class handles reference counting and possible @@ -43,9 +46,6 @@ /// pretty much the same than this one at /// http://dburns.dhs.org/OSG/Articles/RefPointers/RefPointers.html -template -class SGWeakPtr; - template class SGSharedPtr { public: diff --git a/simgear/structure/SGWeakPtr.hxx b/simgear/structure/SGWeakPtr.hxx index 9dd2650a..95e6792e 100644 --- a/simgear/structure/SGWeakPtr.hxx +++ b/simgear/structure/SGWeakPtr.hxx @@ -20,6 +20,10 @@ #include "SGWeakReferenced.hxx" +/** + * Class for handling weak references to classes derived from SGWeakReferenced + * or SGVirtualWeakReferenced. + */ template class SGWeakPtr { public: diff --git a/simgear/structure/SGWeakReferenced.hxx b/simgear/structure/SGWeakReferenced.hxx index f5fd34c9..dbe50574 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 @@ -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,32 @@ 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) + { + // First get the virtual base class, which then can be used to further + // upcast. + return dynamic_cast(static_cast(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 +147,42 @@ 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() {} +}; + #ifdef _MSC_VER # pragma warning(pop) #endif -- 2.39.5