Deluge Firmware 1.3.0
Build date: 2025.06.05
Loading...
Searching...
No Matches
object_pool.h
1/*
2 * Copyright © 2025 Katherine Whitlock
3 *
4 * This file is part of The Synthstrom Audible Deluge Firmware.
5 *
6 * The Synthstrom Audible Deluge Firmware is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software Foundation,
8 * either version 3 of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * See the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along with this program.
15 * If not, see <https://www.gnu.org/licenses/>.
16 */
17#pragma once
18#include <gsl/gsl>
19#include <memory>
20#include <stack>
21#include <vector>
22
23namespace deluge::memory {
28template <typename T, template <typename> typename Alloc = std::allocator>
29class ObjectPool {
30 static constexpr size_t kDefaultSize = 48;
31 ObjectPool() { repopulate(); };
32
33public:
35 using value_type = T;
36
37 ~ObjectPool() { clear(); };
38
41 static constexpr ObjectPool& get() {
42 static thread_local ObjectPool instance;
43 return instance;
44 }
45
48 void resize(size_t n) {
49 capacity_ = n;
50 if (capacity_ < objects_.size()) {
51 // We need to shrink the pool
52 while (objects_.size() > capacity_) {
53 alloc_.deallocate(objects_.top(), 1);
54 objects_.pop();
55 }
56 }
57 }
58
61 [[nodiscard]] size_t capacity() const { return capacity_; }
62
65 [[nodiscard]] size_t size() const { return objects_.size(); }
66
69 static void recycle(gsl::owner<T*> obj) {
70 obj->~T();
71
72 ObjectPool& op = get();
73 if (op.objects_.size() < op.capacity_) {
74 op.objects_.push(obj);
75 }
76 else {
77 Alloc<T>().deallocate(obj, 1);
78 }
79 }
80
83 void repopulate() noexcept(false) {
84 for (size_t i = objects_.size(); i < capacity_; ++i) {
85 objects_.push(alloc_.allocate(1));
86 }
87 }
88
90 using pointer_type = std::unique_ptr<T, decltype(&recycle)>;
91
97 template <typename... Args>
98 [[nodiscard]] pointer_type acquire(Args&&... args) noexcept(false) {
99 T* obj = nullptr;
100 if (objects_.empty()) {
101 obj = alloc_.allocate(1);
102 }
103 else {
104 obj = objects_.top();
105 objects_.pop();
106 }
107 return {new (obj) T(std::forward<Args>(args)...), &recycle};
108 }
109
111 void clear() {
112 while (!objects_.empty()) {
113 alloc_.deallocate(objects_.top(), 1);
114 objects_.pop();
115 }
116 }
117
120 [[nodiscard]] constexpr bool empty() const { return objects_.empty(); }
121
122private:
123 size_t capacity_ = kDefaultSize;
124 std::stack<T*, std::vector<T*, Alloc<T*>>> objects_;
125 Alloc<T> alloc_;
126};
127} // namespace deluge::memory
void clear()
Clears the pool.
Definition object_pool.h:111
void resize(size_t n)
Sets the size of the pool.
Definition object_pool.h:48
size_t size() const
Gets the number of objects in the pool.
Definition object_pool.h:65
pointer_type acquire(Args &&... args) noexcept(false)
Acquires an object from the pool.
Definition object_pool.h:98
size_t capacity() const
Gets the capacity of the pool.
Definition object_pool.h:61
T value_type
The type of object in the pool.
Definition object_pool.h:35
void repopulate() noexcept(false)
Repopulates the pool to its original size.
Definition object_pool.h:83
static constexpr ObjectPool & get()
Gets the global pool for a given object.
Definition object_pool.h:41
std::unique_ptr< T, decltype(&recycle)> pointer_type
A managed pointer type for an object from the pool.
Definition object_pool.h:90
static void recycle(gsl::owner< T * > obj)
Definition object_pool.h:69
constexpr bool empty() const
Checks if the pool is empty.
Definition object_pool.h:120