1 #ifndef SGQUEUE_HXX_INCLUDED
2 #define SGQUEUE_HXX_INCLUDED 1
4 #include <simgear/compiler.h>
9 #include "SGThread.hxx"
12 * SGQueue defines an interface for a FIFO.
13 * It can be implemented using different types of synchronization
22 * Create a new SGQueue object.
27 * Destroy this object.
32 * Returns whether this queue is empty (contains no elements).
34 * @return bool True if queue is empty, otherwisr false.
36 virtual bool empty() = 0;
39 * Add an item to the end of the queue.
41 * @param T object to add.
43 virtual void push( const T& item ) = 0;
46 * View the item from the head of the queue.
48 * @return T next available object.
50 virtual T front() = 0;
53 * Get an item from the head of the queue.
55 * @return T next available object.
60 * Query the size of the queue
62 * @return size_t size of queue.
64 virtual size_t size() = 0;
74 * A simple thread safe queue. All access functions are guarded with a mutex.
77 class SGLockedQueue : public SGQueue<T>
82 * Create a new SGLockedQueue object.
87 * Destroy this object.
92 * Returns whether this queue is empty (contains no elements).
94 * @return bool True if queue is empty, otherwisr false.
96 virtual bool empty() {
97 SGGuard<SGMutex> g(mutex);
98 return this->fifo.empty();
102 * Add an item to the end of the queue.
104 * @param T object to add.
106 virtual void push( const T& item ) {
107 SGGuard<SGMutex> g(mutex);
108 this->fifo.push( item );
112 * View the item from the head of the queue.
114 * @return T next available object.
117 SGGuard<SGMutex> g(mutex);
118 assert( ! this->fifo.empty() );
119 T item = this->fifo.front();
124 * Get an item from the head of the queue.
126 * @return T next available object.
129 SGGuard<SGMutex> g(mutex);
130 //if (fifo.empty()) throw NoSuchElementException();
131 assert( ! this->fifo.empty() );
135 // pthread_exit( PTHREAD_CANCELED );
137 T item = this->fifo.front();
143 * Query the size of the queue
145 * @return size_t size of queue.
147 virtual size_t size() {
148 SGGuard<SGMutex> g(mutex);
149 return this->fifo.size();
155 * Mutex to serialise access.
161 SGLockedQueue(const SGLockedQueue&);
162 SGLockedQueue& operator= (const SGLockedQueue&);
166 * A guarded queue blocks threads trying to retrieve items
167 * when none are available.
170 class SGBlockingQueue : public SGQueue<T>
174 * Create a new SGBlockingQueue.
179 * Destroy this queue.
181 ~SGBlockingQueue() {}
186 virtual bool empty() {
187 SGGuard<SGMutex> g(mutex);
188 return this->fifo.empty();
192 * Add an item to the end of the queue.
194 * @param T object to add.
196 virtual void push( const T& item ) {
197 SGGuard<SGMutex> g(mutex);
198 this->fifo.push( item );
203 * View the item from the head of the queue.
204 * Calling thread is not suspended
206 * @return T next available object.
209 SGGuard<SGMutex> g(mutex);
211 assert(this->fifo.empty() != true);
212 //if (fifo.empty()) throw ??
214 T item = this->fifo.front();
219 * Get an item from the head of the queue.
220 * If no items are available then the calling thread is suspended
222 * @return T next available object.
225 SGGuard<SGMutex> g(mutex);
227 while (this->fifo.empty())
228 not_empty.wait(mutex);
230 assert(this->fifo.empty() != true);
231 //if (fifo.empty()) throw ??
233 T item = this->fifo.front();
239 * Query the size of the queue
241 * @return size_t size of queue.
243 virtual size_t size() {
244 SGGuard<SGMutex> g(mutex);
245 return this->fifo.size();
251 * Mutex to serialise access.
256 * Condition to signal when queue not empty.
258 SGWaitCondition not_empty;
262 SGBlockingQueue( const SGBlockingQueue& );
263 SGBlockingQueue& operator=( const SGBlockingQueue& );
268 * A guarded deque blocks threads trying to retrieve items
269 * when none are available.
272 class SGBlockingDeque
276 * Create a new SGBlockingDequeue.
281 * Destroy this dequeue.
283 ~SGBlockingDeque() {}
288 virtual void clear() {
289 SGGuard<SGMutex> g(mutex);
296 virtual bool empty() {
297 SGGuard<SGMutex> g(mutex);
298 return this->queue.empty();
302 * Add an item to the front of the queue.
304 * @param T object to add.
306 virtual void push_front( const T& item ) {
307 SGGuard<SGMutex> g(mutex);
308 this->queue.push_front( item );
313 * Add an item to the back of the queue.
315 * @param T object to add.
317 virtual void push_back( const T& item ) {
318 SGGuard<SGMutex> g(mutex);
319 this->queue.push_back( item );
324 * View the item from the head of the queue.
325 * Calling thread is not suspended
327 * @return T next available object.
330 SGGuard<SGMutex> g(mutex);
332 assert(this->queue.empty() != true);
333 //if (queue.empty()) throw ??
335 T item = this->queue.front();
340 * Get an item from the head of the queue.
341 * If no items are available then the calling thread is suspended
343 * @return T next available object.
345 virtual T pop_front() {
346 SGGuard<SGMutex> g(mutex);
348 while (this->queue.empty())
349 not_empty.wait(mutex);
351 assert(this->queue.empty() != true);
352 //if (queue.empty()) throw ??
354 T item = this->queue.front();
355 this->queue.pop_front();
360 * Get an item from the tail of the queue.
361 * If no items are available then the calling thread is suspended
363 * @return T next available object.
365 virtual T pop_back() {
366 SGGuard<SGMutex> g(mutex);
368 while (this->queue.empty())
369 not_empty.wait(mutex);
371 assert(this->queue.empty() != true);
372 //if (queue.empty()) throw ??
374 T item = this->queue.back();
375 this->queue.pop_back();
380 * Query the size of the queue
382 * @return size_t size of queue.
384 virtual size_t size() {
385 SGGuard<SGMutex> g(mutex);
386 return this->queue.size();
392 * Mutex to serialise access.
397 * Condition to signal when queue not empty.
399 SGWaitCondition not_empty;
403 SGBlockingDeque( const SGBlockingDeque& );
404 SGBlockingDeque& operator=( const SGBlockingDeque& );
410 #endif // SGQUEUE_HXX_INCLUDED