Webmaster  |  Imprint 
C++ Server Pages
Main  |  License  |  Documentation  |  Download 

/home/tommi/cxxtools/include/cxxtools/smartptr.h

00001 /*
00002  * Copyright (C) 2005 Tommi Maekitalo
00003  * 
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2.1 of the License, or (at your option) any later version.
00008  * 
00009  * As a special exception, you may use this file as part of a free
00010  * software library without restriction. Specifically, if other files
00011  * instantiate templates or use macros or inline functions from this
00012  * file, or you compile this file and link it with other files to
00013  * produce an executable, this file does not by itself cause the
00014  * resulting executable to be covered by the GNU General Public
00015  * License. This exception does not however invalidate any other
00016  * reasons why the executable file might be covered by the GNU Library
00017  * General Public License.
00018  * 
00019  * This library is distributed in the hope that it will be useful,
00020  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00022  * Lesser General Public License for more details.
00023  * 
00024  * You should have received a copy of the GNU Lesser General Public
00025  * License along with this library; if not, write to the Free Software
00026  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
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           // no need to set rc to 0 since the pointer is either
00113           // destroyed or another object is linked in
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           // no need to set rc to 0 since the pointer is either
00156           // destroyed or another object is linked in
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 
Copyright © 2008 The Tntnet Development Team
Tntnet 1.6