SharedPtr.inl 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /* Copyright The kNet Project.
  2. Licensed under the Apache License, Version 2.0 (the "License");
  3. you may not use this file except in compliance with the License.
  4. You may obtain a copy of the License at
  5. http://www.apache.org/licenses/LICENSE-2.0
  6. Unless required by applicable law or agreed to in writing, software
  7. distributed under the License is distributed on an "AS IS" BASIS,
  8. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. See the License for the specific language governing permissions and
  10. limitations under the License. */
  11. #pragma once
  12. /** @file SharedPtr.inl
  13. @brief SharedPtr template functions. */
  14. #include <algorithm>
  15. namespace kNet
  16. {
  17. /** This constructor takes the ownership of the raw pointer and starts managing the
  18. reference count on it, assuming that it is the first pointer to access it.
  19. Thus, when invoking this constructor you need to be sure that the passed pointer
  20. is not being reference-counted someplace else, because the reference count is stored
  21. in the referencing smart pointers rather than the object itself.
  22. @param ptr_ Raw pointer to an object that is not being refCounted anywhere else. */
  23. template<typename T>
  24. SharedPtr<T>::SharedPtr(T *ptr_)
  25. :dataPtr(ptr_)
  26. {
  27. AddRef();
  28. }
  29. /** This constructor increases reference on the existing SharedPtr, and initializes
  30. this to point to the same object and refCount as the existing one. This is the
  31. safe way to copy pointers.
  32. @param rhs The pointer to make copy of. */
  33. template<typename T>
  34. SharedPtr<T>::SharedPtr(const SharedPtr<T> &rhs)
  35. :dataPtr(rhs.dataPtr)
  36. {
  37. AddRef();
  38. }
  39. /** This constructor allows to convert SharedPtr's from Derived types to SharedPtr's
  40. of Base types, or more specifically, from any type A to type B, as long as there
  41. is an implicit conversion operator available for the specified types.
  42. @param rhs The pointer to make copy of. */
  43. template<typename T> // type of this
  44. template<typename T2> // type of rhs
  45. SharedPtr<T>::SharedPtr(const SharedPtr<T2> &rhs)
  46. :dataPtr(dynamic_cast<T*>(const_cast<T2*>(rhs.ptr()))) ///\note Having to resort to const_cast instead of static_cast here.
  47. {
  48. AddRef();
  49. }
  50. /** Decreases refCount on old object and modifies this to point to the new object,
  51. increasing it's refCount.
  52. @param rhs The pointer to make copy of.
  53. @return Reference to this. */
  54. template<typename T>
  55. SharedPtr<T> &SharedPtr<T>::operator=(const SharedPtr<T> &rhs)
  56. {
  57. // No task if the pointers already point to the same object.
  58. if (dataPtr == rhs.dataPtr)
  59. return *this;
  60. SharedPtr<T> copy(*this);
  61. // Decrease refCount on old object (possibly deallocates the data).
  62. Release();
  63. // Assign the new.
  64. dataPtr = rhs.dataPtr;
  65. // Increase reference count for the new.
  66. AddRef();
  67. return *this;
  68. }
  69. /** Decreases refCount on old object (possibly frees it) and takes the ownership of
  70. the new object, making the assumption that this is the first SharedPtr to count
  71. reference to the object.
  72. @param ptr_ Raw pointer to an object that is not being refCounted anywhere else.
  73. @return Reference to this. */
  74. template<typename T>
  75. SharedPtr<T> &SharedPtr<T>::operator=(T *ptr_)
  76. {
  77. if (dataPtr == ptr_) // This and the given pointers point to same object.
  78. return *this;
  79. // Decrease refCount on old object (possibly releases).
  80. Release();
  81. // Assign the new.
  82. dataPtr = ptr_;
  83. AddRef();
  84. return *this;
  85. }
  86. /** Decreases refCount on the object and frees it if it's no longer used. */
  87. template<typename T>
  88. SharedPtr<T>::~SharedPtr()
  89. {
  90. Release();
  91. }
  92. template<typename T>
  93. void SharedPtr<T>::AddRef()
  94. {
  95. if (dataPtr)
  96. dataPtr->AddRef();
  97. }
  98. /** If the reference count drops to zero, the object is freed. */
  99. template<typename T>
  100. void SharedPtr<T>::Release()
  101. {
  102. if (!dataPtr) // if refCount is zero, this pointer wasn't even initialized.
  103. return;
  104. dataPtr->DecRef();
  105. assert(dataPtr->RefCount() >= 0 && "Reference count was decreased to a negative value!!");
  106. // Free the object if no users left
  107. if (dataPtr->RefCount() == 0)
  108. delete dataPtr;
  109. dataPtr = 0;
  110. }
  111. /** @return The reference count of the object this SharedPtr is pointing at, or
  112. 0 if the SharedPtr isn't pointing to anything. */
  113. template<typename T>
  114. unsigned int SharedPtr<T>::RefCount() const
  115. {
  116. if (dataPtr)
  117. return dataPtr->RefCount();
  118. else
  119. return 0;
  120. }
  121. /** Causes an assert failure if the pointer is null. If reading a null pointer
  122. should be considered a legal operation, use .ptr() instead. */
  123. template<typename T>
  124. SharedPtr<T>::operator T*()
  125. {
  126. assert(dataPtr != 0 && dataPtr->RefCount() > 0 && "Tried to dereference a null pointer!");
  127. return dataPtr;
  128. }
  129. /** @return Const pointer to the object or 0. */
  130. template<typename T>
  131. const T *SharedPtr<T>::ptr() const
  132. {
  133. return dataPtr;
  134. }
  135. /** @return Pointer to the object or 0. */
  136. template<typename T>
  137. T *SharedPtr<T>::ptr()
  138. {
  139. return dataPtr;
  140. }
  141. /** Causes an assert failure if the pointer is null.
  142. @return Const pointer to the object. */
  143. template<typename T>
  144. const T *SharedPtr<T>::operator->() const
  145. {
  146. assert(dataPtr != 0 && dataPtr->RefCount() > 0 && "Tried to dereference a null pointer!");
  147. return dataPtr;
  148. }
  149. /** Causes an assert failure if the pointer is null.
  150. @return Pointer to the object. */
  151. template<typename T>
  152. T *SharedPtr<T>::operator->()
  153. {
  154. assert(dataPtr != 0 && dataPtr->RefCount() > 0 && "Tried to dereference a null pointer!");
  155. return dataPtr;
  156. }
  157. /** Causes an assert failure if the pointer is null.
  158. @return Const reference to the object. */
  159. template<typename T>
  160. const T &SharedPtr<T>::operator*() const
  161. {
  162. assert(dataPtr != 0 && dataPtr->RefCount() > 0 && "Tried to dereference a null pointer!");
  163. return *dataPtr;
  164. }
  165. /** Causes an assert failure if the pointer is null.
  166. @return Reference to the object. */
  167. template<typename T>
  168. T &SharedPtr<T>::operator*()
  169. {
  170. assert(dataPtr != 0 && dataPtr->RefCount() > 0 && "Tried to dereference a null pointer!");
  171. return *dataPtr;
  172. }
  173. /** @return true if the pointer is good, false if it's null. */
  174. template<typename T>
  175. SharedPtr<T>::operator bool() const
  176. {
  177. return dataPtr != 0;
  178. }
  179. /** @return true if the pointer is good, false if it's null. */
  180. template<typename T>
  181. SharedPtr<T>::operator bool()
  182. {
  183. return dataPtr != 0;
  184. }
  185. } // ~kNet