Ptr.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  1. //
  2. // Copyright (c) 2008-2017 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #pragma once
  23. #include "../Container/RefCounted.h"
  24. #include <cassert>
  25. #include <cstddef>
  26. #if ATOMIC_CXX11
  27. #include <utility>
  28. #endif
  29. namespace Atomic
  30. {
  31. /// Shared pointer template class with intrusive reference counting.
  32. template <class T> class SharedPtr
  33. {
  34. public:
  35. /// Construct a null shared pointer.
  36. SharedPtr() :
  37. ptr_(0)
  38. {
  39. }
  40. #if ATOMIC_CXX11
  41. /// Construct a null shared pointer.
  42. SharedPtr(std::nullptr_t) :
  43. ptr_(0)
  44. {
  45. }
  46. #endif
  47. /// Copy-construct from another shared pointer.
  48. SharedPtr(const SharedPtr<T>& rhs) :
  49. ptr_(rhs.ptr_)
  50. {
  51. AddRef();
  52. }
  53. /// Copy-construct from another shared pointer allowing implicit upcasting.
  54. template <class U> SharedPtr(const SharedPtr<U>& rhs) :
  55. ptr_(rhs.ptr_)
  56. {
  57. AddRef();
  58. }
  59. /// Construct from a raw pointer.
  60. explicit SharedPtr(T* ptr) :
  61. ptr_(ptr)
  62. {
  63. AddRef();
  64. }
  65. /// Destruct. Release the object reference.
  66. ~SharedPtr()
  67. {
  68. ReleaseRef();
  69. }
  70. /// Assign from another shared pointer.
  71. SharedPtr<T>& operator =(const SharedPtr<T>& rhs)
  72. {
  73. if (ptr_ == rhs.ptr_)
  74. return *this;
  75. ReleaseRef();
  76. ptr_ = rhs.ptr_;
  77. AddRef();
  78. return *this;
  79. }
  80. /// Assign from another shared pointer allowing implicit upcasting.
  81. template <class U> SharedPtr<T>& operator =(const SharedPtr<U>& rhs)
  82. {
  83. if (ptr_ == rhs.ptr_)
  84. return *this;
  85. ReleaseRef();
  86. ptr_ = rhs.ptr_;
  87. AddRef();
  88. return *this;
  89. }
  90. /// Assign from a raw pointer.
  91. SharedPtr<T>& operator =(T* ptr)
  92. {
  93. if (ptr_ == ptr)
  94. return *this;
  95. ReleaseRef();
  96. ptr_ = ptr;
  97. AddRef();
  98. return *this;
  99. }
  100. /// Point to the object.
  101. T* operator ->() const
  102. {
  103. assert(ptr_);
  104. return ptr_;
  105. }
  106. /// Dereference the object.
  107. T& operator *() const
  108. {
  109. assert(ptr_);
  110. return *ptr_;
  111. }
  112. /// Subscript the object if applicable.
  113. T& operator [](const int index)
  114. {
  115. assert(ptr_);
  116. return ptr_[index];
  117. }
  118. /// Test for less than with another shared pointer.
  119. template <class U> bool operator <(const SharedPtr<U>& rhs) const { return ptr_ < rhs.ptr_; }
  120. /// Test for equality with another shared pointer.
  121. template <class U> bool operator ==(const SharedPtr<U>& rhs) const { return ptr_ == rhs.ptr_; }
  122. /// Test for inequality with another shared pointer.
  123. template <class U> bool operator !=(const SharedPtr<U>& rhs) const { return ptr_ != rhs.ptr_; }
  124. /// Convert to a raw pointer.
  125. operator T*() const { return ptr_; }
  126. /// Reset to null and release the object reference.
  127. void Reset() { ReleaseRef(); }
  128. /// Detach without destroying the object even if the refcount goes zero. To be used for scripting language interoperation.
  129. T* Detach()
  130. {
  131. T* ptr = ptr_;
  132. if (ptr_)
  133. {
  134. RefCount* refCount = RefCountPtr();
  135. ++refCount->refs_; // 2 refs
  136. Reset(); // 1 ref
  137. --refCount->refs_; // 0 refs
  138. }
  139. return ptr;
  140. }
  141. /// Perform a static cast from a shared pointer of another type.
  142. template <class U> void StaticCast(const SharedPtr<U>& rhs)
  143. {
  144. ReleaseRef();
  145. ptr_ = static_cast<T*>(rhs.Get());
  146. AddRef();
  147. }
  148. /// Perform a dynamic cast from a shared pointer of another type.
  149. template <class U> void DynamicCast(const SharedPtr<U>& rhs)
  150. {
  151. ReleaseRef();
  152. ptr_ = dynamic_cast<T*>(rhs.Get());
  153. AddRef();
  154. }
  155. /// Check if the pointer is null.
  156. bool Null() const { return ptr_ == 0; }
  157. /// Check if the pointer is not null.
  158. bool NotNull() const { return ptr_ != 0; }
  159. /// Return the raw pointer.
  160. T* Get() const { return ptr_; }
  161. /// Return the object's reference count, or 0 if the pointer is null.
  162. int Refs() const { return ptr_ ? ptr_->Refs() : 0; }
  163. /// Return the object's weak reference count, or 0 if the pointer is null.
  164. int WeakRefs() const { return ptr_ ? ptr_->WeakRefs() : 0; }
  165. /// Return pointer to the RefCount structure.
  166. RefCount* RefCountPtr() const { return ptr_ ? ptr_->RefCountPtr() : 0; }
  167. /// Return hash value for HashSet & HashMap.
  168. unsigned ToHash() const { return (unsigned)((size_t)ptr_ / sizeof(T)); }
  169. private:
  170. template <class U> friend class SharedPtr;
  171. /// Add a reference to the object pointed to.
  172. void AddRef()
  173. {
  174. if (ptr_)
  175. ptr_->AddRef();
  176. }
  177. /// Release the object reference and delete it if necessary.
  178. void ReleaseRef()
  179. {
  180. if (ptr_)
  181. {
  182. ptr_->ReleaseRef();
  183. ptr_ = 0;
  184. }
  185. }
  186. /// Pointer to the object.
  187. T* ptr_;
  188. };
  189. /// Perform a static cast from one shared pointer type to another.
  190. template <class T, class U> SharedPtr<T> StaticCast(const SharedPtr<U>& ptr)
  191. {
  192. SharedPtr<T> ret;
  193. ret.StaticCast(ptr);
  194. return ret;
  195. }
  196. /// Perform a dynamic cast from one weak pointer type to another.
  197. template <class T, class U> SharedPtr<T> DynamicCast(const SharedPtr<U>& ptr)
  198. {
  199. SharedPtr<T> ret;
  200. ret.DynamicCast(ptr);
  201. return ret;
  202. }
  203. /// Weak pointer template class with intrusive reference counting. Does not keep the object pointed to alive.
  204. template <class T> class WeakPtr
  205. {
  206. public:
  207. /// Construct a null weak pointer.
  208. WeakPtr() :
  209. ptr_(0),
  210. refCount_(0)
  211. {
  212. }
  213. #if ATOMIC_CXX11
  214. /// Construct a null weak pointer.
  215. WeakPtr(std::nullptr_t) :
  216. ptr_(0),
  217. refCount_(0)
  218. {
  219. }
  220. #endif
  221. /// Copy-construct from another weak pointer.
  222. WeakPtr(const WeakPtr<T>& rhs) :
  223. ptr_(rhs.ptr_),
  224. refCount_(rhs.refCount_)
  225. {
  226. AddRef();
  227. }
  228. /// Copy-construct from another weak pointer allowing implicit upcasting.
  229. template <class U> WeakPtr(const WeakPtr<U>& rhs) :
  230. ptr_(rhs.ptr_),
  231. refCount_(rhs.refCount_)
  232. {
  233. AddRef();
  234. }
  235. /// Construct from a shared pointer.
  236. WeakPtr(const SharedPtr<T>& rhs) :
  237. ptr_(rhs.Get()),
  238. refCount_(rhs.RefCountPtr())
  239. {
  240. AddRef();
  241. }
  242. /// Construct from a raw pointer.
  243. explicit WeakPtr(T* ptr) :
  244. ptr_(ptr),
  245. refCount_(ptr ? ptr->RefCountPtr() : 0)
  246. {
  247. AddRef();
  248. }
  249. /// Destruct. Release the weak reference to the object.
  250. ~WeakPtr()
  251. {
  252. ReleaseRef();
  253. }
  254. /// Assign from a shared pointer.
  255. WeakPtr<T>& operator =(const SharedPtr<T>& rhs)
  256. {
  257. if (ptr_ == rhs.Get() && refCount_ == rhs.RefCountPtr())
  258. return *this;
  259. ReleaseRef();
  260. ptr_ = rhs.Get();
  261. refCount_ = rhs.RefCountPtr();
  262. AddRef();
  263. return *this;
  264. }
  265. /// Assign from a weak pointer.
  266. WeakPtr<T>& operator =(const WeakPtr<T>& rhs)
  267. {
  268. if (ptr_ == rhs.ptr_ && refCount_ == rhs.refCount_)
  269. return *this;
  270. ReleaseRef();
  271. ptr_ = rhs.ptr_;
  272. refCount_ = rhs.refCount_;
  273. AddRef();
  274. return *this;
  275. }
  276. /// Assign from another weak pointer allowing implicit upcasting.
  277. template <class U> WeakPtr<T>& operator =(const WeakPtr<U>& rhs)
  278. {
  279. if (ptr_ == rhs.ptr_ && refCount_ == rhs.refCount_)
  280. return *this;
  281. ReleaseRef();
  282. ptr_ = rhs.ptr_;
  283. refCount_ = rhs.refCount_;
  284. AddRef();
  285. return *this;
  286. }
  287. /// Assign from a raw pointer.
  288. WeakPtr<T>& operator =(T* ptr)
  289. {
  290. RefCount* refCount = ptr ? ptr->RefCountPtr() : 0;
  291. if (ptr_ == ptr && refCount_ == refCount)
  292. return *this;
  293. ReleaseRef();
  294. ptr_ = ptr;
  295. refCount_ = refCount;
  296. AddRef();
  297. return *this;
  298. }
  299. /// Convert to a shared pointer. If expired, return a null shared pointer.
  300. SharedPtr<T> Lock() const
  301. {
  302. if (Expired())
  303. return SharedPtr<T>();
  304. else
  305. return SharedPtr<T>(ptr_);
  306. }
  307. /// Return raw pointer. If expired, return null.
  308. T* Get() const
  309. {
  310. if (Expired())
  311. return 0;
  312. else
  313. return ptr_;
  314. }
  315. /// Point to the object.
  316. T* operator ->() const
  317. {
  318. T* rawPtr = Get();
  319. assert(rawPtr);
  320. return rawPtr;
  321. }
  322. /// Dereference the object.
  323. T& operator *() const
  324. {
  325. T* rawPtr = Get();
  326. assert(rawPtr);
  327. return *rawPtr;
  328. }
  329. /// Subscript the object if applicable.
  330. T& operator [](const int index)
  331. {
  332. T* rawPtr = Get();
  333. assert(rawPtr);
  334. return (*rawPtr)[index];
  335. }
  336. /// Test for equality with another weak pointer.
  337. template <class U> bool operator ==(const WeakPtr<U>& rhs) const { return ptr_ == rhs.ptr_ && refCount_ == rhs.refCount_; }
  338. /// Test for inequality with another weak pointer.
  339. template <class U> bool operator !=(const WeakPtr<U>& rhs) const { return ptr_ != rhs.ptr_ || refCount_ != rhs.refCount_; }
  340. /// Test for less than with another weak pointer.
  341. template <class U> bool operator <(const WeakPtr<U>& rhs) const { return ptr_ < rhs.ptr_; }
  342. /// Convert to a raw pointer, null if the object is expired.
  343. operator T*() const { return Get(); }
  344. /// Reset to null and release the weak reference.
  345. void Reset() { ReleaseRef(); }
  346. /// Perform a static cast from a weak pointer of another type.
  347. template <class U> void StaticCast(const WeakPtr<U>& rhs)
  348. {
  349. ReleaseRef();
  350. ptr_ = static_cast<T*>(rhs.Get());
  351. refCount_ = rhs.refCount_;
  352. AddRef();
  353. }
  354. /// Perform a dynamic cast from a weak pointer of another type.
  355. template <class U> void DynamicCast(const WeakPtr<U>& rhs)
  356. {
  357. ReleaseRef();
  358. ptr_ = dynamic_cast<T*>(rhs.Get());
  359. if (ptr_)
  360. {
  361. refCount_ = rhs.refCount_;
  362. AddRef();
  363. }
  364. else
  365. refCount_ = 0;
  366. }
  367. /// Check if the pointer is null.
  368. bool Null() const { return refCount_ == 0; }
  369. /// Check if the pointer is not null.
  370. bool NotNull() const { return refCount_ != 0; }
  371. /// Return the object's reference count, or 0 if null pointer or if object has expired.
  372. int Refs() const { return (refCount_ && refCount_->refs_ >= 0) ? refCount_->refs_ : 0; }
  373. /// Return the object's weak reference count.
  374. int WeakRefs() const
  375. {
  376. if (!Expired())
  377. return ptr_->WeakRefs();
  378. else
  379. return refCount_ ? refCount_->weakRefs_ : 0;
  380. }
  381. /// Return whether the object has expired. If null pointer, always return true.
  382. bool Expired() const { return refCount_ ? refCount_->refs_ < 0 : true; }
  383. /// Return pointer to the RefCount structure.
  384. RefCount* RefCountPtr() const { return refCount_; }
  385. /// Return hash value for HashSet & HashMap.
  386. unsigned ToHash() const { return (unsigned)((size_t)ptr_ / sizeof(T)); }
  387. private:
  388. template <class U> friend class WeakPtr;
  389. /// Add a weak reference to the object pointed to.
  390. void AddRef()
  391. {
  392. if (refCount_)
  393. {
  394. assert(refCount_->weakRefs_ >= 0);
  395. ++(refCount_->weakRefs_);
  396. }
  397. }
  398. /// Release the weak reference. Delete the Refcount structure if necessary.
  399. void ReleaseRef()
  400. {
  401. if (refCount_)
  402. {
  403. assert(refCount_->weakRefs_ > 0);
  404. --(refCount_->weakRefs_);
  405. if (Expired() && !refCount_->weakRefs_)
  406. delete refCount_;
  407. }
  408. ptr_ = 0;
  409. refCount_ = 0;
  410. }
  411. /// Pointer to the object.
  412. T* ptr_;
  413. /// Pointer to the RefCount structure.
  414. RefCount* refCount_;
  415. };
  416. /// Perform a static cast from one weak pointer type to another.
  417. template <class T, class U> WeakPtr<T> StaticCast(const WeakPtr<U>& ptr)
  418. {
  419. WeakPtr<T> ret;
  420. ret.StaticCast(ptr);
  421. return ret;
  422. }
  423. /// Perform a dynamic cast from one weak pointer type to another.
  424. template <class T, class U> WeakPtr<T> DynamicCast(const WeakPtr<U>& ptr)
  425. {
  426. WeakPtr<T> ret;
  427. ret.DynamicCast(ptr);
  428. return ret;
  429. }
  430. /// Delete object of type T. T must be complete. See boost::checked_delete.
  431. template<class T> inline void CheckedDelete(T* x)
  432. {
  433. // intentionally complex - simplification causes regressions
  434. typedef char type_must_be_complete[sizeof(T) ? 1 : -1];
  435. (void) sizeof(type_must_be_complete);
  436. delete x;
  437. }
  438. /// Unique pointer template class.
  439. template <class T> class UniquePtr
  440. {
  441. // Make non-copyable
  442. UniquePtr(const UniquePtr&);
  443. UniquePtr& operator=(const UniquePtr&);
  444. public:
  445. /// Construct empty.
  446. UniquePtr() : ptr_(0) { }
  447. /// Construct from pointer.
  448. explicit UniquePtr(T* ptr) : ptr_(ptr) { }
  449. /// Assign from pointer.
  450. UniquePtr& operator = (T* ptr)
  451. {
  452. Reset(ptr);
  453. return *this;
  454. }
  455. #if ATOMIC_CXX11
  456. /// Construct empty.
  457. UniquePtr(std::nullptr_t) { }
  458. /// Move-construct from UniquePtr.
  459. UniquePtr(UniquePtr && up) : ptr_(up.Detach()) { }
  460. /// Move-assign from UniquePtr.
  461. UniquePtr& operator = (UniquePtr && up)
  462. {
  463. Reset(up.Detach());
  464. return *this;
  465. }
  466. #endif
  467. /// Point to the object.
  468. T* operator ->() const
  469. {
  470. assert(ptr_);
  471. return ptr_;
  472. }
  473. /// Dereference the object.
  474. T& operator *() const
  475. {
  476. assert(ptr_);
  477. return *ptr_;
  478. }
  479. /// Test for less than with another unique pointer.
  480. template <class U>
  481. bool operator <(const UniquePtr<U>& rhs) const { return ptr_ < rhs.ptr_; }
  482. /// Test for equality with another unique pointer.
  483. template <class U>
  484. bool operator ==(const UniquePtr<U>& rhs) const { return ptr_ == rhs.ptr_; }
  485. /// Test for inequality with another unique pointer.
  486. template <class U>
  487. bool operator !=(const UniquePtr<U>& rhs) const { return ptr_ != rhs.ptr_; }
  488. /// Cast pointer to bool.
  489. operator bool() const { return !!ptr_; }
  490. /// Swap with another UniquePtr.
  491. void Swap(UniquePtr& up) { Swap(ptr_, up.ptr_); }
  492. /// Detach pointer from UniquePtr without destroying.
  493. T* Detach()
  494. {
  495. T* ptr = ptr_;
  496. ptr_ = 0;
  497. return ptr;
  498. }
  499. /// Check if the pointer is null.
  500. bool Null() const { return ptr_ == 0; }
  501. /// Check if the pointer is not null.
  502. bool NotNull() const { return ptr_ != 0; }
  503. /// Return the raw pointer.
  504. T* Get() const { return ptr_; }
  505. /// Reset.
  506. void Reset(T* ptr = 0)
  507. {
  508. CheckedDelete(ptr_);
  509. ptr_ = ptr;
  510. }
  511. /// Return hash value for HashSet & HashMap.
  512. unsigned ToHash() const { return (unsigned)((size_t)ptr_ / sizeof(T)); }
  513. /// Destruct.
  514. ~UniquePtr()
  515. {
  516. Reset();
  517. }
  518. private:
  519. T* ptr_;
  520. };
  521. /// Swap two UniquePtr-s.
  522. template <class T> void Swap(UniquePtr<T>& first, UniquePtr<T>& second)
  523. {
  524. first.Swap(second);
  525. }
  526. #if ATOMIC_CXX11
  527. /// Construct UniquePtr.
  528. template <class T, class ... Args> UniquePtr<T> MakeUnique(Args && ... args)
  529. {
  530. return UniquePtr<T>(new T(std::forward<Args>(args)...));
  531. }
  532. /// Construct SharedPtr.
  533. template <class T, class ... Args> SharedPtr<T> MakeShared(Args && ... args)
  534. {
  535. return SharedPtr<T>(new T(std::forward<Args>(args)...));
  536. }
  537. #endif
  538. }