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