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.
This commit is contained in:
Thomas Geymayer 2014-05-08 00:19:36 +02:00
parent efbec8b367
commit 9975c751a7
4 changed files with 87 additions and 5 deletions

View File

@ -26,7 +26,9 @@
/// Base class for all reference counted SimGear objects /// Base class for all reference counted SimGear objects
/// Classes derived from this one are meant to be managed with /// Classes derived from this one are meant to be managed with
/// the SGSharedPtr class. /// the SGSharedPtr class.
/// For more info see @SGSharedPtr. ///
/// For more info see SGSharedPtr. For using weak references see
/// SGWeakReferenced.
class SGReferenced { class SGReferenced {
public: public:

View File

@ -24,6 +24,9 @@
#include "SGReferenced.hxx" #include "SGReferenced.hxx"
#include <algorithm> #include <algorithm>
template<typename T>
class SGWeakPtr;
/// This class is a pointer proxy doing reference counting on the object /// This class is a pointer proxy doing reference counting on the object
/// it is pointing to. /// it is pointing to.
/// The SGSharedPtr class handles reference counting and possible /// The SGSharedPtr class handles reference counting and possible
@ -43,9 +46,6 @@
/// pretty much the same than this one at /// pretty much the same than this one at
/// http://dburns.dhs.org/OSG/Articles/RefPointers/RefPointers.html /// http://dburns.dhs.org/OSG/Articles/RefPointers/RefPointers.html
template<typename T>
class SGWeakPtr;
template<typename T> template<typename T>
class SGSharedPtr { class SGSharedPtr {
public: public:

View File

@ -20,6 +20,10 @@
#include "SGWeakReferenced.hxx" #include "SGWeakReferenced.hxx"
/**
* Class for handling weak references to classes derived from SGWeakReferenced
* or SGVirtualWeakReferenced.
*/
template<typename T> template<typename T>
class SGWeakPtr { class SGWeakPtr {
public: public:

View File

@ -21,6 +21,9 @@
#include "SGReferenced.hxx" #include "SGReferenced.hxx"
#include "SGSharedPtr.hxx" #include "SGSharedPtr.hxx"
#include <boost/type_traits/is_base_of.hpp>
#include <boost/utility/enable_if.hpp>
#ifdef _MSC_VER #ifdef _MSC_VER
# pragma warning(push) # pragma warning(push)
// C4355: 'this' : used in base member initializer list // C4355: 'this' : used in base member initializer list
@ -30,7 +33,18 @@
template<typename T> template<typename T>
class SGWeakPtr; 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 { class SGWeakReferenced {
public: public:
/// The object backref and the reference count for this object need to be /// The object backref and the reference count for this object need to be
@ -89,7 +103,7 @@ private:
} while (!mRefcount.compareAndExchange(count, count + 1)); } while (!mRefcount.compareAndExchange(count, count + 1));
// We know that as long as the refcount is not zero, the pointer still // 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. // points to valid data. So it is safe to work on it.
return static_cast<T*>(mWeakReferenced); return up_cast<T>(mWeakReferenced);
} }
SGAtomic mRefcount; SGAtomic mRefcount;
@ -99,6 +113,32 @@ private:
WeakData(void); WeakData(void);
WeakData(const WeakData&); WeakData(const WeakData&);
WeakData& operator=(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; SGSharedPtr<WeakData> mWeakData;
@ -107,6 +147,42 @@ private:
friend class SGWeakPtr; 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 #ifdef _MSC_VER
# pragma warning(pop) # pragma warning(pop)
#endif #endif