130 size_t total_created{0};
160 void safe_dec_borrowed_and_live() noexcept;
162 [[nodiscard]]
bool should_reset_on_acquire() const noexcept;
164 [[nodiscard]]
bool should_reset_on_release() const noexcept;
166 [[noreturn]] static
void throw_invalid_size();
168 [[noreturn]] static
void throw_factory_null_pre_fill();
170 [[noreturn]] static
void throw_factory_null();
172 [[noreturn]]
void throw_exhausted(
size_t pool_size) const;
180 size_t live_count_{0};
181 size_t total_created_{0};
196 template <
typename T>
262 [[nodiscard]] std::unique_ptr<T, typename ObjectPool<T>::PoolDeleter>
get();
271 [[nodiscard]] std::shared_ptr<T>
get_shared();
280 [[nodiscard]] T*
borrow();
301 [[nodiscard]]
size_t size()
const;
306 std::unique_ptr<T> acquire();
308 void release(std::unique_ptr<T> obj) noexcept;
312 std::vector<std::unique_ptr<T>> pool_;
321 template <
typename T>
325 factory_callback_(std::move(factory_callback)),
326 reset_callback_(std::move(reset_callback)) {
327 pool_.reserve(initial_size);
328 for (
size_t i = 0; i < initial_size; ++i) {
329 auto obj = factory_callback_();
336 reset_callback_(*obj);
339 pool_.emplace_back(std::move(obj));
346 template <
typename T>
348 std::unique_ptr<T> obj = acquire();
351 if (should_reset_on_acquire() && reset_callback_) {
352 reset_callback_(*obj);
355 release(std::move(obj));
359 return {obj.release(),
PoolDeleter{this->weak_from_this()}};
362 template <
typename T>
364 std::unique_ptr<T> obj = acquire();
367 if (should_reset_on_acquire() && reset_callback_) {
368 reset_callback_(*obj);
371 release(std::move(obj));
375 return {obj.release(),
PoolDeleter{this->weak_from_this()}};
378 template <
typename T>
380 std::unique_ptr<T> obj = acquire();
383 if (should_reset_on_acquire() && reset_callback_) {
384 reset_callback_(*obj);
387 release(std::move(obj));
391 return obj.release();
394 template <
typename T>
400 std::unique_ptr<T> u(ptr);
401 release(std::move(u));
404 template <
typename T>
406 std::lock_guard lock(mutex_);
407 return {pool_.size(), borrowed_, total_created_, max_size_};
410 template <
typename T>
412 std::lock_guard lock(mutex_);
416 template <
typename T>
418 return [] {
return std::make_unique<T>(); };
421 template <
typename T>
422 inline std::unique_ptr<T> ObjectPool<T>::acquire() {
423 std::unique_lock lock(mutex_);
426 std::unique_ptr<T> obj = std::move(pool_.back());
432 if VUNLIKELY (max_size_ > 0 && live_count_ >= max_size_) {
433 throw_exhausted(pool_.size());
442 std::unique_ptr<T> new_obj;
444 new_obj = factory_callback_();
447 throw_factory_null();
460 template <
typename T>
461 inline void ObjectPool<T>::release(std::unique_ptr<T> obj) noexcept {
466 if (should_reset_on_release() && reset_callback_) {
468 reset_callback_(*obj);
470 safe_dec_borrowed_and_live();
476 std::lock_guard lock(mutex_);
483 pool_.emplace_back(std::move(obj));
485 if (live_count_ > 0) {
492 template <
typename T>
498 if (
auto sp = weak_pool.lock()) {
499 std::unique_ptr<T> u(ptr);
500 sp->release(std::move(u));
Type-independent base of ObjectPool that owns counters, mutex and policy state.
Definition: object_pool.h:106
size_t total_created_
Definition: object_pool.h:181
size_t borrowed() const
Returns the number of objects currently checked out of the pool.
bool should_reset_on_release() const noexcept
size_t live_count_
Definition: object_pool.h:180
size_t max_size() const noexcept
Returns the configured upper bound on live objects.
static void throw_factory_null_pre_fill()
Policy
Decides when (or whether) the user-supplied ResetCallback runs.
Definition: object_pool.h:116
@ kPolicyRelease
Reset on the return-to-pool path.
Definition: object_pool.h:118
std::mutex mutex_
Definition: object_pool.h:177
size_t total_created() const
Returns the cumulative number of objects ever produced by the factory.
Thread-safe recycling pool for instances of T with RAII acquisition.
Definition: object_pool.h:197
std::shared_ptr< T > get_shared()
Acquires an object wrapped in a shared_ptr with automatic return.
Definition: object_pool.h:363
T * borrow()
Acquires an object as a raw pointer; the caller owns the return path.
Definition: object_pool.h:379
ObjectPool(FactoryCallback factory_callback=get_default_factory(), size_t initial_size=0, size_t max_size=0, ResetCallback reset_callback=nullptr, Policy policy=kPolicyRelease)
Constructs the pool and optionally pre-warms the free list.
Definition: object_pool.h:322
void give_back(T *ptr)
Returns an object obtained from borrow() back to the pool.
Definition: object_pool.h:395
size_t size() const
Returns the number of objects currently idle on the free list.
Definition: object_pool.h:411
std::unique_ptr< T, typename ObjectPool< T >::PoolDeleter > get()
Acquires an object wrapped in a unique_ptr with automatic return.
Definition: object_pool.h:347
Stats stats() const
Captures a thread-safe snapshot of pool statistics.
Definition: object_pool.h:405
Pool-backed type-erased callables: copyable vlink::Function and move-only vlink::MoveFunction.
Cross-platform macros for visibility, branch hints, copy prevention, singletons and string helpers.
#define VUNLIKELY(...)
Short alias for VLINK_UNLIKELY.
Definition: macros.h:289
#define VLINK_EXPORT
Definition: macros.h:81
#define VLIKELY(...)
Short alias for VLINK_LIKELY.
Definition: macros.h:284
#define VLINK_DISALLOW_COPY_AND_ASSIGN(classname)
Deletes the copy constructor and copy-assignment operator of classname.
Definition: macros.h:174
Point-in-time snapshot of internal pool counters.
Definition: object_pool.h:127
Custom deleter installed on every RAII handle handed out by get / get_shared.
Definition: object_pool.h:227
std::weak_ptr< ObjectPool< T > > weak_pool
Weak reference to the parent pool.
Definition: object_pool.h:234
void operator()(T *ptr) const noexcept
Returns ptr to the pool, or deletes it when the pool is gone.
Definition: object_pool.h:493