From 5083f22d1ddddd355d75a3d720fc2f5a3acd12a5 Mon Sep 17 00:00:00 2001 From: rubidium Date: Fri, 20 Jul 2007 18:44:04 +0000 Subject: (svn r10644) -Merge (from NoAI): framework for reference counted objects (pointers). --- src/misc/autoptr.hpp | 3 ++- src/misc/countedobj.cpp | 66 +++++++++++++++++++++++++++++++++++++++++++++ src/misc/countedptr.hpp | 72 ++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 133 insertions(+), 8 deletions(-) create mode 100644 src/misc/countedobj.cpp diff --git a/src/misc/autoptr.hpp b/src/misc/autoptr.hpp index 08516d2ea..3719a51f1 100644 --- a/src/misc/autoptr.hpp +++ b/src/misc/autoptr.hpp @@ -38,8 +38,9 @@ public: FORCEINLINE ~AutoPtrT() { if (m_p != NULL) { - delete m_p; + T *p = m_p; m_p = NULL; + delete p; } } diff --git a/src/misc/countedobj.cpp b/src/misc/countedobj.cpp new file mode 100644 index 000000000..a96537977 --- /dev/null +++ b/src/misc/countedobj.cpp @@ -0,0 +1,66 @@ +/* $Id$ */ + +#include "../stdafx.h" + +#include "countedptr.hpp" + +int32 SimpleCountedObject::AddRef() +{ + return ++m_ref_cnt; +} + +int32 SimpleCountedObject::Release() +{ + int32 res = --m_ref_cnt; + assert(res >= 0); + if (res == 0) { + FinalRelease(); + delete this; + } + return res; +} + +/* $Id$ */ + +#include "../stdafx.h" + +#include "countedptr.hpp" + +int32 SimpleCountedObject::AddRef() +{ + return ++m_ref_cnt; +} + +int32 SimpleCountedObject::Release() +{ + int32 res = --m_ref_cnt; + assert(res >= 0); + if (res == 0) { + FinalRelease(); + delete this; + } + return res; +} + +/* $Id$ */ + +#include "../stdafx.h" + +#include "countedptr.hpp" + +int32 SimpleCountedObject::AddRef() +{ + return ++m_ref_cnt; +} + +int32 SimpleCountedObject::Release() +{ + int32 res = --m_ref_cnt; + assert(res >= 0); + if (res == 0) { + FinalRelease(); + delete this; + } + return res; +} + diff --git a/src/misc/countedptr.hpp b/src/misc/countedptr.hpp index 0d6a925b8..e3920e49a 100644 --- a/src/misc/countedptr.hpp +++ b/src/misc/countedptr.hpp @@ -5,7 +5,6 @@ #ifndef COUNTEDPTR_HPP #define COUNTEDPTR_HPP -#if 0 // reenable when needed /** @file CCountedPtr - smart pointer implementation */ /** CCountedPtr - simple reference counting smart pointer. @@ -44,7 +43,7 @@ protected: public: /** release smart pointer (and decrement ref count) if not null */ - FORCEINLINE void Release() {if (m_pT != NULL) {m_pT->Release(); m_pT = NULL;}} + FORCEINLINE void Release() {if (m_pT != NULL) {Tcls* pT = m_pT; m_pT = NULL; pT->Release();}} /** dereference of smart pointer - const way */ FORCEINLINE const Tcls* operator -> () const {assert(m_pT != NULL); return m_pT;}; @@ -56,7 +55,7 @@ public: FORCEINLINE operator const Tcls*() const {assert(m_pT == NULL); return m_pT;} /** raw pointer casting operator - non-const way */ - FORCEINLINE operator Tcls*() {assert(m_pT == NULL); return m_pT;} + FORCEINLINE operator Tcls*() {return m_pT;} /** operator & to support output arguments */ FORCEINLINE Tcls** operator &() {assert(m_pT == NULL); return &m_pT;} @@ -65,7 +64,7 @@ public: FORCEINLINE CCountedPtr& operator = (Tcls* pT) {Assign(pT); return *this;} /** assignment operator from another smart ptr */ - FORCEINLINE CCountedPtr& operator = (CCountedPtr& src) {Assign(src.m_pT); return *this;} + FORCEINLINE CCountedPtr& operator = (const CCountedPtr& src) {Assign(src.m_pT); return *this;} /** assignment operator helper */ FORCEINLINE void Assign(Tcls* pT); @@ -74,10 +73,10 @@ public: FORCEINLINE bool IsNull() const {return m_pT == NULL;} /** another way how to test for NULL value */ - FORCEINLINE bool operator == (const CCountedPtr& sp) const {return m_pT == sp.m_pT;} + //FORCEINLINE bool operator == (const CCountedPtr& sp) const {return m_pT == sp.m_pT;} /** yet another way how to test for NULL value */ - FORCEINLINE bool operator != (const CCountedPtr& sp) const {return m_pT != sp.m_pT;} + //FORCEINLINE bool operator != (const CCountedPtr& sp) const {return m_pT != sp.m_pT;} /** assign pointer w/o incrementing ref count */ FORCEINLINE void Attach(Tcls* pT) {Release(); m_pT = pT;} @@ -98,5 +97,64 @@ FORCEINLINE void CCountedPtr::Assign(Tcls* pT) } } -#endif /* 0 */ +/** + * Adapter wrapper for CCountedPtr like classes that can't be used directly by stl + * collections as item type. For example CCountedPtr has overloaded operator & which + * prevents using CCountedPtr in stl collections (i.e. std::list >) + */ +template struct AdaptT { + T m_t; + + /** construct by wrapping the given object */ + AdaptT(const T &t) + : m_t(t) + {} + + /** assignment operator */ + T& operator = (const T &t) + { + m_t = t; + return t; + } + + /** type-cast operator (used when AdaptT is used instead of T) */ + operator T& () + { + return m_t; + } + + /** const type-cast operator (used when AdaptT is used instead of const T) */ + operator const T& () const + { + return m_t; + } +}; + + +/** Simple counted object. Use it as base of your struct/class if you want to use + * basic reference counting. Your struct/class will destroy and free itself when + * last reference to it is released (using Relese() method). The initial reference + * count (when it is created) is zero (don't forget AddRef() at least one time if + * not using CCountedPtr. + * + * @see misc/countedobj.cpp for implementation. + */ +struct SimpleCountedObject { + int32 m_ref_cnt; + + SimpleCountedObject() + : m_ref_cnt(0) + {} + + virtual ~SimpleCountedObject() + {}; + + virtual int32 AddRef(); + virtual int32 Release(); + virtual void FinalRelease() {}; +}; + + + + #endif /* COUNTEDPTR_HPP */ -- cgit v1.2.3-54-g00ecf