aboutsummaryrefslogtreecommitdiff
path: root/dep/g3dlite/include/G3D/ReferenceCount.h
diff options
context:
space:
mode:
authorjackpoz <giacomopoz@gmail.com>2014-08-22 16:58:23 +0200
committerjackpoz <giacomopoz@gmail.com>2014-08-22 21:00:56 +0200
commit5e8277e923c5545a15bae7c740ab6afaa597a59f (patch)
tree4cf5212c080588a7e868ee60134fc7fff51e400a /dep/g3dlite/include/G3D/ReferenceCount.h
parenta63aa858dcb400eafb97eed1f590e34c27d934a4 (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.h568
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&lt;<I>T</I>&gt; &lt;: RCP&lt;<I>S</I>&gt; if <I>T</I> &lt;: <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&lt;<I>T</I>&gt; &lt;: RCP&lt;<I>S</I>&gt; if <I>T</I> &lt;: <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