]> git.mxchange.org Git - simgear.git/commitdiff
Add support for using SGWeakPtr with virtual base classes.
authorThomas Geymayer <tomgey@gmail.com>
Wed, 7 May 2014 22:19:36 +0000 (00:19 +0200)
committerThomas Geymayer <tomgey@gmail.com>
Wed, 7 May 2014 22:27:00 +0000 (00:27 +0200)
 - 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
simgear/structure/SGSharedPtr.hxx
simgear/structure/SGWeakPtr.hxx
simgear/structure/SGWeakReferenced.hxx

index 6a3038f3576494619e6590144ce3d638d547be31..69788b3f13aa42f4aa70565fcd23590d05db2672 100644 (file)
@@ -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:
index aedd846353a2764cccb3513d6e9839b092dce016..87497b8e0bfde5ec02d0bc12c3b2697769837cdf 100644 (file)
@@ -24,6 +24,9 @@
 #include "SGReferenced.hxx"
 #include <algorithm>
 
+template<typename T>
+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<typename T>
-class SGWeakPtr;
-
 template<typename T>
 class SGSharedPtr {
 public:
index 9dd2650a404851fc1b83543ceb65c338b5e6faf0..95e6792e1fed2878c35e39da7fdede1e6e314da0 100644 (file)
 
 #include "SGWeakReferenced.hxx"
 
+/**
+ * Class for handling weak references to classes derived from SGWeakReferenced
+ * or SGVirtualWeakReferenced.
+ */
 template<typename T>
 class SGWeakPtr {
 public:
index f5fd34c9a47476f8add67c792470b25118b39b72..dbe50574a0061533ea15a1fb8f8c066d31b39cba 100644 (file)
@@ -21,6 +21,9 @@
 #include "SGReferenced.hxx"
 #include "SGSharedPtr.hxx"
 
+#include <boost/type_traits/is_base_of.hpp>
+#include <boost/utility/enable_if.hpp>
+
 #ifdef _MSC_VER
 # pragma warning(push)
   // C4355: 'this' : used in base member initializer list
 
 template<typename T>
 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<T*>(mWeakReferenced);
+      return up_cast<T>(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<class T>
+    static
+    typename boost::enable_if<
+      boost::is_base_of<SGVirtualWeakReferenced, T>,
+      T*
+    >::type
+    up_cast(SGWeakReferenced* ptr)
+    {
+      // First get the virtual base class, which then can be used to further
+      // upcast.
+      return dynamic_cast<T*>(static_cast<SGVirtualWeakReferenced*>(ptr));
+    }
+
+    /// Upcast in a non-virtual class hierarchy
+    template<class T>
+    static
+    typename boost::disable_if<
+      boost::is_base_of<SGVirtualWeakReferenced, T>,
+      T*
+    >::type
+    up_cast(SGWeakReferenced* ptr)
+    {
+      return static_cast<T*>(ptr);
+    }
   };
 
   SGSharedPtr<WeakData> 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<Derived> ptr( new Derived() );
+ * SGWeakPtr<Derived> weak_ptr( ptr );
+ * SGSharedPtr<Base1> ptr1( weak_ptr.lock() );
+ * SGSharedPtr<Base2> ptr2( weak_ptr.lock() );
+ *
+ * @endcode
+ */
+class SGVirtualWeakReferenced:
+  public SGWeakReferenced
+{
+  public:
+    virtual ~SGVirtualWeakReferenced() {}
+};
+
 #ifdef _MSC_VER
 # pragma warning(pop)
 #endif