NCBI C++ ToolKit
resource_pool.hpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 #ifndef UTIL___RESOURCEPOOL__HPP
2 #define UTIL___RESOURCEPOOL__HPP
3 
4 /* $Id: resource_pool.hpp 72358 2016-05-03 17:12:04Z ivanov $
5  * ===========================================================================
6  *
7  * PUBLIC DOMAIN NOTICE
8  * National Center for Biotechnology Information
9  *
10  * This software/database is a "United States Government Work" under the
11  * terms of the United States Copyright Act. It was written as part of
12  * the author's official duties as a United States Government employee and
13  * thus cannot be copyrighted. This software/database is freely available
14  * to the public for use. The National Library of Medicine and the U.S.
15  * Government have not placed any restriction on its use or reproduction.
16  *
17  * Although all reasonable efforts have been taken to ensure the accuracy
18  * and reliability of the software and data, the NLM and the U.S.
19  * Government do not and cannot warrant the performance or results that
20  * may be obtained by using this software or data. The NLM and the U.S.
21  * Government disclaim all warranties, express or implied, including
22  * warranties of performance, merchantability or fitness for any particular
23  * purpose.
24  *
25  * Please cite the author in any work or product based on this material.
26  *
27  * ===========================================================================
28  *
29  * Author: Anatoliy Kuznetsov
30  * General purpose resource pool.
31  */
32 
33 #include <corelib/ncbistd.hpp>
34 #include <corelib/ncbimtx.hpp>
35 #include <deque>
36 #include <vector>
37 
39 
40 /** @addtogroup ResourcePool
41  *
42  * @{
43  */
44 
45  /// Default class factory for resource pool (C++ new/delete)
46  ///
47 template<class Value>
49 {
50 public:
51  static Value* Create() { return new Value; }
52  static void Delete(Value* v) { delete v; }
53 };
54 
55 
56 /// General purpose resource pool (base class, sans default
57 /// constructor arguments for maximum versatility).
58 ///
59 /// Intended use is to store reusable objects.
60 /// Pool frees all vacant objects only upon pools destruction.
61 /// Subsequent Get/Put calls does not result in objects reallocations and
62 /// re-initializations. (So the prime target is performance optimization).
63 ///
64 /// Class can be used synchronized across threads
65 /// (use CFastMutex as Lock parameter)
66 ///
67 /// Default creation/destruction protocol is C++ new/delete.
68 /// Can be overloaded using CF parameter
69 ///
70 template<class Value,
71  class Lock = CNoLock,
74 {
75 public:
76  typedef Value TValue;
77  typedef Lock TLock;
80  typedef CF TClassFactory;
81  typedef Value* TValuePtr;
82  typedef deque<Value*> TPoolList;
83 
84 public:
85  /// Construction
86  ///
87  /// @param upper_limit
88  /// Max pool size. Everything coming to pool above this limit is
89  /// destroyed right away. 0 - upper limit not set
90  ///
91  CResourcePool_Base(size_t capacity_upper_limit, const TClassFactory& cf)
92  : m_CF(cf),
93  m_UpperLimit(capacity_upper_limit)
94  {}
95 
97  {
98  FreeAll();
99  }
100 
101  /// Return max pool size.
102  size_t GetCapacityLimit() const { return m_UpperLimit; }
103 
104  /// Set upper limit for pool capacity (everything above this is deleted)
105  void SetCapacityLimit(size_t capacity_upper_limit)
106  {
107  m_UpperLimit = capacity_upper_limit;
108  }
109 
110  /// Get current pool size (number of objects in the pool)
111  size_t GetSize() const
112  {
113  TReadLockGuard guard(m_Lock);
114  return m_FreeObjects.size();
115  }
116 
117  /// Get object from the pool.
118  ///
119  /// Pool makes no reinitialization or constructor
120  /// call and object is returned in the same state it was put.
121  /// If pool has no vacant objects, class factory is called to produce an object.
122  /// Caller is responsible for deletion or returning object back to the pool.
124  {
125  TWriteLockGuard guard(m_Lock);
126 
127  Value* v;
128  if (m_FreeObjects.empty()) {
129  v = m_CF.Create();
130  } else {
131  typename TPoolList::iterator it = m_FreeObjects.end();
132  v = *(--it);
133  m_FreeObjects.pop_back();
134  }
135  return v;
136  }
137 
138  /// Get object from the pool if there is a vacancy,
139  /// otherwise returns NULL
141  {
142  TWriteLockGuard guard(m_Lock);
143 
144  if (m_FreeObjects.empty()) {
145  return 0;
146  }
147  Value* v;
148  typename TPoolList::iterator it = m_FreeObjects.end();
149  v = *(--it);
150  m_FreeObjects.pop_back();
151  return v;
152  }
153 
154  /// Put object into the pool.
155  ///
156  /// Pool does not check if object is actually
157  /// originated in the very same pool. It's ok to get an object from one pool
158  /// and return it to another pool.
159  /// Method does NOT immidiately destroy the object v.
160  void Put(Value* v)
161  {
162  TWriteLockGuard guard(m_Lock);
163 
164  _ASSERT(v);
165  if (m_UpperLimit && (m_FreeObjects.size() >= m_UpperLimit)) {
166  m_CF.Delete(v);
167  } else {
168  m_FreeObjects.push_back(v);
169  }
170  }
171 
172  void Return(Value* v)
173  {
174  Put(v);
175  }
176 
177  /// Makes the pool to forget the object.
178  ///
179  /// Method scans the free objects list, finds the object and removes
180  /// it from the structure. It is important that the object is not
181  /// deleted and it is responsibility of the caller to destroy it.
182  ///
183  /// @return NULL if object does not belong to the pool or
184  /// object's pointer otherwise.
186  {
187  TWriteLockGuard guard(m_Lock);
188 
189  NON_CONST_ITERATE(typename TPoolList, it, m_FreeObjects) {
190  Value* vp = *it;
191  if (v == vp) {
192  m_FreeObjects.erase(it);
193  return v;
194  }
195  }
196  return 0;
197  }
198 
199  /// Makes pool to forget all objects
200  ///
201  /// Method removes all objects from the internal list but does NOT
202  /// deallocate the objects.
203  void ForgetAll()
204  {
205  TWriteLockGuard guard(m_Lock);
206 
207  m_FreeObjects.clear();
208  }
209 
210  /// Free all pool objects.
211  ///
212  /// Method removes all objects from the internal list and
213  /// deallocates the objects.
214  void FreeAll()
215  {
216  TWriteLockGuard guard(m_Lock);
217 
218  ITERATE(typename TPoolList, it, m_FreeObjects) {
219  Value* v = *it;
220  m_CF.Delete(v);
221  }
222  m_FreeObjects.clear();
223  }
224 
225 
226  /// Get internal list of free objects
227  ///
228  /// Be very careful with this function! It does not provide MT sync.
230  {
231  return m_FreeObjects;
232  }
233 
234  /// Get internal list of free objects
235  ///
236  /// No MT sync here !
237  const TPoolList& GetFreeList() const
238  {
239  return m_FreeObjects;
240  }
241 
242 protected:
245 
246 protected:
248  mutable TLock m_Lock;
250  size_t m_UpperLimit; ///< Upper limit how much to pool
251 };
252 
253 
254 /// General purpose resource pool (standard version, requiring CF to
255 /// have a default constructor).
256 ///
257 template<class Value,
258  class Lock = CNoLock,
260 class CResourcePool : public CResourcePool_Base<Value, Lock, CF>
261 {
262 public:
264  typedef typename TBase::TValue TValue;
265  typedef typename TBase::TLock TLock;
269  typedef typename TBase::TValuePtr TValuePtr;
270  typedef typename TBase::TPoolList TPoolList;
271 
272  CResourcePool(size_t capacity_upper_limit = 0,
273  const TClassFactory& cf = TClassFactory())
274  : TBase(capacity_upper_limit, cf)
275  {}
276 
277 protected:
280 };
281 
282 
283 /// Guard object. Returns object pointer to the pool upon destruction.
284 /// @sa CResourcePool
285 template<class Pool>
287 {
288 public:
289  CResourcePoolGuard(Pool& pool, typename Pool::TValue* v)
290  : m_Pool(pool),
291  m_Value(v)
292  {}
293 
295  {
296  Return();
297  }
298 
299  /// Return the pointer to the caller, not to the pool
300  typename Pool::TValue* Release()
301  {
302  typename Pool::TValue* ret = m_Value;
303  m_Value = 0;
304  return ret;
305  }
306 
307  /// Get the protected pointer
308  typename Pool::TValue* Get() { return m_Value; }
309 
310  /// Return the protected object back to the pool
311  void Return()
312  {
313  if (m_Value) {
314  m_Pool.Return(m_Value);
315  }
316  m_Value = 0;
317  }
318 private:
321 private:
322  Pool& m_Pool;
323  typename Pool::TValue* m_Value;
324 };
325 
326 
327 /// Bucket of resourse pools.
328 ///
329 /// This object is a wrap on a vector of resource pools, it
330 /// automates management of multiple resource pools.
331 ///
332 template<class Value,
333  class Lock = CNoLock,
334  class RPool = CResourcePool<Value, Lock> >
336 {
337 public:
338  typedef Value TValue;
339  typedef Lock TLock;
341  typedef RPool TResourcePool;
342  typedef vector<TResourcePool*> TBucketVector;
343 
344 public:
345  /// Construction
346  ///
347  /// @param bucket_ini
348  /// Initial size of pool bucket.
349  /// Backet resized dynamically if it needs to.
350  /// @param resource_pool_capacity_limit
351  /// Upper limit for how many objects pool can store
352  ///
353  CBucketPool(size_t bucket_ini = 0,
354  size_t resource_pool_capacity_limit = 0)
355  : m_Bucket(bucket_ini),
356  m_ResourcePoolUpperLimit(resource_pool_capacity_limit)
357  {
358  for (size_t i = 0; i < m_Bucket.size(); ++i) {
359  m_Bucket[i] = 0;
360  }
361  }
362 
364  {
365  TWriteLockGuard guard(m_Lock);
366  x_FreeAll_NoLock();
367  }
368 
369  /// Free all objects in all pools
370  ///
372  {
373  // code here optimized for MT competitive execution
374  // it does not hold the top level lock for a long time
375  //
376  size_t bsize;
377  {{
378  TWriteLockGuard guard(m_Lock);
379  bsize = m_Bucket.size();
380  }}
381  for (size_t i = 0; i < bsize; ++i) {
382  TResourcePool* rp = 0;
383  {{
384  TWriteLockGuard guard(m_Lock);
385  if (m_Bucket.size() < i) {
386  break;
387  }
388  rp = m_Bucket[i];
389  }}
390  if (rp) {
391  rp->FreeAll();
392  }
393  } // for
394  }
395 
396  /// Get resource pool for the specified backet
397  ///
398  /// Backet grows automatically upon request
399  ///
401  {
402  TWriteLockGuard guard(m_Lock);
403 
404  // bucket resize
405  while (m_Bucket.size() < backet+1) {
406  m_Bucket.push_back(0);
407  }
408  TResourcePool* rp = m_Bucket[backet];
409  if (!rp) {
411  m_Bucket[backet] = rp;
412  }
413  return rp;
414  }
415 
416  const TBucketVector& GetBucketVector() const { return m_Bucket; }
417 
418 private:
421 private:
423  {
424  for (size_t i = 0; i < m_Bucket.size(); ++i) {
425  delete m_Bucket[i]; m_Bucket[i] = 0;
426  }
427  }
428 
429 protected:
433 };
434 
435 
436 /* @} */
437 
438 
440 
441 
442 #endif /* UTIL___RESOURCEPOOL__HPP */
Bucket of resourse pools.
CNoLock is a simple no-op lock which does no real locking.
Definition: guard.hpp:215
General purpose resource pool (base class, sans default constructor arguments for maximum versatility...
General purpose resource pool (standard version, requiring CF to have a default constructor).
Include a standard set of the NCBI C++ Toolkit most basic headers.
#define ITERATE(Type, Var, Cont)
ITERATE macro to sequence through container elements.
Definition: ncbimisc.hpp:815
#define NON_CONST_ITERATE(Type, Var, Cont)
Non constant version of ITERATE macro.
Definition: ncbimisc.hpp:822
Lock::TWriteLockGuard TWriteLockGuard
void ForgetAll()
Makes pool to forget all objects.
void x_FreeAll_NoLock()
void Return()
Return the protected object back to the pool.
Value * Get()
Get object from the pool.
CBucketPool & operator=(const CBucketPool &)
TBase::TClassFactory TClassFactory
void SetCapacityLimit(size_t capacity_upper_limit)
Set upper limit for pool capacity (everything above this is deleted)
TClassFactory m_CF
CResourcePool_Base< Value, Lock, CF > TBase
Lock::TReadLockGuard TReadLockGuard
deque< Value * > TPoolList
void Return(Value *v)
Value * Forget(Value *v)
Makes the pool to forget the object.
const TPoolList & GetFreeList() const
Get internal list of free objects.
CResourcePool(size_t capacity_upper_limit=0, const TClassFactory &cf=TClassFactory())
void FreeAll()
Free all pool objects.
CResourcePoolGuard & operator=(const CResourcePoolGuard &)
void Put(Value *v)
Put object into the pool.
CBucketPool(const CBucketPool &)
CResourcePool_Base & operator=(const CResourcePool_Base &)
TBase::TPoolList TPoolList
Pool::TValue * Get()
Get the protected pointer.
static void Delete(Value *v)
TBase::TValuePtr TValuePtr
CResourcePool_Base(const CResourcePool_Base &)
CResourcePoolGuard(const CResourcePoolGuard &)
Lock::TWriteLockGuard TWriteLockGuard
CResourcePoolGuard(Pool &pool, typename Pool::TValue *v)
const TBucketVector & GetBucketVector() const
TBucketVector m_Bucket
size_t m_ResourcePoolUpperLimit
size_t m_UpperLimit
Upper limit how much to pool.
vector< TResourcePool * > TBucketVector
CBucketPool(size_t bucket_ini=0, size_t resource_pool_capacity_limit=0)
Construction.
TPoolList & GetFreeList()
Get internal list of free objects.
TResourcePool * GetResourcePool(size_t backet)
Get resource pool for the specified backet.
CResourcePool & operator=(const CResourcePool &)
CResourcePool_Base(size_t capacity_upper_limit, const TClassFactory &cf)
Construction.
TBase::TWriteLockGuard TWriteLockGuard
void FreeAllPools()
Free all objects in all pools.
CResourcePool(const CResourcePool &)
Value * GetIfAvailable()
Get object from the pool if there is a vacancy, otherwise returns NULL.
Pool::TValue * m_Value
TBase::TReadLockGuard TReadLockGuard
Pool::TValue * Release()
Return the pointer to the caller, not to the pool.
size_t GetCapacityLimit() const
Return max pool size.
TBase::TLock TLock
size_t GetSize() const
Get current pool size (number of objects in the pool)
TBase::TValue TValue
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
CGuard< CRWLock, SSimpleReadLock< CRWLock > > TReadLockGuard
Definition: ncbimtx.hpp:916
CGuard< CRWLock, SSimpleWriteLock< CRWLock > > TWriteLockGuard
Definition: ncbimtx.hpp:934
int i
GenericValue< UTF8<> > Value
GenericValue with UTF8 encoding.
Definition: document.h:2107
Multi-threading – mutexes; rw-locks; semaphore.
Default class factory for resource pool (C++ new/delete)
#define _ASSERT
Modified on Fri Sep 20 14:57:08 2024 by modify_doxy.py rev. 669887