Ptr.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. // Copyright (c) 2008-2023 the Urho3D project
  2. // License: MIT
  3. #pragma once
  4. #include "../Base/PrimitiveTypes.h"
  5. #include "../Container/RefCounted.h"
  6. #include "../Container/Swap.h"
  7. #include <cassert>
  8. #include <cstddef>
  9. #include <utility>
  10. namespace Urho3D
  11. {
  12. /// Shared pointer template class with intrusive reference counting.
  13. template <class T> class SharedPtr
  14. {
  15. public:
  16. /// Construct a null shared pointer.
  17. SharedPtr() noexcept :
  18. ptr_(nullptr)
  19. {
  20. }
  21. /// Construct a null shared pointer.
  22. SharedPtr(std::nullptr_t) noexcept : // NOLINT(google-explicit-constructor)
  23. ptr_(nullptr)
  24. {
  25. }
  26. /// Copy-construct from another shared pointer.
  27. SharedPtr(const SharedPtr<T>& rhs) noexcept :
  28. ptr_(rhs.ptr_)
  29. {
  30. AddRef();
  31. }
  32. /// Move-construct from another shared pointer.
  33. SharedPtr(SharedPtr<T>&& rhs) noexcept :
  34. ptr_(rhs.ptr_)
  35. {
  36. rhs.ptr_ = nullptr;
  37. }
  38. /// Copy-construct from another shared pointer allowing implicit upcasting.
  39. template <class U> SharedPtr(const SharedPtr<U>& rhs) noexcept : // NOLINT(google-explicit-constructor)
  40. ptr_(rhs.ptr_)
  41. {
  42. AddRef();
  43. }
  44. /// Construct from a raw pointer.
  45. explicit SharedPtr(T* ptr) noexcept :
  46. ptr_(ptr)
  47. {
  48. AddRef();
  49. }
  50. /// Destruct. Release the object reference.
  51. ~SharedPtr() noexcept
  52. {
  53. ReleaseRef();
  54. }
  55. /// Assign from another shared pointer.
  56. SharedPtr<T>& operator =(const SharedPtr<T>& rhs)
  57. {
  58. if (ptr_ == rhs.ptr_)
  59. return *this;
  60. SharedPtr<T> copy(rhs);
  61. Swap(copy);
  62. return *this;
  63. }
  64. /// Move-assign from another shared pointer.
  65. SharedPtr<T>& operator =(SharedPtr<T>&& rhs)
  66. {
  67. SharedPtr<T> copy(std::move(rhs));
  68. Swap(copy);
  69. return *this;
  70. }
  71. /// Assign from another shared pointer allowing implicit upcasting.
  72. template <class U> SharedPtr<T>& operator =(const SharedPtr<U>& rhs)
  73. {
  74. if (ptr_ == rhs.ptr_)
  75. return *this;
  76. SharedPtr<T> copy(rhs);
  77. Swap(copy);
  78. return *this;
  79. }
  80. /// Assign from a raw pointer.
  81. SharedPtr<T>& operator =(T* ptr)
  82. {
  83. if (ptr_ == ptr)
  84. return *this;
  85. SharedPtr<T> copy(ptr);
  86. Swap(copy);
  87. return *this;
  88. }
  89. /// Point to the object.
  90. T* operator ->() const
  91. {
  92. assert(ptr_);
  93. return ptr_;
  94. }
  95. /// Dereference the object.
  96. T& operator *() const
  97. {
  98. assert(ptr_);
  99. return *ptr_;
  100. }
  101. /// Subscript the object if applicable.
  102. T& operator [](int index)
  103. {
  104. assert(ptr_);
  105. return ptr_[index];
  106. }
  107. /// Test for less than with another shared pointer.
  108. template <class U> bool operator <(const SharedPtr<U>& rhs) const { return ptr_ < rhs.ptr_; }
  109. /// Test for equality with another shared pointer.
  110. template <class U> bool operator ==(const SharedPtr<U>& rhs) const { return ptr_ == rhs.ptr_; }
  111. /// Test for inequality with another shared pointer.
  112. template <class U> bool operator !=(const SharedPtr<U>& rhs) const { return ptr_ != rhs.ptr_; }
  113. /// Convert to a raw pointer.
  114. operator T*() const { return ptr_; } // NOLINT(google-explicit-constructor)
  115. /// Swap with another SharedPtr.
  116. void Swap(SharedPtr<T>& rhs) { Urho3D::Swap(ptr_, rhs.ptr_); }
  117. /// Reset with another pointer.
  118. void Reset(T* ptr = nullptr)
  119. {
  120. SharedPtr<T> copy(ptr);
  121. Swap(copy);
  122. }
  123. /// Detach without destroying the object even if the refcount goes zero. To be used for scripting language interoperation.
  124. T* Detach()
  125. {
  126. T* ptr = ptr_;
  127. if (ptr_)
  128. {
  129. RefCount* refCount = RefCountPtr();
  130. ++refCount->refs_; // 2 refs
  131. Reset(); // 1 ref
  132. --refCount->refs_; // 0 refs
  133. }
  134. return ptr;
  135. }
  136. /// Perform a static cast from a shared pointer of another type.
  137. template <class U> void StaticCast(const SharedPtr<U>& rhs)
  138. {
  139. SharedPtr<T> copy(static_cast<T*>(rhs.Get()));
  140. Swap(copy);
  141. }
  142. /// Perform a dynamic cast from a shared pointer of another type.
  143. template <class U> void DynamicCast(const SharedPtr<U>& rhs)
  144. {
  145. SharedPtr<T> copy(dynamic_cast<T*>(rhs.Get()));
  146. Swap(copy);
  147. }
  148. /// Check if the pointer is null.
  149. bool Null() const { return ptr_ == 0; }
  150. /// Check if the pointer is not null.
  151. bool NotNull() const { return ptr_ != nullptr; }
  152. /// Return the raw pointer.
  153. T* Get() const { return ptr_; }
  154. /// Return the object's reference count, or 0 if the pointer is null.
  155. int Refs() const { return ptr_ ? ptr_->Refs() : 0; }
  156. /// Return the object's weak reference count, or 0 if the pointer is null.
  157. int WeakRefs() const { return ptr_ ? ptr_->WeakRefs() : 0; }
  158. /// Return pointer to the RefCount structure.
  159. RefCount* RefCountPtr() const { return ptr_ ? ptr_->RefCountPtr() : nullptr; }
  160. /// Return hash value for HashSet & HashMap.
  161. hash32 ToHash() const { return (hash32)((size_t)ptr_ / sizeof(T)); }
  162. private:
  163. template <class U> friend class SharedPtr;
  164. /// Add a reference to the object pointed to.
  165. void AddRef()
  166. {
  167. if (ptr_)
  168. ptr_->AddRef();
  169. }
  170. /// Release the object reference and delete it if necessary.
  171. void ReleaseRef()
  172. {
  173. if (ptr_)
  174. {
  175. ptr_->ReleaseRef();
  176. ptr_ = nullptr;
  177. }
  178. }
  179. /// Pointer to the object.
  180. T* ptr_;
  181. };
  182. /// Perform a static cast from one shared pointer type to another.
  183. template <class T, class U> SharedPtr<T> StaticCast(const SharedPtr<U>& ptr)
  184. {
  185. SharedPtr<T> ret;
  186. ret.StaticCast(ptr);
  187. return ret;
  188. }
  189. /// Perform a dynamic cast from one weak pointer type to another.
  190. template <class T, class U> SharedPtr<T> DynamicCast(const SharedPtr<U>& ptr)
  191. {
  192. SharedPtr<T> ret;
  193. ret.DynamicCast(ptr);
  194. return ret;
  195. }
  196. /// Weak pointer template class with intrusive reference counting. Does not keep the object pointed to alive.
  197. template <class T> class WeakPtr
  198. {
  199. public:
  200. /// Construct a null weak pointer.
  201. WeakPtr() noexcept :
  202. ptr_(nullptr),
  203. refCount_(nullptr)
  204. {
  205. }
  206. /// Construct a null weak pointer.
  207. WeakPtr(std::nullptr_t) noexcept : // NOLINT(google-explicit-constructor)
  208. ptr_(nullptr),
  209. refCount_(nullptr)
  210. {
  211. }
  212. /// Copy-construct from another weak pointer.
  213. WeakPtr(const WeakPtr<T>& rhs) noexcept :
  214. ptr_(rhs.ptr_),
  215. refCount_(rhs.refCount_)
  216. {
  217. AddRef();
  218. }
  219. /// Move-construct from another weak pointer.
  220. WeakPtr(WeakPtr<T>&& rhs) noexcept :
  221. ptr_(rhs.ptr_),
  222. refCount_(rhs.refCount_)
  223. {
  224. rhs.ptr_ = nullptr;
  225. rhs.refCount_ = nullptr;
  226. }
  227. /// Copy-construct from another weak pointer allowing implicit upcasting.
  228. template <class U> WeakPtr(const WeakPtr<U>& rhs) noexcept : // NOLINT(google-explicit-constructor)
  229. ptr_(rhs.ptr_),
  230. refCount_(rhs.refCount_)
  231. {
  232. AddRef();
  233. }
  234. /// Construct from a shared pointer.
  235. WeakPtr(const SharedPtr<T>& rhs) noexcept : // NOLINT(google-explicit-constructor)
  236. ptr_(rhs.Get()),
  237. refCount_(rhs.RefCountPtr())
  238. {
  239. AddRef();
  240. }
  241. /// Construct from a raw pointer.
  242. explicit WeakPtr(T* ptr) noexcept :
  243. ptr_(ptr),
  244. refCount_(ptr ? ptr->RefCountPtr() : nullptr)
  245. {
  246. AddRef();
  247. }
  248. /// Destruct. Release the weak reference to the object.
  249. ~WeakPtr() noexcept
  250. {
  251. ReleaseRef();
  252. }
  253. /// Assign from a shared pointer.
  254. WeakPtr<T>& operator =(const SharedPtr<T>& rhs)
  255. {
  256. if (ptr_ == rhs.Get() && refCount_ == rhs.RefCountPtr())
  257. return *this;
  258. WeakPtr<T> copy(rhs);
  259. Swap(copy);
  260. return *this;
  261. }
  262. /// Assign from a weak pointer.
  263. WeakPtr<T>& operator =(const WeakPtr<T>& rhs)
  264. {
  265. if (ptr_ == rhs.ptr_ && refCount_ == rhs.refCount_)
  266. return *this;
  267. WeakPtr<T> copy(rhs);
  268. Swap(copy);
  269. return *this;
  270. }
  271. /// Move-assign from another weak pointer.
  272. WeakPtr<T>& operator =(WeakPtr<T>&& rhs)
  273. {
  274. WeakPtr<T> copy(std::move(rhs));
  275. Swap(copy);
  276. return *this;
  277. }
  278. /// Assign from another weak pointer allowing implicit upcasting.
  279. template <class U> WeakPtr<T>& operator =(const WeakPtr<U>& rhs)
  280. {
  281. if (ptr_ == rhs.ptr_ && refCount_ == rhs.refCount_)
  282. return *this;
  283. ReleaseRef();
  284. ptr_ = rhs.ptr_;
  285. refCount_ = rhs.refCount_;
  286. AddRef();
  287. return *this;
  288. }
  289. /// Assign from a raw pointer.
  290. WeakPtr<T>& operator =(T* ptr)
  291. {
  292. RefCount* refCount = ptr ? ptr->RefCountPtr() : nullptr;
  293. if (ptr_ == ptr && refCount_ == refCount)
  294. return *this;
  295. ReleaseRef();
  296. ptr_ = ptr;
  297. refCount_ = refCount;
  298. AddRef();
  299. return *this;
  300. }
  301. /// Convert to a shared pointer. If expired, return a null shared pointer.
  302. SharedPtr<T> Lock() const
  303. {
  304. if (Expired())
  305. return SharedPtr<T>();
  306. else
  307. return SharedPtr<T>(ptr_);
  308. }
  309. /// Return raw pointer. If expired, return null.
  310. T* Get() const
  311. {
  312. return Expired() ? nullptr : ptr_;
  313. }
  314. /// Point to the object.
  315. T* operator ->() const
  316. {
  317. T* rawPtr = Get();
  318. assert(rawPtr);
  319. return rawPtr;
  320. }
  321. /// Dereference the object.
  322. T& operator *() const
  323. {
  324. T* rawPtr = Get();
  325. assert(rawPtr);
  326. return *rawPtr;
  327. }
  328. /// Subscript the object if applicable.
  329. T& operator [](int index)
  330. {
  331. T* rawPtr = Get();
  332. assert(rawPtr);
  333. return (*rawPtr)[index];
  334. }
  335. /// Test for equality with another weak pointer.
  336. template <class U> bool operator ==(const WeakPtr<U>& rhs) const { return ptr_ == rhs.ptr_ && refCount_ == rhs.refCount_; }
  337. /// Test for inequality with another weak pointer.
  338. template <class U> bool operator !=(const WeakPtr<U>& rhs) const { return ptr_ != rhs.ptr_ || refCount_ != rhs.refCount_; }
  339. /// Test for less than with another weak pointer.
  340. template <class U> bool operator <(const WeakPtr<U>& rhs) const { return ptr_ < rhs.ptr_; }
  341. /// Convert to a raw pointer, null if the object is expired.
  342. operator T*() const { return Get(); } // NOLINT(google-explicit-constructor)
  343. /// Swap with another WeakPtr.
  344. void Swap(WeakPtr<T>& rhs)
  345. {
  346. Urho3D::Swap(ptr_, rhs.ptr_);
  347. Urho3D::Swap(refCount_, rhs.refCount_);
  348. }
  349. /// Reset with another pointer.
  350. void Reset(T* ptr = nullptr)
  351. {
  352. WeakPtr<T> copy(ptr);
  353. Swap(copy);
  354. }
  355. /// Perform a static cast from a weak pointer of another type.
  356. template <class U> void StaticCast(const WeakPtr<U>& rhs)
  357. {
  358. ReleaseRef();
  359. ptr_ = static_cast<T*>(rhs.Get());
  360. refCount_ = rhs.refCount_;
  361. AddRef();
  362. }
  363. /// Perform a dynamic cast from a weak pointer of another type.
  364. template <class U> void DynamicCast(const WeakPtr<U>& rhs)
  365. {
  366. ReleaseRef();
  367. ptr_ = dynamic_cast<T*>(rhs.Get());
  368. if (ptr_)
  369. {
  370. refCount_ = rhs.refCount_;
  371. AddRef();
  372. }
  373. else
  374. refCount_ = 0;
  375. }
  376. /// Check if the pointer is null.
  377. bool Null() const { return refCount_ == nullptr; }
  378. /// Check if the pointer is not null.
  379. bool NotNull() const { return refCount_ != nullptr; }
  380. /// Return the object's reference count, or 0 if null pointer or if object has expired.
  381. int Refs() const { return (refCount_ && refCount_->refs_ >= 0) ? refCount_->refs_ : 0; }
  382. /// Return the object's weak reference count.
  383. int WeakRefs() const
  384. {
  385. if (!Expired())
  386. return ptr_->WeakRefs();
  387. else
  388. return refCount_ ? refCount_->weakRefs_ : 0;
  389. }
  390. /// Return whether the object has expired. If null pointer, always return true.
  391. bool Expired() const { return refCount_ ? refCount_->refs_ < 0 : true; }
  392. /// Return pointer to the RefCount structure.
  393. RefCount* RefCountPtr() const { return refCount_; }
  394. /// Return hash value for HashSet & HashMap.
  395. hash32 ToHash() const { return (hash32)((size_t)ptr_ / sizeof(T)); }
  396. private:
  397. template <class U> friend class WeakPtr;
  398. /// Add a weak reference to the object pointed to.
  399. void AddRef()
  400. {
  401. if (refCount_)
  402. {
  403. assert(refCount_->weakRefs_ >= 0);
  404. ++(refCount_->weakRefs_);
  405. }
  406. }
  407. /// Release the weak reference. Delete the Refcount structure if necessary.
  408. void ReleaseRef()
  409. {
  410. if (refCount_)
  411. {
  412. assert(refCount_->weakRefs_ > 0);
  413. --(refCount_->weakRefs_);
  414. if (Expired() && !refCount_->weakRefs_)
  415. delete refCount_;
  416. }
  417. ptr_ = nullptr;
  418. refCount_ = nullptr;
  419. }
  420. /// Pointer to the object.
  421. T* ptr_;
  422. /// Pointer to the RefCount structure.
  423. RefCount* refCount_;
  424. };
  425. /// Perform a static cast from one weak pointer type to another.
  426. template <class T, class U> WeakPtr<T> StaticCast(const WeakPtr<U>& ptr)
  427. {
  428. WeakPtr<T> ret;
  429. ret.StaticCast(ptr);
  430. return ret;
  431. }
  432. /// Perform a dynamic cast from one weak pointer type to another.
  433. template <class T, class U> WeakPtr<T> DynamicCast(const WeakPtr<U>& ptr)
  434. {
  435. WeakPtr<T> ret;
  436. ret.DynamicCast(ptr);
  437. return ret;
  438. }
  439. /// Delete object of type T. T must be complete. See boost::checked_delete.
  440. template<class T> inline void CheckedDelete(T* x)
  441. {
  442. // intentionally complex - simplification causes regressions
  443. using type_must_be_complete = char[sizeof(T) ? 1 : -1];
  444. (void) sizeof(type_must_be_complete);
  445. delete x;
  446. }
  447. /// Construct SharedPtr.
  448. template <class T, class ... Args> SharedPtr<T> MakeShared(Args&&... args)
  449. {
  450. return SharedPtr<T>(new T(std::forward<Args>(args)...));
  451. }
  452. }