shared_ptr.hpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. #ifndef INCLUDED_AI_BOOST_SHARED_PTR
  2. #define INCLUDED_AI_BOOST_SHARED_PTR
  3. #ifndef BOOST_SHARED_PTR_HPP_INCLUDED
  4. // ------------------------------
  5. // Internal stub
  6. #include <stddef.h> //NULL
  7. #include <algorithm> //std::swap
  8. namespace boost {
  9. namespace detail {
  10. class controller {
  11. public:
  12. controller()
  13. : cnt(1)
  14. {}
  15. public:
  16. template <typename T>
  17. controller* decref(T* pt) {
  18. if (--cnt <= 0) {
  19. delete this;
  20. delete pt;
  21. }
  22. return NULL;
  23. }
  24. controller* incref() {
  25. ++cnt;
  26. return this;
  27. }
  28. long get() const {
  29. return cnt;
  30. }
  31. private:
  32. long cnt;
  33. };
  34. struct empty {};
  35. template <typename DEST, typename SRC>
  36. struct is_convertible_stub {
  37. struct yes {char s[1];};
  38. struct no {char s[2];};
  39. static yes foo(DEST*);
  40. static no foo(...);
  41. enum {result = (sizeof(foo((SRC*)0)) == sizeof(yes) ? 1 : 0)};
  42. };
  43. template <bool> struct enable_if {};
  44. template <> struct enable_if<true> {
  45. typedef empty result;
  46. };
  47. template <typename DEST, typename SRC>
  48. struct is_convertible : public enable_if<is_convertible_stub<DEST,SRC>::result > {
  49. };
  50. }
  51. // ------------------------------
  52. // Small replacement for boost::shared_ptr, not threadsafe because no
  53. // atomic reference counter is in use.
  54. // ------------------------------
  55. template <class T>
  56. class shared_ptr
  57. {
  58. template <typename TT> friend class shared_ptr;
  59. template<class TT, class U> friend shared_ptr<TT> static_pointer_cast (shared_ptr<U> ptr);
  60. template<class TT, class U> friend shared_ptr<TT> dynamic_pointer_cast (shared_ptr<U> ptr);
  61. template<class TT, class U> friend shared_ptr<TT> const_pointer_cast (shared_ptr<U> ptr);
  62. template<class TT> friend bool operator== (const shared_ptr<TT>& a, const shared_ptr<TT>& b);
  63. template<class TT> friend bool operator!= (const shared_ptr<TT>& a, const shared_ptr<TT>& b);
  64. template<class TT> friend bool operator< (const shared_ptr<TT>& a, const shared_ptr<TT>& b);
  65. public:
  66. typedef T element_type;
  67. public:
  68. // provide a default constructor
  69. shared_ptr()
  70. : ptr()
  71. , ctr(NULL)
  72. {
  73. }
  74. // construction from an existing object of type T
  75. explicit shared_ptr(T* ptr)
  76. : ptr(ptr)
  77. , ctr(ptr ? new detail::controller() : NULL)
  78. {
  79. }
  80. shared_ptr(const shared_ptr& r)
  81. : ptr(r.ptr)
  82. , ctr(r.ctr ? r.ctr->incref() : NULL)
  83. {
  84. }
  85. template <typename Y>
  86. shared_ptr(const shared_ptr<Y>& r,typename detail::is_convertible<T,Y>::result = detail::empty())
  87. : ptr(r.ptr)
  88. , ctr(r.ctr ? r.ctr->incref() : NULL)
  89. {
  90. }
  91. // automatic destruction of the wrapped object when all
  92. // references are freed.
  93. ~shared_ptr() {
  94. if (ctr) {
  95. ctr = ctr->decref(ptr);
  96. }
  97. }
  98. shared_ptr& operator=(const shared_ptr& r) {
  99. if (this == &r) {
  100. return *this;
  101. }
  102. if (ctr) {
  103. ctr->decref(ptr);
  104. }
  105. ptr = r.ptr;
  106. ctr = ptr?r.ctr->incref():NULL;
  107. return *this;
  108. }
  109. template <typename Y>
  110. shared_ptr& operator=(const shared_ptr<Y>& r) {
  111. if (this == &r) {
  112. return *this;
  113. }
  114. if (ctr) {
  115. ctr->decref(ptr);
  116. }
  117. ptr = r.ptr;
  118. ctr = ptr?r.ctr->incref():NULL;
  119. return *this;
  120. }
  121. // pointer access
  122. inline operator T*() const {
  123. return ptr;
  124. }
  125. inline T* operator-> () const {
  126. return ptr;
  127. }
  128. // standard semantics
  129. inline T* get() {
  130. return ptr;
  131. }
  132. inline const T* get() const {
  133. return ptr;
  134. }
  135. inline operator bool () const {
  136. return ptr != NULL;
  137. }
  138. inline bool unique() const {
  139. return use_count() == 1;
  140. }
  141. inline long use_count() const {
  142. return ctr->get();
  143. }
  144. inline void reset (T* t = 0) {
  145. if (ctr) {
  146. ctr->decref(ptr);
  147. }
  148. ptr = t;
  149. ctr = ptr?new detail::controller():NULL;
  150. }
  151. void swap(shared_ptr & b) {
  152. std::swap(ptr, b.ptr);
  153. std::swap(ctr, b.ctr);
  154. }
  155. private:
  156. // for use by the various xxx_pointer_cast helper templates
  157. explicit shared_ptr(T* ptr, detail::controller* ctr)
  158. : ptr(ptr)
  159. , ctr(ctr->incref())
  160. {
  161. }
  162. private:
  163. // encapsulated object pointer
  164. T* ptr;
  165. // control block
  166. detail::controller* ctr;
  167. };
  168. template<class T>
  169. inline void swap(shared_ptr<T> & a, shared_ptr<T> & b)
  170. {
  171. a.swap(b);
  172. }
  173. template<class T>
  174. bool operator== (const shared_ptr<T>& a, const shared_ptr<T>& b) {
  175. return a.ptr == b.ptr;
  176. }
  177. template<class T>
  178. bool operator!= (const shared_ptr<T>& a, const shared_ptr<T>& b) {
  179. return a.ptr != b.ptr;
  180. }
  181. template<class T>
  182. bool operator< (const shared_ptr<T>& a, const shared_ptr<T>& b) {
  183. return a.ptr < b.ptr;
  184. }
  185. template<class T, class U>
  186. inline shared_ptr<T> static_pointer_cast( shared_ptr<U> ptr)
  187. {
  188. return shared_ptr<T>(static_cast<T*>(ptr.ptr),ptr.ctr);
  189. }
  190. template<class T, class U>
  191. inline shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> ptr)
  192. {
  193. return shared_ptr<T>(dynamic_cast<T*>(ptr.ptr),ptr.ctr);
  194. }
  195. template<class T, class U>
  196. inline shared_ptr<T> const_pointer_cast( shared_ptr<U> ptr)
  197. {
  198. return shared_ptr<T>(const_cast<T*>(ptr.ptr),ptr.ctr);
  199. }
  200. } // end of namespace boost
  201. #else
  202. # error "shared_ptr.h was already included"
  203. #endif
  204. #endif // INCLUDED_AI_BOOST_SHARED_PTR