diff options
author | jackpoz <giacomopoz@gmail.com> | 2014-08-22 16:58:23 +0200 |
---|---|---|
committer | jackpoz <giacomopoz@gmail.com> | 2014-08-22 21:00:56 +0200 |
commit | 5e8277e923c5545a15bae7c740ab6afaa597a59f (patch) | |
tree | 4cf5212c080588a7e868ee60134fc7fff51e400a /dep/g3dlite/include/G3D/ReferenceCount.h | |
parent | a63aa858dcb400eafb97eed1f590e34c27d934a4 (diff) |
Core/Dependencies: Update G3D to v9.0 r4036
Diffstat (limited to 'dep/g3dlite/include/G3D/ReferenceCount.h')
-rw-r--r-- | dep/g3dlite/include/G3D/ReferenceCount.h | 568 |
1 files changed, 27 insertions, 541 deletions
diff --git a/dep/g3dlite/include/G3D/ReferenceCount.h b/dep/g3dlite/include/G3D/ReferenceCount.h index 84591c6d8e5..d3ac0391585 100644 --- a/dep/g3dlite/include/G3D/ReferenceCount.h +++ b/dep/g3dlite/include/G3D/ReferenceCount.h @@ -1,14 +1,12 @@ /** - @file ReferenceCount.h + \file G3D/ReferenceCount.h Reference Counting Garbage Collector for C++ - @maintainer Morgan McGuire, http://graphics.cs.williams.edu - @cite Adapted and extended from Justin Miller's "RGC" class that appeared in BYTE magazine. - @cite See also http://www.jelovic.com/articles/cpp_without_memory_errors_slides.htm + \maintainer Morgan McGuire, http://graphics.cs.williams.edu - @created 2001-10-23 - @edited 2009-04-25 + \created 2001-10-23 + \edited 2013-01-05 */ #ifndef G3D_ReferenceCount_h #define G3D_ReferenceCount_h @@ -17,552 +15,40 @@ #include "G3D/debug.h" #include "G3D/AtomicInt32.h" -namespace G3D { - -#ifdef _MSC_VER -// Turn off "conditional expression is constant" warning; MSVC generates this -// for debug assertions in inlined methods. -# pragma warning (disable : 4127) -#endif - -/** Base class for WeakReferenceCountedPointer */ -class _WeakPtr { -public: - inline virtual ~_WeakPtr() {} - -protected: - friend class ReferenceCountedObject; - - /** Called by ReferenceCountedObject to tell a weak pointer that its underlying object was collected. */ - virtual void objectCollected() = 0; -}; - -/** Used internally by ReferenceCountedObject */ -class _WeakPtrLinkedList { -public: - _WeakPtr* weakPtr; - _WeakPtrLinkedList* next; - - inline _WeakPtrLinkedList() : weakPtr(NULL), next(NULL) {} - - /** Inserts this node into the head of the list that previously had n as its head. */ - inline _WeakPtrLinkedList(_WeakPtr* p, _WeakPtrLinkedList* n) : weakPtr(p), next(n) {} -}; - -/** - Objects that are reference counted inherit from this. Subclasses - <B>must</B> have a public destructor (the default destructor is fine) - and <B>publicly</B> inherit ReferenceCountedObject. - - Multiple inheritance from a reference counted object is dangerous-- use - at your own risk. +#define USE_SHARED_PTR - ReferenceCountedPointer and ReferenceCountedObject are threadsafe. - You can create and drop references on multiple threads without - violating integrity. WeakReferenceCountedPointer is <i>not</i> - threadsafe. Introducing a weak pointer destroys all thread safety, - even for strong pointers to the same object (this is inherent in the - design of the class; we cannot fix it without slowing down the - performance of reference counted objects.) - - <B>Usage Example</B> - - <PRE> +#define ReferenceCountedPointer shared_ptr +#define WeakReferenceCountedPointer weak_ptr +namespace G3D { -class Foo : public G3D::ReferenceCountedObject { +class ReferenceCountedObject : public enable_shared_from_this<ReferenceCountedObject> { public: - int x; + virtual ~ReferenceCountedObject() {}; }; -class Bar : public Foo {}; - -typedef G3D::ReferenceCountedPointer<Foo> FooRef; -typedef G3D::WeakReferenceCountedPointer<Foo> WeakFooRef; -typedef G3D::ReferenceCountedPointer<Bar> BarRef; - - -int main(int argc, char *argv[]) { - - WeakFooRef x; - - { - FooRef a = new Foo(); - - // Reference count == 1 - - x = a; - // Weak references do not increase count - - { - FooRef b = a; - // Reference count == 2 - } - - // Reference count == 1 - } - // No more strong references; object automatically deleted. - // x is set to NULL automatically. - - // Example of using dynamic cast on reference counted objects - BarRef b = new Bar(); - - // No cast needed to go down the heirarchy. - FooRef f = b; +} // namespace - // We can't cast the reference object because it is a class. - // Instead we must extract the pointer and cast that: - b = dynamic_cast<Bar*>(&*f); +namespace G3D { - return 0; +template<class T> +bool isNull(const ReferenceCountedPointer<T>& ptr) { + return ! ptr; } -</PRE> - */ -class ReferenceCountedObject { -public: - - /** - The long name is to keep this from accidentally conflicting with - a subclass's variable name. Do not use or explicitly manipulate - this value--its type may change in the future and is not part - of the supported API. - */ - AtomicInt32 ReferenceCountedObject_refCount; - - /** - Linked list of all weak pointers that reference this (some may be - on the stack!). Do not use or explicitly manipulate this value. - */ - _WeakPtrLinkedList* ReferenceCountedObject_weakPointer; - -protected: - - ReferenceCountedObject(); - -public: - - /** Automatically called immediately before the object is deleted. - This is not called from the destructor because it needs to be invoked - before the subclass destructor. - */ - void ReferenceCountedObject_zeroWeakPointers(); - - virtual ~ReferenceCountedObject(); - - - /** - Note: copies will initially start out with 0 - references and 0 weak references like any other object. - */ - ReferenceCountedObject(const ReferenceCountedObject& notUsed); - - ReferenceCountedObject& operator=(const ReferenceCountedObject& other); -}; - - - -/** - Use ReferenceCountedPointer<T> in place of T* in your program. - T must subclass ReferenceCountedObject. -@deprecated To be replaced by boost::shared_ptr in 7.0 - */ -template <class T> -class ReferenceCountedPointer { -private: - - T* m_pointer; - -public: - typedef T element_type; - - inline T* pointer() const { - return m_pointer; - } - -private: - - /** Nulls out the pointer and drops a reference. If the reference - count hits zero. */ - void zeroPointer() { - if (m_pointer != NULL) { - - ReferenceCountedObject* pointer = ((ReferenceCountedObject*)m_pointer); - debugAssert(G3D::isValidHeapPointer(m_pointer)); - debugAssertM(pointer->ReferenceCountedObject_refCount.value() > 0, - "Dangling reference detected."); - - // Only delete if this instance caused the count to hit - // exactly zero. If there is a race condition, the value - // may be zero after decrement returns, but only one of - // the instances will get a zero return value. - if (pointer->ReferenceCountedObject_refCount.decrement() == 0) { - // We held the last reference, so delete the object. - // This test is threadsafe because there is no way for - // the reference count to increase after the last - // reference was dropped (assuming the application does - // not voilate the class abstraction). - //debugPrintf(" delete 0x%x\n", m_pointer); - - // We must zero the weak pointers *before* deletion in case there - // are cycles of weak references. - // Note that since there are no strong references at this point, - // it is perfectly fair to zero the weak pointers anyway. - pointer->ReferenceCountedObject_zeroWeakPointers(); - delete pointer; - } - - m_pointer = NULL; - } - } - - /** Non-atomic (except for the referencec increment). Can only be - called in contexts like the copy constructor or initial - constructor where it is known that the reference count will - not hit zero on some other thread. */ - void setPointer(T* x) { - if (x != m_pointer) { - zeroPointer(); - - if (x != NULL) { - debugAssert(G3D::isValidHeapPointer(x)); - - m_pointer = x; - - // Note that the ref count can be zero if this is the - // first pointer to it - ReferenceCountedObject* pointer = (ReferenceCountedObject*)m_pointer; - debugAssertM(pointer->ReferenceCountedObject_refCount.value() >= 0, - "Negative reference count detected."); - pointer->ReferenceCountedObject_refCount.increment(); - } - } - } - -public: - - inline ReferenceCountedPointer() : m_pointer(NULL) {} - /** - Allow silent cast <i>to</i> the base class. - - <pre> - SubRef s = new Sub(); - BaseRef b = s; - </pre> - - i.e., compile-time subtyping rule - RCP<<I>T</I>> <: RCP<<I>S</I>> if <I>T</I> <: <I>S</I> - */ - template <class S> - inline ReferenceCountedPointer(const ReferenceCountedPointer<S>& p) : - m_pointer(NULL) { - setPointer(p.pointer()); - } - -# if (! defined(MSC_VER) || (MSC_VER >= 1300)) - /** - Explicit cast to a subclass. Acts like dynamic cast; the result will be NULL if - the cast cannot succeed. Not supported on VC6. - <pre> - SubRef s = new Sub(); - BaseRef b = s; - s = b.downcast<Sub>(); // Note that the template argument is the object type, not the pointer type. - </pre> - */ - template <class S> - ReferenceCountedPointer<S> downcast() { - return ReferenceCountedPointer<S>(dynamic_cast<S*>(m_pointer)); - } - - template <class S> - const ReferenceCountedPointer<S> downcast() const { - return ReferenceCountedPointer<S>(dynamic_cast<const S*>(m_pointer)); - } -# endif - - // We need an explicit version of the copy constructor as well or - // the default copy constructor will be used. - inline ReferenceCountedPointer(const ReferenceCountedPointer<T>& p) : m_pointer(NULL) { - setPointer(p.m_pointer); - } - - /** Allows construction from a raw pointer. That object will thereafter be - reference counted -- do not call delete on it. - - Use of const allows downcast on const references */ - inline ReferenceCountedPointer(const T* p) : m_pointer(NULL) { - // only const constructor is defined to remove ambiguity using NULL - setPointer(const_cast<T*>(p)); - } - - - inline ~ReferenceCountedPointer() { - zeroPointer(); - } - - inline size_t hashCode() const { - return reinterpret_cast<size_t>(m_pointer);; - } - - inline const ReferenceCountedPointer<T>& operator=(const ReferenceCountedPointer<T>& p) { - setPointer(p.m_pointer); - return *this; - } - - inline ReferenceCountedPointer<T>& operator=(T* p) { - setPointer(p); - return *this; - } - - inline bool operator==(const ReferenceCountedPointer<T>& y) const { - return (m_pointer == y.m_pointer); - } - - inline bool operator!=(const ReferenceCountedPointer<T>& y) const { - return (m_pointer != y.m_pointer); - } - - bool operator < (const ReferenceCountedPointer<T>& y) const { - return (m_pointer < y.m_pointer); - } - - bool operator > (const ReferenceCountedPointer<T>& y) const { - return (m_pointer > y.m_pointer); - } - - bool operator <= (const ReferenceCountedPointer<T>& y) const { - return (m_pointer <= y.m_pointer); - } - - bool operator >= (const ReferenceCountedPointer<T>& y) const { - return (m_pointer >= y.m_pointer); - } - - inline T& operator*() const { - debugAssertM(m_pointer != NULL, "Dereferenced a NULL ReferenceCountedPointer"); - return (*m_pointer); - } - - inline T* operator->() const { - debugAssertM(m_pointer != NULL, "Dereferenced a NULL ReferenceCountedPointer"); - return m_pointer; - } - - inline bool isNull() const { - return (m_pointer == NULL); - } - - inline bool notNull() const { - return (m_pointer != NULL); - } - - // TODO: distinguish between last strong and last any pointer - /** - Returns true if this is the last reference to an object. - Useful for flushing memoization caches-- a cache that holds the last - reference is unnecessarily keeping an object alive. - - <b>Not threadsafe.</b> - - @deprecated Use WeakReferenceCountedPointer for caches - */ - inline int isLastReference() const { - return (m_pointer->ReferenceCountedObject_refCount.value() == 1); - } -}; - - -/** - A weak pointer allows the object it references to be garbage collected. - Weak pointers are commonly used in caches, where it is important to hold - a pointer to an object without keeping that object alive solely for the - cache's benefit (i.e., the object can be collected as soon as all - pointers to it <B>outside</B> the cache are gone). They are also convenient - for adding back-pointers in tree and list structures. - - Weak pointers may become NULL at any point (when their target is collected). - Therefore the only way to reference the target is to convert to a strong - pointer and then check that it is not NULL. - -@deprecated To be replaced by boost::weak_ptr in 7.0 - */ -template <class T> -class WeakReferenceCountedPointer : public _WeakPtr { -private: - - /** NULL if the object has been collected. */ - T* pointer; - -public: - /** - Creates a strong pointer, which prevents the object from being - garbage collected. The strong pointer may be NULL, which means - that the underlying. - */ - // There is intentionally no way to check if the - // WeakReferenceCountedPointer has a null reference without - // creating a strong pointer since there is no safe way to use - // that information-- the pointer could be collected by a - // subsequent statement. - ReferenceCountedPointer<T> createStrongPtr() const { - // TODO: What if the object's destructor is called while we - // are in this method? - return ReferenceCountedPointer<T>(pointer); - } - -private: - - /** Thread issues: safe because this is only called when another - object is guaranteed to keep p alive for the duration of this - call. */ - void setPointer(T* p) { - // TODO: must prevent the object from being collected while in - // this method - - zeroPointer(); - pointer = p; - - if (pointer != NULL) { - // TODO: threadsafe: must update the list atomically - - // Add myself to the head of my target's list of weak pointers - _WeakPtrLinkedList* head = - new _WeakPtrLinkedList - (this, - pointer->ReferenceCountedObject_weakPointer); - - pointer->ReferenceCountedObject_weakPointer = head; - } else { - - } - } - - - /** - Removes this from its target's list of weak pointers. Called - when the weak pointer goes out of scope. - - Thread issues: depends on the thread safety of createStrongPtr. - */ - void zeroPointer() { - // Grab a strong reference to prevent the object from being collected while we - // are traversing its list. - ReferenceCountedPointer<T> strong = createStrongPtr(); - - // If the following test fails then the object was collected before we - // reached it. - if (strong.notNull()) { - debugAssertM(((ReferenceCountedObject*)pointer)->ReferenceCountedObject_weakPointer != NULL, - "Weak pointer exists without a backpointer from the object."); - - // Remove myself from my target's list of weak pointers - _WeakPtrLinkedList** node = &((ReferenceCountedObject*)pointer)->ReferenceCountedObject_weakPointer; - while ((*node)->weakPtr != this) { - node = &((*node)->next); - debugAssertM(*node != NULL, - "Weak pointer exists without a backpointer from the object (2)."); - } - - // Node must now point at the node for me. Remove node and - // close the linked list behind it. - _WeakPtrLinkedList* temp = *node; - *node = temp->next; - - // Now delete the node corresponding to me - delete temp; - } - - pointer = NULL; - } - -public: - - WeakReferenceCountedPointer() : pointer(0) {} - - /** - Allow compile time subtyping rule - RCP<<I>T</I>> <: RCP<<I>S</I>> if <I>T</I> <: <I>S</I> - */ - template <class S> - inline WeakReferenceCountedPointer(const WeakReferenceCountedPointer<S>& p) : pointer(0) { - // Threadsafe: the object cannot be collected while the other pointer exists. - setPointer(p.pointer); - } - - template <class S> - inline WeakReferenceCountedPointer(const ReferenceCountedPointer<S>& p) : pointer(0) { - // Threadsafe: the object cannot be collected while the other - // pointer exists. - setPointer(p.pointer()); - } - - // Gets called a *lot* when weak pointers are on the stack - WeakReferenceCountedPointer( - const WeakReferenceCountedPointer<T>& weakPtr) : pointer(0) { - setPointer(weakPtr.pointer); - } - - WeakReferenceCountedPointer( - const ReferenceCountedPointer<T>& strongPtr) : pointer(0) { - setPointer(strongPtr.pointer()); - } - - ~WeakReferenceCountedPointer() { - zeroPointer(); - } - - WeakReferenceCountedPointer<T>& operator=(const WeakReferenceCountedPointer<T>& other) { - // Threadsafe: the object cannot be collected while the other pointer exists. - - // I now point at other's target - setPointer(other.pointer); - - return *this; - } - - WeakReferenceCountedPointer<T>& operator=(const ReferenceCountedPointer<T>& other) { - - // Threadsafe: the object cannot be collected while the other pointer exists. - - // I now point at other's target - setPointer(other.pointer()); - - return *this; - } - - bool operator==(const WeakReferenceCountedPointer<T>& other) const { - return pointer == other.pointer; - } - - bool operator!=(const WeakReferenceCountedPointer<T>& other) const { - return pointer != other.pointer; - } - - bool operator < (const WeakReferenceCountedPointer<T>& y) const { - return (pointer < y.pointer); - } - - bool operator > (const WeakReferenceCountedPointer<T>& y) const { - return (pointer > y.pointer); - } - - bool operator <= (const WeakReferenceCountedPointer<T>& y) const { - return (pointer <= y.pointer); - } - - bool operator >= (const ReferenceCountedPointer<T>& y) const { - return (pointer >= y.pointer); - } - -protected: +template<class T> +bool notNull(const ReferenceCountedPointer<T>& ptr) { + return (bool)ptr; +} - /** Invoked by the destructor on ReferenceCountedPointer. */ - void objectCollected() { - debugAssertM(pointer != NULL, - "Removed a weak pointer twice."); - pointer = NULL; - } +template<class T> +bool isNull(const T* ptr) { + return ptr == NULL; +} -}; +template<class T> +bool notNull(const T* ptr) { + return ptr != NULL; +} } // namespace |