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();
56 template<int STACK_SIZE>
59 TYPE Peek() const;
61 void Wait();
63 void WaitTimeout(int ms);
65 void Signal();
67 void EraseMatchingElements(const TYPE& e);
68
69protected:
74};
75
76//------------------------------------------------------------------------------
79template<class TYPE>
81 signalOnEnqueueEnabled(true)
82{
83 // empty
84}
85
86//------------------------------------------------------------------------------
89template<class TYPE>
91{
92 this->criticalSection.Enter();
93 this->queue = rhs.queue;
94 this->signalOnEnqueueEnabled = rhs.signalOnEnqueueEnabled;
95 this->criticalSection.Leave();
96}
97
98//------------------------------------------------------------------------------
101template<class TYPE> void
103{
104 this->criticalSection.Enter();
105 this->queue = rhs.queue;
106 this->signalOnEnqueueEnabled = rhs.signalOnEnqueueEnabled;
107 this->criticalSection.Leave();
108}
109
110//------------------------------------------------------------------------------
113template<class TYPE> void
115{
116 this->criticalSection.Enter();
117 this->signalOnEnqueueEnabled = b;
118 this->criticalSection.Leave();
119}
120
121//------------------------------------------------------------------------------
124template<class TYPE> void
126{
127 this->criticalSection.Enter();
128 this->queue.Clear();
129 this->criticalSection.Leave();
130}
131
132//------------------------------------------------------------------------------
135template<class TYPE> SizeT
137{
138 return this->queue.Size();
139}
140
141//------------------------------------------------------------------------------
144template<class TYPE> bool
146{
147 this->criticalSection.Enter();
148 bool isEmpty = this->queue.IsEmpty();
149 this->criticalSection.Leave();
150 return isEmpty;
151}
152
153//------------------------------------------------------------------------------
156template<class TYPE> void
158{
159 this->criticalSection.Enter();
160 this->queue.Enqueue(e);
161 this->criticalSection.Leave();
162 if (this->signalOnEnqueueEnabled)
163 {
164 this->enqueueEvent.Signal();
165 }
166}
167
168//------------------------------------------------------------------------------
171template<class TYPE> void
173{
174 this->criticalSection.Enter();
175 this->queue.Enqueue(std::move(e));
176 this->criticalSection.Leave();
177 if (this->signalOnEnqueueEnabled)
178 {
179 this->enqueueEvent.Signal();
180 }
181}
182
183//------------------------------------------------------------------------------
186template<class TYPE> void
188{
189 this->criticalSection.Enter();
190 for (auto &i : a)
191 {
192 this->queue.Enqueue(i);
193 }
194 this->criticalSection.Leave();
195 if (this->signalOnEnqueueEnabled)
196 {
197 this->enqueueEvent.Signal();
198 }
199}
200
201//------------------------------------------------------------------------------
204template<class TYPE> TYPE
206{
207 this->criticalSection.Enter();
208 TYPE e = this->queue.Dequeue();
209 this->criticalSection.Leave();
210 return e;
211}
212
213//------------------------------------------------------------------------------
216template<class TYPE> void
218{
219 this->criticalSection.Enter();
220#if NEBULA_ENABLE_PERFORMANCE_WARNINGS
221 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());
222#endif
223 outArray.Clear();
224 for (IndexT i = 0; i < this->queue.Size(); i++)
225 {
226 outArray.Append(std::move(this->queue[i]));
227 }
228 this->queue.Clear();
229 this->criticalSection.Leave();
230}
231
232//------------------------------------------------------------------------------
235template<class TYPE>
236template<int STACK_SIZE>
237void
239{
240 this->criticalSection.Enter();
241#if NEBULA_ENABLE_PERFORMANCE_WARNINGS
242 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());
243#endif
244 outArray.Clear();
245 for (IndexT i = 0; i < this->queue.Size(); i++)
246 {
247 outArray.Append(std::move(this->queue[i]));
248 }
249 this->queue.Clear();
250 this->criticalSection.Leave();
251}
252
253//------------------------------------------------------------------------------
256template<class TYPE> TYPE
258{
259 this->criticalSection.Enter();
260 TYPE e = this->queue.Peek();
261 this->criticalSection.Leave();
262 return e;
263}
264
265//------------------------------------------------------------------------------
268template<class TYPE> void
270{
271 if (this->signalOnEnqueueEnabled && this->IsEmpty())
272 {
273 this->enqueueEvent.Wait();
274 }
275}
276
277//------------------------------------------------------------------------------
280template<class TYPE> void
282{
283 if (this->signalOnEnqueueEnabled && this->IsEmpty())
284 {
285 this->enqueueEvent.WaitTimeout(ms);
286 }
287}
288
289//------------------------------------------------------------------------------
295template<class TYPE> void
297{
298 this->enqueueEvent.Signal();
299}
300
301//------------------------------------------------------------------------------
304template<class TYPE> void
306{
307 this->criticalSection.Enter();
308 IndexT i;
309 for (i = this->queue.Size() - 1; i >= 0; i--)
310 {
311 if (e == this->queue[i])
312 {
313 this->queue.EraseIndex(i);
314 }
315 }
316 this->criticalSection.Leave();
317}
318
319} // namespace Threading
320//------------------------------------------------------------------------------
321
Critical section objects are used to protect a portion of code from parallel execution.
Thread-safe version of Util::Queue.
Definition safequeue.h:27
void DequeueAll(Util::Array< TYPE > &outArray)
dequeue all events (only requires one lock)
Definition safequeue.h:217
void Signal()
signal the internal event, so that Wait() will return
Definition safequeue.h:296
void EnqueueArray(const Util::Array< TYPE > &a)
enqueue an array of elements
Definition safequeue.h:187
TYPE Peek() const
access to element at front of queue without removing it
Definition safequeue.h:257
void EraseMatchingElements(const TYPE &e)
erase all matching elements
Definition safequeue.h:305
SafeQueue(const SafeQueue< TYPE > &rhs)
copy constructor
Definition safequeue.h:90
bool IsEmpty() const
return true if queue is empty
Definition safequeue.h:145
void DequeueAll(Util::Array< TYPE, STACK_SIZE > &outArray)
Dequeue all events to an array with a stack size.
Definition safequeue.h:238
void WaitTimeout(int ms)
wait until queue contains at least one element, or time-out happens
Definition safequeue.h:281
void SetSignalOnEnqueueEnabled(bool b)
enable/disable signalling on Enqueue() (default is enabled)
Definition safequeue.h:114
Event enqueueEvent
Definition safequeue.h:71
void Enqueue(const TYPE &e)
add element to the back of the queue
Definition safequeue.h:157
void Wait()
wait until queue contains at least one element
Definition safequeue.h:269
Util::Queue< TYPE > queue
Definition safequeue.h:73
bool signalOnEnqueueEnabled
Definition safequeue.h:72
TYPE Dequeue()
remove the element from the front of the queue
Definition safequeue.h:205
bool IsSignalOnEnqueueEnabled() const
return signalling-on-Enqueue() flag
SizeT Size() const
returns number of elements in the queue
Definition safequeue.h:136
void operator=(const SafeQueue< TYPE > &rhs)
assignment operator
Definition safequeue.h:102
SafeQueue()
constructor
Definition safequeue.h:80
void Clear()
remove all elements from the queue
Definition safequeue.h:125
void Enqueue(TYPE &&e)
Definition safequeue.h:172
CriticalSection criticalSection
Definition safequeue.h:70
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:49
int IndexT
Definition types.h:48