observer_ptr 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  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_OBSERVER_PTR
  14. #define OSG_OBSERVER_PTR
  15. #include <osg/Notify>
  16. #include <osg/ref_ptr>
  17. #include <osg/Observer>
  18. #include <OpenThreads/ScopedLock>
  19. #include <OpenThreads/Mutex>
  20. namespace osg {
  21. /** Smart pointer for observed objects, that automatically set pointers to them to null when they are deleted.
  22. * To use the observer_ptr<> robustly in multi-threaded applications it is recommend to access the pointer via
  23. * the lock() method that passes back a ref_ptr<> that safely takes a reference to the object to prevent deletion
  24. * during usage of the object. In certain conditions it may be safe to use the pointer directly without using lock(),
  25. * which will confer a performance advantage, the conditions are:
  26. * 1) The data structure is only accessed/deleted in single threaded/serial way.
  27. * 2) The data strucutre is guaranteed by high level management of data strucutures and threads which avoid
  28. * possible situations where the observer_ptr<>'s object may be deleted by one thread whilst being accessed
  29. * by another.
  30. * If you are in any doubt about whether it is safe to access the object safe then use the
  31. * ref_ptr<> observer_ptr<>.lock() combination. */
  32. template<class T>
  33. class observer_ptr
  34. {
  35. public:
  36. typedef T element_type;
  37. observer_ptr() : _reference(0), _ptr(0) {}
  38. /**
  39. * Create a observer_ptr from a ref_ptr.
  40. */
  41. observer_ptr(const ref_ptr<T>& rp)
  42. {
  43. _reference = rp.valid() ? rp->getOrCreateObserverSet() : 0;
  44. _ptr = (_reference.valid() && _reference->getObserverdObject()!=0) ? rp.get() : 0;
  45. }
  46. /**
  47. * Create a observer_ptr from a raw pointer. For compatibility;
  48. * the result might not be lockable.
  49. */
  50. observer_ptr(T* rp)
  51. {
  52. _reference = rp ? rp->getOrCreateObserverSet() : 0;
  53. _ptr = (_reference.valid() && _reference->getObserverdObject()!=0) ? rp : 0;
  54. }
  55. observer_ptr(const observer_ptr& wp) :
  56. _reference(wp._reference),
  57. _ptr(wp._ptr)
  58. {
  59. }
  60. ~observer_ptr()
  61. {
  62. }
  63. observer_ptr& operator = (const observer_ptr& wp)
  64. {
  65. if (&wp==this) return *this;
  66. _reference = wp._reference;
  67. _ptr = wp._ptr;
  68. return *this;
  69. }
  70. observer_ptr& operator = (const ref_ptr<T>& rp)
  71. {
  72. _reference = rp.valid() ? rp->getOrCreateObserverSet() : 0;
  73. _ptr = (_reference.valid() && _reference->getObserverdObject()!=0) ? rp.get() : 0;
  74. return *this;
  75. }
  76. observer_ptr& operator = (T* rp)
  77. {
  78. _reference = rp ? rp->getOrCreateObserverSet() : 0;
  79. _ptr = (_reference.valid() && _reference->getObserverdObject()!=0) ? rp : 0;
  80. return *this;
  81. }
  82. /**
  83. * Assign the observer_ptr to a ref_ptr. The ref_ptr will be valid if the
  84. * referenced object hasn't been deleted and has a ref count > 0.
  85. */
  86. bool lock(ref_ptr<T>& rptr) const
  87. {
  88. if (!_reference)
  89. {
  90. rptr = 0;
  91. return false;
  92. }
  93. Referenced* obj = _reference->addRefLock();
  94. if (!obj)
  95. {
  96. rptr = 0;
  97. return false;
  98. }
  99. rptr = _ptr;
  100. obj->unref_nodelete();
  101. return rptr.valid();
  102. }
  103. /** Comparison operators. These continue to work even after the
  104. * observed object has been deleted.
  105. */
  106. bool operator == (const observer_ptr& wp) const { return _reference == wp._reference; }
  107. bool operator != (const observer_ptr& wp) const { return _reference != wp._reference; }
  108. bool operator < (const observer_ptr& wp) const { return _reference < wp._reference; }
  109. bool operator > (const observer_ptr& wp) const { return wp._reference < _reference; }
  110. // Non-strict interface, for compatibility
  111. // comparison operator for const T*.
  112. inline bool operator == (const T* ptr) const { return _ptr == ptr; }
  113. inline bool operator != (const T* ptr) const { return _ptr != ptr; }
  114. inline bool operator < (const T* ptr) const { return _ptr < ptr; }
  115. inline bool operator > (const T* ptr) const { return _ptr > ptr; }
  116. // Convenience methods for operating on object, however, access is not automatically threadsafe.
  117. // To make thread safe, one should either ensure at a high level
  118. // that the object will not be deleted while operating on it, or
  119. // by using the observer_ptr<>::lock() to get a ref_ptr<> that
  120. // ensures the objects stay alive throughout all access to it.
  121. // Throw an error if _reference is null?
  122. inline T& operator*() const { return *_ptr; }
  123. inline T* operator->() const { return _ptr; }
  124. // get the raw C pointer
  125. inline T* get() const { return (_reference.valid() && _reference->getObserverdObject()!=0) ? _ptr : 0; }
  126. inline bool operator!() const { return get() == 0; }
  127. inline bool valid() const { return get() != 0; }
  128. protected:
  129. osg::ref_ptr<ObserverSet> _reference;
  130. T* _ptr;
  131. };
  132. }
  133. #endif