Ptr.h 18 KB

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