ObjectPool.h 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. //
  2. // ObjectPool.h
  3. //
  4. // $Id: //poco/1.4/Foundation/include/Poco/ObjectPool.h#1 $
  5. //
  6. // Library: Foundation
  7. // Package: Core
  8. // Module: ObjectPool
  9. //
  10. // Definition of the ObjectPool template class and friends.
  11. //
  12. // Copyright (c) 2010-2012, Applied Informatics Software Engineering GmbH.
  13. // and Contributors.
  14. //
  15. // SPDX-License-Identifier: BSL-1.0
  16. //
  17. #ifndef Foundation_ObjectPool_INCLUDED
  18. #define Foundation_ObjectPool_INCLUDED
  19. #include "Poco/Poco.h"
  20. #include "Poco/Mutex.h"
  21. #include "Poco/AutoPtr.h"
  22. #include "Poco/SharedPtr.h"
  23. #include <vector>
  24. #include <cctype>
  25. namespace Poco {
  26. template <class C, class P = C*>
  27. class PoolableObjectFactory
  28. /// A PoolableObjectFactory is responsible for creating and resetting
  29. /// objects managed by an ObjectPool.
  30. ///
  31. /// Together with an ObjectPool, a PoolableObjectFactory is used as
  32. /// a policy class to change the behavior of the ObjectPool when
  33. /// creating new objects, returning used objects back to the pool
  34. /// and destroying objects, when the pool itself is destroyed or
  35. /// shrinked.
  36. {
  37. public:
  38. P createObject()
  39. /// Create and return a new object.
  40. {
  41. return new C;
  42. }
  43. bool validateObject(P pObject)
  44. /// Checks whether the object is still valid
  45. /// and can be reused.
  46. ///
  47. /// Returns true if the object is valid,
  48. /// false otherwise.
  49. ///
  50. /// To maintain the integrity of the pool, this method
  51. /// must not throw an exception.
  52. {
  53. return true;
  54. }
  55. void activateObject(P pObject)
  56. /// Called before an object is handed out by the pool.
  57. /// Also called for newly created objects, before
  58. /// they are given out for the first time.
  59. {
  60. }
  61. void deactivateObject(P pObject)
  62. /// Called after an object has been given back to the
  63. /// pool and the object is still valid (a prior call
  64. /// to validateObject() returned true).
  65. ///
  66. /// To maintain the integrity of the pool, this method
  67. /// must not throw an exception.
  68. {
  69. }
  70. void destroyObject(P pObject)
  71. /// Destroy an object.
  72. ///
  73. /// To maintain the integrity of the pool, this method
  74. /// must not throw an exception.
  75. {
  76. delete pObject;
  77. }
  78. };
  79. template <class C>
  80. class PoolableObjectFactory <C, Poco::AutoPtr<C> >
  81. {
  82. public:
  83. Poco::AutoPtr<C> createObject()
  84. {
  85. return new C;
  86. }
  87. bool validateObject(Poco::AutoPtr<C> pObject)
  88. {
  89. return true;
  90. }
  91. void activateObject(Poco::AutoPtr<C> pObject)
  92. {
  93. }
  94. void deactivateObject(Poco::AutoPtr<C> pObject)
  95. {
  96. }
  97. void destroyObject(Poco::AutoPtr<C> pObject)
  98. {
  99. }
  100. };
  101. template <class C>
  102. class PoolableObjectFactory <C, Poco::SharedPtr<C> >
  103. {
  104. public:
  105. Poco::SharedPtr<C> createObject()
  106. {
  107. return new C;
  108. }
  109. bool validateObject(Poco::SharedPtr<C> pObject)
  110. {
  111. return true;
  112. }
  113. void activateObject(Poco::SharedPtr<C> pObject)
  114. {
  115. }
  116. void deactivateObject(Poco::SharedPtr<C> pObject)
  117. {
  118. }
  119. void destroyObject(Poco::SharedPtr<C> pObject)
  120. {
  121. }
  122. };
  123. template <class C, class P = C*, class F = PoolableObjectFactory<C, P> >
  124. class ObjectPool
  125. /// An ObjectPool manages a pool of objects of a certain class.
  126. ///
  127. /// The number of objects managed by the pool can be restricted.
  128. ///
  129. /// When an object is requested from the pool:
  130. /// - If an object is available from the pool, an object from the pool is
  131. /// removed from the pool, activated (using the factory) and returned.
  132. /// - Otherwise, if the peak capacity of the pool has not yet been reached,
  133. /// a new object is created and activated, using the object factory, and returned.
  134. /// - If the peak capacity has already been reached, null is returned.
  135. ///
  136. /// When an object is returned to the pool:
  137. /// - If the object is valid (checked by calling validateObject()
  138. /// from the object factory), the object is deactivated. If the
  139. /// number of objects in the pool is below the capacity,
  140. /// the object is added to the pool. Otherwise it is destroyed.
  141. /// - If the object is not valid, it is destroyed immediately.
  142. {
  143. public:
  144. ObjectPool(std::size_t capacity, std::size_t peakCapacity):
  145. /// Creates a new ObjectPool with the given capacity
  146. /// and peak capacity.
  147. ///
  148. /// The PoolableObjectFactory must have a public default constructor.
  149. _capacity(capacity),
  150. _peakCapacity(peakCapacity),
  151. _size(0)
  152. {
  153. poco_assert (capacity <= peakCapacity);
  154. }
  155. ObjectPool(const F& factory, std::size_t capacity, std::size_t peakCapacity):
  156. /// Creates a new ObjectPool with the given PoolableObjectFactory,
  157. /// capacity and peak capacity. The PoolableObjectFactory must have
  158. /// a public copy constructor.
  159. _factory(factory),
  160. _capacity(capacity),
  161. _peakCapacity(peakCapacity),
  162. _size(0)
  163. {
  164. poco_assert (capacity <= peakCapacity);
  165. }
  166. ~ObjectPool()
  167. /// Destroys the ObjectPool.
  168. {
  169. try
  170. {
  171. for (typename std::vector<P>::iterator it = _pool.begin(); it != _pool.end(); ++it)
  172. {
  173. _factory.destroyObject(*it);
  174. }
  175. }
  176. catch (...)
  177. {
  178. poco_unexpected();
  179. }
  180. }
  181. P borrowObject()
  182. /// Obtains an object from the pool, or creates a new object if
  183. /// possible.
  184. ///
  185. /// Returns null if no object is available.
  186. ///
  187. /// If activating the object fails, the object is destroyed and
  188. /// the exception is passed on to the caller.
  189. {
  190. Poco::FastMutex::ScopedLock lock(_mutex);
  191. if (!_pool.empty())
  192. {
  193. P pObject = _pool.back();
  194. _pool.pop_back();
  195. return activateObject(pObject);
  196. }
  197. else if (_size < _peakCapacity)
  198. {
  199. P pObject = _factory.createObject();
  200. activateObject(pObject);
  201. _size++;
  202. return pObject;
  203. }
  204. else return 0;
  205. }
  206. void returnObject(P pObject)
  207. /// Returns an object to the pool.
  208. {
  209. Poco::FastMutex::ScopedLock lock(_mutex);
  210. if (_factory.validateObject(pObject))
  211. {
  212. _factory.deactivateObject(pObject);
  213. if (_pool.size() < _capacity)
  214. {
  215. _pool.push_back(pObject);
  216. }
  217. else
  218. {
  219. _factory.destroyObject(pObject);
  220. _size--;
  221. }
  222. }
  223. else
  224. {
  225. _factory.destroyObject(pObject);
  226. }
  227. }
  228. std::size_t capacity() const
  229. {
  230. return _capacity;
  231. }
  232. std::size_t peakCapacity() const
  233. {
  234. return _peakCapacity;
  235. }
  236. std::size_t size() const
  237. {
  238. Poco::FastMutex::ScopedLock lock(_mutex);
  239. return _size;
  240. }
  241. std::size_t available() const
  242. {
  243. Poco::FastMutex::ScopedLock lock(_mutex);
  244. return _pool.size() + _peakCapacity - _size;
  245. }
  246. protected:
  247. P activateObject(P pObject)
  248. {
  249. try
  250. {
  251. _factory.activateObject(pObject);
  252. }
  253. catch (...)
  254. {
  255. _factory.destroyObject(pObject);
  256. throw;
  257. }
  258. return pObject;
  259. }
  260. private:
  261. ObjectPool();
  262. ObjectPool(const ObjectPool&);
  263. ObjectPool& operator = (const ObjectPool&);
  264. F _factory;
  265. std::size_t _capacity;
  266. std::size_t _peakCapacity;
  267. std::size_t _size;
  268. std::vector<P> _pool;
  269. mutable Poco::FastMutex _mutex;
  270. };
  271. } // namespace Poco
  272. #endif // Foundation_ObjectPool_INCLUDED