aboutsummaryrefslogtreecommitdiff
path: root/src/stable/synchroqueue.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/stable/synchroqueue.h')
-rw-r--r--src/stable/synchroqueue.h454
1 files changed, 227 insertions, 227 deletions
diff --git a/src/stable/synchroqueue.h b/src/stable/synchroqueue.h
index 1c16e15..8dbedba 100644
--- a/src/stable/synchroqueue.h
+++ b/src/stable/synchroqueue.h
@@ -15,233 +15,233 @@
15 15
16namespace Bu 16namespace Bu
17{ 17{
18 /** 18 /**
19 * A thread-safe queue class. This class is a very simple queue with some 19 * A thread-safe queue class. This class is a very simple queue with some
20 * cool extra functionality for use with the Synchro system. The main extra 20 * cool extra functionality for use with the Synchro system. The main extra
21 * that it provides is the option to either dequeue without blocking, with 21 * that it provides is the option to either dequeue without blocking, with
22 * infinite blocking, or with timed blocking, which will return a value if 22 * infinite blocking, or with timed blocking, which will return a value if
23 * something is enqueued within the specified time limit, or NULL if the 23 * something is enqueued within the specified time limit, or NULL if the
24 * time limit is exceded. 24 * time limit is exceded.
25 *@ingroup Threading Containers 25 *@ingroup Threading Containers
26 */ 26 */
27 template <class T> 27 template <class T>
28 class SynchroQueue 28 class SynchroQueue
29 { 29 {
30 private: 30 private:
31 /** 31 /**
32 * Helper struct. Keeps track of linked-list items for the queue data. 32 * Helper struct. Keeps track of linked-list items for the queue data.
33 */ 33 */
34 typedef struct Item 34 typedef struct Item
35 { 35 {
36 T pData; 36 T pData;
37 Item *pNext; 37 Item *pNext;
38 } Item; 38 } Item;
39 39
40 public: 40 public:
41 /** 41 /**
42 * Construct an empty queue. 42 * Construct an empty queue.
43 */ 43 */
44 SynchroQueue() : 44 SynchroQueue() :
45 pStart( NULL ), 45 pStart( NULL ),
46 pEnd( NULL ), 46 pEnd( NULL ),
47 nSize( 0 ) 47 nSize( 0 )
48 { 48 {
49 } 49 }
50 50
51 /** 51 /**
52 * Destroy the queue. This function will simply free all contained 52 * Destroy the queue. This function will simply free all contained
53 * structures. If you stored pointers in the queue, this will lose the 53 * structures. If you stored pointers in the queue, this will lose the
54 * pointers without cleaning up the memory they pointed to. Make sure 54 * pointers without cleaning up the memory they pointed to. Make sure
55 * you're queue is empty before allowing it to be destroyed! 55 * you're queue is empty before allowing it to be destroyed!
56 */ 56 */
57 ~SynchroQueue() 57 ~SynchroQueue()
58 { 58 {
59 cBlock.lock(); 59 cBlock.lock();
60 Item *pCur = pStart; 60 Item *pCur = pStart;
61 while( pCur ) 61 while( pCur )
62 { 62 {
63 Item *pTmp = pCur->pNext; 63 Item *pTmp = pCur->pNext;
64 delete pCur; 64 delete pCur;
65 pCur = pTmp; 65 pCur = pTmp;
66 } 66 }
67 cBlock.unlock(); 67 cBlock.unlock();
68 } 68 }
69 69
70 /** 70 /**
71 * Enqueue a pieces of data. The new data will go at the end of the 71 * Enqueue a pieces of data. The new data will go at the end of the
72 * queue, and unless another piece of data is enqueued, will be the 72 * queue, and unless another piece of data is enqueued, will be the
73 * last piece of data to be dequeued. 73 * last piece of data to be dequeued.
74 *@param pData The data to enqueue. If this is not a primitive data 74 *@param pData The data to enqueue. If this is not a primitive data
75 * type it's probably best to use a pointer type. 75 * type it's probably best to use a pointer type.
76 */ 76 */
77 void enqueue( T pData ) 77 void enqueue( T pData )
78 { 78 {
79 cBlock.lock(); 79 cBlock.lock();
80 80
81 if( pStart == NULL ) 81 if( pStart == NULL )
82 { 82 {
83 pStart = pEnd = new Item; 83 pStart = pEnd = new Item;
84 pStart->pData = pData; 84 pStart->pData = pData;
85 pStart->pNext = NULL; 85 pStart->pNext = NULL;
86 nSize++; 86 nSize++;
87 } 87 }
88 else 88 else
89 { 89 {
90 pEnd->pNext = new Item; 90 pEnd->pNext = new Item;
91 pEnd = pEnd->pNext; 91 pEnd = pEnd->pNext;
92 pEnd->pData = pData; 92 pEnd->pData = pData;
93 pEnd->pNext = NULL; 93 pEnd->pNext = NULL;
94 nSize++; 94 nSize++;
95 } 95 }
96 96
97 cBlock.signal(); 97 cBlock.signal();
98 98
99 cBlock.unlock(); 99 cBlock.unlock();
100 } 100 }
101 101
102 /** 102 /**
103 * Dequeue the first item from the queue. This function can operate in 103 * Dequeue the first item from the queue. This function can operate in
104 * two different modes, blocking and non-blocking. In non-blocking 104 * two different modes, blocking and non-blocking. In non-blocking
105 * mode it will return immediately weather there was data in the queue 105 * mode it will return immediately weather there was data in the queue
106 * or not. If there was data it will remove it from the queue and 106 * or not. If there was data it will remove it from the queue and
107 * return it to the caller. 107 * return it to the caller.
108 * 108 *
109 * In blocking mode it will block forever wating for data to be 109 * In blocking mode it will block forever wating for data to be
110 * enqueued. When data finally is enqueued this function will return 110 * enqueued. When data finally is enqueued this function will return
111 * immediately with the new data. The only way this function should 111 * immediately with the new data. The only way this function should
112 * ever return a null in blocking mode is if the calling thread was 112 * ever return a null in blocking mode is if the calling thread was
113 * cancelled. It's probably a good idea to check for NULL return 113 * cancelled. It's probably a good idea to check for NULL return
114 * values even if you use blocking, just to be on the safe side. 114 * values even if you use blocking, just to be on the safe side.
115 *@param bBlock Set to true to enable blocking, leave as false to work 115 *@param bBlock Set to true to enable blocking, leave as false to work
116 * in non-blocking mode. 116 * in non-blocking mode.
117 *@returns The next piece of data in the queue, or NULL if no data was 117 *@returns The next piece of data in the queue, or NULL if no data was
118 * in the queue. 118 * in the queue.
119 */ 119 */
120 T dequeue( bool bBlock=false ) 120 T dequeue( bool bBlock=false )
121 { 121 {
122 cBlock.lock(); 122 cBlock.lock();
123 if( pStart == NULL ) 123 if( pStart == NULL )
124 { 124 {
125 if( bBlock ) 125 if( bBlock )
126 { 126 {
127 cBlock.wait(); 127 cBlock.wait();
128 128
129 if( pStart == NULL ) 129 if( pStart == NULL )
130 { 130 {
131 cBlock.unlock(); 131 cBlock.unlock();
132 return NULL; 132 return NULL;
133 } 133 }
134 T pTmp = pStart->pData; 134 T pTmp = pStart->pData;
135 Item *pDel = pStart; 135 Item *pDel = pStart;
136 pStart = pStart->pNext; 136 pStart = pStart->pNext;
137 delete pDel; 137 delete pDel;
138 nSize--; 138 nSize--;
139 139
140 cBlock.unlock(); 140 cBlock.unlock();
141 return pTmp; 141 return pTmp;
142 142
143 } 143 }
144 144
145 cBlock.unlock(); 145 cBlock.unlock();
146 return NULL; 146 return NULL;
147 } 147 }
148 else 148 else
149 { 149 {
150 T pTmp = pStart->pData; 150 T pTmp = pStart->pData;
151 Item *pDel = pStart; 151 Item *pDel = pStart;
152 pStart = pStart->pNext; 152 pStart = pStart->pNext;
153 delete pDel; 153 delete pDel;
154 nSize--; 154 nSize--;
155 155
156 cBlock.unlock(); 156 cBlock.unlock();
157 return pTmp; 157 return pTmp;
158 } 158 }
159 } 159 }
160 160
161 /** 161 /**
162 * Operates just like the other dequeue function in blocking mode with 162 * Operates just like the other dequeue function in blocking mode with
163 * one twist. This function will block for at most nSec seconds and 163 * one twist. This function will block for at most nSec seconds and
164 * nUSec micro-seconds. If the timer is up and no data is available, 164 * nUSec micro-seconds. If the timer is up and no data is available,
165 * this will just return NULL. If data is enqueued before the timeout 165 * this will just return NULL. If data is enqueued before the timeout
166 * expires, it will dequeue and exit immediately. 166 * expires, it will dequeue and exit immediately.
167 *@param nSec The number of seconds to wait, max. 167 *@param nSec The number of seconds to wait, max.
168 *@param nUSec The number of micro-seconds to wait, max. 168 *@param nUSec The number of micro-seconds to wait, max.
169 *@returns The next piece of data in the queue, or NULL if the timeout 169 *@returns The next piece of data in the queue, or NULL if the timeout
170 * was exceeded. 170 * was exceeded.
171 */ 171 */
172 T dequeue( int nSec, int nUSec ) 172 T dequeue( int nSec, int nUSec )
173 { 173 {
174 cBlock.lock(); 174 cBlock.lock();
175 if( pStart == NULL ) 175 if( pStart == NULL )
176 { 176 {
177 cBlock.wait( nSec, nUSec ); 177 cBlock.wait( nSec, nUSec );
178 178
179 if( pStart == NULL ) 179 if( pStart == NULL )
180 { 180 {
181 cBlock.unlock(); 181 cBlock.unlock();
182 return NULL; 182 return NULL;
183 } 183 }
184 184
185 T pTmp = pStart->pData; 185 T pTmp = pStart->pData;
186 Item *pDel = pStart; 186 Item *pDel = pStart;
187 pStart = pStart->pNext; 187 pStart = pStart->pNext;
188 delete pDel; 188 delete pDel;
189 nSize--; 189 nSize--;
190 190
191 cBlock.unlock(); 191 cBlock.unlock();
192 return pTmp; 192 return pTmp;
193 } 193 }
194 else 194 else
195 { 195 {
196 T pTmp = pStart->pData; 196 T pTmp = pStart->pData;
197 Item *pDel = pStart; 197 Item *pDel = pStart;
198 pStart = pStart->pNext; 198 pStart = pStart->pNext;
199 delete pDel; 199 delete pDel;
200 nSize--; 200 nSize--;
201 201
202 cBlock.unlock(); 202 cBlock.unlock();
203 return pTmp; 203 return pTmp;
204 } 204 }
205 } 205 }
206 206
207 /** 207 /**
208 * Checks to see if the queue has data in it or not. Note that there 208 * Checks to see if the queue has data in it or not. Note that there
209 * is no function to determine the length of the queue. This data 209 * is no function to determine the length of the queue. This data
210 * isn't kept track of. If you really need to know, fix this. 210 * isn't kept track of. If you really need to know, fix this.
211 *@returns True if the queue is empty, false if it has data in it. 211 *@returns True if the queue is empty, false if it has data in it.
212 */ 212 */
213 bool isEmpty() 213 bool isEmpty()
214 { 214 {
215 cBlock.lock(); 215 cBlock.lock();
216 bool bEmpty = (pStart == NULL ); 216 bool bEmpty = (pStart == NULL );
217 cBlock.unlock(); 217 cBlock.unlock();
218 218
219 return bEmpty; 219 return bEmpty;
220 } 220 }
221 221
222 long getSize() 222 long getSize()
223 { 223 {
224 cBlock.lock(); 224 cBlock.lock();
225 long nRet = nSize; 225 long nRet = nSize;
226 cBlock.unlock(); 226 cBlock.unlock();
227 227
228 return nRet; 228 return nRet;
229 } 229 }
230 230
231 void unblockAll() 231 void unblockAll()
232 { 232 {
233 cBlock.lock(); 233 cBlock.lock();
234 cBlock.broadcast(); 234 cBlock.broadcast();
235 cBlock.unlock(); 235 cBlock.unlock();
236 } 236 }
237 237
238 private: 238 private:
239 Item *pStart; /**< The start of the queue, the next element to dequeue. */ 239 Item *pStart; /**< The start of the queue, the next element to dequeue. */
240 Item *pEnd; /**< The end of the queue, the last element to dequeue. */ 240 Item *pEnd; /**< The end of the queue, the last element to dequeue. */
241 long nSize; /**< The number of items in the queue. */ 241 long nSize; /**< The number of items in the queue. */
242 242
243 Condition cBlock; /**< The condition for blocking dequeues. */ 243 Condition cBlock; /**< The condition for blocking dequeues. */
244 }; 244 };
245} 245}
246 246
247#endif 247#endif