Zrythm v2.0.0-DEV
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
object_pool.h
1// SPDX-FileCopyrightText: © 2024 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
4#pragma once
5
6#include <memory>
7#include <mutex>
8#include <vector>
9
10#include "utils/mpmc_queue.h"
11
17
18template <typename T, bool EnableDebug = false>
19class [[deprecated ("Use a pre-filled MPMCQueue instead")]] ObjectPool
20{
21public:
22 static_assert (
23 std::is_default_constructible_v<T>,
24 "T must be default-constructible");
25
26 ObjectPool (size_t initial_capacity = 64) { reserve (initial_capacity); }
27
28 T * acquire ()
29 {
30 T * object;
31 if (available_.pop_front (object))
32 {
33 if constexpr (EnableDebug)
34 {
35 num_in_use.fetch_add (1, std::memory_order_relaxed);
36 }
37 return object;
38 }
39
40 if (size_ == capacity_)
41 {
42 expand ();
43 }
44
45 return acquire ();
46 }
47
48 void release (T * object)
49 {
50 available_.push_back (object);
51 if constexpr (EnableDebug)
52 {
53 num_in_use.fetch_add (-1);
54 }
55 }
56
57 void reserve (size_t size)
58 {
59 available_.reserve (size);
60 while (size_ < size)
61 {
62 expand ();
63 }
64 }
65
66 auto get_num_in_use () const { return num_in_use.load (); }
67 auto get_capacity () const { return capacity_.load (); }
68 auto get_size () const { return size_.load (); }
69
70private:
71 void expand ()
72 {
73 std::lock_guard<std::mutex> lock (expand_mutex_);
74
75 // Check again after acquiring lock in case another thread already expanded
76 if (size_ == capacity_)
77 {
78 size_t old_capacity = capacity_;
79 if (capacity_ == 0)
80 {
81 capacity_ = 1;
82 }
83 capacity_.store (capacity_ * 2);
84
85 buffer_.reserve (capacity_);
86
87 for (size_t i = old_capacity; i < capacity_; ++i)
88 {
89 buffer_.emplace_back (std::make_unique<T> ());
90 available_.push_back (buffer_.back ().get ());
91 }
92
93 size_.store (capacity_.load ());
94 }
95 }
96
97 std::vector<std::unique_ptr<T>> buffer_;
98 MPMCQueue<T *> available_;
99 std::atomic<size_t> capacity_{ 0 };
100 std::atomic<size_t> size_{ 0 };
101 std::mutex expand_mutex_;
102
103 // Debug counter
104 std::atomic<size_t> num_in_use;
105};
Multiple Producer Multiple Consumer lock-free queue.
Definition mpmc_queue.h:65