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
33namespace Common {
34
44public:
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
78protected:
79 virtual void destructObject() = 0;
80
81private:
82 RefValue _weakRefCount; // Weak ref count + 1 if object ref count > 0
83 RefValue _strongRefCount;
84};
85
86template<class T>
88public:
89 BasePtrTrackerImpl(T *ptr) : _ptr(ptr) {}
90
91protected:
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
100template<class T, class DL>
102public:
103 BasePtrTrackerDeletionImpl(T *ptr, DL d) : _ptr(ptr), _deleter(d) {}
104
105private:
106 void destructObject() override {
107 _deleter(_ptr);
108 }
109
110 T *_ptr;
111 DL _deleter;
112};
113
114template<class T>
115class WeakPtr;
116
158template<class T>
159class SharedPtr : public SafeBool<SharedPtr<T> > {
160 template<class T2>
161 friend class WeakPtr;
162 template<class T2>
163 friend class SharedPtr;
164public:
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
364private:
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
380template<class T>
381class WeakPtr {
382 template<class T2>
383 friend class WeakPtr;
384 template<class T2>
385 friend class SharedPtr;
386public:
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
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
545private:
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
555template <typename T>
557 inline void operator()(T *object) {
558 static_assert(sizeof(T) > 0, "cannot delete incomplete type");
559 delete object;
560 }
561};
562
563template <typename T>
565 inline void operator()(T *object) {
566 static_assert(sizeof(T) > 0, "cannot delete incomplete type");
567 delete[] object;
568 }
569};
570
571template<typename T, class DL = DefaultDeleter<T> >
572class ScopedPtr : private NonCopyable, public SafeBool<ScopedPtr<T, DL> > {
573 template<class T2, class DL2>
574 friend class ScopedPtr;
575public:
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 return *this;
618 }
619
623 template<class T2>
625 PointerType oldPointer = _pointer;
626 _pointer = other._pointer;
627 other._pointer = nullptr;
628 DL()(oldPointer);
629 return *this;
630 }
631
637 PointerType get() const { return _pointer; }
638
645 PointerType release() {
646 PointerType r = _pointer;
647 _pointer = nullptr;
648 return r;
649 }
650
651private:
652 PointerType _pointer;
653};
654
655template<typename T, class DL = DefaultDeleter<T> >
656class DisposablePtr : private NonCopyable, public SafeBool<DisposablePtr<T, DL> > {
657public:
658 typedef T ValueType;
659 typedef T *PointerType;
660 typedef T &ReferenceType;
661
662 explicit DisposablePtr(PointerType o, DisposeAfterUse::Flag dispose) : _pointer(o), _dispose(dispose), _shared() {}
663 explicit DisposablePtr(SharedPtr<T> o) : _pointer(o.get()), _dispose(DisposeAfterUse::NO), _shared(o) {}
664 DisposablePtr(DisposablePtr<T, DL>&& o) : _pointer(o._pointer), _dispose(o._dispose), _shared(o._shared) {
665 o._pointer = nullptr;
666 o._dispose = DisposeAfterUse::NO;
667 o._shared.reset();
668 }
669
671 if (_dispose) DL()(_pointer);
672 }
673
675 reset(o._pointer, o._dispose);
676 _shared = move(o._shared);
677 o._pointer = nullptr;
678 o._dispose = DisposeAfterUse::NO;
679 return *this;
680 }
681
682 ReferenceType operator*() const { return *_pointer; }
683 PointerType operator->() const { return _pointer; }
684
689 bool operator_bool() const { return _pointer != nullptr; }
690
694 void reset(PointerType o, DisposeAfterUse::Flag dispose) {
695 if (_dispose) DL()(_pointer);
696 _pointer = o;
697 _dispose = dispose;
698 _shared.reset();
699 }
700
704 void reset() {
705 reset(nullptr, DisposeAfterUse::NO);
706 }
707
708 template <class T2>
709 bool isDynamicallyCastable() {
710 return dynamic_cast<T2 *>(_pointer) != nullptr;
711 }
712
713 /* Destroys the smart pointer while returning a pointer to
714 assign to a new object.
715 */
716 template <class T2, class DL2 = DefaultDeleter<T2> >
717 DisposablePtr<T2, DL2> moveAndDynamicCast() {
718 DisposablePtr<T2, DL2> ret(nullptr, DisposeAfterUse::NO);
719 ret._pointer = dynamic_cast<T2 *>(_pointer);
720 ret._dispose = _dispose;
721 ret._shared = _shared.template dynamicCast<T2>();
722 _pointer = nullptr;
723 _dispose = DisposeAfterUse::NO;
724 _shared.reset();
725 return ret;
726 }
727
733 PointerType get() const { return _pointer; }
734
735 template <class T2, class DL2>
736 friend class DisposablePtr;
737
738private:
739 DisposablePtr() : _pointer(nullptr), _dispose(DisposeAfterUse::NO), _shared() {}
740 PointerType _pointer;
741 DisposeAfterUse::Flag _dispose;
742 SharedPtr<T> _shared;
743};
744
745
751#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM) || defined(_M_ARM64))
752
753template<class T>
754class UnalignedPtr {
755public:
756 UnalignedPtr();
757 UnalignedPtr(__unaligned T *ptr);
758
759 T load() const;
760 void store(const T &value) const;
761
762private:
763 __unaligned T *_ptr;
764};
765
766template<class T>
767UnalignedPtr<T>::UnalignedPtr() : _ptr(nullptr) {
768}
769
770template<class T>
771UnalignedPtr<T>::UnalignedPtr(__unaligned T *ptr) : _ptr(ptr) {
772}
773
774template<class T>
775T UnalignedPtr<T>::load() const {
776 return *_ptr;
777}
778
779template<class T>
780void UnalignedPtr<T>::store(const T &value) const {
781 *_ptr = value;
782}
783
784#else
785
786template<class T>
788public:
789 UnalignedPtr();
790 UnalignedPtr(T *ptr);
791
792 T load() const;
793 void store(const T &value) const;
794
795private:
796 void *_ptr;
797};
798
799template<class T>
800UnalignedPtr<T>::UnalignedPtr() : _ptr(nullptr) {
801}
802
803template<class T>
804UnalignedPtr<T>::UnalignedPtr(T *ptr) : _ptr(ptr) {
805}
806
807template<class T>
808T UnalignedPtr<T>::load() const {
809 T result;
810 memcpy(&result, _ptr, sizeof(T));
811 return result;
812}
813
814template<class T>
815void UnalignedPtr<T>::store(const T &value) const {
816 memcpy(_ptr, &value, sizeof(T));
817}
818
819#endif
820
823} // End of namespace Common
824
825#endif
Definition: ptr.h:87
Definition: ptr.h:43
Definition: ptr.h:656
void reset()
Definition: ptr.h:704
bool operator_bool() const
Definition: ptr.h:689
void reset(PointerType o, DisposeAfterUse::Flag dispose)
Definition: ptr.h:694
PointerType get() const
Definition: ptr.h:733
Definition: noncopyable.h:39
Definition: ptr.h:572
void reset(PointerType o=nullptr)
Definition: ptr.h:607
PointerType get() const
Definition: ptr.h:637
ScopedPtr(ScopedPtr< T2 > &&o)
Definition: ptr.h:587
ScopedPtr & operator=(std::nullptr_t)
Definition: ptr.h:615
bool operator_bool() const
Definition: ptr.h:598
PointerType release()
Definition: ptr.h:645
ScopedPtr & operator=(ScopedPtr< T2 > &&other)
Definition: ptr.h:624
Definition: ptr.h:159
PointerType get() const
Definition: ptr.h:229
SharedPtr< T2 > constCast() const
Definition: ptr.h:352
bool unique() const
Definition: ptr.h:271
int refCount() const
Definition: ptr.h:260
void reset(const SharedPtr< T2 > &r)
Definition: ptr.h:289
bool operator_bool() const
Definition: ptr.h:253
void reset()
Definition: ptr.h:278
void reset(T *ptr)
Definition: ptr.h:324
SharedPtr< T2 > staticCast() const
Definition: ptr.h:336
SharedPtr< T2 > dynamicCast() const
Definition: ptr.h:344
SharedPtr< T2 > reinterpretCast() const
Definition: ptr.h:360
void reset(const WeakPtr< T2 > &r)
Definition: ptr.h:305
Definition: ptr.h:787
Definition: ptr.h:381
WeakPtr< T2 > constCast() const
Definition: ptr.h:435
WeakPtr< T2 > staticCast() const
Definition: ptr.h:419
bool expired() const
Definition: ptr.h:466
void reset()
Definition: ptr.h:506
WeakPtr< T2 > dynamicCast() const
Definition: ptr.h:427
bool owner_before(const WeakPtr< T2 > &other) const
Definition: ptr.h:474
bool owner_before(const SharedPtr< T2 > &other) const
Definition: ptr.h:482
int refCount() const
Definition: ptr.h:457
void reset(const WeakPtr< T2 > &r)
Definition: ptr.h:533
SharedPtr< T > lock() const
Definition: ptr.h:450
WeakPtr< T2 > reinterpretCast() const
Definition: ptr.h:443
void reset(const SharedPtr< T2 > &r)
Definition: ptr.h:517
Out move(In first, In last, Out dst)
Definition: algorithm.h:109
Definition: algorithm.h:29
Definition: ptr.h:564
Definition: ptr.h:556
Definition: safe-bool.h:56