diff options
Diffstat (limited to '')
-rw-r--r-- | src/stable/synchroqueue.h | 454 |
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 | ||
16 | namespace Bu | 16 | namespace 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 |