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

/home/tommi/cxxtools/include/cxxtools/pool.h

00001 /*
00002  * Copyright (C) 2011 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 #include <cxxtools/smartptr.h>
00030 #include <cxxtools/noncopyable.h>
00031 #include <cxxtools/mutex.h>
00032 #include <vector>
00033 
00034 namespace cxxtools
00035 {
00039   template <class T>
00040   class DefaultCreator
00041   {
00042     public:
00043       T* operator() ()
00044       { return new T(); }
00045   };
00046 
00056   template <typename ObjectType,
00057             typename CreatorType = DefaultCreator<ObjectType>,
00058             template <class> class OwnershipPolicy = RefLinked,
00059             template <class> class DestroyPolicy = DeletePolicy>
00060   class Pool : private NonCopyable
00061   {
00062     public:
00063       class Ptr : public OwnershipPolicy<ObjectType>,
00064                   public DestroyPolicy<ObjectType>
00065       {
00066           ObjectType* object;
00067           Pool* pool;
00068           typedef OwnershipPolicy<ObjectType> OwnershipPolicyType;
00069           typedef DestroyPolicy<ObjectType> DestroyPolicyType;
00070 
00071           void doUnlink()
00072           {
00073             if (OwnershipPolicyType::unlink(object))
00074             {
00075               if (pool == 0 || !pool->put(*this))
00076                 DestroyPolicyType::destroy(object);
00077             }
00078           }
00079 
00080         public:
00081           Ptr()
00082             : object(0)
00083             {}
00084           Ptr(ObjectType* ptr)
00085             : object(ptr)
00086             { OwnershipPolicyType::link(*this, ptr); }
00087           Ptr(const Ptr& ptr)
00088             : object(ptr.object),
00089               pool(ptr.pool)
00090             { OwnershipPolicyType::link(ptr, ptr.object); }
00091           ~Ptr()
00092             { doUnlink(); }
00093 
00094           Ptr& operator= (const Ptr& ptr)
00095           {
00096             if (object != ptr.object)
00097             {
00098               doUnlink();
00099               object = ptr.object;
00100               pool = ptr.pool;
00101               OwnershipPolicyType::link(ptr, object);
00102             }
00103             return *this;
00104           }
00105 
00107           ObjectType* operator->() const              { return object; }
00109           ObjectType& operator*() const               { return *object; }
00110 
00111           bool operator== (const ObjectType* p) const { return object == p; }
00112           bool operator!= (const ObjectType* p) const { return object != p; }
00113           bool operator< (const ObjectType* p) const  { return object < p; }
00114           bool operator! () const { return object == 0; }
00115           operator bool () const  { return object != 0; }
00116 
00117           ObjectType* getPointer()              { return object; }
00118           const ObjectType* getPointer() const  { return object; }
00119           operator ObjectType* ()               { return object; }
00120           operator const ObjectType* () const   { return object; }
00121 
00122           void setPool(Pool* p)
00123           { pool = p; }
00124 
00125           // don't put the object back to the pool
00126           void release()
00127           { pool = 0; }
00128       };
00129 
00130     private:
00131       typedef std::vector<Ptr> Container;
00132       Container freePool;
00133       unsigned maxSpare;
00134       mutable Mutex mutex;
00135       CreatorType creator;
00136 
00137       bool put(Ptr& po) // returns true, if object was put into the freePool vector
00138       {
00139         MutexLock lock(mutex);
00140         if (maxSpare == 0 || freePool.size() < maxSpare)
00141         {
00142           po.setPool(0);
00143           freePool.push_back(po);
00144           return true;
00145         }
00146 
00147         return false;
00148       }
00149 
00150     public:
00151       explicit Pool(unsigned maxSpare_ = 0, CreatorType creator_ = CreatorType())
00152         : maxSpare(maxSpare_),
00153           creator(creator_)
00154           { }
00155 
00156       explicit Pool(CreatorType creator_)
00157         : maxSpare(0),
00158           creator(creator_)
00159           { }
00160 
00161       ~Pool()
00162       {
00163         freePool.clear();
00164       }
00165 
00166       Ptr get()
00167       {
00168         MutexLock lock(mutex);
00169         Ptr po;
00170         if (freePool.empty())
00171         {
00172           po = creator();
00173         }
00174         else
00175         {
00176           po = freePool.back();
00177           freePool.pop_back();
00178         }
00179 
00180         po.setPool(this);
00181         return po;
00182       }
00183 
00184       void drop(unsigned keep = 0)
00185       {
00186         MutexLock lock(mutex);
00187         if (freePool.size() > keep)
00188           freePool.resize(keep);
00189       }
00190 
00191       unsigned getMaximumSize() const
00192       {
00193         MutexLock lock(mutex);
00194         return maxSpare;
00195       }
00196 
00197       unsigned size() const
00198       {
00199         MutexLock lock(mutex);
00200         return freePool.size();
00201       }
00202 
00203       unsigned getCurrentSize() const
00204       {
00205         MutexLock lock(mutex);
00206         return freePool.size();
00207       }
00208 
00209       void setMaximumSize(unsigned s)
00210       {
00211         MutexLock lock(mutex);
00212         maxSpare = s;
00213         if (freePool.size() > s)
00214           freePool.resize(s);
00215       }
00216 
00217       CreatorType& getCreator()
00218       { return creator; }
00219 
00220       const CreatorType& getCreator() const
00221       { return creator; }
00222 
00223   };
00224 
00225 }
Copyright © 2008 The Tntnet Development Team
Tntnet 1.6