00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef CXXTOOLS_SMARTPTR_H
00030 #define CXXTOOLS_SMARTPTR_H
00031
00032 #include <cxxtools/atomicity.h>
00033
00034 namespace cxxtools
00035 {
00036 template <typename objectType>
00037 class RefLinked
00038 {
00039 mutable const RefLinked* prev;
00040 mutable const RefLinked* next;
00041
00042 protected:
00043 RefLinked()
00044 : prev(0),
00045 next(0)
00046 { }
00047
00048 bool unlink(objectType* object)
00049 {
00050 bool ret = false;
00051 if (object)
00052 {
00053 if (next == this)
00054 {
00055 ret = true;
00056 }
00057 else
00058 {
00059 next->prev = prev;
00060 prev->next = next;
00061 }
00062 next = prev = this;
00063 }
00064 return ret;
00065 }
00066
00067 void link(const RefLinked& ptr, objectType* object)
00068 {
00069 if (object)
00070 {
00071 prev = &ptr;
00072 next = ptr.next;
00073 prev->next = this;
00074 next->prev = this;
00075 }
00076 }
00077 };
00078
00079 template <typename objectType>
00080 class InternalRefCounted
00081 {
00082 protected:
00083 bool unlink(objectType* object)
00084 {
00085 if (object)
00086 object->release();
00087 return false;
00088 }
00089
00090 void link(const InternalRefCounted& ptr, objectType* object)
00091 {
00092 if (object)
00093 object->addRef();
00094 }
00095
00096 };
00097
00098 template <typename objectType>
00099 class ExternalRefCounted
00100 {
00101 unsigned* rc;
00102
00103 protected:
00104 ExternalRefCounted()
00105 : rc(0) { }
00106
00107 bool unlink(objectType* object)
00108 {
00109 if (object && --*rc <= 0)
00110 {
00111 delete rc;
00112
00113
00114 return true;
00115 }
00116 else
00117 return false;
00118 }
00119
00120 void link(const ExternalRefCounted& ptr, objectType* object)
00121 {
00122 if (object)
00123 {
00124 if (ptr.rc == 0)
00125 rc = new unsigned(1);
00126 else
00127 {
00128 rc = ptr.rc;
00129 ++*rc;
00130 }
00131 }
00132 else
00133 rc = 0;
00134 }
00135
00136 public:
00137 unsigned refs() const
00138 { return rc ? *rc : 0; }
00139 };
00140
00141 template <typename objectType>
00142 class ExternalAtomicRefCounted
00143 {
00144 volatile atomic_t* rc;
00145
00146 protected:
00147 ExternalAtomicRefCounted()
00148 : rc(0) { }
00149
00150 bool unlink(objectType* object)
00151 {
00152 if (object && atomicDecrement(*rc) <= 0)
00153 {
00154 delete rc;
00155
00156
00157 return true;
00158 }
00159 else
00160 return false;
00161 }
00162
00163 void link(const ExternalAtomicRefCounted& ptr, objectType* object)
00164 {
00165 if (object)
00166 {
00167 if (ptr.rc == 0)
00168 rc = new atomic_t(1);
00169 else
00170 {
00171 rc = ptr.rc;
00172 atomicIncrement(*rc);
00173 }
00174 }
00175 else
00176 rc = 0;
00177 }
00178
00179 public:
00180 atomic_t refs() const
00181 { return rc ? *rc : 0; }
00182 };
00183
00184 template <typename objectType>
00185 class DefaultDestroyPolicy
00186 {
00187 public:
00188 static void destroy(objectType* ptr)
00189 { delete ptr; }
00190 };
00191
00192 template <typename T>
00193 class FreeDestroyPolicy
00194 {
00195 protected:
00196 void destroy(T* ptr)
00197 { free(ptr); }
00198 };
00199
00200 template <typename objectType>
00201 class ArrayDestroyPolicy
00202 {
00203 public:
00204 static void destroy(objectType* ptr)
00205 { delete[] ptr; }
00206 };
00207
00230 template <typename objectType,
00231 template <class> class ownershipPolicy = InternalRefCounted,
00232 template <class> class destroyPolicy = DefaultDestroyPolicy>
00233 class SmartPtr : public ownershipPolicy<objectType>,
00234 public destroyPolicy<objectType>
00235 {
00236 objectType* object;
00237 typedef ownershipPolicy<objectType> ownershipPolicyType;
00238 typedef destroyPolicy<objectType> destroyPolicyType;
00239
00240 public:
00241 SmartPtr()
00242 : object(0)
00243 {}
00244 SmartPtr(objectType* ptr)
00245 : object(ptr)
00246 { ownershipPolicyType::link(*this, ptr); }
00247 SmartPtr(const SmartPtr& ptr)
00248 : object(ptr.object)
00249 { ownershipPolicyType::link(ptr, ptr.object); }
00250 ~SmartPtr()
00251 { if (ownershipPolicyType::unlink(object))
00252 destroy(object); }
00253
00254 SmartPtr& operator= (const SmartPtr& ptr)
00255 {
00256 if (object != ptr.object)
00257 {
00258 if (ownershipPolicyType::unlink(object))
00259 destroy(object);
00260
00261 object = ptr.object;
00262
00263 ownershipPolicyType::link(ptr, object);
00264 }
00265 return *this;
00266 }
00267
00269 objectType* operator->() const { return object; }
00271 objectType& operator*() const { return *object; }
00272
00273 bool operator== (const objectType* p) const { return object == p; }
00274 bool operator!= (const objectType* p) const { return object != p; }
00275 bool operator< (const objectType* p) const { return object < p; }
00276 bool operator! () const { return object == 0; }
00277 operator bool () const { return object != 0; }
00278
00279 objectType* getPointer() { return object; }
00280 const objectType* getPointer() const { return object; }
00281 operator objectType* () { return object; }
00282 operator const objectType* () const { return object; }
00283 };
00284
00285 }
00286
00287 #endif // CXXTOOLS_SMARTPTR_H
00288