| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317 |
- //
- // ObjectPool.h
- //
- // $Id: //poco/1.4/Foundation/include/Poco/ObjectPool.h#1 $
- //
- // Library: Foundation
- // Package: Core
- // Module: ObjectPool
- //
- // Definition of the ObjectPool template class and friends.
- //
- // Copyright (c) 2010-2012, Applied Informatics Software Engineering GmbH.
- // and Contributors.
- //
- // SPDX-License-Identifier: BSL-1.0
- //
- #ifndef Foundation_ObjectPool_INCLUDED
- #define Foundation_ObjectPool_INCLUDED
- #include "Poco/Poco.h"
- #include "Poco/Mutex.h"
- #include "Poco/AutoPtr.h"
- #include "Poco/SharedPtr.h"
- #include <vector>
- #include <cctype>
- namespace Poco {
- template <class C, class P = C*>
- class PoolableObjectFactory
- /// A PoolableObjectFactory is responsible for creating and resetting
- /// objects managed by an ObjectPool.
- ///
- /// Together with an ObjectPool, a PoolableObjectFactory is used as
- /// a policy class to change the behavior of the ObjectPool when
- /// creating new objects, returning used objects back to the pool
- /// and destroying objects, when the pool itself is destroyed or
- /// shrinked.
- {
- public:
- P createObject()
- /// Create and return a new object.
- {
- return new C;
- }
-
- bool validateObject(P pObject)
- /// Checks whether the object is still valid
- /// and can be reused.
- ///
- /// Returns true if the object is valid,
- /// false otherwise.
- ///
- /// To maintain the integrity of the pool, this method
- /// must not throw an exception.
- {
- return true;
- }
-
- void activateObject(P pObject)
- /// Called before an object is handed out by the pool.
- /// Also called for newly created objects, before
- /// they are given out for the first time.
- {
- }
-
- void deactivateObject(P pObject)
- /// Called after an object has been given back to the
- /// pool and the object is still valid (a prior call
- /// to validateObject() returned true).
- ///
- /// To maintain the integrity of the pool, this method
- /// must not throw an exception.
- {
- }
-
- void destroyObject(P pObject)
- /// Destroy an object.
- ///
- /// To maintain the integrity of the pool, this method
- /// must not throw an exception.
- {
- delete pObject;
- }
- };
- template <class C>
- class PoolableObjectFactory <C, Poco::AutoPtr<C> >
- {
- public:
- Poco::AutoPtr<C> createObject()
- {
- return new C;
- }
-
- bool validateObject(Poco::AutoPtr<C> pObject)
- {
- return true;
- }
-
- void activateObject(Poco::AutoPtr<C> pObject)
- {
- }
-
- void deactivateObject(Poco::AutoPtr<C> pObject)
- {
- }
-
- void destroyObject(Poco::AutoPtr<C> pObject)
- {
- }
- };
- template <class C>
- class PoolableObjectFactory <C, Poco::SharedPtr<C> >
- {
- public:
- Poco::SharedPtr<C> createObject()
- {
- return new C;
- }
-
- bool validateObject(Poco::SharedPtr<C> pObject)
- {
- return true;
- }
-
- void activateObject(Poco::SharedPtr<C> pObject)
- {
- }
-
- void deactivateObject(Poco::SharedPtr<C> pObject)
- {
- }
-
- void destroyObject(Poco::SharedPtr<C> pObject)
- {
- }
- };
- template <class C, class P = C*, class F = PoolableObjectFactory<C, P> >
- class ObjectPool
- /// An ObjectPool manages a pool of objects of a certain class.
- ///
- /// The number of objects managed by the pool can be restricted.
- ///
- /// When an object is requested from the pool:
- /// - If an object is available from the pool, an object from the pool is
- /// removed from the pool, activated (using the factory) and returned.
- /// - Otherwise, if the peak capacity of the pool has not yet been reached,
- /// a new object is created and activated, using the object factory, and returned.
- /// - If the peak capacity has already been reached, null is returned.
- ///
- /// When an object is returned to the pool:
- /// - If the object is valid (checked by calling validateObject()
- /// from the object factory), the object is deactivated. If the
- /// number of objects in the pool is below the capacity,
- /// the object is added to the pool. Otherwise it is destroyed.
- /// - If the object is not valid, it is destroyed immediately.
- {
- public:
- ObjectPool(std::size_t capacity, std::size_t peakCapacity):
- /// Creates a new ObjectPool with the given capacity
- /// and peak capacity.
- ///
- /// The PoolableObjectFactory must have a public default constructor.
- _capacity(capacity),
- _peakCapacity(peakCapacity),
- _size(0)
- {
- poco_assert (capacity <= peakCapacity);
- }
-
- ObjectPool(const F& factory, std::size_t capacity, std::size_t peakCapacity):
- /// Creates a new ObjectPool with the given PoolableObjectFactory,
- /// capacity and peak capacity. The PoolableObjectFactory must have
- /// a public copy constructor.
- _factory(factory),
- _capacity(capacity),
- _peakCapacity(peakCapacity),
- _size(0)
- {
- poco_assert (capacity <= peakCapacity);
- }
-
- ~ObjectPool()
- /// Destroys the ObjectPool.
- {
- try
- {
- for (typename std::vector<P>::iterator it = _pool.begin(); it != _pool.end(); ++it)
- {
- _factory.destroyObject(*it);
- }
- }
- catch (...)
- {
- poco_unexpected();
- }
- }
-
- P borrowObject()
- /// Obtains an object from the pool, or creates a new object if
- /// possible.
- ///
- /// Returns null if no object is available.
- ///
- /// If activating the object fails, the object is destroyed and
- /// the exception is passed on to the caller.
- {
- Poco::FastMutex::ScopedLock lock(_mutex);
-
- if (!_pool.empty())
- {
- P pObject = _pool.back();
- _pool.pop_back();
- return activateObject(pObject);
- }
- else if (_size < _peakCapacity)
- {
- P pObject = _factory.createObject();
- activateObject(pObject);
- _size++;
- return pObject;
- }
- else return 0;
- }
-
- void returnObject(P pObject)
- /// Returns an object to the pool.
- {
- Poco::FastMutex::ScopedLock lock(_mutex);
- if (_factory.validateObject(pObject))
- {
- _factory.deactivateObject(pObject);
- if (_pool.size() < _capacity)
- {
- _pool.push_back(pObject);
- }
- else
- {
- _factory.destroyObject(pObject);
- _size--;
- }
- }
- else
- {
- _factory.destroyObject(pObject);
- }
- }
- std::size_t capacity() const
- {
- return _capacity;
- }
-
- std::size_t peakCapacity() const
- {
- return _peakCapacity;
- }
-
- std::size_t size() const
- {
- Poco::FastMutex::ScopedLock lock(_mutex);
-
- return _size;
- }
-
- std::size_t available() const
- {
- Poco::FastMutex::ScopedLock lock(_mutex);
- return _pool.size() + _peakCapacity - _size;
- }
- protected:
- P activateObject(P pObject)
- {
- try
- {
- _factory.activateObject(pObject);
- }
- catch (...)
- {
- _factory.destroyObject(pObject);
- throw;
- }
- return pObject;
- }
-
- private:
- ObjectPool();
- ObjectPool(const ObjectPool&);
- ObjectPool& operator = (const ObjectPool&);
-
- F _factory;
- std::size_t _capacity;
- std::size_t _peakCapacity;
- std::size_t _size;
- std::vector<P> _pool;
- mutable Poco::FastMutex _mutex;
- };
- } // namespace Poco
- #endif // Foundation_ObjectPool_INCLUDED
|