SharedArrayPtr.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. //
  2. // Urho3D Engine
  3. // Copyright (c) 2008-2011 Lasse Öörni
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. #ifndef COMMON_SHAREDARRAYPTR_H
  24. #define COMMON_SHAREDARRAYPTR_H
  25. #include "Exception.h"
  26. #include "RefCount.h"
  27. //! Shared array pointer template class. Uses non-intrusive reference counting
  28. template <class T> class SharedArrayPtr
  29. {
  30. public:
  31. //! Construct a null shared array pointer
  32. SharedArrayPtr() :
  33. mPtr(0),
  34. mRefCount(0)
  35. {
  36. }
  37. //! Copy-construct from another shared array pointer
  38. SharedArrayPtr(const SharedArrayPtr<T>& rhs) :
  39. mPtr(rhs.mPtr),
  40. mRefCount(rhs.mRefCount)
  41. {
  42. if (mRefCount)
  43. ++(mRefCount->mRefs);
  44. }
  45. //! Construct from a raw pointer
  46. explicit SharedArrayPtr(T* ptr) :
  47. mPtr(ptr),
  48. mRefCount(new RefCount())
  49. {
  50. ++(mRefCount->mRefs);
  51. }
  52. //! Destruct. Release the array reference
  53. ~SharedArrayPtr()
  54. {
  55. release();
  56. }
  57. //! Assign from another shared array pointer
  58. SharedArrayPtr<T>& operator = (const SharedArrayPtr<T>& rhs)
  59. {
  60. if (mPtr == rhs.mPtr)
  61. return *this;
  62. release();
  63. mPtr = rhs.mPtr;
  64. mRefCount = rhs.mRefCount;
  65. if (mRefCount)
  66. ++(mRefCount->mRefs);
  67. return *this;
  68. }
  69. //! Assign from a raw pointer
  70. SharedArrayPtr<T>& operator = (T* ptr)
  71. {
  72. if (mPtr == ptr)
  73. return *this;
  74. release();
  75. if (ptr)
  76. {
  77. mPtr = ptr;
  78. mRefCount = new RefCount();
  79. ++(mRefCount->mRefs);
  80. }
  81. return *this;
  82. }
  83. //! Point to the array
  84. T* operator -> () const { return mPtr; }
  85. //! Dereference the array
  86. T& operator * () const { return *mPtr; }
  87. //! Subscript the array
  88. T& operator [] (const int index) { return mPtr[index]; }
  89. //! Test for equality with another shared pointer
  90. bool operator == (const SharedArrayPtr<T>& rhs) const { return mPtr == rhs.mPtr; }
  91. //! Test for inequality with another shared pointer
  92. bool operator != (const SharedArrayPtr<T>& rhs) const { return mPtr != rhs.mPtr; }
  93. //! Return true if points to an array
  94. operator bool () const { return mPtr != 0; }
  95. //! Convert to a raw pointer
  96. operator T* () const { return mPtr; }
  97. //! Reset to null and release the array reference
  98. void reset()
  99. {
  100. release();
  101. }
  102. //! Perform a static cast from a shared array pointer of another type
  103. template <class U> void staticCast(const SharedArrayPtr<U>& rhs)
  104. {
  105. release();
  106. mPtr = static_cast<T*>(rhs.getPtr());
  107. mRefCount = rhs.getRefCountPtr();
  108. if (mRefCount)
  109. ++(mRefCount->mRefs);
  110. }
  111. //! Perform a dynatic cast from a shared array pointer of another type
  112. template <class U> void dynamicCast(const SharedArrayPtr<U>& rhs)
  113. {
  114. release();
  115. mPtr = dynamic_cast<T*>(rhs.getPtr());
  116. if (mPtr)
  117. {
  118. mRefCount = rhs.getRefCountPtr();
  119. if (mRefCount)
  120. ++(mRefCount->mRefs);
  121. }
  122. else
  123. mRefCount = 0;
  124. }
  125. //! Check if the pointer is null
  126. bool isNull() const { return mPtr == 0; }
  127. //! Check if the pointer is not null
  128. bool notNull() const { return mPtr != 0; }
  129. //! Return the raw pointer
  130. T* getPtr() const { return mPtr; }
  131. //! Return the array's reference count, or 0 if the pointer is null
  132. unsigned getRefCount() const { return mRefCount ? mRefCount->mRefs : 0; }
  133. //! Return the array's weak reference count, or 0 if the pointer is null
  134. unsigned getWeakRefCount() const { return mRefCount ? mRefCount->mWeakRefs : 0; }
  135. //! Return pointer to the RefCount structure
  136. RefCount* getRefCountPtr() const { return mRefCount; }
  137. private:
  138. //! Prevent direct assignment from a shared array pointer of different type
  139. template <class U> SharedArrayPtr<T>& operator = (const SharedArrayPtr<U>& rhs);
  140. //! Release the array reference and delete it and the RefCount structure as applicable
  141. void release()
  142. {
  143. if (mRefCount)
  144. {
  145. if (mRefCount->mRefs)
  146. {
  147. --(mRefCount->mRefs);
  148. if (!mRefCount->mRefs)
  149. {
  150. mRefCount->mExpired = true;
  151. delete[] mPtr;
  152. }
  153. }
  154. if ((!mRefCount->mRefs) && (!mRefCount->mWeakRefs))
  155. delete mRefCount;
  156. }
  157. mPtr = 0;
  158. mRefCount = 0;
  159. }
  160. //! Pointer to the array
  161. T* mPtr;
  162. //! Pointer to the RefCount structure
  163. RefCount* mRefCount;
  164. };
  165. //! Perform a static cast from one shared array pointer type to another
  166. template <class T, class U> SharedArrayPtr<T> staticCast(const SharedArrayPtr<U>& ptr)
  167. {
  168. SharedArrayPtr<T> ret;
  169. ret.staticCast(ptr);
  170. return ret;
  171. }
  172. //! Perform a dynamic cast from one shared array pointer type to another
  173. template <class T, class U> SharedArrayPtr<T> dynamicCast(const SharedArrayPtr<U>& ptr)
  174. {
  175. SharedArrayPtr<T> ret;
  176. ret.dynamicCast(ptr);
  177. return ret;
  178. }
  179. //! Weak array pointer template class. Uses non-intrusive reference counting
  180. template <class T> class WeakArrayPtr
  181. {
  182. public:
  183. //! Construct a null weak array pointer
  184. WeakArrayPtr() :
  185. mPtr(0),
  186. mRefCount(0)
  187. {
  188. }
  189. //! Construct from a shared array pointer
  190. WeakArrayPtr(const SharedArrayPtr<T>& rhs) :
  191. mPtr(rhs.getPtr()),
  192. mRefCount(rhs.getRefCountPtr())
  193. {
  194. if (mRefCount)
  195. ++(mRefCount->mWeakRefs);
  196. }
  197. //! Copy-construct from another weak array pointer
  198. WeakArrayPtr(const WeakArrayPtr<T>& rhs) :
  199. mPtr(rhs.mPtr),
  200. mRefCount(rhs.mRefCount)
  201. {
  202. if (mRefCount)
  203. ++(mRefCount->mWeakRefs);
  204. }
  205. //! Destruct. Release the weak reference to the array
  206. ~WeakArrayPtr()
  207. {
  208. release();
  209. }
  210. //! Assign from a shared array pointer
  211. WeakArrayPtr<T>& operator = (const SharedArrayPtr<T>& rhs)
  212. {
  213. if ((mPtr == rhs.getPtr()) && (mRefCount == rhs.getRefCountPtr()))
  214. return *this;
  215. release();
  216. mPtr = rhs.getPtr();
  217. mRefCount = rhs.getRefCountPtr();
  218. if (mRefCount)
  219. ++(mRefCount->mWeakRefs);
  220. return *this;
  221. }
  222. //! Assign from another weak array pointer
  223. WeakArrayPtr<T>& operator = (const WeakArrayPtr<T>& rhs)
  224. {
  225. if ((mPtr == rhs.mPtr) && (mRefCount == rhs.mRefCount))
  226. return *this;
  227. release();
  228. mPtr = rhs.mPtr;
  229. mRefCount = rhs.mRefCount;
  230. if (mRefCount)
  231. ++(mRefCount->mWeakRefs);
  232. return *this;
  233. }
  234. //! Convert to shared array pointer. If expired, return a null shared array pointer
  235. SharedArrayPtr<T> toShared() const
  236. {
  237. if (isExpired())
  238. return SharedArrayPtr<T>();
  239. else
  240. return SharedArrayPtr<T>(mPtr, mRefCount);
  241. }
  242. //! Return raw pointer. If expired, return null
  243. T* getPtr() const
  244. {
  245. if (isExpired())
  246. return 0;
  247. else
  248. return mPtr;
  249. }
  250. //! Point to the array. If RefCounted safety checks are enabled, throw an exception if the array has expired
  251. T* operator -> () const
  252. {
  253. #ifdef ENABLE_REFCOUNTED_CHECKS
  254. if (isExpired())
  255. EXCEPTION("Dereference of an expired RefCounted array");
  256. #endif
  257. return getPtr();
  258. }
  259. //! Dereference the array. If RefCounted safety checks are enabled, throw an exception if the array has expired
  260. T& operator * () const
  261. {
  262. #ifdef ENABLE_REFCOUNTED_CHECKS
  263. if (isExpired())
  264. EXCEPTION("Dereference of an expired RefCounted array");
  265. #endif
  266. return *getPtr();
  267. }
  268. //! Subscript the array. If RefCounted safety checks are enabled, throw an exception if the array has expired
  269. T& operator [] (const int index)
  270. {
  271. #ifdef ENABLE_REFCOUNTED_CHECKS
  272. if (isExpired())
  273. EXCEPTION("Dereference of an expired RefCounted array");
  274. #endif
  275. return mPtr[index];
  276. }
  277. //! Test for equality with another weak array pointer
  278. bool operator == (const WeakArrayPtr<T>& rhs) const { return (mPtr == rhs.mPtr) && (mRefCount == rhs.mRefCount); }
  279. //! Test for inequality with another weak array pointer
  280. bool operator != (const WeakArrayPtr<T>& rhs) const { return (mPtr != rhs.mPtr) || (mRefCount != rhs.mRefCount); }
  281. //! Return true if points to an array which is not expired
  282. operator bool () const { return !isExpired(); }
  283. //! Convert to a raw pointer, null if array is expired
  284. operator T* () const { return getPtr(); }
  285. //! Reset to null and release the weak reference
  286. void reset()
  287. {
  288. release();
  289. }
  290. //! Perform a static cast from a weak array pointer of another type
  291. template <class U> void staticCast(const WeakArrayPtr<U>& rhs)
  292. {
  293. release();
  294. mPtr = static_cast<T*>(rhs.getPtr());
  295. mRefCount = rhs.mRefCount;
  296. if (mRefCount)
  297. ++(mRefCount->mWeakRefs);
  298. }
  299. //! Perform a dynamic cast from a weak array pointer of another type
  300. template <class U> void dynamicCast(const WeakArrayPtr<U>& rhs)
  301. {
  302. release();
  303. mPtr = dynamic_cast<T*>(rhs.getPtr());
  304. if (mPtr)
  305. {
  306. mRefCount = rhs.mRefCount;
  307. if (mRefCount)
  308. ++(mRefCount->mWeakRefs);
  309. }
  310. else
  311. mRefCount = 0;
  312. }
  313. //! Check if the pointer is null
  314. bool isNull() const { return mRefCount == 0; }
  315. //! Check if the pointer is not null
  316. bool notNull() const { return mRefCount != 0; }
  317. //! Return the array's reference count, or 0 if null pointer or if array is expired
  318. unsigned getRefCount() const { return mRefCount ? mRefCount->mRefs : 0; }
  319. //! Return the array's weak reference count
  320. unsigned getWeakRefCount() const { return mRefCount ? mRefCount->mWeakRefs : 0; }
  321. //! Return whether the array has expired. If null pointer, always return true
  322. bool isExpired() const { return mRefCount ? mRefCount->mExpired : true; }
  323. //! Return pointer to RefCount structure
  324. RefCount* getRefCountPtr() const { return mRefCount; }
  325. private:
  326. //! Prevent direct assignment from a weak array pointer of different type
  327. template <class U> WeakArrayPtr<T>& operator = (const WeakArrayPtr<U>& rhs);
  328. //! Release the weak reference. Delete the Refcount structure if the array has expired and this was the last weak reference
  329. void release()
  330. {
  331. if (mRefCount)
  332. {
  333. if (mRefCount->mWeakRefs)
  334. --(mRefCount->mWeakRefs);
  335. if ((!mRefCount->mRefs) && (!mRefCount->mWeakRefs))
  336. delete mRefCount;
  337. }
  338. mPtr = 0;
  339. mRefCount = 0;
  340. }
  341. //! Pointer to the array
  342. T* mPtr;
  343. //! Pointer to the RefCount structure
  344. RefCount* mRefCount;
  345. };
  346. //! Perform a static cast from one weak array pointer type to another
  347. template <class T, class U> WeakArrayPtr<T> staticCast(const WeakArrayPtr<U>& ptr)
  348. {
  349. WeakArrayPtr<T> ret;
  350. ret.staticCast(ptr);
  351. return ret;
  352. }
  353. //! Perform a dynamic cast from one weak pointer type to another
  354. template <class T, class U> WeakArrayPtr<T> dynamicCast(const WeakArrayPtr<U>& ptr)
  355. {
  356. WeakArrayPtr<T> ret;
  357. ret.dynamicCast(ptr);
  358. return ret;
  359. }
  360. #endif // COMMON_SHAREDARRAYPTR_H