Ptr.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. // Copyright (C) 2009-2022, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma once
  6. #include <AnKi/Util/Allocator.h>
  7. namespace anki {
  8. /// @addtogroup util_memory
  9. /// @{
  10. /// Common code for all pointers
  11. template<typename T>
  12. class PtrBase
  13. {
  14. template<typename Y>
  15. friend class PtrBase;
  16. public:
  17. /// Dereference
  18. T& operator*() const
  19. {
  20. ANKI_ASSERT(m_ptr);
  21. return *m_ptr;
  22. }
  23. /// Dereference
  24. T* operator->() const
  25. {
  26. ANKI_ASSERT(m_ptr);
  27. return m_ptr;
  28. }
  29. T* get() const
  30. {
  31. ANKI_ASSERT(m_ptr);
  32. return m_ptr;
  33. }
  34. Bool isCreated() const
  35. {
  36. return m_ptr != nullptr;
  37. }
  38. /// @name Compare operators
  39. /// @{
  40. explicit operator Bool() const
  41. {
  42. return isCreated();
  43. }
  44. Bool operator==(const PtrBase& other) const
  45. {
  46. return m_ptr == other.m_ptr;
  47. }
  48. Bool operator!=(const PtrBase& other) const
  49. {
  50. return m_ptr != other.m_ptr;
  51. }
  52. Bool operator<(const PtrBase& other) const
  53. {
  54. return m_ptr < other.m_ptr;
  55. }
  56. Bool operator<=(const PtrBase& other) const
  57. {
  58. return m_ptr <= other.m_ptr;
  59. }
  60. Bool operator>(const PtrBase& other) const
  61. {
  62. return m_ptr > other.m_ptr;
  63. }
  64. Bool operator>=(const PtrBase& other) const
  65. {
  66. return m_ptr >= other.m_ptr;
  67. }
  68. /// @}
  69. protected:
  70. T* m_ptr;
  71. PtrBase()
  72. : m_ptr(nullptr)
  73. {
  74. }
  75. PtrBase(T* ptr)
  76. : m_ptr(ptr)
  77. {
  78. }
  79. };
  80. /// A simple template class to wrap simple pointers.
  81. template<typename T>
  82. class WeakPtr : public PtrBase<T>
  83. {
  84. template<typename>
  85. friend class WeakPtr;
  86. public:
  87. using Base = PtrBase<T>;
  88. WeakPtr()
  89. : Base()
  90. {
  91. }
  92. explicit WeakPtr(T* ptr)
  93. : Base(ptr)
  94. {
  95. }
  96. WeakPtr(const WeakPtr& other)
  97. : Base(other.m_ptr)
  98. {
  99. }
  100. template<typename Y>
  101. WeakPtr(const WeakPtr<Y>& other)
  102. : Base(other.m_ptr)
  103. {
  104. }
  105. WeakPtr(WeakPtr&& other)
  106. : Base(other.m_ptr)
  107. {
  108. other.m_ptr = nullptr;
  109. }
  110. /// Destroy.
  111. ~WeakPtr()
  112. {
  113. Base::m_ptr = nullptr;
  114. }
  115. /// Copy.
  116. WeakPtr& operator=(const WeakPtr& other)
  117. {
  118. Base::m_ptr = other.m_ptr;
  119. return *this;
  120. }
  121. /// Copy.
  122. template<typename Y>
  123. WeakPtr& operator=(const WeakPtr<Y>& other)
  124. {
  125. Base::m_ptr = other.m_ptr;
  126. return *this;
  127. }
  128. /// Copy.
  129. WeakPtr& operator=(T* ptr)
  130. {
  131. Base::m_ptr = ptr;
  132. return *this;
  133. }
  134. /// Copy.
  135. template<typename Y>
  136. WeakPtr& operator=(Y* ptr)
  137. {
  138. Base::m_ptr = ptr;
  139. return *this;
  140. }
  141. /// Move.
  142. WeakPtr& operator=(WeakPtr&& other)
  143. {
  144. Base::m_ptr = other.m_ptr;
  145. other.m_ptr = nullptr;
  146. return *this;
  147. }
  148. /// Cast to the pointer type.
  149. operator T*()
  150. {
  151. return Base::m_ptr;
  152. }
  153. /// Cast to the pointer type.
  154. operator const T*() const
  155. {
  156. return Base::m_ptr;
  157. }
  158. /// @name Arithmetic operators
  159. /// @{
  160. WeakPtr& operator++()
  161. {
  162. ANKI_ASSERT(Base::m_ptr);
  163. ++Base::m_ptr;
  164. return *this;
  165. }
  166. WeakPtr& operator--()
  167. {
  168. ANKI_ASSERT(Base::m_ptr);
  169. --Base::m_ptr;
  170. return *this;
  171. }
  172. WeakPtr operator+(const WeakPtr& other) const
  173. {
  174. ANKI_ASSERT(Base::m_ptr);
  175. WeakPtr out(Base::m_ptr + other.m_ptr);
  176. return out;
  177. }
  178. WeakPtr& operator+=(const WeakPtr& other)
  179. {
  180. ANKI_ASSERT(Base::m_ptr);
  181. Base::m_ptr += other.m_ptr;
  182. return *this;
  183. }
  184. WeakPtr operator-(const WeakPtr& other) const
  185. {
  186. ANKI_ASSERT(Base::m_ptr);
  187. WeakPtr out(Base::m_ptr - other.m_ptr);
  188. return out;
  189. }
  190. WeakPtr& operator-=(const WeakPtr& other)
  191. {
  192. ANKI_ASSERT(Base::m_ptr);
  193. Base::m_ptr -= other.m_ptr;
  194. return *this;
  195. }
  196. T& operator[](const PtrSize i)
  197. {
  198. return Base::m_ptr[i];
  199. }
  200. const T& operator[](const PtrSize i) const
  201. {
  202. return Base::m_ptr[i];
  203. }
  204. /// @}
  205. };
  206. /// UniquePtr default deleter.
  207. template<typename T>
  208. class DefaultPtrDeleter
  209. {
  210. public:
  211. void operator()(T* x)
  212. {
  213. auto alloc = x->getAllocator();
  214. alloc.template deleteInstance<T>(x);
  215. }
  216. };
  217. /// UniquePtr alternative deleter.
  218. template<typename T>
  219. class AllocatorPtrDeleter
  220. {
  221. public:
  222. GenericMemoryPoolAllocator<U8> m_allocator;
  223. AllocatorPtrDeleter()
  224. {
  225. }
  226. AllocatorPtrDeleter(GenericMemoryPoolAllocator<U8> alloc)
  227. : m_allocator(alloc)
  228. {
  229. }
  230. void operator()(T* x)
  231. {
  232. m_allocator.template deleteInstance<T>(x);
  233. }
  234. };
  235. /// A unique pointer.
  236. template<typename T, typename TDeleter = DefaultPtrDeleter<T>>
  237. class UniquePtr : public PtrBase<T>
  238. {
  239. public:
  240. using Base = PtrBase<T>;
  241. using Deleter = TDeleter;
  242. using Base::m_ptr;
  243. UniquePtr()
  244. : Base()
  245. {
  246. }
  247. explicit UniquePtr(T* ptr, const Deleter& deleter = Deleter())
  248. : Base(ptr)
  249. , m_deleter(deleter)
  250. {
  251. }
  252. /// Non-copyable.
  253. UniquePtr(const UniquePtr& other) = delete;
  254. /// Move.
  255. UniquePtr(UniquePtr&& other)
  256. : Base()
  257. {
  258. move(other);
  259. }
  260. /// Destroy.
  261. ~UniquePtr()
  262. {
  263. destroy();
  264. }
  265. /// Non-copyable.
  266. UniquePtr& operator=(const UniquePtr& other) = delete;
  267. /// Move.
  268. UniquePtr& operator=(UniquePtr&& other)
  269. {
  270. move(other);
  271. return *this;
  272. }
  273. /// Set a new pointer. Will destroy the previous.
  274. void reset(T* ptr, const Deleter& deleter = Deleter())
  275. {
  276. destroy();
  277. m_ptr = ptr;
  278. m_deleter = deleter;
  279. }
  280. /// Move the ownership of the pointer outside the UniquePtr.
  281. void moveAndReset(T*& ptr)
  282. {
  283. ptr = m_ptr;
  284. m_ptr = nullptr;
  285. m_deleter = Deleter();
  286. }
  287. private:
  288. Deleter m_deleter;
  289. void destroy()
  290. {
  291. if(m_ptr)
  292. {
  293. m_deleter(m_ptr);
  294. m_ptr = nullptr;
  295. m_deleter = Deleter();
  296. }
  297. }
  298. void move(UniquePtr& b)
  299. {
  300. reset(b.m_ptr, b.m_deleter);
  301. b.m_ptr = nullptr;
  302. }
  303. };
  304. /// An intrusive pointer.
  305. template<typename T, typename TDeleter = DefaultPtrDeleter<T>>
  306. class IntrusivePtr : public PtrBase<T>
  307. {
  308. template<typename Y, typename TD>
  309. friend class IntrusivePtr;
  310. public:
  311. using Base = PtrBase<T>;
  312. using Deleter = TDeleter;
  313. using Base::m_ptr;
  314. IntrusivePtr()
  315. : Base()
  316. {
  317. }
  318. explicit IntrusivePtr(T* ptr)
  319. : Base()
  320. {
  321. reset(ptr);
  322. }
  323. /// Copy.
  324. IntrusivePtr(const IntrusivePtr& other)
  325. : Base()
  326. {
  327. reset(other.m_ptr);
  328. }
  329. /// Move.
  330. IntrusivePtr(IntrusivePtr&& other)
  331. : Base()
  332. {
  333. move(other);
  334. }
  335. /// Copy, compatible pointer.
  336. template<typename Y>
  337. IntrusivePtr(const IntrusivePtr<Y, TDeleter>& other)
  338. : Base()
  339. {
  340. reset(other.m_ptr);
  341. }
  342. /// Decrease refcount and delete the pointer if refcount is zero.
  343. ~IntrusivePtr()
  344. {
  345. destroy();
  346. }
  347. /// Copy.
  348. IntrusivePtr& operator=(const IntrusivePtr& other)
  349. {
  350. reset(other.m_ptr);
  351. return *this;
  352. }
  353. /// Move.
  354. IntrusivePtr& operator=(IntrusivePtr&& other)
  355. {
  356. destroy();
  357. move(other);
  358. return *this;
  359. }
  360. /// Copy, compatible.
  361. template<typename Y, typename YDeleter>
  362. IntrusivePtr& operator=(const IntrusivePtr<Y, YDeleter>& other)
  363. {
  364. reset(other.m_ptr);
  365. return *this;
  366. }
  367. /// Set a new pointer. Will destroy the previous.
  368. void reset(T* ptr)
  369. {
  370. destroy();
  371. if(ptr)
  372. {
  373. ptr->retain();
  374. m_ptr = ptr;
  375. }
  376. }
  377. private:
  378. void destroy()
  379. {
  380. if(m_ptr)
  381. {
  382. auto count = m_ptr->release();
  383. if(ANKI_UNLIKELY(count == 1))
  384. {
  385. TDeleter deleter;
  386. deleter(m_ptr);
  387. }
  388. m_ptr = nullptr;
  389. }
  390. }
  391. void move(IntrusivePtr& b)
  392. {
  393. ANKI_ASSERT(m_ptr == nullptr);
  394. m_ptr = b.m_ptr;
  395. b.m_ptr = nullptr;
  396. }
  397. };
  398. /// @}
  399. } // end namespace anki