SPH
SharedPtr.h
Go to the documentation of this file.
1 #pragma once
2 
7 
9 #include <atomic>
10 
12 
13 namespace Detail {
15 private:
16  std::atomic<int> useCnt;
17  std::atomic<int> weakCnt;
18 
19 public:
21  useCnt = 1;
22  weakCnt = 1;
23  }
24 
26  const int cnt = ++useCnt;
27  SPH_ASSERT(cnt > 0);
28  return cnt;
29  }
30 
31  INLINE int getUseCount() const {
32  return useCnt;
33  }
34 
36  const int cnt = ++weakCnt;
37  SPH_ASSERT(cnt > 0);
38  return cnt;
39  }
40 
42  while (true) {
43  int cnt = useCnt;
44  if (cnt == 0 || useCnt.compare_exchange_strong(cnt, cnt + 1)) {
45  return cnt != 0;
46  }
47  }
48  }
49 
51  const int cnt = --useCnt;
52  SPH_ASSERT(cnt >= 0);
53  if (cnt == 0) {
54  this->deletePtr();
55  }
56  }
57 
59  const int cnt = --weakCnt;
60  SPH_ASSERT(cnt >= 0);
61  if (cnt == 0) {
62  this->deleteBlock();
63  }
64  }
65 
66  virtual void* getPtr() = 0;
67 
68  virtual void deletePtr() = 0;
69 
71  alignedDelete(this);
72  }
73 };
74 
75 template <typename T>
77 private:
78  T* ptr;
79 
80 public:
81  ControlBlock(T* ptr)
82  : ptr(ptr) {}
83 
84  INLINE virtual void* getPtr() override {
85  SPH_ASSERT(ptr);
86  return ptr;
87  }
88 
89  virtual void deletePtr() override {
90  alignedDelete(ptr);
91  }
92 };
93 } // namespace Detail
94 
95 template <typename T>
96 class SharedPtr {
97  template <typename>
98  friend class SharedPtr;
99  template <typename>
100  friend class WeakPtr;
101  friend class SharedToken;
102  friend class WeakToken;
103  template <typename>
104  friend class LockingPtr;
105  template <typename>
106  friend class SharedFromThis;
107 
108 protected:
109  T* ptr;
111 
113  : ptr(ptr)
114  , block(block) {}
115 
116 public:
118  : ptr(nullptr)
119  , block(nullptr) {}
120 
121  explicit SharedPtr(T* ptr)
122  : ptr(ptr) {
123  if (ptr) {
124  block = alignedNew<Detail::ControlBlock<T>>(ptr);
125  } else {
126  block = nullptr;
127  }
128  setSharedFromThis(*this);
129  }
130 
131  SharedPtr(const SharedPtr& other)
132  : ptr(other.ptr) {
133  this->copyBlock(other);
134  }
135 
136  template <typename T2>
137  SharedPtr(const SharedPtr<T2>& other)
138  : ptr(other.ptr) {
139  this->copyBlock(other);
140  }
141 
143  : ptr(other.ptr)
144  , block(other.block) {
145  other.ptr = nullptr;
146  other.block = nullptr;
147  }
148 
149  template <typename T2>
151  : ptr(other.ptr)
152  , block(other.block) {
153  other.ptr = nullptr;
154  other.block = nullptr;
155  }
156 
157  template <typename T2>
159  : SharedPtr(ptr.release()) {}
160 
161  SharedPtr(std::nullptr_t)
162  : ptr(nullptr)
163  , block(nullptr) {}
164 
165  SharedPtr& operator=(const SharedPtr& other) {
166  this->reset();
167  ptr = other.ptr;
168  this->copyBlock(other);
169  return *this;
170  }
171 
172  template <typename T2>
174  this->reset();
175  ptr = other.ptr;
176  this->copyBlock(other);
177  return *this;
178  }
179 
181  std::swap(ptr, other.ptr);
182  std::swap(block, other.block);
183  return *this;
184  }
185 
186  template <typename T2>
188  this->reset();
189  ptr = other.ptr;
190  block = other.block;
191  other.ptr = nullptr;
192  other.block = nullptr;
193  return *this;
194  }
195 
196  SharedPtr& operator=(std::nullptr_t) {
197  this->reset();
198  return *this;
199  }
200 
202  this->reset();
203  }
204 
205  INLINE T* operator->() const {
206  SPH_ASSERT(ptr);
207  return ptr;
208  }
209 
210  INLINE T& operator*() const {
211  SPH_ASSERT(ptr);
212  return *ptr;
213  }
214 
215  INLINE explicit operator bool() const {
216  return ptr != nullptr;
217  }
218 
219  INLINE bool operator!() const {
220  return ptr == nullptr;
221  }
222 
223  INLINE RawPtr<T> get() const {
224  return ptr;
225  }
226 
227  INLINE void reset() {
228  if (block) {
231  block = nullptr;
232  }
233  ptr = nullptr;
234  }
235 
237  if (block) {
238  block->deleteBlock();
239  block = nullptr;
240  return ptr;
241  } else {
242  return nullptr;
243  }
244  }
245 
247  if (!block) {
248  return 0;
249  } else {
250  return block->getUseCount();
251  }
252  }
253 
254  template <typename... TArgs>
255  INLINE decltype(auto) operator()(TArgs&&... args) const {
256  SPH_ASSERT(ptr);
257  return (*ptr)(std::forward<TArgs>(args)...);
258  }
259 
260 private:
261  template <typename T2>
262  INLINE void copyBlock(const SharedPtr<T2>& other) {
263  if (other.block) {
264  SPH_ASSERT(ptr != nullptr);
265  block = other.block;
268  } else {
269  block = nullptr;
270  }
271  }
272 };
273 
274 
275 template <typename T>
276 bool operator==(const SharedPtr<T>& ptr, std::nullptr_t) {
277  return !ptr;
278 }
279 
280 template <typename T>
281 bool operator==(std::nullptr_t, const SharedPtr<T>& ptr) {
282  return !ptr;
283 }
284 
285 template <typename T>
286 bool operator!=(const SharedPtr<T>& ptr, std::nullptr_t) {
287  return bool(ptr);
288 }
289 
290 template <typename T>
291 bool operator!=(std::nullptr_t, const SharedPtr<T>& ptr) {
292  return bool(ptr);
293 }
294 
295 template <typename T>
296 bool operator==(const SharedPtr<T>& ptr1, const SharedPtr<T>& ptr2) {
297  return ptr1.get() == ptr2.get();
298 }
299 
300 template <typename T>
301 bool operator!=(const SharedPtr<T>& ptr1, const SharedPtr<T>& ptr2) {
302  return ptr1.get() != ptr2.get();
303 }
304 
305 template <typename T>
306 bool operator<(const SharedPtr<T>& ptr1, const SharedPtr<T>& ptr2) {
307  return ptr1.get() < ptr2.get();
308 }
309 
310 template <typename T>
311 class WeakPtr {
312 private:
314 
315 public:
317  : block(nullptr) {}
318 
319  WeakPtr(const WeakPtr& other)
320  : block(other.block) {
321  if (block) {
322  block->increaseWeakCnt();
323  }
324  }
325 
326  template <typename T2>
327  WeakPtr(const WeakPtr<T2>& other)
328  : block(other.block) {
329  if (block) {
330  block->increaseWeakCnt();
331  }
332  }
333 
334  template <typename T2>
335  WeakPtr(const SharedPtr<T2>& ptr)
336  : block(ptr.block) {
337  if (block) {
338  block->increaseWeakCnt();
339  }
340  }
341 
342  WeakPtr(std::nullptr_t)
343  : block(nullptr) {}
344 
346  this->reset();
347  }
348 
349  WeakPtr& operator=(const WeakPtr& other) {
350  this->reset();
351  block = other.block;
352  if (block) {
353  block->increaseWeakCnt();
354  }
355  return *this;
356  }
357 
358  template <typename T2>
359  WeakPtr& operator=(const WeakPtr<T2>& other) {
360  this->reset();
361  block = other.block;
362  if (block) {
363  block->increaseWeakCnt();
364  }
365  return *this;
366  }
367 
368  WeakPtr& operator=(std::nullptr_t) {
369  this->reset();
370  return *this;
371  }
372 
373  SharedPtr<T> lock() const {
374  if (block && block->increaseUseCntIfNonzero()) {
375  SharedPtr<T> ptr;
376  ptr.block = block;
377  ptr.ptr = static_cast<T*>(block->getPtr());
378  block->increaseWeakCnt();
379  return ptr;
380  } else {
381  return nullptr;
382  }
383  }
384 
385  INLINE void reset() {
386  if (block) {
387  block->decreaseWeakCnt();
388  block = nullptr;
389  }
390  }
391 
393  if (!block) {
394  return 0;
395  } else {
396  return block->getUseCount();
397  }
398  }
399 
400  INLINE explicit operator bool() const {
401  return this->getUseCount() > 0;
402  }
403 
404  INLINE bool operator!() const {
405  return this->getUseCount() == 0;
406  }
407 };
408 
409 template <typename T, typename... TArgs>
410 INLINE SharedPtr<T> makeShared(TArgs&&... args) {
411  return SharedPtr<T>(alignedNew<T>(std::forward<TArgs>(args)...));
412 }
413 
414 template <typename T>
416 private:
417  WeakPtr<T> ptr;
418 
419 public:
420  using SHARE_FROM_THIS_TAG = void;
421 
422  void setWeakPtr(const WeakPtr<T>& weakPtr) {
423  ptr = weakPtr;
424  }
425 
427  SharedPtr<T> sharedPtr = ptr.lock();
428  SPH_ASSERT(sharedPtr);
429  return sharedPtr;
430  }
431 
433  return ptr;
434  }
435 };
436 
438 
439 template <typename T, typename TEnabler = void>
441  static constexpr bool value = false;
442 };
443 template <typename T>
444 struct IsShareFromThis<T, typename T::SHARE_FROM_THIS_TAG> {
445  static constexpr bool value = true;
446 };
447 
448 template <typename T>
449 std::enable_if_t<IsShareFromThis<T>::value> setSharedFromThis(const SharedPtr<T>& ptr) {
450  ptr->setWeakPtr(ptr);
451 }
452 
453 template <typename T>
454 std::enable_if_t<!IsShareFromThis<T>::value> setSharedFromThis(const SharedPtr<T>& UNUSED(ptr)) {
455  // do nothing
456 }
457 
INLINE void alignedDelete(T *ptr)
Deletes an object previously allocated using alignedNew.
#define SPH_ASSERT(x,...)
Definition: Assert.h:94
Simplified implementation of std::unique_ptr, using only default deleter.
NAMESPACE_SPH_BEGIN
Definition: BarnesHut.cpp:13
uint32_t Size
Integral type used to index arrays (by default).
Definition: Globals.h:16
#define INLINE
Macros for conditional compilation based on selected compiler.
Definition: Object.h:31
#define UNUSED(x)
Definition: Object.h:37
#define NAMESPACE_SPH_END
Definition: Object.h:12
INLINE SharedPtr< T > makeShared(TArgs &&... args)
Definition: SharedPtr.h:410
bool operator==(const SharedPtr< T > &ptr, std::nullptr_t)
Definition: SharedPtr.h:276
std::enable_if_t< IsShareFromThis< T >::value > setSharedFromThis(const SharedPtr< T > &ptr)
Definition: SharedPtr.h:449
bool operator!=(const SharedPtr< T > &ptr, std::nullptr_t)
Definition: SharedPtr.h:286
bool operator<(const SharedPtr< T > &ptr1, const SharedPtr< T > &ptr2)
Definition: SharedPtr.h:306
Wrapper of pointer that deletes the resource from destructor.
Definition: AutoPtr.h:15
INLINE void decreaseUseCnt()
Definition: SharedPtr.h:50
INLINE int getUseCount() const
Definition: SharedPtr.h:31
INLINE int increaseWeakCnt()
Definition: SharedPtr.h:35
INLINE void deleteBlock()
Definition: SharedPtr.h:70
INLINE void decreaseWeakCnt()
Definition: SharedPtr.h:58
INLINE int increaseUseCnt()
Definition: SharedPtr.h:25
virtual void deletePtr()=0
INLINE bool increaseUseCntIfNonzero()
Definition: SharedPtr.h:41
virtual void * getPtr()=0
ControlBlock(T *ptr)
Definition: SharedPtr.h:81
virtual void deletePtr() override
Definition: SharedPtr.h:89
virtual INLINE void * getPtr() override
Definition: SharedPtr.h:84
Non-owning wrapper of pointer.
Definition: RawPtr.h:19
void SHARE_FROM_THIS_TAG
Definition: SharedPtr.h:420
void setWeakPtr(const WeakPtr< T > &weakPtr)
Definition: SharedPtr.h:422
WeakPtr< T > weakFromThis() const
Definition: SharedPtr.h:432
SharedPtr< T > sharedFromThis() const
Definition: SharedPtr.h:426
SharedPtr & operator=(const SharedPtr &other)
Definition: SharedPtr.h:165
INLINE RawPtr< T > get() const
Definition: SharedPtr.h:223
INLINE T & operator*() const
Definition: SharedPtr.h:210
SharedPtr(AutoPtr< T2 > &&ptr)
Definition: SharedPtr.h:158
SharedPtr & operator=(SharedPtr &&other)
Definition: SharedPtr.h:180
INLINE Size getUseCount()
Definition: SharedPtr.h:246
SharedPtr(std::nullptr_t)
Definition: SharedPtr.h:161
SharedPtr(const SharedPtr &other)
Definition: SharedPtr.h:131
Detail::ControlBlockHolder * block
Definition: SharedPtr.h:110
INLINE void reset()
Definition: SharedPtr.h:227
SharedPtr(T *ptr)
Definition: SharedPtr.h:121
SharedPtr(T *ptr, Detail::ControlBlockHolder *block)
Definition: SharedPtr.h:112
SharedPtr(SharedPtr &&other)
Definition: SharedPtr.h:142
SharedPtr(const SharedPtr< T2 > &other)
Definition: SharedPtr.h:137
SharedPtr(SharedPtr< T2 > &&other)
Definition: SharedPtr.h:150
friend class SharedFromThis
Definition: SharedPtr.h:106
INLINE T * operator->() const
Definition: SharedPtr.h:205
INLINE T * release()
Definition: SharedPtr.h:236
SharedPtr & operator=(const SharedPtr< T2 > &other)
Definition: SharedPtr.h:173
SharedPtr & operator=(std::nullptr_t)
Definition: SharedPtr.h:196
~SharedPtr()
Definition: SharedPtr.h:201
INLINE bool operator!() const
Definition: SharedPtr.h:219
SharedPtr & operator=(SharedPtr< T2 > &&other)
Definition: SharedPtr.h:187
INLINE void reset()
Definition: SharedPtr.h:385
SharedPtr< T > lock() const
Definition: SharedPtr.h:373
INLINE bool operator!() const
Definition: SharedPtr.h:404
~WeakPtr()
Definition: SharedPtr.h:345
WeakPtr & operator=(const WeakPtr &other)
Definition: SharedPtr.h:349
WeakPtr & operator=(const WeakPtr< T2 > &other)
Definition: SharedPtr.h:359
WeakPtr()
Definition: SharedPtr.h:316
WeakPtr(std::nullptr_t)
Definition: SharedPtr.h:342
WeakPtr(const WeakPtr< T2 > &other)
Definition: SharedPtr.h:327
WeakPtr(const WeakPtr &other)
Definition: SharedPtr.h:319
WeakPtr & operator=(std::nullptr_t)
Definition: SharedPtr.h:368
INLINE Size getUseCount() const
Definition: SharedPtr.h:392
WeakPtr(const SharedPtr< T2 > &ptr)
Definition: SharedPtr.h:335
void swap(Sph::Array< T, TCounter > &ar1, Sph::Array< T, TCounter > &ar2)
Definition: Array.h:580
static constexpr bool value
Definition: SharedPtr.h:441
Base class for all polymorphic objects.
Definition: Object.h:88