]> git.mxchange.org Git - simgear.git/blob - simgear/threads/SGQueue.hxx
9d4dcf31259840442a6f697c23aacd730b52956f
[simgear.git] / simgear / threads / SGQueue.hxx
1 #ifndef SGQUEUE_HXX_INCLUDED
2 #define SGQUEUE_HXX_INCLUDED 1
3
4 #include <simgear/compiler.h>
5
6 #if defined ( SG_HAVE_STD_INCLUDES )
7 #  include <cassert>
8 #else
9 #  include <assert.h>
10 #endif
11
12 #include <queue>
13 #include "SGThread.hxx"
14 #include "SGGuard.hxx"
15
16 /**
17  * SGQueue defines an interface for a FIFO.
18  * It can be implemented using different types of synchronization
19  * and protection.
20  */
21 template<class T>
22 class SGQueue
23 {
24 public:
25
26     /**
27      * Create a new SGQueue object.
28      */
29     SGQueue() {}
30
31     /**
32      * Destroy this object.
33      */
34     virtual ~SGQueue() {}
35
36     /**
37      * Returns whether this queue is empty (contains no elements).
38      *
39      * @return bool True if queue is empty, otherwisr false.
40      */
41     virtual bool empty() = 0;
42
43     /**
44      * Add an item to the end of the queue.
45      *
46      * @param T object to add.
47      */
48     virtual void push( const T& item ) = 0;
49
50     /**
51      * View the item from the head of the queue.
52      *
53      * @return T next available object.
54      */
55     virtual T front() = 0;
56
57     /**
58      * Get an item from the head of the queue.
59      *
60      * @return T next available object.
61      */
62     virtual T pop() = 0;
63
64 protected:
65     /**
66      * 
67      */
68     std::queue<T> fifo;
69 };
70
71 /**
72  * A simple thread safe queue.  All access functions are guarded with a mutex.
73  */
74 template<class T, class SGLOCK=SGMutex>
75 class SGLockedQueue : public SGQueue<T>
76 {
77 public:
78
79     /**
80      * Create a new SGLockedQueue object.
81      */
82     SGLockedQueue() {}
83
84     /**
85      * Destroy this object.
86      */
87     ~SGLockedQueue() {}
88
89     /**
90      * Returns whether this queue is empty (contains no elements).
91      *
92      * @return bool True if queue is empty, otherwisr false.
93      */
94     virtual bool empty() {
95         SGGuard<SGLOCK> g(mutex);
96         return fifo.empty();
97     }
98
99     /**
100      * Add an item to the end of the queue.
101      *
102      * @param T object to add.
103      */
104     virtual void push( const T& item ) {
105         SGGuard<SGLOCK> g(mutex);
106         fifo.push( item );
107     }
108
109     /**
110      * View the item from the head of the queue.
111      *
112      * @return T next available object.
113      */
114     virtual T front() {
115         SGGuard<SGLOCK> g(mutex);
116         assert( ! fifo.empty() );
117         T item = fifo.front();
118         return item;
119     }
120
121     /**
122      * Get an item from the head of the queue.
123      *
124      * @return T next available object.
125      */
126     virtual T pop() {
127         SGGuard<SGLOCK> g(mutex);
128         //if (fifo.empty()) throw NoSuchElementException();
129         assert( ! fifo.empty() );
130 //      if (fifo.empty())
131 //      {
132 //          mutex.unlock();
133 //          pthread_exit( PTHREAD_CANCELED );
134 //      }
135         T item = fifo.front();
136         fifo.pop();
137         return item;
138     }
139 private:
140
141     /**
142      * Mutex to serialise access.
143      */
144     SGLOCK mutex;
145
146 private:
147     // Prevent copying.
148     SGLockedQueue(const SGLockedQueue&);
149     SGLockedQueue& operator= (const SGLockedQueue&);
150 };
151
152 /**
153  * A guarded queue blocks threads trying to retrieve items
154  * when none are available.
155  */
156 template<class T>
157 class SGBlockingQueue : public SGQueue<T>
158 {
159 public:
160     /**
161      * Create a new SGBlockingQueue.
162      */
163     SGBlockingQueue() {}
164
165     /**
166      * Destroy this queue.
167      */
168     ~SGBlockingQueue() { mutex.unlock(); }
169
170     /**
171      * 
172      */
173     virtual bool empty() {
174         SGGuard<SGMutex> g(mutex);
175         return fifo.empty();
176     }
177
178     /**
179      * Add an item to the end of the queue.
180      *
181      * @param T object to add.
182      */
183     virtual void push( const T& item ) {
184         SGGuard<SGMutex> g(mutex);
185         fifo.push( item );
186         not_empty.signal();
187     }
188
189     /**
190      * View the item from the head of the queue.
191      * Calling thread is not suspended
192      *
193      * @return T next available object.
194      */
195     virtual T front() {
196         SGGuard<SGMutex> g(mutex);
197
198         assert(fifo.empty() != true);
199         //if (fifo.empty()) throw ??
200
201         T item = fifo.front();
202         return item;
203     }
204
205     /**
206      * Get an item from the head of the queue.
207      * If no items are available then the calling thread is suspended
208      *
209      * @return T next available object.
210      */
211     virtual T pop() {
212         SGGuard<SGMutex> g(mutex);
213
214         while (fifo.empty())
215             not_empty.wait(mutex);
216
217         assert(fifo.empty() != true);
218         //if (fifo.empty()) throw ??
219
220         T item = fifo.front();
221         fifo.pop();
222         return item;
223     }
224
225 private:
226
227     /**
228      * Mutex to serialise access.
229      */
230     SGMutex mutex;
231
232     /**
233      * Condition to signal when queue not empty.
234      */
235     SGPthreadCond not_empty;
236
237 private:
238     // Prevent copying.
239     SGBlockingQueue( const SGBlockingQueue& );
240     SGBlockingQueue& operator=( const SGBlockingQueue& );
241 };
242
243 #endif // SGQUEUE_HXX_INCLUDED