Ptr.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  1. // Copyright (C) 2009-present, 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/MemoryPool.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. T* tryGet() const
  35. {
  36. return m_ptr;
  37. }
  38. Bool isCreated() const
  39. {
  40. return m_ptr != nullptr;
  41. }
  42. /// @name Compare operators
  43. /// @{
  44. explicit operator Bool() const
  45. {
  46. return isCreated();
  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. Bool operator>=(const PtrBase& other) const
  69. {
  70. return m_ptr >= other.m_ptr;
  71. }
  72. /// @}
  73. protected:
  74. T* m_ptr;
  75. PtrBase()
  76. : m_ptr(nullptr)
  77. {
  78. }
  79. PtrBase(T* ptr)
  80. : m_ptr(ptr)
  81. {
  82. }
  83. };
  84. /// A simple template class to wrap simple pointers.
  85. template<typename T>
  86. class WeakPtr : public PtrBase<T>
  87. {
  88. template<typename>
  89. friend class WeakPtr;
  90. public:
  91. using Base = PtrBase<T>;
  92. WeakPtr()
  93. : Base()
  94. {
  95. }
  96. explicit WeakPtr(T* ptr)
  97. : Base(ptr)
  98. {
  99. }
  100. WeakPtr(const WeakPtr& other)
  101. : Base(other.m_ptr)
  102. {
  103. }
  104. template<typename Y>
  105. WeakPtr(const WeakPtr<Y>& other)
  106. : Base(other.m_ptr)
  107. {
  108. }
  109. WeakPtr(WeakPtr&& other)
  110. : Base(other.m_ptr)
  111. {
  112. other.m_ptr = nullptr;
  113. }
  114. /// Destroy.
  115. ~WeakPtr()
  116. {
  117. Base::m_ptr = nullptr;
  118. }
  119. /// Copy.
  120. WeakPtr& operator=(const WeakPtr& other)
  121. {
  122. Base::m_ptr = other.m_ptr;
  123. return *this;
  124. }
  125. /// Copy.
  126. template<typename Y>
  127. WeakPtr& operator=(const WeakPtr<Y>& other)
  128. {
  129. Base::m_ptr = other.m_ptr;
  130. return *this;
  131. }
  132. /// Copy.
  133. WeakPtr& operator=(T* ptr)
  134. {
  135. Base::m_ptr = ptr;
  136. return *this;
  137. }
  138. /// Copy.
  139. template<typename Y>
  140. WeakPtr& operator=(Y* ptr)
  141. {
  142. Base::m_ptr = ptr;
  143. return *this;
  144. }
  145. /// Move.
  146. WeakPtr& operator=(WeakPtr&& other)
  147. {
  148. Base::m_ptr = other.m_ptr;
  149. other.m_ptr = nullptr;
  150. return *this;
  151. }
  152. /// Cast to the pointer type.
  153. operator T*()
  154. {
  155. return Base::m_ptr;
  156. }
  157. /// Cast to the pointer type.
  158. operator const T*() const
  159. {
  160. return Base::m_ptr;
  161. }
  162. /// @name Arithmetic operators
  163. /// @{
  164. WeakPtr& operator++()
  165. {
  166. ANKI_ASSERT(Base::m_ptr);
  167. ++Base::m_ptr;
  168. return *this;
  169. }
  170. WeakPtr& operator--()
  171. {
  172. ANKI_ASSERT(Base::m_ptr);
  173. --Base::m_ptr;
  174. return *this;
  175. }
  176. WeakPtr operator+(const WeakPtr& other) const
  177. {
  178. ANKI_ASSERT(Base::m_ptr);
  179. WeakPtr out(Base::m_ptr + other.m_ptr);
  180. return out;
  181. }
  182. WeakPtr& operator+=(const WeakPtr& other)
  183. {
  184. ANKI_ASSERT(Base::m_ptr);
  185. Base::m_ptr += other.m_ptr;
  186. return *this;
  187. }
  188. WeakPtr operator-(const WeakPtr& other) const
  189. {
  190. ANKI_ASSERT(Base::m_ptr);
  191. WeakPtr out(Base::m_ptr - other.m_ptr);
  192. return out;
  193. }
  194. WeakPtr& operator-=(const WeakPtr& other)
  195. {
  196. ANKI_ASSERT(Base::m_ptr);
  197. Base::m_ptr -= other.m_ptr;
  198. return *this;
  199. }
  200. T& operator[](const PtrSize i)
  201. {
  202. return Base::m_ptr[i];
  203. }
  204. const T& operator[](const PtrSize i) const
  205. {
  206. return Base::m_ptr[i];
  207. }
  208. /// @}
  209. };
  210. /// UniquePtr default deleter.
  211. template<typename T>
  212. class DefaultPtrDeleter
  213. {
  214. public:
  215. void operator()(T* x)
  216. {
  217. auto& pool = x->getMemoryPool();
  218. deleteInstance<T>(pool, x);
  219. }
  220. };
  221. /// A unique pointer.
  222. template<typename T, typename TDeleter = DefaultPtrDeleter<T>>
  223. class UniquePtr : public PtrBase<T>
  224. {
  225. public:
  226. using Base = PtrBase<T>;
  227. using Deleter = TDeleter;
  228. using Base::m_ptr;
  229. UniquePtr()
  230. : Base()
  231. {
  232. }
  233. explicit UniquePtr(T* ptr, const Deleter& deleter = Deleter())
  234. : Base(ptr)
  235. , m_deleter(deleter)
  236. {
  237. }
  238. /// Non-copyable.
  239. UniquePtr(const UniquePtr& other) = delete;
  240. /// Move.
  241. UniquePtr(UniquePtr&& other)
  242. : Base()
  243. {
  244. move(other);
  245. }
  246. /// Destroy.
  247. ~UniquePtr()
  248. {
  249. destroy();
  250. }
  251. /// Non-copyable.
  252. UniquePtr& operator=(const UniquePtr& other) = delete;
  253. /// Move.
  254. UniquePtr& operator=(UniquePtr&& other)
  255. {
  256. move(other);
  257. return *this;
  258. }
  259. /// Set a new pointer. Will destroy the previous.
  260. void reset(T* ptr, const Deleter& deleter = Deleter())
  261. {
  262. destroy();
  263. m_ptr = ptr;
  264. m_deleter = deleter;
  265. }
  266. /// Move the ownership of the pointer outside the UniquePtr.
  267. void moveAndReset(T*& ptr)
  268. {
  269. ptr = m_ptr;
  270. m_ptr = nullptr;
  271. m_deleter = Deleter();
  272. }
  273. private:
  274. Deleter m_deleter;
  275. void destroy()
  276. {
  277. if(m_ptr)
  278. {
  279. m_deleter(m_ptr);
  280. m_ptr = nullptr;
  281. m_deleter = Deleter();
  282. }
  283. }
  284. void move(UniquePtr& b)
  285. {
  286. reset(b.m_ptr, b.m_deleter);
  287. b.m_ptr = nullptr;
  288. }
  289. };
  290. /// An intrusive pointer.
  291. template<typename T, typename TDeleter = DefaultPtrDeleter<T>>
  292. class IntrusivePtr : public PtrBase<T>
  293. {
  294. template<typename Y, typename TD>
  295. friend class IntrusivePtr;
  296. public:
  297. using Base = PtrBase<T>;
  298. using Deleter = TDeleter;
  299. using Base::m_ptr;
  300. IntrusivePtr()
  301. : Base()
  302. {
  303. }
  304. explicit IntrusivePtr(T* ptr)
  305. : Base()
  306. {
  307. reset(ptr);
  308. }
  309. /// Copy.
  310. IntrusivePtr(const IntrusivePtr& other)
  311. : Base()
  312. {
  313. reset(other.m_ptr);
  314. }
  315. /// Move.
  316. IntrusivePtr(IntrusivePtr&& other)
  317. : Base()
  318. {
  319. move(other);
  320. }
  321. /// Copy, compatible pointer.
  322. template<typename Y>
  323. IntrusivePtr(const IntrusivePtr<Y, TDeleter>& other)
  324. : Base()
  325. {
  326. reset(other.m_ptr);
  327. }
  328. /// Decrease refcount and delete the pointer if refcount is zero.
  329. ~IntrusivePtr()
  330. {
  331. destroy();
  332. }
  333. /// Copy.
  334. IntrusivePtr& operator=(const IntrusivePtr& other)
  335. {
  336. reset(other.m_ptr);
  337. return *this;
  338. }
  339. /// Move.
  340. IntrusivePtr& operator=(IntrusivePtr&& other)
  341. {
  342. destroy();
  343. move(other);
  344. return *this;
  345. }
  346. /// Copy, compatible.
  347. template<typename Y, typename YDeleter>
  348. IntrusivePtr& operator=(const IntrusivePtr<Y, YDeleter>& other)
  349. {
  350. reset(other.m_ptr);
  351. return *this;
  352. }
  353. /// Set a new pointer. Will destroy the previous.
  354. void reset(T* ptr)
  355. {
  356. destroy();
  357. if(ptr)
  358. {
  359. ptr->retain();
  360. m_ptr = ptr;
  361. }
  362. }
  363. private:
  364. void destroy()
  365. {
  366. if(m_ptr)
  367. {
  368. auto count = m_ptr->release();
  369. if(count == 1) [[unlikely]]
  370. {
  371. TDeleter deleter;
  372. deleter(m_ptr);
  373. }
  374. m_ptr = nullptr;
  375. }
  376. }
  377. void move(IntrusivePtr& b)
  378. {
  379. ANKI_ASSERT(m_ptr == nullptr);
  380. m_ptr = b.m_ptr;
  381. b.m_ptr = nullptr;
  382. }
  383. };
  384. /// An intrusive pointer. Same as IntrusivePtr but without deleter. The T::release is supposed to delete.
  385. template<typename T>
  386. class IntrusiveNoDelPtr : public PtrBase<T>
  387. {
  388. template<typename Y>
  389. friend class IntrusiveNoDelPtr;
  390. public:
  391. using Base = PtrBase<T>;
  392. using Base::m_ptr;
  393. IntrusiveNoDelPtr()
  394. : Base()
  395. {
  396. }
  397. explicit IntrusiveNoDelPtr(T* ptr)
  398. : Base()
  399. {
  400. reset(ptr);
  401. }
  402. /// Copy.
  403. IntrusiveNoDelPtr(const IntrusiveNoDelPtr& other)
  404. : Base()
  405. {
  406. reset(other.m_ptr);
  407. }
  408. /// Move.
  409. IntrusiveNoDelPtr(IntrusiveNoDelPtr&& other)
  410. : Base()
  411. {
  412. move(other);
  413. }
  414. /// Copy, compatible pointer.
  415. template<typename Y>
  416. IntrusiveNoDelPtr(const IntrusiveNoDelPtr<Y>& other)
  417. : Base()
  418. {
  419. reset(other.m_ptr);
  420. }
  421. /// Decrease refcount and delete the pointer if refcount is zero.
  422. ~IntrusiveNoDelPtr()
  423. {
  424. destroy();
  425. }
  426. /// Copy.
  427. IntrusiveNoDelPtr& operator=(const IntrusiveNoDelPtr& other)
  428. {
  429. reset(other.m_ptr);
  430. return *this;
  431. }
  432. /// Move.
  433. IntrusiveNoDelPtr& operator=(IntrusiveNoDelPtr&& other)
  434. {
  435. destroy();
  436. move(other);
  437. return *this;
  438. }
  439. /// Copy, compatible.
  440. template<typename Y>
  441. IntrusiveNoDelPtr& operator=(const IntrusiveNoDelPtr<Y>& other)
  442. {
  443. reset(other.m_ptr);
  444. return *this;
  445. }
  446. /// Set a new pointer. Will destroy the previous.
  447. void reset(T* ptr)
  448. {
  449. destroy();
  450. if(ptr)
  451. {
  452. ptr->retain();
  453. m_ptr = ptr;
  454. }
  455. }
  456. private:
  457. void destroy()
  458. {
  459. if(m_ptr)
  460. {
  461. m_ptr->release();
  462. m_ptr = nullptr;
  463. }
  464. }
  465. void move(IntrusiveNoDelPtr& b)
  466. {
  467. ANKI_ASSERT(m_ptr == nullptr);
  468. m_ptr = b.m_ptr;
  469. b.m_ptr = nullptr;
  470. }
  471. };
  472. /// @}
  473. } // end namespace anki