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 #ifndef CXXTOOLS_POOL_H
30 #define CXXTOOLS_POOL_H
31 
32 #include <cxxtools/smartptr.h>
33 #include <cxxtools/noncopyable.h>
34 #include <cxxtools/mutex.h>
35 #include <vector>
36 
37 namespace cxxtools
38 {
40  template <class T>
42  {
43  public:
45  { return new T(); }
46  };
47 
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  pool(0)
84  {}
85  Ptr(ObjectType* ptr)
86  : object(ptr),
87  pool(0)
88  { OwnershipPolicyType::link(*this, ptr); }
89  Ptr(const Ptr& ptr)
90  : object(ptr.object),
91  pool(ptr.pool)
92  { OwnershipPolicyType::link(ptr, ptr.object); }
93  ~Ptr()
94  { doUnlink(); }
95 
96  Ptr& operator= (const Ptr& ptr)
97  {
98  if (object != ptr.object)
99  {
100  doUnlink();
101  object = ptr.object;
102  pool = ptr.pool;
103  OwnershipPolicyType::link(ptr, object);
104  }
105  return *this;
106  }
107 
109  ObjectType* operator->() const { return object; }
111  ObjectType& operator*() const { return *object; }
112 
113  bool operator== (const ObjectType* p) const { return object == p; }
114  bool operator!= (const ObjectType* p) const { return object != p; }
115  bool operator< (const ObjectType* p) const { return object < p; }
116  bool operator! () const { return object == 0; }
117  operator bool () const { return object != 0; }
118 
119  ObjectType* getPointer() { return object; }
120  const ObjectType* getPointer() const { return object; }
121  operator ObjectType* () { return object; }
122  operator const ObjectType* () const { return object; }
123 
124  void setPool(Pool* p)
125  { pool = p; }
126 
127  // don't put the object back to the pool
128  void release()
129  { pool = 0; }
130  };
131 
132  private:
133  typedef std::vector<Ptr> Container;
134  Container freePool;
135  unsigned maxSpare;
136  mutable Mutex mutex;
137  CreatorType creator;
138 
139  bool put(Ptr& po) // returns true, if object was put into the freePool vector
140  {
141  MutexLock lock(mutex);
142  if (maxSpare == 0 || freePool.size() < maxSpare)
143  {
144  po.setPool(0);
145  freePool.push_back(po);
146  return true;
147  }
148 
149  return false;
150  }
151 
152  public:
153  explicit Pool(unsigned maxSpare_ = 0, CreatorType creator_ = CreatorType())
154  : maxSpare(maxSpare_),
155  creator(creator_)
156  { }
157 
158  explicit Pool(CreatorType creator_)
159  : maxSpare(0),
160  creator(creator_)
161  { }
162 
164  {
165  freePool.clear();
166  }
167 
168  Ptr get()
169  {
170  MutexLock lock(mutex);
171  Ptr po;
172  if (freePool.empty())
173  {
174  po = creator();
175  }
176  else
177  {
178  po = freePool.back();
179  freePool.pop_back();
180  }
181 
182  po.setPool(this);
183  return po;
184  }
185 
186  void drop(unsigned keep = 0)
187  {
188  MutexLock lock(mutex);
189  if (freePool.size() > keep)
190  freePool.resize(keep);
191  }
192 
193  unsigned getMaximumSize() const
194  {
195  MutexLock lock(mutex);
196  return maxSpare;
197  }
198 
199  unsigned size() const
200  {
201  MutexLock lock(mutex);
202  return freePool.size();
203  }
204 
205  unsigned getCurrentSize() const
206  {
207  MutexLock lock(mutex);
208  return freePool.size();
209  }
210 
211  void setMaximumSize(unsigned s)
212  {
213  MutexLock lock(mutex);
214  maxSpare = s;
215  if (freePool.size() > s)
216  freePool.resize(s);
217  }
218 
219  CreatorType& getCreator()
220  { return creator; }
221 
222  const CreatorType& getCreator() const
223  { return creator; }
224 
225  };
226 
227 }
228 
229 #endif