27 template <
typename TType>
32 using Deleter = std::function<void(TType *)>;
34 using Object = std::unique_ptr<TType, Deleter>;
40 std::vector<std::unique_ptr<TType>> availableElements;
41 size_t maximumSize = std::numeric_limits<size_t>::max();
46 std::shared_ptr<Data> _data;
53 _data(
std::make_shared<Data>())
62 std::scoped_lock<std::mutex> lock(_data->mutex);
67 Pool &operator=(
const Pool &) =
delete;
75 std::scoped_lock<std::mutex> lock(_data->mutex);
77 if (_data->closed ==
true)
79 throw std::runtime_error(
"Can't edit the maximulm allocated size of a closed pool");
82 _data->maximumSize = p_size;
84 while (_data->availableElements.size() > _data->maximumSize)
86 _data->availableElements.pop_back();
96 std::scoped_lock<std::mutex> lock(_data->mutex);
97 return _data->availableElements.size();
100 template <
typename... TArgs>
107 std::scoped_lock<std::mutex> lock(_data->mutex);
109 if (_data->closed ==
true)
111 throw std::runtime_error(
"Can't allocate a new object in closed pool");
114 _data->availableElements.emplace_back(std::make_unique<TType>(std::forward<TArgs>(p_args)...));
117 template <
typename... TArgs>
123 void resize(
size_t p_newSize, TArgs &&...p_args)
125 std::scoped_lock<std::mutex> lock(_data->mutex);
127 if (_data->closed ==
true)
129 throw std::runtime_error(
"Can't resize a closed pool");
132 while (_data->availableElements.size() > p_newSize)
134 _data->availableElements.pop_back();
137 while (_data->availableElements.size() < p_newSize)
139 _data->availableElements.emplace_back(std::make_unique<TType>(std::forward<TArgs>(p_args)...));
148 std::scoped_lock<std::mutex> lock(_data->mutex);
150 if (_data->closed ==
true)
152 throw std::runtime_error(
"Can't release a closed pool");
155 _data->availableElements.clear();
158 template <
typename... TArgs>
167 std::scoped_lock<std::mutex> lock(_data->mutex);
169 if (_data->closed ==
true)
171 throw std::runtime_error(
"Can't obtain object from a closed pool");
175 TType *rawPtr =
nullptr;
178 std::scoped_lock<std::mutex> lock(_data->mutex);
180 if (_data->availableElements.empty())
183 rawPtr =
new TType(std::forward<TArgs>(p_args)...);
187 rawPtr = _data->availableElements.back().release();
188 _data->availableElements.pop_back();
192 new (rawPtr) TType(std::forward<TArgs>(p_args)...);
196 std::weak_ptr<Data> weakData = _data;
198 auto deleter = [weakData](TType *p_ptr) {
199 if (
auto weakDataContent = weakData.lock())
201 std::scoped_lock<std::mutex> lock(weakDataContent->mutex);
203 if (weakDataContent->closed ==
false && weakDataContent->availableElements.size() < weakDataContent->maximumSize)
205 weakDataContent->availableElements.emplace_back(p_ptr);
214 return Object(rawPtr, deleter);
Thread-safe object pool that reuses allocations with custom destruction.
Definition spk_pool.hpp:29
void resize(size_t p_newSize, TArgs &&...p_args)
Adjusts the pool size by constructing or discarding objects.
Definition spk_pool.hpp:123
Pool()
Constructs an empty pool with unlimited capacity.
Definition spk_pool.hpp:52
std::unique_ptr< TType, Deleter > Object
Unique pointer type that recycles its payload back into the pool.
Definition spk_pool.hpp:34
void setMaximumAllocationSize(size_t p_size)
Limits the number of recyclable objects stored by the pool.
Definition spk_pool.hpp:73
~Pool()
Marks the pool as closed and prevents further allocations.
Definition spk_pool.hpp:60
void allocate(TArgs &&...p_args)
Pre-allocates a new instance and pushes it into the available set.
Definition spk_pool.hpp:105
std::function< void(TType *)> Deleter
Custom deleter used to return instances to the pool.
Definition spk_pool.hpp:32
void release()
Clears all cached objects without closing the pool.
Definition spk_pool.hpp:146
size_t size() const
Retrieves the number of available objects stored in the pool.
Definition spk_pool.hpp:94
Object obtain(TArgs &&...p_args)
Provides an object from the pool, constructing one if necessary.
Definition spk_pool.hpp:164