/* ** Command & Conquer Renegade(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ /****************************************************************************** * * FILE * $Archive: /Commando/Code/WWOnline/RefPtr.h $ * * DESCRIPTION * RefPtr<> and RefPtrConst<> are const-friendly, polymorphic reference * counting smart pointers. * * The pointed-to class must be derived from RefCount. * * RefPtr replaces X* * RefPtrConst replaces const X* * * Dynamic_Cast replaces dynamic_cast and dynamic_cast * Reinterpret_Cast replaces reinterpret_cast and reinterpret_cast * Const_Cast replaces const_cast and const_cast * * IsValid() replaces (x != NULL) * * Member function Attach() or assigning RefPtr() will NULL a pointer. * * Generally, RefPtr<> and RefPtrConst<> behave like their raw pointer * counterparts, except of course they are reference counted and will delete * the pointed-to object when the last reference is lost. The major * syntatical differences are the use of RefPtrConst<> to represent a pointer * to a constant object (I found it impossible to represent this within rc_ptr) * and the use of the upper-case cast functions (it is not possible to overload * these built-in functions). * * An explicit goal of this class is to completely avoid the "new" and "delete" * operators in client code. The constructors for these pointers are private; * they are friends of the pointed-to class. This forces the use of Factory * Method functions (or similar) in the pointed-to class. Pointed-to classes * should make the constructor protected or private to disallow clients from * creating an instance with "new". If this is done, it becomes very difficult * for the client to accidentally leak objects and/or misuse the pointed-to * class or the reference counting pointers. * * PROGRAMMER * Steven Clinard * $Author: Denzil_l $ * * VERSION INFO * $Modtime: 7/06/01 4:23p $ * $Revision: 1 $ * ******************************************************************************/ #ifndef __REFPTR_H__ #define __REFPTR_H__ #include "RefCounted.h" #include #include template class RefPtr; template class RefPtrConst; class RefPtrBase { public: inline bool operator==(const RefPtrBase& rhs) const {return (mRefObject == rhs.mRefObject);} inline bool operator!=(const RefPtrBase& rhs) const {return !operator==(rhs);} inline bool IsValid(void) const {return (mRefObject != NULL);} inline void Release(void) { if (IsValid()) { mRefObject->ReleaseReference(); mRefObject = NULL; } } protected: RefPtrBase() : mRefObject(NULL) {} RefPtrBase(RefCounted* object) : mRefObject(object) { assert((mRefObject == NULL) || (mRefObject->ReferenceCount() == 0)); if (IsValid()) { mRefObject->AddReference(); } } RefPtrBase(const RefPtrBase& object) : mRefObject(object.mRefObject) { assert(!"RefPtrBase(const RefPtrBase&) - Why is this being called?"); if (IsValid()) { mRefObject->AddReference(); } } virtual ~RefPtrBase() {Release();} const RefPtrBase& operator=(const RefPtrBase&); inline RefCounted* const GetRefObject(void) {return mRefObject;} inline const RefCounted* const GetRefObject(void) const {return mRefObject;} inline void Attach(RefCounted* object) { // If objects are different if (object != mRefObject) { // Add reference to new object if (object != NULL) { object->AddReference(); } // Release reference to old object Release(); // Assign new object mRefObject = object; } } private: RefCounted* mRefObject; template friend RefPtr Dynamic_Cast(RefPtrBase&); template friend RefPtr Reinterpret_Cast(RefPtrBase&); }; template class RefPtr : public RefPtrBase { public: RefPtr() : RefPtrBase() {} template RefPtr(const RefPtr& derived) : RefPtrBase() { Attach(static_cast(const_cast(derived.ReferencedObject()))); } RefPtr(const RefPtr& object) : RefPtrBase() { Attach(static_cast(const_cast(object.ReferencedObject()))); } virtual ~RefPtr() {} template inline const RefPtr& operator=(const RefPtr& derived) { Attach(static_cast(const_cast(derived.ReferencedObject()))); return *this; } inline const RefPtr& operator=(const RefPtr& object) { Attach(static_cast(const_cast(object.ReferencedObject()))); return *this; } inline Type& operator*() const { assert(IsValid()); return *const_cast(ReferencedObject()); } inline Type* const operator->() const { assert(IsValid()); return const_cast(ReferencedObject()); } // Template function for implicit conversion ops template inline operator RefPtr() {return RefPtr(GetRefObject());} // These are public mostly because I can't seem to declare rc_ptr as a friend inline Type* const ReferencedObject(void) {return reinterpret_cast(GetRefObject());} inline const Type* const ReferencedObject(void) const {return reinterpret_cast(GetRefObject());} RefPtr(Type* object) : RefPtrBase() { Attach(static_cast(object)); } inline const RefPtr& operator=(Type* object) { Attach(static_cast(object)); return *this; } private: friend RefPtr Dynamic_Cast(RefPtrBase&); friend RefPtr Reinterpret_Cast(RefPtrBase&); friend RefPtr Const_Cast(RefPtrConst&); }; template class RefPtrConst : public RefPtrBase { public: RefPtrConst() : RefPtrConst() {} template RefPtrConst(const RefPtr& derived) : RefPtrBase() { Attach(static_cast(derived.ReferencedObject())); } RefPtrConst(const RefPtr& object) : RefPtrBase() { Attach(static_cast(const_cast(object.ReferencedObject()))); } template RefPtrConst(const RefPtrConst& derived) : RefPtrBase() { Attach(static_cast(derived.ReferencedObject())); } RefPtrConst(const RefPtrConst& object) : RefPtrBase() { Attach(static_cast(object.ReferencedObject())); } template inline const RefPtrConst& operator=(const RefPtr& derived) { Attach(static_cast(derived.ReferencedObject())); return *this; } inline const RefPtrConst& operator=(const RefPtr& object) { Attach(static_cast(object.ReferencedObject())); return *this; } template inline const RefPtrConst& operator=(const RefPtrConst& derived) { Attach(static_cast(derived.ReferencedObject())); return *this; } inline const RefPtrConst& operator=(const RefPtrConst& object) { Attach(static_cast(object.ReferencedObject())); return *this; } virtual ~RefPtrConst() {} inline const Type& operator*() const { assert(IsValid()); return *ReferencedObject(); } inline const Type* const operator->() const { assert(IsValid()); return ReferencedObject(); } // This is public mostly because I can't seem to declare rc_ptr as a friend inline const Type* const ReferencedObject() const {return reinterpret_cast(GetRefObject());} RefPtrConst(const Type* object) : RefPtrBase() { Attach(static_cast(object)); } const RefPtrConst& operator=(const Type* object) { Attach(static_cast(object)); } }; template RefPtr Dynamic_Cast(RefPtrBase& base) { RefPtr derived; derived.Attach(base.GetRefObject()); return derived; } template RefPtr Reinterpret_Cast(RefPtrBase& rhs) { RefPtr object; object.Attach(rhs.GetRefObject()); return object; } template RefPtr Const_Cast(RefPtrConst& rhs) { RefPtr object; object.Attach(static_cast(rhs.ReferencedObject())); return object; } #endif // __REFPTR_H__