SharedPtr.h 7.6 KB

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