Deluge Firmware 1.3.0
Build date: 2025.04.16
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
22namespace deluge::memory {
27template <typename T, template <typename> typename Alloc = std::allocator>
28class ObjectPool {
29 static constexpr size_t kDefaultSize = 48;
30 ObjectPool() { repopulate(); };
31
32public:
34 using value_type = T;
35
36 ~ObjectPool() { clear(); };
37
40 static constexpr ObjectPool& get() {
41 static thread_local ObjectPool instance;
42 return instance;
43 }
44
47 void resize(size_t n) {
48 capacity_ = n;
49 if (capacity_ < objects_.size()) {
50 // We need to shrink the pool
51 while (objects_.size() > capacity_) {
52 alloc_.deallocate(objects_.top(), 1);
53 objects_.pop();
54 }
55 }
56 }
57
60 [[nodiscard]] size_t capacity() const { return capacity_; }
61
64 [[nodiscard]] size_t size() const { return objects_.size(); }
65
68 static void recycle(gsl::owner<T*> obj) {
69 obj->~T();
70
71 ObjectPool& op = get();
72 if (op.objects_.size() < op.capacity_) {
73 op.objects_.push(obj);
74 }
75 else {
76 Alloc<T>().deallocate(obj, 1);
77 }
78 }
79
82 void repopulate() noexcept(false) {
83 for (size_t i = objects_.size(); i < capacity_; ++i) {
84 objects_.push(alloc_.allocate(1));
85 }
86 }
87
89 using pointer_type = std::unique_ptr<T, decltype(&recycle)>;
90
96 template <typename... Args>
97 [[nodiscard]] pointer_type acquire(Args&&... args) noexcept(false) {
98 T* obj = nullptr;
99 if (objects_.empty()) {
100 obj = alloc_.allocate(1);
101 }
102 else {
103 obj = objects_.top();
104 objects_.pop();
105 }
106 return {new (obj) T(std::forward<Args>(args)...), &recycle};
107 }
108
110 void clear() {
111 while (!objects_.empty()) {
112 alloc_.deallocate(objects_.top(), 1);
113 objects_.pop();
114 }
115 }
116
119 [[nodiscard]] constexpr bool empty() const { return objects_.empty(); }
120
121private:
122 size_t capacity_ = kDefaultSize;
123 std::stack<T*, std::vector<T*, Alloc<T*>>> objects_;
124 Alloc<T> alloc_;
125};
126} // namespace deluge::memory
void clear()
Clears the pool.
Definition object_pool.h:110
void resize(size_t n)
Sets the size of the pool.
Definition object_pool.h:47
size_t size() const
Gets the number of objects in the pool.
Definition object_pool.h:64
pointer_type acquire(Args &&... args) noexcept(false)
Acquires an object from the pool.
Definition object_pool.h:97
size_t capacity() const
Gets the capacity of the pool.
Definition object_pool.h:60
T value_type
The type of object in the pool.
Definition object_pool.h:34
void repopulate() noexcept(false)
Repopulates the pool to its original size.
Definition object_pool.h:82
static constexpr ObjectPool & get()
Gets the global pool for a given object.
Definition object_pool.h:40
std::unique_ptr< T, decltype(&recycle)> pointer_type
A managed pointer type for an object from the pool.
Definition object_pool.h:89
static void recycle(gsl::owner< T * > obj)
Definition object_pool.h:68
constexpr bool empty() const
Checks if the pool is empty.
Definition object_pool.h:119