pool.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2011 Tommi Maekitalo
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * As a special exception, you may use this file as part of a free
10  * software library without restriction. Specifically, if other files
11  * instantiate templates or use macros or inline functions from this
12  * file, or you compile this file and link it with other files to
13  * produce an executable, this file does not by itself cause the
14  * resulting executable to be covered by the GNU General Public
15  * License. This exception does not however invalidate any other
16  * reasons why the executable file might be covered by the GNU Library
17  * General Public License.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22  * Lesser General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public
25  * License along with this library; if not, write to the Free Software
26  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27  */
28 
29 #include <cxxtools/smartptr.h>
30 #include <cxxtools/noncopyable.h>
31 #include <cxxtools/mutex.h>
32 #include <vector>
33 
34 namespace cxxtools
35 {
39  template <class T>
41  {
42  public:
44  { return new T(); }
45  };
46 
56  template <typename ObjectType,
57  typename CreatorType = DefaultCreator<ObjectType>,
58  template <class> class OwnershipPolicy = RefLinked,
59  template <class> class DestroyPolicy = DeletePolicy>
60  class Pool : private NonCopyable
61  {
62  public:
63  class Ptr : public OwnershipPolicy<ObjectType>,
64  public DestroyPolicy<ObjectType>
65  {
66  ObjectType* object;
67  Pool* pool;
68  typedef OwnershipPolicy<ObjectType> OwnershipPolicyType;
69  typedef DestroyPolicy<ObjectType> DestroyPolicyType;
70 
71  void doUnlink()
72  {
73  if (OwnershipPolicyType::unlink(object))
74  {
75  if (pool == 0 || !pool->put(*this))
76  DestroyPolicyType::destroy(object);
77  }
78  }
79 
80  public:
81  Ptr()
82  : object(0)
83  {}
84  Ptr(ObjectType* ptr)
85  : object(ptr)
86  { OwnershipPolicyType::link(*this, ptr); }
87  Ptr(const Ptr& ptr)
88  : object(ptr.object),
89  pool(ptr.pool)
90  { OwnershipPolicyType::link(ptr, ptr.object); }
91  ~Ptr()
92  { doUnlink(); }
93 
94  Ptr& operator= (const Ptr& ptr)
95  {
96  if (object != ptr.object)
97  {
98  doUnlink();
99  object = ptr.object;
100  pool = ptr.pool;
101  OwnershipPolicyType::link(ptr, object);
102  }
103  return *this;
104  }
105 
107  ObjectType* operator->() const { return object; }
109  ObjectType& operator*() const { return *object; }
110 
111  bool operator== (const ObjectType* p) const { return object == p; }
112  bool operator!= (const ObjectType* p) const { return object != p; }
113  bool operator< (const ObjectType* p) const { return object < p; }
114  bool operator! () const { return object == 0; }
115  operator bool () const { return object != 0; }
116 
117  ObjectType* getPointer() { return object; }
118  const ObjectType* getPointer() const { return object; }
119  operator ObjectType* () { return object; }
120  operator const ObjectType* () const { return object; }
121 
122  void setPool(Pool* p)
123  { pool = p; }
124 
125  // don't put the object back to the pool
126  void release()
127  { pool = 0; }
128  };
129 
130  private:
131  typedef std::vector<Ptr> Container;
132  Container freePool;
133  unsigned maxSpare;
134  mutable Mutex mutex;
135  CreatorType creator;
136 
137  bool put(Ptr& po) // returns true, if object was put into the freePool vector
138  {
139  MutexLock lock(mutex);
140  if (maxSpare == 0 || freePool.size() < maxSpare)
141  {
142  po.setPool(0);
143  freePool.push_back(po);
144  return true;
145  }
146 
147  return false;
148  }
149 
150  public:
151  explicit Pool(unsigned maxSpare_ = 0, CreatorType creator_ = CreatorType())
152  : maxSpare(maxSpare_),
153  creator(creator_)
154  { }
155 
156  explicit Pool(CreatorType creator_)
157  : maxSpare(0),
158  creator(creator_)
159  { }
160 
162  {
163  freePool.clear();
164  }
165 
166  Ptr get()
167  {
168  MutexLock lock(mutex);
169  Ptr po;
170  if (freePool.empty())
171  {
172  po = creator();
173  }
174  else
175  {
176  po = freePool.back();
177  freePool.pop_back();
178  }
179 
180  po.setPool(this);
181  return po;
182  }
183 
184  void drop(unsigned keep = 0)
185  {
186  MutexLock lock(mutex);
187  if (freePool.size() > keep)
188  freePool.resize(keep);
189  }
190 
191  unsigned getMaximumSize() const
192  {
193  MutexLock lock(mutex);
194  return maxSpare;
195  }
196 
197  unsigned size() const
198  {
199  MutexLock lock(mutex);
200  return freePool.size();
201  }
202 
203  unsigned getCurrentSize() const
204  {
205  MutexLock lock(mutex);
206  return freePool.size();
207  }
208 
209  void setMaximumSize(unsigned s)
210  {
211  MutexLock lock(mutex);
212  maxSpare = s;
213  if (freePool.size() > s)
214  freePool.resize(s);
215  }
216 
217  CreatorType& getCreator()
218  { return creator; }
219 
220  const CreatorType& getCreator() const
221  { return creator; }
222 
223  };
224 
225 }