Ptr.h 6.9 KB

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