Referenced 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
  2. *
  3. * This library is open source and may be redistributed and/or modified under
  4. * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
  5. * (at your option) any later version. The full license is in LICENSE file
  6. * included with this distribution, and on the openscenegraph.org website.
  7. *
  8. * This library is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * OpenSceneGraph Public License for more details.
  12. */
  13. #ifndef OSG_REFERENCED
  14. #define OSG_REFERENCED 1
  15. #include <osg/Export>
  16. #include <OpenThreads/ScopedLock>
  17. #include <OpenThreads/Mutex>
  18. #include <OpenThreads/Atomic>
  19. #if !defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
  20. # define _OSG_REFERENCED_USE_ATOMIC_OPERATIONS
  21. #endif
  22. namespace osg {
  23. // forward declare, declared after Referenced below.
  24. class DeleteHandler;
  25. class Observer;
  26. class ObserverSet;
  27. class State;
  28. /** template class to help enforce static initialization order. */
  29. template <typename T, T M()>
  30. struct depends_on
  31. {
  32. depends_on() { M(); }
  33. };
  34. /** Base class for providing reference counted objects.*/
  35. class OSG_EXPORT Referenced
  36. {
  37. public:
  38. Referenced();
  39. /** Deprecated, Referenced is now always uses thread safe ref/unref, use default Referenced() constructor instead */
  40. explicit Referenced(bool threadSafeRefUnref);
  41. Referenced(const Referenced&);
  42. inline Referenced& operator = (const Referenced&) { return *this; }
  43. /** Deprecated, Referenced is always theadsafe so there method now has no effect and does not need to be called.*/
  44. virtual void setThreadSafeRefUnref(bool /*threadSafe*/) {}
  45. /** Get whether a mutex is used to ensure ref() and unref() are thread safe.*/
  46. #if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
  47. bool getThreadSafeRefUnref() const { return true; }
  48. #else
  49. bool getThreadSafeRefUnref() const { return _refMutex!=0; }
  50. #endif
  51. /** Get the mutex used to ensure thread safety of ref()/unref(). */
  52. #if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
  53. OpenThreads::Mutex* getRefMutex() const { return getGlobalReferencedMutex(); }
  54. #else
  55. OpenThreads::Mutex* getRefMutex() const { return _refMutex; }
  56. #endif
  57. /** Get the optional global Referenced mutex, this can be shared between all osg::Referenced.*/
  58. static OpenThreads::Mutex* getGlobalReferencedMutex();
  59. /** Increment the reference count by one, indicating that
  60. this object has another pointer which is referencing it.*/
  61. inline int ref() const;
  62. /** Decrement the reference count by one, indicating that
  63. a pointer to this object is no longer referencing it. If the
  64. reference count goes to zero, it is assumed that this object
  65. is no longer referenced and is automatically deleted.*/
  66. inline int unref() const;
  67. /** Decrement the reference count by one, indicating that
  68. a pointer to this object is no longer referencing it. However, do
  69. not delete it, even if ref count goes to 0. Warning, unref_nodelete()
  70. should only be called if the user knows exactly who will
  71. be responsible for, one should prefer unref() over unref_nodelete()
  72. as the latter can lead to memory leaks.*/
  73. int unref_nodelete() const;
  74. /** Return the number of pointers currently referencing this object. */
  75. inline int referenceCount() const { return _refCount; }
  76. /** Get the ObserverSet if one is attached, otherwise return NULL.*/
  77. ObserverSet* getObserverSet() const
  78. {
  79. #if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
  80. return static_cast<ObserverSet*>(_observerSet.get());
  81. #else
  82. return static_cast<ObserverSet*>(_observerSet);
  83. #endif
  84. }
  85. /** Get the ObserverSet if one is attached, otherwise create an ObserverSet, attach it, then return this newly created ObserverSet.*/
  86. ObserverSet* getOrCreateObserverSet() const;
  87. /** Add a Observer that is observing this object, notify the Observer when this object gets deleted.*/
  88. void addObserver(Observer* observer) const;
  89. /** Remove Observer that is observing this object.*/
  90. void removeObserver(Observer* observer) const;
  91. #if 0
  92. /** Resize any per context GLObject buffers to specified size. */
  93. virtual void resizeGLObjectBuffers(unsigned int /*maxSize*/) {}
  94. /** If State is non-zero, this function releases any associated OpenGL objects for
  95. * the specified graphics context. Otherwise, releases OpenGL objects
  96. * for all graphics contexts. */
  97. virtual void releaseGLObjects(osg::State* = 0) const {}
  98. #endif
  99. public:
  100. friend class DeleteHandler;
  101. /** Set a DeleteHandler to which deletion of all referenced counted objects
  102. * will be delegated.*/
  103. static void setDeleteHandler(DeleteHandler* handler);
  104. /** Get a DeleteHandler.*/
  105. static DeleteHandler* getDeleteHandler();
  106. protected:
  107. virtual ~Referenced();
  108. void signalObserversAndDelete(bool signalDelete, bool doDelete) const;
  109. void deleteUsingDeleteHandler() const;
  110. #if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
  111. mutable OpenThreads::AtomicPtr _observerSet;
  112. mutable OpenThreads::Atomic _refCount;
  113. #else
  114. mutable OpenThreads::Mutex* _refMutex;
  115. mutable int _refCount;
  116. mutable void* _observerSet;
  117. #endif
  118. };
  119. inline int Referenced::ref() const
  120. {
  121. #if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
  122. return ++_refCount;
  123. #else
  124. if (_refMutex)
  125. {
  126. OpenThreads::ScopedLock<OpenThreads::Mutex> lock(*_refMutex);
  127. return ++_refCount;
  128. }
  129. else
  130. {
  131. return ++_refCount;
  132. }
  133. #endif
  134. }
  135. inline int Referenced::unref() const
  136. {
  137. int newRef;
  138. #if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
  139. newRef = --_refCount;
  140. bool needDelete = (newRef == 0);
  141. #else
  142. bool needDelete = false;
  143. if (_refMutex)
  144. {
  145. OpenThreads::ScopedLock<OpenThreads::Mutex> lock(*_refMutex);
  146. newRef = --_refCount;
  147. needDelete = newRef==0;
  148. }
  149. else
  150. {
  151. newRef = --_refCount;
  152. needDelete = newRef==0;
  153. }
  154. #endif
  155. if (needDelete)
  156. {
  157. signalObserversAndDelete(true,true);
  158. }
  159. return newRef;
  160. }
  161. // intrusive_ptr_add_ref and intrusive_ptr_release allow
  162. // use of osg Referenced classes with boost::intrusive_ptr
  163. inline void intrusive_ptr_add_ref(Referenced* p) { p->ref(); }
  164. inline void intrusive_ptr_release(Referenced* p) { p->unref(); }
  165. }
  166. #endif