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 #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
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)
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 }