0%
SharedPtr & WeakPtr
RefCounter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
|
template<class T> class RefCounter { public: RefCounter(T* value_) : value(value_) {} ~RefCounter() {}
int GetRefCount() const { return refCount; }
int GetWeakRefCount() const { return weakRefCount; }
void IncRef() { refCount++; weakRefCount++; }
bool IncRefIfNotZero() { if (refCount) { IncRef(); return true; } return false; }
void DecRef() { if (--refCount == 0) { FreeValue(); } if (--weakRefCount == 0) { FreeSelf(); } }
void IncWeakRef() { weakRefCount++; }
void DecWeakRef() { if (--weakRefCount == 0) { FreeSelf(); } }
void FreeValue() { delete value; value = nullptr; }
void FreeSelf() { this->~RefCounter(); delete this; }
private: int refCount = 1; int weakRefCount = 1;
T* value; };
|
SharedPtr
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
| template<class T> class WeakPtr;
template<class T> class SharedPtr { public: SharedPtr() {} SharedPtr(T* value_ = nullptr) { if (value_) { AllocImpl(value_); } }
SharedPtr(const SharedPtr& sharedPtr) : refCounter(sharedPtr.refCounter) , value(sharedPtr.value) { if (refCounter) { refCounter->IncRef(); } }
SharedPtr(SharedPtr&& sharedPtr) : refCounter(sharedPtr.refCounter) , value(sharedPtr.value) { sharedPtr.refCounter = nullptr; sharedPtr.value = nullptr; }
SharedPtr(const WeakPtr<T>& weakPtr) { if (weakPtr.refCounter && weakPtr.refCounter->IncRefIfNotZero()) { refCounter = weakPtr.refCounter; value = weakPtr.value; } }
~SharedPtr() { if (refCounter) { refCounter->DecRef(); refCounter = nullptr; value = nullptr; } } SharedPtr& operator=(const SharedPtr& sharedPtr) { if (&sharedPtr != this) { SharedPtr(sharedPtr).Swap(*this); } return *this; }
SharedPtr& operator=(SharedPtr&& sharedPtr) { if (&sharedPtr != this) { SharedPtr(move(sharedPtr)).Swap(*this); } return *this; }
int UseCount() const { return refCounter ? refCounter->GetRefCount() : 0; }
T* Get() const { return value; }
void Swap(SharedPtr& sharedPtr) { swap(value, sharedPtr.value); swap(refCounter, sharedPtr.refCounter); }
void Reset(T* value_ = nullptr) { SharedPtr(value_).Swap(*this); }
private: template<class T> friend class WeakPtr;
RefCounter<T>* refCounter = nullptr; T* value = nullptr;
void AllocImpl(T* value_) { refCounter = new RefCounter<T>(value_); value = value_; } };
|
WeakPtr
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
|
template<class T> class WeakPtr { public: WeakPtr(const WeakPtr& weakPtr) : refCounter(weakPtr.refCounter) , value(weakPtr.value) { if (refCounter) { refCounter->IncWeakRef(); } }
~WeakPtr() { if (refCounter) { refCounter->DecWeakRef(); } }
bool Expired() const { return !refCounter || refCounter->GetRefCount() == 0; } SharedPtr<T> Lock() { return SharedPtr<T>(*this); }
private: RefCounter<T>* refCounter = nullptr; T* value = nullptr; };
|
EnableSharedFromThis
EnableSharedFromThis
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| template<class T> class EnableSharedFromThis { public: using _ESFT_TYPE = EnableSharedFromThis; SharedPtr<T> SharedFromThis() { return SharedPtr<T>(_enableSharedWeakPtr); } WeakPtr<T> WeakFromThis() { return _enableSharedWeakPtr; } protected: EnableSharedFromThis() : _enableSharedWeakPtr() { } EnableSharedFromThis& operator=(const EnableSharedFromThis&) { return *this; } ~EnableSharedFromThis() = default;
private: template<class T> friend class SharedPtr; mutable WeakPtr<T> _enableSharedWeakPtr; };
|
CanEnableShared
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| template<class T, class = void> struct CanEnableShared : false_type {};
template<class T> struct CanEnableShared<T, void_t<typename T::_ESFT_TYPE>> : is_convertible<remove_cv_t<T>*, typename T::_ESFT_TYPE*>::type { };
SharedPtr::SharedPtr(T* t) { if constexpr (conjunction_v<CanEnableShared<T>>) { if(t && t->_enableSharedWeakPtr.expired()) { t->_enableSharedWeakPtr = *this; } } }
|