TmplBlockBuffer.tli 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. // TmplBlockBuffer.cpp
  2. //
  3. #pragma once
  4. #ifndef ASSERT
  5. #include <assert.h>
  6. #define ASSERT assert
  7. #endif
  8. #include "TmplBlockBuffer.tlh"
  9. #define DataNull nullptr
  10. template <typename T>
  11. TmplBlockBuffer <T>::TmplBlockBuffer ()
  12. {
  13. Init ();
  14. }
  15. template <typename T>
  16. TmplBlockBuffer <T>::~TmplBlockBuffer ()
  17. {
  18. if (GetData () == DataNull)
  19. return;
  20. if (InterlockedDecrement (&GetData ()->nRefs) <= 0)
  21. {
  22. delete m_pMetaData;
  23. delete m_pObject;
  24. }
  25. }
  26. template <typename T>
  27. void TmplBlockBuffer <T>::Init (void)
  28. {
  29. m_pObject = nullptr;
  30. m_pMetaData = (MetaData *) DataNull;
  31. }
  32. template <typename T>
  33. TmplBlockBuffer <T>::TmplBlockBuffer (const TmplBlockBuffer <T> & h)
  34. {
  35. Init ();
  36. ShadowCopyFrom (h);
  37. }
  38. template <typename T>
  39. TmplBlockBuffer <T>::TmplBlockBuffer (TmplBlockBuffer <T> && h)
  40. {
  41. Init ();
  42. MoveAssign (h);
  43. }
  44. // 从 h 构造一个新的对象, 但是我只要前面的 count 个字符
  45. // 如果 count 比 h.nCount 大, 那就重新分配然后 memcpy
  46. template <typename T>
  47. TmplBlockBuffer <T>::TmplBlockBuffer (TmplBlockBuffer && h, int count)
  48. {
  49. Init ();
  50. // 如果啥都不想要
  51. if (count <= 0) return;
  52. // 如果源是 null
  53. if (h.GetData () == DataNull)
  54. {
  55. GetBufferSetCount (count);
  56. return;
  57. }
  58. // 如果要的很少
  59. if (count <= h.GetData ()->nCount)
  60. {
  61. MoveAssign (h);
  62. ASSERT (m_pMetaData->nCount >= count);
  63. m_pMetaData->nCount = count;
  64. return;
  65. }
  66. // 如果要的太多了
  67. {
  68. auto pDst = GetBufferSetCount (count);
  69. auto pSrc = h.As ();
  70. memcpy (pDst, pSrc, h.GetCount ());
  71. h.Init ();
  72. return;
  73. }
  74. }
  75. template <typename T>
  76. TmplBlockBuffer <T>::TmplBlockBuffer (T * object, int count)
  77. {
  78. Init ();
  79. Attach (object, count);
  80. }
  81. template <typename T>
  82. void TmplBlockBuffer <T>::Attach (T * object, int count)
  83. {
  84. Release ();
  85. if (count <= 0) return;
  86. if (object == nullptr) return;
  87. m_pObject = object;
  88. m_pMetaData = new MetaData;
  89. m_pMetaData->nRefs = 1;
  90. m_pMetaData->nCount = count;
  91. }
  92. // 注意, 有可能无法 Detach 的, 因为对象可能被其他地方引用了
  93. // 如果 Detach 失败, 数据不受影响
  94. template <typename T>
  95. T * TmplBlockBuffer <T>::Detach ()
  96. {
  97. if (GetData () == DataNull) return nullptr;
  98. ASSERT (GetData ()->nRefs != 0);
  99. if (GetData ()->nRefs > 1) return nullptr;
  100. long nRef = InterlockedDecrement (&GetData ()->nRefs);
  101. ASSERT (nRef <= 0);
  102. if (nRef > 0)
  103. // 前面已经判断过, 因此不会出现减一后还大于 0 的情况. 以下代码只是以防万一
  104. {
  105. Init (); // 前面既然已经减了 1, 我只好变成 Init 了
  106. return NULL;
  107. }
  108. T * object = m_pObject;
  109. m_pObject = nullptr;
  110. delete m_pMetaData;
  111. m_pMetaData = nullptr;
  112. Init ();
  113. return object;
  114. }
  115. template <typename T>
  116. void TmplBlockBuffer <T>::Release ()
  117. {
  118. T * object = Detach ();
  119. delete object;
  120. Init ();
  121. }
  122. template <typename T>
  123. void TmplBlockBuffer <T>::CopyFrom (const TmplBlockBuffer <T> & h)
  124. {
  125. Release ();
  126. if (! h.m_pObject) return;
  127. int count = h.GetData ()->nCount;
  128. if (count <= 0) return;
  129. T * object = new T [count];
  130. ASSERT (object);
  131. memcpy (object, h.m_pObject, sizeof (T) * count);
  132. Attach (object, count);
  133. }
  134. template <typename T>
  135. void TmplBlockBuffer <T>::ShadowCopyFrom (const TmplBlockBuffer <T> & h)
  136. {
  137. if (m_pObject == h.m_pObject)
  138. return;
  139. if (h.GetData () == DataNull)
  140. {
  141. Release ();
  142. return;
  143. }
  144. if (GetData () != DataNull)
  145. if (GetData ()->nRefs < 0)
  146. {
  147. CopyFrom (h);
  148. return;
  149. }
  150. if (h.GetData ()->nRefs < 0)
  151. {
  152. CopyFrom (h);
  153. return;
  154. }
  155. // else
  156. {
  157. // can just copy references around
  158. Release ();
  159. m_pObject = h.m_pObject;
  160. m_pMetaData = h.m_pMetaData;
  161. InterlockedIncrement (&GetData ()->nRefs);
  162. }
  163. }
  164. // 移动赋值
  165. template <typename T>
  166. TmplBlockBuffer <T> & TmplBlockBuffer <T>::operator = (TmplBlockBuffer <T> && Src)
  167. {
  168. MoveAssign (Src);
  169. return *this;
  170. }
  171. // 移动赋值
  172. template <typename T>
  173. void TmplBlockBuffer <T>::MoveAssign (TmplBlockBuffer <T> & Src)
  174. {
  175. Release ();
  176. m_pObject = Src.m_pObject;
  177. m_pMetaData = Src.m_pMetaData;
  178. Src.Init ();
  179. }
  180. template <typename T>
  181. T * TmplBlockBuffer <T>::GetBufferSetCount (int count)
  182. {
  183. Release ();
  184. if (count <= 0) return nullptr;
  185. T * object = new T [count];
  186. ASSERT (object);
  187. Attach (object, count);
  188. return object;
  189. }
  190. template <typename T>
  191. void TmplBlockBuffer <T>::CopyFrom (const T * from, int count)
  192. {
  193. Release ();
  194. if (count <= 0) return;
  195. if (! from) return;
  196. T * object = new T [count];
  197. ASSERT (object);
  198. memcpy (object, from, sizeof (T) * count);
  199. Attach (object, count);
  200. }
  201. template <typename T>
  202. void TmplBlockBuffer <T>::CopyTo (T * to, int count) const
  203. {
  204. if (count <= 0) return;
  205. if (! to) return;
  206. if (! m_pObject) return;
  207. memcpy (to, m_pObject, sizeof (T) * min (count, GetData ()->nCount));
  208. }
  209. template <typename T>
  210. TmplBlockBuffer <T> & TmplBlockBuffer <T>::operator = (const TmplBlockBuffer <T> & h)
  211. {
  212. ShadowCopyFrom (h);
  213. return *this;
  214. }
  215. template <typename T>
  216. TmplBlockBuffer <T>::operator bool () const
  217. {
  218. return m_pObject;
  219. }
  220. template <typename T>
  221. TmplBlockBuffer <T>::operator T * ()
  222. {
  223. return m_pObject;
  224. }
  225. template <typename T>
  226. TmplBlockBuffer <T>::operator const T * () const
  227. {
  228. return m_pObject;
  229. }
  230. template <typename T>
  231. bool TmplBlockBuffer <T>::IsEmpty () const
  232. {
  233. return (m_pObject == nullptr);
  234. }