smart_ptr.h 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. #pragma once
  2. #include <util/generic/ptr.h>
  3. #include <library/cpp/deprecated/atomic/atomic.h>
  4. namespace NNeh {
  5. //limited emulation shared_ptr/weak_ptr from boost lib.
  6. //the main value means the weak_ptr functionality, else recommended use types from util/generic/ptr.h
  7. //smart pointer counter shared between shared and weak ptrs.
  8. class TSPCounted: public TThrRefBase {
  9. public:
  10. inline TSPCounted() noexcept
  11. : C_(0)
  12. {
  13. }
  14. inline void Inc() noexcept {
  15. AtomicIncrement(C_);
  16. }
  17. //return false if C_ already 0, else increment and return true
  18. inline bool TryInc() noexcept {
  19. for (;;) {
  20. intptr_t curVal(AtomicGet(C_));
  21. if (!curVal) {
  22. return false;
  23. }
  24. intptr_t newVal(curVal + 1);
  25. if (AtomicCas(&C_, newVal, curVal)) {
  26. return true;
  27. }
  28. }
  29. }
  30. inline intptr_t Dec() noexcept {
  31. return AtomicDecrement(C_);
  32. }
  33. inline intptr_t Value() const noexcept {
  34. return AtomicGet(C_);
  35. }
  36. private:
  37. TAtomic C_;
  38. };
  39. typedef TIntrusivePtr<TSPCounted> TSPCountedRef;
  40. class TWeakCount;
  41. class TSPCount {
  42. public:
  43. TSPCount(TSPCounted* c = nullptr) noexcept
  44. : C_(c)
  45. {
  46. }
  47. inline void Swap(TSPCount& r) noexcept {
  48. DoSwap(C_, r.C_);
  49. }
  50. inline size_t UseCount() const noexcept {
  51. if (!C_) {
  52. return 0;
  53. }
  54. return C_->Value();
  55. }
  56. inline bool operator!() const noexcept {
  57. return !C_;
  58. }
  59. inline TSPCounted* GetCounted() const noexcept {
  60. return C_.Get();
  61. }
  62. inline void Reset() noexcept {
  63. if (!!C_) {
  64. C_.Drop();
  65. }
  66. }
  67. protected:
  68. TIntrusivePtr<TSPCounted> C_;
  69. };
  70. class TSharedCount: public TSPCount {
  71. public:
  72. inline TSharedCount() noexcept {
  73. }
  74. /// @throws std::bad_alloc
  75. inline explicit TSharedCount(const TSharedCount& r)
  76. : TSPCount(r.C_.Get())
  77. {
  78. if (!!C_) {
  79. (C_->Inc());
  80. }
  81. }
  82. //'c' must exist and has already increased ref
  83. inline explicit TSharedCount(TSPCounted* c) noexcept
  84. : TSPCount(c)
  85. {
  86. }
  87. public:
  88. /// @throws std::bad_alloc
  89. inline void Inc() {
  90. if (!C_) {
  91. TSPCountedRef(new TSPCounted()).Swap(C_);
  92. }
  93. C_->Inc();
  94. }
  95. inline bool TryInc() noexcept {
  96. if (!C_) {
  97. return false;
  98. }
  99. return C_->TryInc();
  100. }
  101. inline intptr_t Dec() noexcept {
  102. if (!C_) {
  103. Y_ASSERT(0);
  104. return 0;
  105. }
  106. return C_->Dec();
  107. }
  108. void Drop() noexcept {
  109. C_.Drop();
  110. }
  111. protected:
  112. template <class Y>
  113. friend class TSharedPtrB;
  114. // 'c' MUST BE already incremented
  115. void Assign(TSPCounted* c) noexcept {
  116. TSPCountedRef(c).Swap(C_);
  117. }
  118. private:
  119. TSharedCount& operator=(const TSharedCount&); //disable
  120. };
  121. class TWeakCount: public TSPCount {
  122. public:
  123. inline TWeakCount() noexcept {
  124. }
  125. inline explicit TWeakCount(const TWeakCount& r) noexcept
  126. : TSPCount(r.GetCounted())
  127. {
  128. }
  129. inline explicit TWeakCount(const TSharedCount& r) noexcept
  130. : TSPCount(r.GetCounted())
  131. {
  132. }
  133. private:
  134. TWeakCount& operator=(const TWeakCount&); //disable
  135. };
  136. template <class T>
  137. class TWeakPtrB;
  138. template <class T>
  139. class TSharedPtrB {
  140. public:
  141. inline TSharedPtrB() noexcept
  142. : T_(nullptr)
  143. {
  144. }
  145. /// @throws std::bad_alloc
  146. inline TSharedPtrB(T* t)
  147. : T_(nullptr)
  148. {
  149. if (t) {
  150. THolder<T> h(t);
  151. C_.Inc();
  152. T_ = h.Release();
  153. }
  154. }
  155. inline TSharedPtrB(const TSharedPtrB<T>& r) noexcept
  156. : T_(r.T_)
  157. , C_(r.C_)
  158. {
  159. Y_ASSERT((!!T_ && !!C_.UseCount()) || (!T_ && !C_.UseCount()));
  160. }
  161. inline TSharedPtrB(const TWeakPtrB<T>& r) noexcept
  162. : T_(r.T_)
  163. {
  164. if (T_) {
  165. TSPCounted* spc = r.C_.GetCounted();
  166. if (spc && spc->TryInc()) {
  167. C_.Assign(spc);
  168. } else { //obsolete ptr
  169. T_ = nullptr;
  170. }
  171. }
  172. }
  173. inline ~TSharedPtrB() {
  174. Reset();
  175. }
  176. TSharedPtrB& operator=(const TSharedPtrB<T>& r) noexcept {
  177. TSharedPtrB<T>(r).Swap(*this);
  178. return *this;
  179. }
  180. TSharedPtrB& operator=(const TWeakPtrB<T>& r) noexcept {
  181. TSharedPtrB<T>(r).Swap(*this);
  182. return *this;
  183. }
  184. void Swap(TSharedPtrB<T>& r) noexcept {
  185. DoSwap(T_, r.T_);
  186. DoSwap(C_, r.C_);
  187. Y_ASSERT((!!T_ && !!UseCount()) || (!T_ && !UseCount()));
  188. }
  189. inline bool operator!() const noexcept {
  190. return !T_;
  191. }
  192. inline T* Get() noexcept {
  193. return T_;
  194. }
  195. inline T* operator->() noexcept {
  196. return T_;
  197. }
  198. inline T* operator->() const noexcept {
  199. return T_;
  200. }
  201. inline T& operator*() noexcept {
  202. return *T_;
  203. }
  204. inline T& operator*() const noexcept {
  205. return *T_;
  206. }
  207. inline void Reset() noexcept {
  208. if (T_) {
  209. if (C_.Dec() == 0) {
  210. delete T_;
  211. }
  212. T_ = nullptr;
  213. C_.Drop();
  214. }
  215. }
  216. inline size_t UseCount() const noexcept {
  217. return C_.UseCount();
  218. }
  219. protected:
  220. template <class Y>
  221. friend class TWeakPtrB;
  222. T* T_;
  223. TSharedCount C_;
  224. };
  225. template <class T>
  226. class TWeakPtrB {
  227. public:
  228. inline TWeakPtrB() noexcept
  229. : T_(nullptr)
  230. {
  231. }
  232. inline TWeakPtrB(const TWeakPtrB<T>& r) noexcept
  233. : T_(r.T_)
  234. , C_(r.C_)
  235. {
  236. }
  237. inline TWeakPtrB(const TSharedPtrB<T>& r) noexcept
  238. : T_(r.T_)
  239. , C_(r.C_)
  240. {
  241. }
  242. TWeakPtrB& operator=(const TWeakPtrB<T>& r) noexcept {
  243. TWeakPtrB(r).Swap(*this);
  244. return *this;
  245. }
  246. TWeakPtrB& operator=(const TSharedPtrB<T>& r) noexcept {
  247. TWeakPtrB(r).Swap(*this);
  248. return *this;
  249. }
  250. inline void Swap(TWeakPtrB<T>& r) noexcept {
  251. DoSwap(T_, r.T_);
  252. DoSwap(C_, r.C_);
  253. }
  254. inline void Reset() noexcept {
  255. T_ = 0;
  256. C_.Reset();
  257. }
  258. inline size_t UseCount() const noexcept {
  259. return C_.UseCount();
  260. }
  261. protected:
  262. template <class Y>
  263. friend class TSharedPtrB;
  264. T* T_;
  265. TWeakCount C_;
  266. };
  267. }