src/foundation/ZRefCount.h

00001 /*  @(#) $Id: ZRefCount.h,v 1.14 2006/10/16 03:20:44 agreen Exp $ */
00002 
00003 /* ------------------------------------------------------------
00004 Copyright (c) 2000 Andrew Green and Learning in Motion, Inc.
00005 http://www.zoolib.org
00006 
00007 Permission is hereby granted, free of charge, to any person obtaining a copy
00008 of this software and associated documentation files (the "Software"), to deal
00009 in the Software without restriction, including without limitation the rights
00010 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00011 copies of the Software, and to permit persons to whom the Software is
00012 furnished to do so, subject to the following conditions:
00013 
00014 The above copyright notice and this permission notice shall be included in
00015 all copies or substantial portions of the Software.
00016 
00017 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00018 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00020 COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00021 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00022 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00023 ------------------------------------------------------------ */
00024 
00025 #ifndef __ZRefCount__
00026 #define __ZRefCount__ 1
00027 #include "zconfig.h"
00028 
00029 #include "ZDebug.h"
00030 #include "ZThread.h" // For ZThreadSafe_Get, ZThreadSafe_Inc && ZThreadSafe_DecAndTest
00031 
00032 #include "ZCompat_operator_bool.h"
00033 
00034 /*
00035 Checked/slow versus unchecked/fast access to refcounted objects can be enabled
00036 on a class by class basis. Simply declare/define in your class a method thus:
00037 
00038   static inline bool sCheckAccessEnabled() { return true; }
00039 
00040 Have it return true if access checks should be made when using ZRefs to instances
00041 of this class, or false if not.
00042 
00043 The implementations provided by ZRefCounted and ZRefCountedWithFinalization return
00044 whatever is #defined in ZCONFIG_RefCount_CheckAccessDefault. If no definition of
00045 ZCONFIG_RefCount_CheckAccessDefault exists then this file defines it to be true if
00046 ZCONFIG_Debug is greater than zero. So for debug builds we default to checked access, and
00047 for non-debug builds we default to unchecked access.
00048 
00049 NB The method must be declared public, otherwise ZRef<> will not be able to access it.
00050 */
00051 
00052 #ifndef ZCONFIG_RefCount_CheckAccessDefault
00053 #       define ZCONFIG_RefCount_CheckAccessDefault (ZCONFIG_Debug > 0)
00054 #endif
00055 
00056 // =================================================================================================
00057 #pragma mark -
00058 #pragma mark * ZRefCounted
00059 
00060 class ZRefCounted
00061         {
00062 public:
00063         ZRefCounted() { ZThreadSafe_Set(fRefCount, 0); }
00064         virtual ~ZRefCounted();
00065 
00066         int GetRefCount() const { return ZThreadSafe_Get(fRefCount); }
00067 
00068         static void sIncRefCount(ZRefCounted* iObject)
00069                 {
00070                 if (iObject)
00071                         ZThreadSafe_Inc(iObject->fRefCount);
00072                 }
00073         static void sDecRefCount(ZRefCounted* iObject)
00074                 {
00075                 if (iObject && ZThreadSafe_DecAndTest(iObject->fRefCount))
00076                         delete iObject;
00077                 }
00078 
00079         static void sCheckAccess(ZRefCounted* iObject);
00080 
00081         static bool sCheckAccessEnabled() { return ZCONFIG_RefCount_CheckAccessDefault; }
00082 
00083 private:
00084         ZThreadSafe_t fRefCount;
00085         };
00086 
00087 // =================================================================================================
00088 #pragma mark -
00089 #pragma mark * ZRefCountedWithFinalization
00090 
00091 class ZRefCountedWithFinalization
00092         {
00093 public:
00094         ZRefCountedWithFinalization() { ZThreadSafe_Set(fRefCount, 0); }
00095         virtual ~ZRefCountedWithFinalization();
00096 
00097         int GetRefCount() const { return ZThreadSafe_Get(fRefCount); }
00098 
00099         virtual void Initialize();
00100 
00101         virtual void Finalize();
00102 
00103         void FinalizationComplete();
00104 
00105         static void sIncRefCount(ZRefCountedWithFinalization* iObject)
00106                 {
00107                 if (iObject && 0 == ZThreadSafe_IncReturnOld(iObject->fRefCount))
00108                         iObject->Initialize();
00109                 }
00110 
00111         static void sDecRefCount(ZRefCountedWithFinalization* iObject);
00112 
00113         static void sCheckAccess(ZRefCountedWithFinalization* iObject);
00114 
00115         static bool sCheckAccessEnabled() { return ZCONFIG_RefCount_CheckAccessDefault; }
00116 
00117 private:
00118         ZThreadSafe_t fRefCount;
00119         };
00120 
00121 // =================================================================================================
00122 #pragma mark -
00123 #pragma mark * ZRef declaration
00124 
00125 template <class S> class ZRefSafe;
00126 
00127 template <class T>
00128 class ZRef
00129         {
00130 private:
00131     ZOOLIB_DEFINE_OPERATOR_BOOL_TYPES_T(ZRef<T>,
00132         operator_bool_generator_type, operator_bool_type);
00133 
00134 public:
00135         ZRef();
00136         ~ZRef();
00137 
00138         ZRef(T* iObject);
00139         ZRef& operator=(T* iObject);
00140         bool operator==(const T* iObject) const;
00141         bool operator!=(const T* iObject) const;
00142 
00143         ZRef(const ZRef& iOther);
00144         ZRef& operator=(const ZRef& iOther);
00145         bool operator==(const ZRef& iOther) const;
00146         bool operator!=(const ZRef& iOther) const;
00147 
00148         template <class O> ZRef(const ZRef<O>& iOther);
00149         template <class O> ZRef& operator=(const ZRef<O>& iOther);
00150         template <class O> bool operator==(const ZRef<O>& iOther) const;
00151         template <class O> bool operator!=(const ZRef<O>& iOther) const;
00152         template <class O> bool operator<(const ZRef<O>& iOther) const;
00153 
00154         template <class S> ZRef(const ZRefSafe<S>& iOther);
00155         template <class S> ZRef& operator=(const ZRefSafe<S>& iOther);
00156 
00157         T* operator->() const;
00158 
00159         operator operator_bool_type() const
00160                 { return operator_bool_generator_type::translate(fObject); }
00161 
00162         void Clear();
00163 
00164         T* GetObject() const { return fObject; }
00165 
00166         void swap(ZRef& iOther) { std::swap(fObject, iOther.fObject); }
00167 
00168 private:
00169         T* fObject;
00170         };
00171 
00172 // =================================================================================================
00173 #pragma mark -
00174 #pragma mark * ZRefSafe declaration
00175 
00176 template <class S>
00177 class ZRefSafe
00178         {
00179     ZOOLIB_DEFINE_OPERATOR_BOOL_TYPES_T(ZRefSafe<S>,
00180         operator_bool_generator_type, operator_bool_type);
00181 
00182         ZRefSafe(const ZRefSafe&); // Not implemented
00183         const ZRefSafe& operator=(const ZRefSafe&); // Not implemented
00184 public:
00185         ZRefSafe();
00186         ~ZRefSafe();
00187 
00188         ZRefSafe(S* iObject);
00189         ZRefSafe& operator=(S* iObject);
00190 
00191         template <class T> ZRefSafe(const ZRef<T>& iOther);
00192         template <class T> ZRefSafe& operator=(const ZRef<T>& iOther);
00193 
00194         operator operator_bool_type() const
00195                 { return operator_bool_generator_type::translate(fObject); }
00196 
00197         S* GetObject() const { return fObject; }
00198 
00199         void Acquire() const { fMutex.Acquire(); }
00200         void Release() const { fMutex.Release(); }
00201 
00202 private:
00203         mutable ZMutexNR fMutex;
00204         S* fObject;
00205         };
00206 
00207 // =================================================================================================
00208 #pragma mark -
00209 #pragma mark * ZRef inline definitions
00210 
00211 namespace std {
00212 template <class T>
00213 inline void swap(ZRef<T>& a, ZRef<T>& b)
00214         { a.swap(b); }
00215 }
00216 
00217 template <class T>
00218 inline ZRef<T>::ZRef()
00219 :       fObject(nil)
00220         {}
00221 
00222 template <class T>
00223 inline ZRef<T>::~ZRef()
00224         {
00225         T::sDecRefCount(fObject);
00226         }
00227 
00228 template <class T>
00229 inline ZRef<T>::ZRef(T* iObject)
00230 :       fObject(iObject)
00231         {
00232         T::sIncRefCount(fObject);
00233         }
00234 
00235 template <class T>
00236 inline ZRef<T>& ZRef<T>::operator=(T* iObject)
00237         {
00238         T::sIncRefCount(iObject);
00239         T::sDecRefCount(fObject);
00240         fObject = iObject;
00241         return *this;
00242         }
00243 
00244 template <class T>
00245 inline bool ZRef<T>::operator==(const T* iObject) const
00246         { return fObject == iObject; }
00247 
00248 template <class T>
00249 inline bool ZRef<T>::operator!=(const T* iObject) const
00250         { return fObject != iObject; }
00251 
00252 template <class T>
00253 inline ZRef<T>::ZRef(const ZRef& iOther)
00254 :       fObject(iOther.GetObject())
00255         {
00256         T::sIncRefCount(fObject);
00257         }
00258 
00259 template <class T>
00260 inline ZRef<T>& ZRef<T>::operator=(const ZRef& iOther)
00261         {
00262         T::sIncRefCount(iOther.GetObject());
00263         T::sDecRefCount(fObject);
00264         fObject = iOther.GetObject();
00265         return *this;
00266         }
00267 
00268 template <class T>
00269 inline bool ZRef<T>::operator==(const ZRef& iOther) const
00270         { return fObject == iOther.GetObject(); }
00271 
00272 template <class T>
00273 inline bool ZRef<T>::operator!=(const ZRef& iOther) const
00274         { return fObject != iOther.GetObject(); }
00275 
00276 template <class T> template <class O>
00277 inline ZRef<T>::ZRef(const ZRef<O>& iOther)
00278 :       fObject(iOther.GetObject())
00279         {
00280         T::sIncRefCount(fObject);
00281         }
00282 
00283 template <class T> template <class O>
00284 inline ZRef<T>& ZRef<T>::operator=(const ZRef<O>& iOther)
00285         {
00286         O::sIncRefCount(iOther.GetObject());
00287         T::sDecRefCount(fObject);
00288         fObject = iOther.GetObject();
00289         return *this;
00290         }
00291 
00292 template <class T> template <class O>
00293 inline bool ZRef<T>::operator==(const ZRef<O>& iOther) const
00294         { return fObject == iOther.GetObject(); }
00295 
00296 template <class T> template <class O>
00297 inline bool ZRef<T>::operator!=(const ZRef<O>& iOther) const
00298         { return fObject != iOther.GetObject(); }
00299 
00300 template <class T> template <class O>
00301 inline bool ZRef<T>::operator<(const ZRef<O>& iOther) const
00302         { return fObject < iOther.GetObject(); }
00303 
00304 template <class T> template <class S>
00305 ZRef<T>::ZRef(const ZRefSafe<S>& iOther)
00306         {
00307         iOther.Acquire();
00308         fObject = iOther.GetObject();
00309         T::sIncRefCount(fObject);
00310         iOther.Release();
00311         }
00312 
00313 template <class T> template <class S>
00314 ZRef<T>& ZRef<T>::operator=(const ZRefSafe<S>& iOther)
00315         {
00316         iOther.Acquire();
00317         T* temp = iOther.GetObject();
00318         S::sIncRefCount(temp);
00319         iOther.Release();
00320 
00321         T::sDecRefCount(fObject);
00322         fObject = temp;
00323         }
00324 
00325 template <class T>
00326 inline T* ZRef<T>::operator->() const
00327         {
00328         if (T::sCheckAccessEnabled())
00329                 T::sCheckAccess(fObject);
00330         return fObject;
00331         }
00332 
00333 template <class T>
00334 inline void ZRef<T>::Clear()
00335         {
00336         T::sDecRefCount(fObject);
00337         fObject = nil;
00338         }
00339 
00340 // =================================================================================================
00341 #pragma mark -
00342 #pragma mark * ZRefSafe inline definitions
00343 
00344 template <class S>
00345 inline ZRefSafe<S>::ZRefSafe()
00346 :       fObject(nil)
00347         {}
00348 
00349 template <class S>
00350 inline ZRefSafe<S>::~ZRefSafe()
00351         {
00352         S::sDecRefCount(fObject);
00353         }
00354 
00355 template <class S>
00356 inline ZRefSafe<S>::ZRefSafe(S* iObject)
00357 :       fObject(iObject)
00358         {
00359         S::sIncRefCount(iObject);
00360         }
00361 
00362 template <class S>
00363 inline ZRefSafe<S>& ZRefSafe<S>::operator=(S* iObject)
00364         {
00365         S::sIncRefCount(iObject);
00366 
00367         fMutex.Acquire();
00368         S* temp = fObject;
00369         fObject = iObject;
00370         fMutex.Release();
00371 
00372         S::sDecRefCount(temp);
00373         return *this;
00374         }
00375 
00376 template <class S> template <class T>
00377 inline ZRefSafe<S>::ZRefSafe(const ZRef<T>& iOther)
00378 :       fObject(iOther.GetObject())
00379         {
00380         S::sIncRefCount(fObject);
00381         }
00382 
00383 template<class S> template <class T>
00384 inline ZRefSafe<S>& ZRefSafe<S>::operator=(const ZRef<T>& iOther)
00385         {
00386         T::sIncRefCount(iOther.GetObject());
00387 
00388         fMutex.Acquire();
00389         S* temp = fObject;
00390         fObject = iOther.GetObject();
00391         fMutex.Release();
00392 
00393         S::sDecRefCount(temp);
00394         return *this;
00395         }
00396 
00397 // =================================================================================================
00398 #pragma mark -
00399 #pragma mark * ZRef casts
00400 
00401 template <class O, class T> inline O* ZRefDynamicCast(const ZRef<T>& iVal)
00402         { return dynamic_cast<O*>(iVal.GetObject()); }
00403 
00404 template <class O, class T> inline O* ZRefStaticCast(const ZRef<T>& iVal)
00405         { return static_cast<O*>(iVal.GetObject()); }
00406 
00407 // =================================================================================================
00408 
00409 #endif // __ZRefCount__

Generated on Thu Jul 26 11:21:51 2007 for ZooLib by  doxygen 1.4.7