Nebula
Loading...
Searching...
No Matches
safequeue.h
Go to the documentation of this file.
1#pragma once
2//------------------------------------------------------------------------------
19#include "util/queue.h"
21#include "threading/event.h"
22
23//------------------------------------------------------------------------------
24namespace Threading
25{
26template<class TYPE> class SafeQueue
27{
28public:
33
35 void operator=(const SafeQueue<TYPE>& rhs);
41 SizeT Size() const;
43 bool IsEmpty() const;
45 void Clear();
47 void Enqueue(const TYPE& e);
48 void Enqueue(TYPE&& e);
52 TYPE Dequeue();
54 TYPE DequeueSafe(const TYPE& failed);
58 template<int STACK_SIZE>
61 TYPE Peek() const;
63 void Wait();
65 void WaitTimeout(int ms);
67 void Signal();
69 void EraseMatchingElements(const TYPE& e);
70
71protected:
76};
77
78//------------------------------------------------------------------------------
81template<class TYPE>
84{
85 // empty
86}
87
88//------------------------------------------------------------------------------
91template<class TYPE>
93{
94 this->criticalSection.Enter();
95 this->queue = rhs.queue;
97 this->criticalSection.Leave();
98}
99
100//------------------------------------------------------------------------------
103template<class TYPE> void
105{
106 this->criticalSection.Enter();
107 this->queue = rhs.queue;
109 this->criticalSection.Leave();
110}
111
112//------------------------------------------------------------------------------
115template<class TYPE> void
117{
118 this->criticalSection.Enter();
119 this->signalOnEnqueueEnabled = b;
120 this->criticalSection.Leave();
121}
122
123//------------------------------------------------------------------------------
126template<class TYPE> bool
128{
129 this->criticalSection.Enter();
130 return this->signalOnEnqueueEnabled;
131 this->criticalSection.Leave();
132}
133
134//------------------------------------------------------------------------------
137template<class TYPE> void
139{
140 this->criticalSection.Enter();
141 this->queue.Clear();
142 this->criticalSection.Leave();
143}
144
145//------------------------------------------------------------------------------
148template<class TYPE> SizeT
150{
151 return this->queue.Size();
152}
153
154//------------------------------------------------------------------------------
157template<class TYPE> bool
159{
160 this->criticalSection.Enter();
161 bool isEmpty = this->queue.IsEmpty();
162 this->criticalSection.Leave();
163 return isEmpty;
164}
165
166//------------------------------------------------------------------------------
169template<class TYPE> void
171{
172 this->criticalSection.Enter();
173 this->queue.Enqueue(e);
174 this->criticalSection.Leave();
175 if (this->signalOnEnqueueEnabled)
176 {
177 this->enqueueEvent.Signal();
178 }
179}
180
181//------------------------------------------------------------------------------
184template<class TYPE> void
186{
187 this->criticalSection.Enter();
188 this->queue.Enqueue(std::move(e));
189 this->criticalSection.Leave();
190 if (this->signalOnEnqueueEnabled)
191 {
192 this->enqueueEvent.Signal();
193 }
194}
195
196//------------------------------------------------------------------------------
199template<class TYPE> void
201{
202 this->criticalSection.Enter();
203 for (auto &i : a)
204 {
205 this->queue.Enqueue(i);
206 }
207 this->criticalSection.Leave();
208 if (this->signalOnEnqueueEnabled)
209 {
210 this->enqueueEvent.Signal();
211 }
212}
213
214//------------------------------------------------------------------------------
217template<class TYPE> TYPE
219{
220 this->criticalSection.Enter();
221 TYPE e = this->queue.Dequeue();
222 this->criticalSection.Leave();
223 return e;
224}
225
226//------------------------------------------------------------------------------
229template<class TYPE> TYPE
231{
232 this->criticalSection.Enter();
233 TYPE e = failed;
234 if (!this->queue.IsEmpty())
235 {
236 e = this->queue.Dequeue();
237 }
238 this->criticalSection.Leave();
239 return e;
240}
241
242//------------------------------------------------------------------------------
245template<class TYPE> void
247{
248 this->criticalSection.Enter();
249#if NEBULA_ENABLE_PERFORMANCE_WARNINGS
250 n_warn_fmt(outArray.Capacity() >= this->queue.Size(), "SafeQueue::DequeueAll(): (PERFORMANCE) Output array is too small (%d), requires (%d), array will have to grow.\n", outArray.Capacity(), this->queue.Size());
251#endif
252 outArray.Clear();
253 for (IndexT i = 0; i < this->queue.Size(); i++)
254 {
255 outArray.Append(std::move(this->queue[i]));
256 }
257 this->queue.Clear();
258 this->criticalSection.Leave();
259}
260
261//------------------------------------------------------------------------------
264template<class TYPE>
265template<int STACK_SIZE>
266void
268{
269 this->criticalSection.Enter();
270#if NEBULA_ENABLE_PERFORMANCE_WARNINGS
271 n_warn_fmt(outArray.Capacity() >= this->queue.Size(), "SafeQueue::DequeueAll(): (PERFORMANCE) Output array is too small (%d), requires (%d), array will have to grow.\n", outArray.Capacity(), this->queue.Size());
272#endif
273 outArray.Clear();
274 for (IndexT i = 0; i < this->queue.Size(); i++)
275 {
276 outArray.Append(std::move(this->queue[i]));
277 }
278 this->queue.Clear();
279 this->criticalSection.Leave();
280}
281
282//------------------------------------------------------------------------------
285template<class TYPE> TYPE
287{
288 this->criticalSection.Enter();
289 TYPE e = this->queue.Peek();
290 this->criticalSection.Leave();
291 return e;
292}
293
294//------------------------------------------------------------------------------
297template<class TYPE> void
299{
300 if (this->signalOnEnqueueEnabled && this->IsEmpty())
301 {
302 this->enqueueEvent.Wait();
303 }
304}
305
306//------------------------------------------------------------------------------
309template<class TYPE> void
311{
312 if (this->signalOnEnqueueEnabled && this->IsEmpty())
313 {
314 this->enqueueEvent.WaitTimeout(ms);
315 }
316}
317
318//------------------------------------------------------------------------------
324template<class TYPE> void
326{
327 this->enqueueEvent.Signal();
328}
329
330//------------------------------------------------------------------------------
333template<class TYPE> void
335{
336 this->criticalSection.Enter();
337 IndexT i;
338 for (i = this->queue.Size() - 1; i >= 0; i--)
339 {
340 if (e == this->queue[i])
341 {
342 this->queue.EraseIndex(i);
343 }
344 }
345 this->criticalSection.Leave();
346}
347
348} // namespace Threading
349//------------------------------------------------------------------------------
350
Critical section objects are used to protect a portion of code from parallel execution.
void DequeueAll(Util::Array< TYPE > &outArray)
dequeue all events (only requires one lock)
Definition safequeue.h:246
void Signal()
signal the internal event, so that Wait() will return
Definition safequeue.h:325
void EnqueueArray(const Util::Array< TYPE > &a)
enqueue an array of elements
Definition safequeue.h:200
TYPE Peek() const
access to element at front of queue without removing it
Definition safequeue.h:286
TYPE DequeueSafe(const TYPE &failed)
remove the element from the front of the queue and returns the failed object if empty
Definition safequeue.h:230
void EraseMatchingElements(const TYPE &e)
erase all matching elements
Definition safequeue.h:334
SafeQueue(const SafeQueue< TYPE > &rhs)
copy constructor
Definition safequeue.h:92
bool IsEmpty() const
return true if queue is empty
Definition safequeue.h:158
void DequeueAll(Util::Array< TYPE, STACK_SIZE > &outArray)
Dequeue all events to an array with a stack size.
Definition safequeue.h:267
void WaitTimeout(int ms)
wait until queue contains at least one element, or time-out happens
Definition safequeue.h:310
void SetSignalOnEnqueueEnabled(bool b)
enable/disable signalling on Enqueue() (default is enabled)
Definition safequeue.h:116
Event enqueueEvent
Definition safequeue.h:73
void Enqueue(const TYPE &e)
add element to the back of the queue
Definition safequeue.h:170
void Wait()
wait until queue contains at least one element
Definition safequeue.h:298
Util::Queue< TYPE > queue
Definition safequeue.h:75
bool signalOnEnqueueEnabled
Definition safequeue.h:74
TYPE Dequeue()
remove the element from the front of the queue
Definition safequeue.h:218
bool IsSignalOnEnqueueEnabled() const
return signalling-on-Enqueue() flag
Definition safequeue.h:127
SizeT Size() const
returns number of elements in the queue
Definition safequeue.h:149
void operator=(const SafeQueue< TYPE > &rhs)
assignment operator
Definition safequeue.h:104
SafeQueue()
constructor
Definition safequeue.h:82
void Clear()
remove all elements from the queue
Definition safequeue.h:138
void Enqueue(TYPE &&e)
Definition safequeue.h:185
CriticalSection criticalSection
Definition safequeue.h:72
Nebula's dynamic array class.
Definition array.h:60
const SizeT Capacity() const
get overall allocated size of array in number of elements
Definition array.h:900
void Clear()
clear array (calls destructors)
Definition array.h:1207
void Append(const TYPE &first, const ELEM_TYPE &... elements)
Append multiple elements to the end of the array.
Definition array.h:1334
Nebula's queue class (a FIFO container).
Definition queue.h:28
#define n_warn_fmt(exp, msg,...)
Definition debug.h:56
The Jobs2 system provides a set of threads and a pool of jobs from which threads can pickup work.
Definition jobs2.h:16
int SizeT
Definition types.h:42
int IndexT
Definition types.h:41