Ptr.h 17 KB

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