#pragma once #include /** * A smart pointer to an object which implements AddRef/Release. */ template class ref_count_ptr { typedef ReferencedType* reference_type; public: ref_count_ptr(): reference_(nullptr) { } explicit ref_count_ptr(ReferencedType* in_reference,bool bAddRef = true) { reference_ = in_reference; if(reference_ && bAddRef) { reference_->AddRef(); } } ref_count_ptr(const ref_count_ptr& copy) { reference_ = copy.reference_; if(reference_) { reference_->AddRef(); } } template explicit ref_count_ptr(const ref_count_ptr& copy) { reference_ = static_cast(copy.get_reference()); if (reference_) { reference_->AddRef(); } } ref_count_ptr(ref_count_ptr&& move) noexcept { reference_ = move.reference_; move.reference_ = nullptr; } template explicit ref_count_ptr(ref_count_ptr&& move) { reference_ = static_cast(move.get_reference()); move.reference_ = nullptr; } ~ref_count_ptr() { if(reference_) { reference_->Release(); } } ref_count_ptr& operator=(ReferencedType* in_reference) { if (reference_ != in_reference) { // Call AddRef before Release, in case the new reference is the same as the old reference. ReferencedType* old_reference = reference_; reference_ = in_reference; if (reference_) { reference_->AddRef(); } if (old_reference) { old_reference->Release(); } } return *this; } ref_count_ptr& operator=(const ref_count_ptr& in_ptr) { return *this = in_ptr.reference_; } template ref_count_ptr& operator=(const ref_count_ptr& in_ptr) { return *this = in_ptr.GetReference(); } ref_count_ptr& operator=(ref_count_ptr&& in_ptr) noexcept { if (this != &in_ptr) { ReferencedType* old_reference = reference_; reference_ = in_ptr.reference_; in_ptr.reference_ = nullptr; if(old_reference) { old_reference->Release(); } } return *this; } template ref_count_ptr& operator=(ref_count_ptr&& in_ptr) { // InPtr is a different type (or we would have called the other operator), so we need not test &InPtr != this ReferencedType* old_reference = reference_; reference_ = in_ptr.reference_; in_ptr.reference_ = nullptr; if (old_reference) { old_reference->Release(); } return *this; } ReferencedType* operator->() const { return reference_; } operator reference_type() const { return reference_; } ReferencedType** get_init_reference() { *this = nullptr; return &reference_; } ReferencedType* get_reference() const { return reference_; } friend bool is_valid_ref(const ref_count_ptr& in_reference) { return in_reference.reference_ != nullptr; } bool is_valid() const { return reference_ != nullptr; } void safe_release() { *this = nullptr; } unsigned int get_ref_count() { unsigned int result = 0; if (reference_) { result = reference_->GetRefCount(); assert(result > 0); // you should never have a zero ref count if there is a live ref counted pointer (*this is live) } return result; } void swap(ref_count_ptr& in_ptr) noexcept // this does not change the reference count, and so is faster { ReferencedType* old_reference = reference_; reference_ = in_ptr.reference_; in_ptr.reference_ = old_reference; } // void Serialize(FArchive& Ar) // { // reference_type PtrReference = Reference; // Ar << PtrReference; // if(Ar.IsLoading()) // { // *this = PtrReference; // } // } private: ReferencedType* reference_; template friend class ref_count_ptr; public: bool operator==(const ref_count_ptr& b) const { return get_reference() == b.get_reference(); } bool operator==(ReferencedType* b) const { return get_reference() == b; } };