changeset 7296:75a41d83dd01 draft

(svn r10644) -Merge (from NoAI): framework for reference counted objects (pointers).
author rubidium <rubidium@openttd.org>
date Fri, 20 Jul 2007 18:44:04 +0000
parents 9a2cabefad4d
children 2d5412e07b5e
files src/misc/autoptr.hpp src/misc/countedobj.cpp src/misc/countedptr.hpp
diffstat 3 files changed, 133 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/src/misc/autoptr.hpp
+++ b/src/misc/autoptr.hpp
@@ -38,8 +38,9 @@
 	FORCEINLINE ~AutoPtrT()
 	{
 		if (m_p != NULL) {
-			delete m_p;
+			T *p = m_p;
 			m_p = NULL;
+			delete p;
 		}
 	}
 
new file mode 100644
--- /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;
+}
+
--- 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 @@
 
 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 @@
 	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 @@
 	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 @@
 	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 @@
 	}
 }
 
-#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<CCountedPtr<MyType> >)
+ */
+template <class T> 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<T>.
+ *
+ *  @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 */