Nix (Dev) 3.5.10
dev - 3.5.10 - 1af9301
Loading...
Searching...
No Matches
CircularQueue.hpp
Go to the documentation of this file.
1#ifndef IV_SRC_CONTAINERS_CIRCULARQUEUE_HPP_
2#define IV_SRC_CONTAINERS_CIRCULARQUEUE_HPP_
3
4#include <array>
5#include <condition_variable>
6#include <functional>
7#include <mutex>
8#include <type_traits>
9
11{
12
13template<typename T, uint64_t Size>
15{
16public:
17 CircularQueue() = default;
18 CircularQueue(const CircularQueue &) = delete;
19
21 {
22 clear();
23 }
24
25 CircularQueue &operator=(const CircularQueue &other) = delete;
26
27 void pop(T &item)
28 {
29 std::unique_lock<std::mutex> lock(m_mutex);
30
31 if (unblockingEmpty())
32 {
33 m_cond.wait(lock);
34 }
35
36 item = m_data[m_front];
38 }
39
40 void pop()
41 {
42 std::unique_lock<std::mutex> lock(m_mutex);
43
44 if (unblockingEmpty())
45 {
46 m_cond.wait(lock);
47 }
48
50 }
51
52 bool popWithFilter(T &item, const std::function<bool(const T &)> &filter)
53 {
54 std::unique_lock<std::mutex> lock(m_mutex);
55
56 if (unblockingEmpty())
57 {
58 m_cond.wait(lock);
59 }
60
61 while (not unblockingEmpty() and not filter(m_data[m_front]))
62 {
64 }
65
66 if (not unblockingEmpty())
67 {
68 item = m_data[m_front];
70 return true;
71 }
72
73 return false;
74 }
75
76 void get(T &item)
77 {
78 std::unique_lock<std::mutex> lock(m_mutex);
79
80 if (unblockingEmpty())
81 {
82 m_cond.wait(lock);
83 }
84
85 item = m_data[m_front];
86 }
87
88 virtual bool push(const T &item)
89 {
90 std::unique_lock<std::mutex> lock(m_mutex);
91
92 if (not unblockingFull())
93 {
94 m_data[m_rear] = item;
95 m_rear = (m_rear + 1) % Size;
96 ++m_occupied;
97 m_cond.notify_one();
98
99 return true;
100 }
101
102 return false;
103 }
104
105 void clear()
106 {
107 std::unique_lock<std::mutex> lock(m_mutex);
108
109 while (not unblockingEmpty())
110 {
111 if constexpr (std::is_pointer_v<T>)
112 {
113 delete &m_data[m_front];
114 m_data[m_front] = nullptr;
115 }
116
118 }
119 }
120
121 bool empty()
122 {
123 std::unique_lock<std::mutex> lock(m_mutex);
124 return unblockingEmpty();
125 }
126
127 bool full()
128 {
129 std::unique_lock<std::mutex> lock(m_mutex);
130 return unblockingFull();
131 }
132
133 uint64_t size()
134 {
135 return Size;
136 }
137
138 uint64_t occupied()
139 {
140 std::unique_lock<std::mutex> lock(m_mutex);
141 return m_occupied;
142 }
143
144private:
145 [[nodiscard]] bool unblockingFull() const
146 {
147 return m_occupied == Size;
148 }
149
150 [[nodiscard]] bool unblockingEmpty() const
151 {
152 return m_occupied == 0;
153 }
154
156 {
157 m_front = (m_front + 1) % Size;
158 --m_occupied;
159 }
160
161 static_assert(std::is_default_constructible_v<T>, "T must be default constructible");
162 static_assert(Size >= 50, "Size is too small!");
163 static_assert(Size <= 5000, "Size is too long!");
164
165 std::array<T, Size> m_data;
166 uint64_t m_front {0};
167 uint64_t m_rear {0};
168 uint64_t m_occupied {0};
169 std::mutex m_mutex;
170 std::condition_variable_any m_cond;
171};
172
173template<typename T, uint64_t Size>
175{
176public:
179
185 bool push(const T &item) override
186 {
187 bool didPop {false};
188 while (not CircularQueue<T, Size>::push(item))
189 {
190 didPop = true;
192 }
193
194 return didPop;
195 }
196};
197
198}// namespace iv::containers
199
200#endif//IV_SRC_CONTAINERS_CIRCULARQUEUE_HPP_
Definition CircularQueue.hpp:15
uint64_t m_occupied
Definition CircularQueue.hpp:168
void get(T &item)
Definition CircularQueue.hpp:76
virtual bool push(const T &item)
Definition CircularQueue.hpp:88
void unblockingPop()
Definition CircularQueue.hpp:155
uint64_t occupied()
Definition CircularQueue.hpp:138
std::condition_variable_any m_cond
Definition CircularQueue.hpp:170
std::array< T, Size > m_data
Definition CircularQueue.hpp:165
uint64_t m_rear
Definition CircularQueue.hpp:167
std::mutex m_mutex
Definition CircularQueue.hpp:169
void clear()
Definition CircularQueue.hpp:105
virtual ~CircularQueue()
Definition CircularQueue.hpp:20
void pop()
Definition CircularQueue.hpp:40
bool empty()
Definition CircularQueue.hpp:121
uint64_t size()
Definition CircularQueue.hpp:133
bool popWithFilter(T &item, const std::function< bool(const T &)> &filter)
Definition CircularQueue.hpp:52
CircularQueue & operator=(const CircularQueue &other)=delete
bool unblockingFull() const
Definition CircularQueue.hpp:145
bool full()
Definition CircularQueue.hpp:127
bool unblockingEmpty() const
Definition CircularQueue.hpp:150
CircularQueue(const CircularQueue &)=delete
void pop(T &item)
Definition CircularQueue.hpp:27
uint64_t m_front
Definition CircularQueue.hpp:166
Definition CircularQueue.hpp:175
OverwritingCircularQueue(const OverwritingCircularQueue &)=delete
bool push(const T &item) override
Pushes an item into the queue. If the queue is full, it will pop the front item and push the new one.
Definition CircularQueue.hpp:185
Definition CircularQueue.hpp:11