00001 #ifndef __loaded__reference_count_h__ 00002 #define __loaded__reference_count_h__ 00003 using namespace std; 00004 #line 1 "reference-count.h++" 00005 #include <assert.h> 00006 #ifndef SINGLE_THREADED 00007 #include "cmpxchg.h" 00008 #endif 00009 00018 //#define SINGLE_THREADED 00019 class ReferenceCount 00020 { 00021 public: 00026 volatile int reference_count; 00027 ReferenceCount(): reference_count(0) 00028 { 00029 } 00030 ReferenceCount(const ReferenceCount&): reference_count(0) 00031 { 00032 } 00033 ReferenceCount& operator =(const ReferenceCount& o) 00034 { 00035 assert(&o!=this); 00036 reference_count=0; 00037 return *this; 00038 } 00042 void incref() 00043 { 00044 #ifdef SINGLE_THREADED 00045 assert(reference_count>=0); 00046 reference_count++; 00047 #else 00048 int before; 00049 do 00050 { 00051 before = reference_count; 00052 } 00053 while(cmpxchg(&reference_count,before,before+1)!=before); 00054 assert(before>=0); 00055 #endif 00056 } 00060 int decref() 00061 { 00062 #ifdef SINGLE_THREADED 00063 return --reference_count; 00064 #else 00065 int before; 00066 do 00067 { 00068 before = reference_count; 00069 } 00070 while(cmpxchg(&reference_count,before,before-1)!=before); 00071 return before-1; 00072 #endif 00073 } 00078 virtual ~ReferenceCount() 00079 { 00080 assert(reference_count==-1); 00081 } 00082 }; 00083 00088 template <class ReferenceCountedObject> 00089 class Smart 00090 { 00091 public: 00092 ReferenceCountedObject* ptr; 00093 void incref() const 00094 { 00095 if (ptr) 00096 ptr->incref(); 00097 } 00111 void decref() const 00112 { 00113 if (ptr && ptr->decref()==0) 00114 { 00115 ptr->decref(); 00116 delete ptr; 00117 } 00118 } 00119 public: 00120 explicit Smart(ReferenceCountedObject* p = 0) : ptr(p) 00121 { 00122 incref(); 00123 } 00124 Smart(const Smart<ReferenceCountedObject>& o) : ptr(o.ptr) 00125 { 00126 incref(); 00127 } 00128 Smart<ReferenceCountedObject>& operator=(const Smart<ReferenceCountedObject>&o) 00129 { 00130 o.incref(); 00131 decref(); 00132 ptr=o.ptr; 00133 return *this; 00134 } 00135 template <class AnotherReferenceCountedObject> 00136 Smart<ReferenceCountedObject>& operator=(const Smart<AnotherReferenceCountedObject>&o) 00137 { 00138 o.incref(); 00139 decref(); 00140 ptr=(ReferenceCountedObject*)o.ptr; 00141 return *this; 00142 } 00143 00144 bool operator==(const Smart<ReferenceCountedObject>&o) const 00145 { 00146 return ptr==o.ptr; 00147 } 00148 bool operator!=(const Smart<ReferenceCountedObject>&o) const 00149 { 00150 return ptr!=o.ptr; 00151 } 00152 bool operator<(const Smart<ReferenceCountedObject>&o) const 00153 { 00154 return ptr<o.ptr; 00155 } 00156 bool operator<=(const Smart<ReferenceCountedObject>&o) const 00157 { 00158 return ptr<=o.ptr; 00159 } 00160 bool operator>=(const Smart<ReferenceCountedObject>&o) const 00161 { 00162 return ptr>=o.ptr; 00163 } 00164 ~Smart() 00165 { 00166 decref(); 00167 } 00168 ReferenceCountedObject& operator*() 00169 { 00170 return *ptr; 00171 } 00172 ReferenceCountedObject* operator->() 00173 { 00174 return ptr; 00175 } 00176 operator bool() 00177 { 00178 return ptr; 00179 } 00180 template <class AnotherReferenceCountedObject> 00181 operator Smart<AnotherReferenceCountedObject>() 00182 { 00183 return Smart<AnotherReferenceCountedObject>((AnotherReferenceCountedObject*)ptr); 00184 } 00185 }; 00186 #endif // __loaded__reference_count_h__