SharedPtr.h 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. //
  2. // SharedPtr.h
  3. //
  4. // $Id: //poco/1.4/Foundation/include/Poco/SharedPtr.h#1 $
  5. //
  6. // Library: Foundation
  7. // Package: Core
  8. // Module: SharedPtr
  9. //
  10. // Definition of the SharedPtr template class.
  11. //
  12. // Copyright (c) 2005-2008, Applied Informatics Software Engineering GmbH.
  13. // and Contributors.
  14. //
  15. // SPDX-License-Identifier: BSL-1.0
  16. //
  17. #ifndef Foundation_SharedPtr_INCLUDED
  18. #define Foundation_SharedPtr_INCLUDED
  19. #include "Poco/Foundation.h"
  20. #include "Poco/Exception.h"
  21. #include "Poco/AtomicCounter.h"
  22. #include <algorithm>
  23. namespace Poco {
  24. class ReferenceCounter
  25. /// Simple ReferenceCounter object, does not delete itself when count reaches 0.
  26. {
  27. public:
  28. ReferenceCounter(): _cnt(1)
  29. {
  30. }
  31. void duplicate()
  32. {
  33. ++_cnt;
  34. }
  35. int release()
  36. {
  37. return --_cnt;
  38. }
  39. int referenceCount() const
  40. {
  41. return _cnt.value();
  42. }
  43. private:
  44. AtomicCounter _cnt;
  45. };
  46. template <class C>
  47. class ReleasePolicy
  48. /// The default release policy for SharedPtr, which
  49. /// simply uses the delete operator to delete an object.
  50. {
  51. public:
  52. static void release(C* pObj)
  53. /// Delete the object.
  54. /// Note that pObj can be 0.
  55. {
  56. delete pObj;
  57. }
  58. };
  59. template <class C>
  60. class ReleaseArrayPolicy
  61. /// The release policy for SharedPtr holding arrays.
  62. {
  63. public:
  64. static void release(C* pObj)
  65. /// Delete the object.
  66. /// Note that pObj can be 0.
  67. {
  68. delete [] pObj;
  69. }
  70. };
  71. template <class C, class RC = ReferenceCounter, class RP = ReleasePolicy<C> >
  72. class SharedPtr
  73. /// SharedPtr is a "smart" pointer for classes implementing
  74. /// reference counting based garbage collection.
  75. /// SharedPtr is thus similar to AutoPtr. Unlike the
  76. /// AutoPtr template, which can only be used with
  77. /// classes that support reference counting, SharedPtr
  78. /// can be used with any class. For this to work, a
  79. /// SharedPtr manages a reference count for the object
  80. /// it manages.
  81. ///
  82. /// SharedPtr works in the following way:
  83. /// If an SharedPtr is assigned an ordinary pointer to
  84. /// an object (via the constructor or the assignment operator),
  85. /// it takes ownership of the object and the object's reference
  86. /// count is initialized to one.
  87. /// If the SharedPtr is assigned another SharedPtr, the
  88. /// object's reference count is incremented by one.
  89. /// The destructor of SharedPtr decrements the object's
  90. /// reference count by one and deletes the object if the
  91. /// reference count reaches zero.
  92. /// SharedPtr supports dereferencing with both the ->
  93. /// and the * operator. An attempt to dereference a null
  94. /// SharedPtr results in a NullPointerException being thrown.
  95. /// SharedPtr also implements all relational operators and
  96. /// a cast operator in case dynamic casting of the encapsulated data types
  97. /// is required.
  98. {
  99. public:
  100. SharedPtr(): _pCounter(new RC), _ptr(0)
  101. {
  102. }
  103. SharedPtr(C* ptr)
  104. try:
  105. _pCounter(new RC),
  106. _ptr(ptr)
  107. {
  108. }
  109. catch (...)
  110. {
  111. RP::release(ptr);
  112. }
  113. template <class Other, class OtherRP>
  114. SharedPtr(const SharedPtr<Other, RC, OtherRP>& ptr): _pCounter(ptr._pCounter), _ptr(const_cast<Other*>(ptr.get()))
  115. {
  116. _pCounter->duplicate();
  117. }
  118. SharedPtr(const SharedPtr& ptr): _pCounter(ptr._pCounter), _ptr(ptr._ptr)
  119. {
  120. _pCounter->duplicate();
  121. }
  122. ~SharedPtr()
  123. {
  124. try
  125. {
  126. release();
  127. }
  128. catch (...)
  129. {
  130. poco_unexpected();
  131. }
  132. }
  133. SharedPtr& assign(C* ptr)
  134. {
  135. if (get() != ptr)
  136. {
  137. SharedPtr tmp(ptr);
  138. swap(tmp);
  139. }
  140. return *this;
  141. }
  142. SharedPtr& assign(const SharedPtr& ptr)
  143. {
  144. if (&ptr != this)
  145. {
  146. SharedPtr tmp(ptr);
  147. swap(tmp);
  148. }
  149. return *this;
  150. }
  151. template <class Other, class OtherRP>
  152. SharedPtr& assign(const SharedPtr<Other, RC, OtherRP>& ptr)
  153. {
  154. if (ptr.get() != _ptr)
  155. {
  156. SharedPtr tmp(ptr);
  157. swap(tmp);
  158. }
  159. return *this;
  160. }
  161. SharedPtr& operator = (C* ptr)
  162. {
  163. return assign(ptr);
  164. }
  165. SharedPtr& operator = (const SharedPtr& ptr)
  166. {
  167. return assign(ptr);
  168. }
  169. template <class Other, class OtherRP>
  170. SharedPtr& operator = (const SharedPtr<Other, RC, OtherRP>& ptr)
  171. {
  172. return assign<Other>(ptr);
  173. }
  174. void swap(SharedPtr& ptr)
  175. {
  176. std::swap(_ptr, ptr._ptr);
  177. std::swap(_pCounter, ptr._pCounter);
  178. }
  179. template <class Other>
  180. SharedPtr<Other, RC, RP> cast() const
  181. /// Casts the SharedPtr via a dynamic cast to the given type.
  182. /// Returns an SharedPtr containing NULL if the cast fails.
  183. /// Example: (assume class Sub: public Super)
  184. /// SharedPtr<Super> super(new Sub());
  185. /// SharedPtr<Sub> sub = super.cast<Sub>();
  186. /// poco_assert (sub.get());
  187. {
  188. Other* pOther = dynamic_cast<Other*>(_ptr);
  189. if (pOther)
  190. return SharedPtr<Other, RC, RP>(_pCounter, pOther);
  191. return SharedPtr<Other, RC, RP>();
  192. }
  193. template <class Other>
  194. SharedPtr<Other, RC, RP> unsafeCast() const
  195. /// Casts the SharedPtr via a static cast to the given type.
  196. /// Example: (assume class Sub: public Super)
  197. /// SharedPtr<Super> super(new Sub());
  198. /// SharedPtr<Sub> sub = super.unsafeCast<Sub>();
  199. /// poco_assert (sub.get());
  200. {
  201. Other* pOther = static_cast<Other*>(_ptr);
  202. return SharedPtr<Other, RC, RP>(_pCounter, pOther);
  203. }
  204. C* operator -> ()
  205. {
  206. return deref();
  207. }
  208. const C* operator -> () const
  209. {
  210. return deref();
  211. }
  212. C& operator * ()
  213. {
  214. return *deref();
  215. }
  216. const C& operator * () const
  217. {
  218. return *deref();
  219. }
  220. C* get()
  221. {
  222. return _ptr;
  223. }
  224. const C* get() const
  225. {
  226. return _ptr;
  227. }
  228. operator C* ()
  229. {
  230. return _ptr;
  231. }
  232. operator const C* () const
  233. {
  234. return _ptr;
  235. }
  236. bool operator ! () const
  237. {
  238. return _ptr == 0;
  239. }
  240. bool isNull() const
  241. {
  242. return _ptr == 0;
  243. }
  244. bool operator == (const SharedPtr& ptr) const
  245. {
  246. return get() == ptr.get();
  247. }
  248. bool operator == (const C* ptr) const
  249. {
  250. return get() == ptr;
  251. }
  252. bool operator == (C* ptr) const
  253. {
  254. return get() == ptr;
  255. }
  256. bool operator != (const SharedPtr& ptr) const
  257. {
  258. return get() != ptr.get();
  259. }
  260. bool operator != (const C* ptr) const
  261. {
  262. return get() != ptr;
  263. }
  264. bool operator != (C* ptr) const
  265. {
  266. return get() != ptr;
  267. }
  268. bool operator < (const SharedPtr& ptr) const
  269. {
  270. return get() < ptr.get();
  271. }
  272. bool operator < (const C* ptr) const
  273. {
  274. return get() < ptr;
  275. }
  276. bool operator < (C* ptr) const
  277. {
  278. return get() < ptr;
  279. }
  280. bool operator <= (const SharedPtr& ptr) const
  281. {
  282. return get() <= ptr.get();
  283. }
  284. bool operator <= (const C* ptr) const
  285. {
  286. return get() <= ptr;
  287. }
  288. bool operator <= (C* ptr) const
  289. {
  290. return get() <= ptr;
  291. }
  292. bool operator > (const SharedPtr& ptr) const
  293. {
  294. return get() > ptr.get();
  295. }
  296. bool operator > (const C* ptr) const
  297. {
  298. return get() > ptr;
  299. }
  300. bool operator > (C* ptr) const
  301. {
  302. return get() > ptr;
  303. }
  304. bool operator >= (const SharedPtr& ptr) const
  305. {
  306. return get() >= ptr.get();
  307. }
  308. bool operator >= (const C* ptr) const
  309. {
  310. return get() >= ptr;
  311. }
  312. bool operator >= (C* ptr) const
  313. {
  314. return get() >= ptr;
  315. }
  316. int referenceCount() const
  317. {
  318. return _pCounter->referenceCount();
  319. }
  320. private:
  321. C* deref() const
  322. {
  323. if (!_ptr)
  324. throw NullPointerException();
  325. return _ptr;
  326. }
  327. void release()
  328. {
  329. poco_assert_dbg (_pCounter);
  330. int i = _pCounter->release();
  331. if (i == 0)
  332. {
  333. RP::release(_ptr);
  334. _ptr = 0;
  335. delete _pCounter;
  336. _pCounter = 0;
  337. }
  338. }
  339. SharedPtr(RC* pCounter, C* ptr): _pCounter(pCounter), _ptr(ptr)
  340. /// for cast operation
  341. {
  342. poco_assert_dbg (_pCounter);
  343. _pCounter->duplicate();
  344. }
  345. private:
  346. RC* _pCounter;
  347. C* _ptr;
  348. template <class OtherC, class OtherRC, class OtherRP> friend class SharedPtr;
  349. };
  350. template <class C, class RC, class RP>
  351. inline void swap(SharedPtr<C, RC, RP>& p1, SharedPtr<C, RC, RP>& p2)
  352. {
  353. p1.swap(p2);
  354. }
  355. } // namespace Poco
  356. #endif // Foundation_SharedPtr_INCLUDED