ScummVM API documentation
ptr.h
1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #ifndef COMMON_PTR_H
23 #define COMMON_PTR_H
24 
25 #include "common/scummsys.h"
26 #include "common/noncopyable.h"
27 #include "common/safe-bool.h"
28 #include "common/types.h"
29 
30 /* For nullptr_t */
31 #include <cstddef>
32 
33 namespace Common {
34 
44 public:
45  typedef int RefValue;
46 
47  BasePtrTrackerInternal() : _weakRefCount(1), _strongRefCount(1) {}
48  virtual ~BasePtrTrackerInternal() {}
49 
50  void incWeak() {
51  _weakRefCount++;
52  }
53 
54  void decWeak() {
55  if (--_weakRefCount == 0)
56  delete this;
57  }
58 
59  void incStrong() {
60  _strongRefCount++;
61  }
62 
63  void decStrong() {
64  if (--_strongRefCount == 0) {
65  destructObject();
66  decWeak();
67  }
68  }
69 
70  bool isAlive() const {
71  return _strongRefCount > 0;
72  }
73 
74  RefValue getStrongCount() const {
75  return _strongRefCount;
76  }
77 
78 protected:
79  virtual void destructObject() = 0;
80 
81 private:
82  RefValue _weakRefCount; // Weak ref count + 1 if object ref count > 0
83  RefValue _strongRefCount;
84 };
85 
86 template<class T>
88 public:
89  BasePtrTrackerImpl(T *ptr) : _ptr(ptr) {}
90 
91 protected:
92  void destructObject() override {
93  STATIC_ASSERT(sizeof(T) > 0, SharedPtr_cannot_delete_incomplete_type);
94  delete _ptr;
95  }
96 
97  T *_ptr;
98 };
99 
100 template<class T, class DL>
102 public:
103  BasePtrTrackerDeletionImpl(T *ptr, DL d) : _ptr(ptr), _deleter(d) {}
104 
105 private:
106  void destructObject() override {
107  _deleter(_ptr);
108  }
109 
110  T *_ptr;
111  DL _deleter;
112 };
113 
114 template<class T>
115 class WeakPtr;
116 
158 template<class T>
159 class SharedPtr : public SafeBool<SharedPtr<T> > {
160  template<class T2>
161  friend class WeakPtr;
162  template<class T2>
163  friend class SharedPtr;
164 public:
165  // Invariant: If _tracker is non-null, then the object is alive
166  typedef T *PointerType;
167  typedef T &ReferenceType;
168  typedef BasePtrTrackerInternal::RefValue RefValue;
169 
170  SharedPtr() : _pointer(nullptr), _tracker(nullptr) {
171  }
172 
173  SharedPtr(std::nullptr_t) : _pointer(nullptr), _tracker(nullptr) {
174  }
175 
176  ~SharedPtr() {
177  if (_tracker)
178  _tracker->decStrong();
179  }
180 
181  template<class T2>
182  explicit SharedPtr(T2 *p) : _pointer(p), _tracker(p ? (new BasePtrTrackerImpl<T2>(p)) : nullptr) {
183  }
184 
185  template<class T2, class DL>
186  SharedPtr(T2 *p, DL d) : _pointer(p), _tracker(p ? (new BasePtrTrackerDeletionImpl<T2, DL>(p, d)) : nullptr) {
187  }
188 
189  SharedPtr(const SharedPtr<T> &r) : _pointer(r._pointer), _tracker(r._tracker) {
190  if (_tracker)
191  _tracker->incStrong();
192  }
193 
194  template<class T2>
195  SharedPtr(const SharedPtr<T2> &r) : _pointer(r._pointer), _tracker(r._tracker) {
196  if (_tracker)
197  _tracker->incStrong();
198  }
199 
200  template<class T2>
201  explicit SharedPtr(const WeakPtr<T2> &r) : _pointer(nullptr), _tracker(nullptr) {
202  if (r._tracker && r._tracker->isAlive()) {
203  _pointer = r._pointer;
204  _tracker = r._tracker;
205  _tracker->incStrong();
206  }
207  }
208 
209  SharedPtr &operator=(const SharedPtr &r) {
210  reset(r);
211  return *this;
212  }
213 
214  template<class T2>
215  SharedPtr &operator=(const SharedPtr<T2> &r) {
216  reset(r);
217  return *this;
218  }
219 
220  T &operator*() const { assert(_pointer); return *_pointer; }
221  T *operator->() const { assert(_pointer); return _pointer; }
222 
229  PointerType get() const { return _pointer; }
230 
231  template<class T2>
232  bool operator==(const SharedPtr<T2> &r) const {
233  return _pointer == r.get();
234  }
235 
236  template<class T2>
237  bool operator!=(const SharedPtr<T2> &r) const {
238  return _pointer != r.get();
239  }
240 
241  bool operator==(std::nullptr_t) const {
242  return _pointer == nullptr;
243  }
244 
245  bool operator!=(std::nullptr_t) const {
246  return _pointer != nullptr;
247  }
248 
253  bool operator_bool() const {
254  return _pointer != nullptr;
255  }
256 
260  int refCount() const {
261  if (_tracker == nullptr)
262  return 0;
263  return _tracker->getStrongCount();
264  }
265 
271  bool unique() const {
272  return refCount() == 1;
273  }
274 
278  void reset() {
279  if (_tracker)
280  _tracker->decStrong();
281  _tracker = nullptr;
282  _pointer = nullptr;
283  }
284 
288  template<class T2>
289  void reset(const SharedPtr<T2> &r) {
290  BasePtrTrackerInternal *oldTracker = _tracker;
291 
292  _pointer = r._pointer;
293  _tracker = r._tracker;
294 
295  if (_tracker)
296  _tracker->incStrong();
297  if (oldTracker)
298  oldTracker->decStrong();
299  }
300 
304  template<class T2>
305  void reset(const WeakPtr<T2> &r) {
306  BasePtrTrackerInternal *oldTracker = _tracker;
307 
308  if (r._tracker && r._tracker->isAlive()) {
309  _tracker = r._tracker;
310  _pointer = r._pointer;
311  _tracker->incStrong();
312  } else {
313  _tracker = nullptr;
314  _pointer = nullptr;
315  }
316 
317  if (oldTracker)
318  oldTracker->decStrong();
319  }
320 
324  void reset(T *ptr) {
325  if (_tracker)
326  _tracker->decStrong();
327 
328  _pointer = ptr;
329  _tracker = new BasePtrTrackerImpl<T>(ptr);
330  }
331 
335  template<class T2>
337  return SharedPtr<T2>(static_cast<T2 *>(_pointer), _tracker);
338  }
339 
343  template<class T2>
345  return SharedPtr<T2>(dynamic_cast<T2 *>(_pointer), _tracker);
346  }
347 
351  template<class T2>
353  return SharedPtr<T2>(const_cast<T2 *>(_pointer), _tracker);
354  }
355 
359  template<class T2>
361  return SharedPtr<T2>(reinterpret_cast<T2 *>(_pointer), _tracker);
362  }
363 
364 private:
365  SharedPtr(T *pointer, BasePtrTrackerInternal *tracker) : _pointer(pointer), _tracker(tracker) {
366  if (tracker)
367  tracker->incStrong();
368  }
369 
370  T *_pointer;
371  BasePtrTrackerInternal *_tracker;
372 };
373 
374 
375 
380 template<class T>
381 class WeakPtr {
382  template<class T2>
383  friend class WeakPtr;
384  template<class T2>
385  friend class SharedPtr;
386 public:
387  WeakPtr() : _pointer(nullptr), _tracker(nullptr) {
388  }
389 
390  WeakPtr(std::nullptr_t) : _pointer(nullptr), _tracker(nullptr) {
391  }
392 
393  WeakPtr(const WeakPtr<T> &r) : _pointer(r._pointer), _tracker(r._tracker) {
394  if (_tracker)
395  _tracker->incWeak();
396  }
397 
398  ~WeakPtr() {
399  if (_tracker)
400  _tracker->decWeak();
401  }
402 
403  template<class T2>
404  WeakPtr(const WeakPtr<T2> &r) : _pointer(r._pointer), _tracker(r._tracker) {
405  if (_tracker)
406  _tracker->incWeak();
407  }
408 
409  template<class T2>
410  WeakPtr(const SharedPtr<T2> &r) : _pointer(r._pointer), _tracker(r._tracker) {
411  if (_tracker)
412  _tracker->incWeak();
413  }
414 
418  template<class T2>
420  return WeakPtr<T2>(expired() ? nullptr : static_cast<T2 *>(_pointer), _tracker);
421  }
422 
426  template<class T2>
428  return WeakPtr<T2>(expired() ? nullptr : dynamic_cast<T2 *>(_pointer), _tracker);
429  }
430 
434  template<class T2>
436  return WeakPtr<T2>(expired() ? nullptr : const_cast<T2 *>(_pointer), _tracker);
437  }
438 
442  template<class T2>
444  return WeakPtr<T2>(expired() ? nullptr : reinterpret_cast<T2 *>(_pointer), _tracker);
445  }
446 
450  SharedPtr<T> lock() const {
451  return SharedPtr<T>(*this);
452  }
453 
457  int refCount() const {
458  if (_tracker == nullptr)
459  return 0;
460  return _tracker->getStrongCount();
461  }
462 
466  bool expired() const {
467  return _tracker == nullptr || _tracker->getStrongCount() == 0;
468  }
469 
473  template<class T2>
474  bool owner_before(const WeakPtr<T2>& other) const {
475  return _tracker < other._tracker;
476  }
477 
481  template<class T2>
482  bool owner_before(const SharedPtr<T2> &other) const {
483  return _tracker < other._tracker;
484  }
485 
486  WeakPtr<T> &operator=(const WeakPtr<T> &r) {
487  reset(r);
488  return *this;
489  }
490 
491  template<class T2>
492  WeakPtr<T> &operator=(const WeakPtr<T2> &r) {
493  reset(r);
494  return *this;
495  }
496 
497  template<class T2>
498  WeakPtr<T> &operator=(const SharedPtr<T2> &r) {
499  reset(r);
500  return *this;
501  }
502 
506  void reset() {
507  if (_tracker)
508  _tracker->decWeak();
509  _tracker = nullptr;
510  _pointer = nullptr;
511  }
512 
516  template<class T2>
517  void reset(const SharedPtr<T2> &r) {
518  BasePtrTrackerInternal *oldTracker = _tracker;
519 
520  _pointer = r._pointer;
521  _tracker = r._tracker;
522 
523  if (_tracker)
524  _tracker->incWeak();
525  if (oldTracker)
526  oldTracker->decWeak();
527  }
528 
532  template<class T2>
533  void reset(const WeakPtr<T2> &r) {
534  BasePtrTrackerInternal *oldTracker = _tracker;
535 
536  _pointer = r._pointer;
537  _tracker = r._tracker;
538 
539  if (_tracker)
540  _tracker->incWeak();
541  if (oldTracker)
542  oldTracker->decWeak();
543  }
544 
545 private:
546  WeakPtr(T *pointer, BasePtrTrackerInternal *tracker) : _pointer(pointer), _tracker(tracker) {
547  if (tracker)
548  tracker->incWeak();
549  }
550 
551  T *_pointer;
552  BasePtrTrackerInternal *_tracker;
553 };
554 
555 template <typename T>
557  inline void operator()(T *object) {
558  STATIC_ASSERT(sizeof(T) > 0, cannot_delete_incomplete_type);
559  delete object;
560  }
561 };
562 
563 template <typename T>
564 struct ArrayDeleter {
565  inline void operator()(T *object) {
566  STATIC_ASSERT(sizeof(T) > 0, cannot_delete_incomplete_type);
567  delete[] object;
568  }
569 };
570 
571 template<typename T, class DL = DefaultDeleter<T> >
572 class ScopedPtr : private NonCopyable, public SafeBool<ScopedPtr<T, DL> > {
573  template<class T2, class DL2>
574  friend class ScopedPtr;
575 public:
576  typedef T ValueType;
577  typedef T *PointerType;
578  typedef T &ReferenceType;
579 
580  explicit ScopedPtr(PointerType o = nullptr) : _pointer(o) {}
581  ScopedPtr(std::nullptr_t) : _pointer(nullptr) {}
582 
586  template<class T2>
587  ScopedPtr(ScopedPtr<T2> &&o) : _pointer(o._pointer) {
588  o._pointer = nullptr;
589  }
590 
591  ReferenceType operator*() const { return *_pointer; }
592  PointerType operator->() const { return _pointer; }
593 
598  bool operator_bool() const { return _pointer != nullptr; }
599 
600  ~ScopedPtr() {
601  DL()(_pointer);
602  }
603 
607  void reset(PointerType o = nullptr) {
608  DL()(_pointer);
609  _pointer = o;
610  }
611 
615  ScopedPtr &operator=(std::nullptr_t) {
616  reset(nullptr);
617  }
618 
622  template<class T2>
624  PointerType oldPointer = _pointer;
625  _pointer = other._pointer;
626  other._pointer = nullptr;
627  DL()(oldPointer);
628  return *this;
629  }
630 
636  PointerType get() const { return _pointer; }
637 
644  PointerType release() {
645  PointerType r = _pointer;
646  _pointer = nullptr;
647  return r;
648  }
649 
650 private:
651  PointerType _pointer;
652 };
653 
654 template<typename T, class DL = DefaultDeleter<T> >
655 class DisposablePtr : private NonCopyable, public SafeBool<DisposablePtr<T, DL> > {
656 public:
657  typedef T ValueType;
658  typedef T *PointerType;
659  typedef T &ReferenceType;
660 
661  explicit DisposablePtr(PointerType o, DisposeAfterUse::Flag dispose) : _pointer(o), _dispose(dispose), _shared() {}
662  explicit DisposablePtr(SharedPtr<T> o) : _pointer(o.get()), _dispose(DisposeAfterUse::NO), _shared(o) {}
663  DisposablePtr(DisposablePtr<T, DL>&& o) : _pointer(o._pointer), _dispose(o._dispose), _shared(o._shared) {
664  o._pointer = nullptr;
665  o._dispose = DisposeAfterUse::NO;
666  o._shared.reset();
667  }
668 
669  ~DisposablePtr() {
670  if (_dispose) DL()(_pointer);
671  }
672 
673  ReferenceType operator*() const { return *_pointer; }
674  PointerType operator->() const { return _pointer; }
675 
680  bool operator_bool() const { return _pointer != nullptr; }
681 
685  void reset(PointerType o, DisposeAfterUse::Flag dispose) {
686  if (_dispose) DL()(_pointer);
687  _pointer = o;
688  _dispose = dispose;
689  _shared.reset();
690  }
691 
695  void reset() {
696  reset(nullptr, DisposeAfterUse::NO);
697  }
698 
699  template <class T2>
700  bool isDynamicallyCastable() {
701  return dynamic_cast<T2 *>(_pointer) != nullptr;
702  }
703 
704  /* Destroys the smart pointer while returning a pointer to
705  assign to a new object.
706  */
707  template <class T2, class DL2 = DefaultDeleter<T2> >
708  DisposablePtr<T2, DL2> moveAndDynamicCast() {
709  DisposablePtr<T2, DL2> ret(nullptr, DisposeAfterUse::NO);
710  ret._pointer = dynamic_cast<T2 *>(_pointer);
711  ret._dispose = _dispose;
712  ret._shared = _shared.template dynamicCast<T2>();
713  _pointer = nullptr;
714  _dispose = DisposeAfterUse::NO;
715  _shared.reset();
716  return ret;
717  }
718 
724  PointerType get() const { return _pointer; }
725 
726  template <class T2, class DL2>
727  friend class DisposablePtr;
728 
729 private:
730  DisposablePtr() : _pointer(nullptr), _dispose(DisposeAfterUse::NO), _shared() {}
731  PointerType _pointer;
732  DisposeAfterUse::Flag _dispose;
733  SharedPtr<T> _shared;
734  bool _isvalid;
735 };
736 
737 
743 #if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM) || defined(_M_ARM64))
744 
745 template<class T>
746 class UnalignedPtr {
747 public:
748  UnalignedPtr();
749  UnalignedPtr(__unaligned T *ptr);
750 
751  T load() const;
752  void store(const T &value) const;
753 
754 private:
755  __unaligned T *_ptr;
756 };
757 
758 template<class T>
759 UnalignedPtr<T>::UnalignedPtr() : _ptr(nullptr) {
760 }
761 
762 template<class T>
763 UnalignedPtr<T>::UnalignedPtr(__unaligned T *ptr) : _ptr(ptr) {
764 }
765 
766 template<class T>
767 T UnalignedPtr<T>::load() const {
768  return *_ptr;
769 }
770 
771 template<class T>
772 void UnalignedPtr<T>::store(const T &value) const {
773  *_ptr = value;
774 }
775 
776 #else
777 
778 template<class T>
780 public:
781  UnalignedPtr();
782  UnalignedPtr(T *ptr);
783 
784  T load() const;
785  void store(const T &value) const;
786 
787 private:
788  void *_ptr;
789 };
790 
791 template<class T>
792 UnalignedPtr<T>::UnalignedPtr() : _ptr(nullptr) {
793 }
794 
795 template<class T>
796 UnalignedPtr<T>::UnalignedPtr(T *ptr) : _ptr(ptr) {
797 }
798 
799 template<class T>
800 T UnalignedPtr<T>::load() const {
801  T result;
802  memcpy(&result, _ptr, sizeof(T));
803  return result;
804 }
805 
806 template<class T>
807 void UnalignedPtr<T>::store(const T &value) const {
808  memcpy(_ptr, &value, sizeof(T));
809 }
810 
811 #endif
812 
815 } // End of namespace Common
816 
817 #endif
bool expired() const
Definition: ptr.h:466
WeakPtr< T2 > dynamicCast() const
Definition: ptr.h:427
void reset(const WeakPtr< T2 > &r)
Definition: ptr.h:533
bool unique() const
Definition: ptr.h:271
Definition: ptr.h:115
void reset(T *ptr)
Definition: ptr.h:324
ScopedPtr & operator=(std::nullptr_t)
Definition: ptr.h:615
SharedPtr< T2 > reinterpretCast() const
Definition: ptr.h:360
void reset(const SharedPtr< T2 > &r)
Definition: ptr.h:289
ScopedPtr(ScopedPtr< T2 > &&o)
Definition: ptr.h:587
SharedPtr< T2 > staticCast() const
Definition: ptr.h:336
bool owner_before(const WeakPtr< T2 > &other) const
Definition: ptr.h:474
bool operator_bool() const
Definition: ptr.h:253
int refCount() const
Definition: ptr.h:260
SharedPtr< T > lock() const
Definition: ptr.h:450
Definition: ptr.h:564
void reset()
Definition: ptr.h:278
void reset(const SharedPtr< T2 > &r)
Definition: ptr.h:517
WeakPtr< T2 > constCast() const
Definition: ptr.h:435
Definition: ptr.h:572
Definition: noncopyable.h:39
PointerType release()
Definition: ptr.h:644
PointerType get() const
Definition: ptr.h:229
WeakPtr< T2 > staticCast() const
Definition: ptr.h:419
bool operator_bool() const
Definition: ptr.h:598
Definition: algorithm.h:29
Definition: ptr.h:556
bool operator_bool() const
Definition: ptr.h:680
bool owner_before(const SharedPtr< T2 > &other) const
Definition: ptr.h:482
void reset(PointerType o=nullptr)
Definition: ptr.h:607
Definition: ptr.h:43
Definition: ptr.h:87
ScopedPtr & operator=(ScopedPtr< T2 > &&other)
Definition: ptr.h:623
void reset()
Definition: ptr.h:695
SharedPtr< T2 > dynamicCast() const
Definition: ptr.h:344
void reset(PointerType o, DisposeAfterUse::Flag dispose)
Definition: ptr.h:685
void reset(const WeakPtr< T2 > &r)
Definition: ptr.h:305
void reset()
Definition: ptr.h:506
Definition: safe-bool.h:56
Definition: ptr.h:159
SharedPtr< T2 > constCast() const
Definition: ptr.h:352
Definition: ptr.h:655
WeakPtr< T2 > reinterpretCast() const
Definition: ptr.h:443
Definition: ptr.h:779
int refCount() const
Definition: ptr.h:457