Corium 1.1.0
High-Performance Zero-Heap C++20 MPSC Application Runtime
Loading...
Searching...
No Matches
QueuePolicies.hpp
Go to the documentation of this file.
1
7#pragma once
8
9#include <cstddef>
10#include <cstdint>
11#include <queue>
12#include <type_traits>
13#include <utility>
14
15#if defined(_WIN32) || defined(_WIN64) || defined(__unix__) || defined(__APPLE__) || (defined(_GLIBCXX_HAS_GTHREADS) && _GLIBCXX_HAS_GTHREADS) || defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
16#include <mutex>
17#ifndef CORIUM_HAS_STD_MUTEX
18#define CORIUM_HAS_STD_MUTEX 1
19#endif
20#else
21#ifndef CORIUM_HAS_STD_MUTEX
22#define CORIUM_HAS_STD_MUTEX 0
23#endif
24#endif
25
26#include "corium/Events.hpp"
28
29namespace corium {
30
32enum class EventPriority : uint8_t {
33 High = 0,
34 Normal = 1,
35 Low = 2
36};
37
42template <typename EventVariant = DefaultEvents, size_t Capacity = 1024>
44public:
45 using EventType = EventVariant;
46 static constexpr std::size_t capacity = Capacity;
47
48 struct PushResult {
49 bool pushed;
51 };
52
54 PushResult tryPush(EventVariant&& event, EventPriority priority = EventPriority::Normal)
55 {
56 (void)priority;
57 auto res = _ringBuffer.tryPush(std::move(event));
58 return {res.pushed, res.wasEmpty};
59 }
60
62 PushResult tryPush(const EventVariant& event, EventPriority priority = EventPriority::Normal)
63 {
64 EventVariant copy = event;
65 return tryPush(std::move(copy), priority);
66 }
67
69 bool tryPop(EventVariant& event)
70 {
71 return _ringBuffer.tryPop(event);
72 }
73
75 [[nodiscard]] bool empty() const noexcept
76 {
77 return _ringBuffer.empty();
78 }
79
80private:
82};
83
90template <
91 typename EventVariant = DefaultEvents,
92 size_t HighCapacity = 256,
93 size_t NormalCapacity = 1024,
94 size_t LowCapacity = 0
95>
97public:
98 using EventType = EventVariant;
100 static constexpr std::size_t capacity = HighCapacity + NormalCapacity + (LowCapacity > 0 ? LowCapacity : 0);
101
102 struct PushResult {
103 bool pushed;
105 };
106
108 PushResult tryPush(EventVariant&& event, EventPriority priority = EventPriority::Normal)
109 {
110 bool wasOverallEmpty = empty();
111 bool pushed = false;
112
113 switch (priority) {
114 case EventPriority::High: {
115 auto res = _highRingBuffer.tryPush(std::move(event));
116 pushed = res.pushed;
117 break;
118 }
120 auto res = _normalRingBuffer.tryPush(std::move(event));
121 pushed = res.pushed;
122 break;
123 }
124 case EventPriority::Low: {
125 if constexpr (LowCapacity > 0) {
126 auto res = _lowRingBuffer.tryPush(std::move(event));
127 pushed = res.pushed;
128 } else {
129 auto res = _normalRingBuffer.tryPush(std::move(event));
130 pushed = res.pushed;
131 }
132 break;
133 }
134 }
135
136 return {pushed, wasOverallEmpty};
137 }
138
140 PushResult tryPush(const EventVariant& event, EventPriority priority = EventPriority::Normal)
141 {
142 EventVariant copy = event;
143 return tryPush(std::move(copy), priority);
144 }
145
147 bool tryPop(EventVariant& event)
148 {
149 if (_highRingBuffer.tryPop(event)) {
150 return true;
151 }
152 if (_normalRingBuffer.tryPop(event)) {
153 return true;
154 }
155 if constexpr (LowCapacity > 0) {
156 if (_lowRingBuffer.tryPop(event)) {
157 return true;
158 }
159 }
160 return false;
161 }
162
164 [[nodiscard]] bool empty() const noexcept
165 {
166 bool isEmpty = _highRingBuffer.empty() && _normalRingBuffer.empty();
167 if constexpr (LowCapacity > 0) {
168 isEmpty = isEmpty && _lowRingBuffer.empty();
169 }
170 return isEmpty;
171 }
172
173private:
176 [[no_unique_address]] std::conditional_t<(LowCapacity > 0),
177 MpscRingBuffer<EventVariant, (LowCapacity > 0 ? LowCapacity : 1)>,
178 std::monostate
179 > _lowRingBuffer{};
180};
181
184template <typename EventVariant = DefaultEvents>
186public:
187 using EventType = EventVariant;
188
189 struct PushResult {
190 bool pushed;
192 };
193
196 {
197 (void)priority;
198#if CORIUM_HAS_STD_MUTEX
199 std::lock_guard<std::mutex> lock(_mutex);
200#endif
201 bool wasEmpty = _queue.empty();
202 _queue.push(std::move(event));
203 return {true, wasEmpty};
204 }
205
207 bool tryPop(EventVariant& event)
208 {
209#if CORIUM_HAS_STD_MUTEX
210 std::lock_guard<std::mutex> lock(_mutex);
211#endif
212 if (_queue.empty()) {
213 return false;
214 }
215 event = std::move(_queue.front());
216 _queue.pop();
217 return true;
218 }
219
221 [[nodiscard]] bool empty() const
222 {
223#if CORIUM_HAS_STD_MUTEX
224 std::lock_guard<std::mutex> lock(_mutex);
225#endif
226 return _queue.empty();
227 }
228
229private:
230 std::queue<EventVariant> _queue;
231#if CORIUM_HAS_STD_MUTEX
232 mutable std::mutex _mutex;
233#endif
234};
235
239template <typename EventVariant = DefaultEvents>
241public:
242 using EventType = EventVariant;
243
244 struct PushResult {
245 bool pushed = false;
246 bool wasEmpty = false;
247 };
248
251 {
252 return {false, false};
253 }
254
256 bool tryPop(EventVariant&) noexcept
257 {
258 return false;
259 }
260
262 [[nodiscard]] bool empty() const noexcept
263 {
264 return true;
265 }
266};
267
268} // namespace corium
269
Standard lifecycle events (QuitEvent, ErrorEvent, TimerEvent).
Lock-free Multi-Producer Single-Consumer (MPSC) bounded ring buffer based on Dmitry Vyukov's algorith...
Queue Policy for a traditional mutex-protected blocking queue (power saving).
Definition QueuePolicies.hpp:185
bool tryPop(EventVariant &event)
Try to pop an event from the blocking queue.
Definition QueuePolicies.hpp:207
EventVariant EventType
Definition QueuePolicies.hpp:187
bool empty() const
Check if queue is empty.
Definition QueuePolicies.hpp:221
PushResult tryPush(EventVariant event, EventPriority priority=EventPriority::Normal)
Try to push an event into the blocking queue.
Definition QueuePolicies.hpp:195
Queue Policy for fixed-capacity, zero-allocation lock-free MPSC RingBuffer.
Definition QueuePolicies.hpp:43
PushResult tryPush(EventVariant &&event, EventPriority priority=EventPriority::Normal)
Try to push an event into the lock-free queue (thread-safe, zero allocations).
Definition QueuePolicies.hpp:54
EventVariant EventType
Definition QueuePolicies.hpp:45
bool empty() const noexcept
Check if queue is empty.
Definition QueuePolicies.hpp:75
PushResult tryPush(const EventVariant &event, EventPriority priority=EventPriority::Normal)
Try to push an event into the lock-free queue (const lvalue overload).
Definition QueuePolicies.hpp:62
static constexpr std::size_t capacity
Accessible queue capacity for profiler wiring.
Definition QueuePolicies.hpp:46
bool tryPop(EventVariant &event)
Try to pop an event from the lock-free queue (single consumer).
Definition QueuePolicies.hpp:69
Lock-free Multiple-Producer, Single-Consumer (MPSC) RingBuffer. Implements Dmitry Vyukov's algorithm ...
Definition MpscRingBuffer.hpp:33
Zero-overhead Queue Policy for services or buses that do not receive or queue incoming events....
Definition QueuePolicies.hpp:240
bool empty() const noexcept
Always returns true as no events can be queued.
Definition QueuePolicies.hpp:262
EventVariant EventType
Definition QueuePolicies.hpp:242
PushResult tryPush(EventVariant, EventPriority=EventPriority::Normal) noexcept
Always fails to push events as queue capacity is 0.
Definition QueuePolicies.hpp:250
bool tryPop(EventVariant &) noexcept
Always fails to pop events as queue capacity is 0.
Definition QueuePolicies.hpp:256
Queue Policy supporting strict event priorities using separate lock-free MPSC ring buffers....
Definition QueuePolicies.hpp:96
bool tryPop(EventVariant &event)
Try to pop an event from the priority queue (strict priority order: High -> Normal -> Low).
Definition QueuePolicies.hpp:147
PushResult tryPush(const EventVariant &event, EventPriority priority=EventPriority::Normal)
Try to push an event into the priority queue (const lvalue overload).
Definition QueuePolicies.hpp:140
PushResult tryPush(EventVariant &&event, EventPriority priority=EventPriority::Normal)
Try to push an event into the priority queue (thread-safe, zero dynamic allocation).
Definition QueuePolicies.hpp:108
static constexpr std::size_t capacity
Total accessible capacity (high + normal; low is optional).
Definition QueuePolicies.hpp:100
EventVariant EventType
Definition QueuePolicies.hpp:98
bool empty() const noexcept
Check if all priority queues are empty.
Definition QueuePolicies.hpp:164
Definition Application.hpp:16
std::variant< QuitEvent, TickEvent, UpdateEvent, ErrorEvent, SignalEvent > DefaultEvents
Default variant list of core Corium events.
Definition Events.hpp:62
EventPriority
Event priority levels for multi-priority queue policies.
Definition QueuePolicies.hpp:32
Definition QueuePolicies.hpp:189
bool wasEmpty
Definition QueuePolicies.hpp:191
bool pushed
Definition QueuePolicies.hpp:190
Definition QueuePolicies.hpp:48
bool wasEmpty
Definition QueuePolicies.hpp:50
bool pushed
Definition QueuePolicies.hpp:49
Definition QueuePolicies.hpp:244
bool pushed
Definition QueuePolicies.hpp:245
bool wasEmpty
Definition QueuePolicies.hpp:246
Definition QueuePolicies.hpp:102
bool pushed
Definition QueuePolicies.hpp:103
bool wasEmpty
Definition QueuePolicies.hpp:104