IBR-DTNSuite
0.12
Main Page
Namespaces
Classes
Files
File List
File Members
Queue.h
Go to the documentation of this file.
1
/*
2
* Queue.h
3
*
4
* Copyright (C) 2011 IBR, TU Braunschweig
5
*
6
* Written-by: Johannes Morgenroth <morgenroth@ibr.cs.tu-bs.de>
7
*
8
* Licensed under the Apache License, Version 2.0 (the "License");
9
* you may not use this file except in compliance with the License.
10
* You may obtain a copy of the License at
11
*
12
* http://www.apache.org/licenses/LICENSE-2.0
13
*
14
* Unless required by applicable law or agreed to in writing, software
15
* distributed under the License is distributed on an "AS IS" BASIS,
16
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
* See the License for the specific language governing permissions and
18
* limitations under the License.
19
*
20
*/
21
22
#ifndef IBRCOMMON_QUEUE_H_
23
#define IBRCOMMON_QUEUE_H_
24
25
#include "
ibrcommon/thread/MutexLock.h
"
26
#include "
ibrcommon/thread/Conditional.h
"
27
#include "
ibrcommon/Exceptions.h
"
28
#include "
ibrcommon/thread/Semaphore.h
"
29
#include "
ibrcommon/thread/Thread.h
"
30
#include <queue>
31
#include <iostream>
32
33
namespace
ibrcommon
34
{
35
class
QueueUnblockedException
:
public
ibrcommon::Exception
36
{
37
public
:
38
enum
type_t
39
{
40
QUEUE_ABORT
= 0,
41
QUEUE_ERROR
= 1,
42
QUEUE_TIMEOUT
= 2
43
};
44
45
QueueUnblockedException
(
const
type_t
r,
string
what
=
"Queue is unblocked."
) throw() : ibrcommon::
Exception
(
what
),
reason
(r)
46
{
47
};
48
49
QueueUnblockedException
(
const
ibrcommon::Conditional::ConditionalAbortException
&ex,
string
what
=
"Queue is unblocked."
) throw() : ibrcommon::
Exception
(
what
)
50
{
51
switch
(ex.
reason
)
52
{
53
case
ibrcommon::Conditional::ConditionalAbortException::COND_ABORT
:
54
reason
=
QUEUE_ABORT
;
55
_what
=
"queue function aborted in "
+
what
;
56
break
;
57
58
case
ibrcommon::Conditional::ConditionalAbortException::COND_ERROR
:
59
reason
=
QUEUE_ERROR
;
60
_what
=
"queue function error in "
+
what
;
61
break
;
62
63
case
ibrcommon::Conditional::ConditionalAbortException::COND_TIMEOUT
:
64
reason
=
QUEUE_TIMEOUT
;
65
_what
=
"queue function timeout in "
+
what
;
66
break
;
67
}
68
};
69
70
type_t
reason
;
71
};
72
73
template
<
class
T>
74
class
Queue
75
{
76
ibrcommon::Conditional
_cond;
77
std::queue<T> _queue;
78
ibrcommon::Semaphore
_sem;
79
bool
_limit;
80
81
public
:
82
Queue
(
unsigned
int
max = 0) : _sem(max), _limit(max > 0)
83
{};
84
85
virtual
~Queue
()
86
{
87
abort
();
88
};
89
90
/* Test whether container is empty (public member function) */
91
bool
empty
( )
92
{
93
ibrcommon::MutexLock
l(_cond);
94
return
_queue.empty();
95
}
96
97
/* Return size (public member function) */
98
size_t
size
( )
const
99
{
100
return
_queue.size();
101
}
102
103
/* Access next element (public member function) */
104
T&
front
( )
105
{
106
ibrcommon::MutexLock
l(_cond);
107
return
_queue.front();
108
}
109
110
const
T&
front
( )
const
111
{
112
ibrcommon::MutexLock
l(_cond);
113
return
_queue.front();
114
}
115
116
/* Access last element (public member function) */
117
T&
back
( )
118
{
119
ibrcommon::MutexLock
l(_cond);
120
return
_queue.back();
121
}
122
123
const
T&
back
( )
const
124
{
125
ibrcommon::MutexLock
l(_cond);
126
return
_queue.back();
127
}
128
129
/* Insert element (public member function) */
130
void
push
(
const
T& x )
131
{
132
if
(_limit) _sem.
wait
();
133
134
ibrcommon::MutexLock
l(_cond);
135
_queue.push(x);
136
_cond.
signal
(
true
);
137
}
138
139
/* Delete next element (public member function) */
140
void
pop
()
141
{
142
ibrcommon::MutexLock
l(_cond);
143
__pop
();
144
}
145
146
T
get
(
bool
blocking =
false
,
size_t
timeout = 0)
throw
(
QueueUnblockedException
)
147
{
148
try
{
149
ibrcommon::MutexLock
l(_cond);
150
if
(_queue.empty())
151
{
152
if
(blocking)
153
{
154
if
(timeout == 0)
155
{
156
__wait
(
QUEUE_NOT_EMPTY
);
157
}
158
else
159
{
160
__wait
(
QUEUE_NOT_EMPTY
, timeout);
161
}
162
}
163
else
164
{
165
throw
QueueUnblockedException
(
QueueUnblockedException::QUEUE_ABORT
,
"getnpop(): queue is empty!"
);
166
}
167
}
168
169
return
_queue.front();
170
}
catch
(
const
ibrcommon::Conditional::ConditionalAbortException
&ex) {
171
throw
QueueUnblockedException
(ex,
"getnpop()"
);
172
}
173
}
174
175
T
getnpop
(
bool
blocking =
false
,
size_t
timeout = 0) throw (
QueueUnblockedException
)
176
{
177
try
{
178
ibrcommon::MutexLock
l(_cond);
179
if
(_queue.empty())
180
{
181
if
(blocking)
182
{
183
if
(timeout == 0)
184
{
185
__wait
(
QUEUE_NOT_EMPTY
);
186
}
187
else
188
{
189
__wait
(
QUEUE_NOT_EMPTY
, timeout);
190
}
191
}
192
else
193
{
194
throw
QueueUnblockedException(
QueueUnblockedException::QUEUE_ABORT
,
"getnpop(): queue is empty!"
);
195
}
196
}
197
198
T ret = _queue.front();
199
__pop
();
200
return
ret;
201
}
catch
(
const
ibrcommon::Conditional::ConditionalAbortException
&ex) {
202
throw
QueueUnblockedException(ex,
"getnpop()"
);
203
}
204
}
205
206
void
abort
() throw ()
207
{
208
ibrcommon::MutexLock
l(_cond);
209
_cond.
abort
();
210
}
211
212
void
reset
() throw ()
213
{
214
_cond.
reset
();
215
}
216
217
enum
WAIT_MODES
218
{
219
QUEUE_NOT_EMPTY
= 0,
220
QUEUE_EMPTY
= 1
221
};
222
223
void
wait
(
WAIT_MODES
mode,
const
size_t
timeout = 0) throw (
QueueUnblockedException
)
224
{
225
ibrcommon::MutexLock
l(_cond);
226
if
(timeout == 0)
227
{
228
__wait
(mode);
229
}
230
else
231
{
232
__wait
(mode, timeout);
233
}
234
}
235
236
class
Locked
237
{
238
public
:
239
Locked
(
Queue<T>
&queue)
240
: _queue(queue), _lock(queue._cond), _changed(false)
241
{
242
};
243
244
virtual
~Locked
()
245
{
246
if
(_changed) _queue._cond.signal(
true
);
247
};
248
249
void
wait
(
WAIT_MODES
mode,
const
size_t
timeout = 0) throw (
QueueUnblockedException
)
250
{
251
if
(timeout == 0)
252
{
253
_queue.__wait(mode);
254
}
255
else
256
{
257
_queue.__wait(mode, timeout);
258
}
259
}
260
261
void
pop
()
262
{
263
_queue.__pop();
264
}
265
266
const
T&
front
()
const
267
{
268
return
_queue._queue.front();
269
}
270
271
T&
front
()
272
{
273
return
_queue._queue.front();
274
}
275
276
bool
empty
()
277
{
278
return
_queue._queue.empty();
279
}
280
281
size_t
size
()
282
{
283
return
_queue._queue.size();
284
}
285
286
void
push
(
const
T &p)
287
{
288
_queue._queue.push(p);
289
_changed =
true
;
290
}
291
292
private
:
293
Queue<T>
&_queue;
294
ibrcommon::MutexLock
_lock;
295
bool
_changed;
296
};
297
298
typename
Queue<T>::Locked
exclusive
()
299
{
300
return
typename
Queue<T>::Locked
(*
this
);
301
}
302
303
protected
:
304
void
__push
(
const
T& x )
305
{
306
_queue.push(x);
307
_cond.
signal
(
true
);
308
}
309
310
void
__pop
()
311
{
312
if
(!_queue.empty())
313
{
314
_queue.pop();
315
if
(_limit) _sem.
post
();
316
_cond.
signal
(
true
);
317
}
318
}
319
320
void
__wait
(
const
WAIT_MODES
mode)
throw
(
QueueUnblockedException
)
321
{
322
try
{
323
switch
(mode)
324
{
325
case
QUEUE_NOT_EMPTY
:
326
{
327
while
(_queue.empty())
328
{
329
_cond.
wait
();
330
}
331
break
;
332
}
333
334
case
QUEUE_EMPTY
:
335
{
336
while
(!_queue.empty())
337
{
338
_cond.
wait
();
339
}
340
break
;
341
}
342
}
343
}
catch
(
const
ibrcommon::Conditional::ConditionalAbortException
&ex) {
344
switch
(ex.
reason
)
345
{
346
case
ibrcommon::Conditional::ConditionalAbortException::COND_ABORT
:
347
_cond.
reset
();
348
break
;
349
350
default
:
351
break
;
352
}
353
354
throw
QueueUnblockedException
(ex,
"__wait()"
);
355
}
356
}
357
358
void
__wait
(
const
WAIT_MODES
mode,
const
size_t
timeout)
throw
(
QueueUnblockedException
)
359
{
360
try
{
361
struct
timespec ts;
362
Conditional::gettimeout
(timeout, &ts);
363
364
switch
(mode)
365
{
366
case
QUEUE_NOT_EMPTY
:
367
{
368
while
(_queue.empty())
369
{
370
_cond.
wait
(&ts);
371
}
372
break
;
373
}
374
375
case
QUEUE_EMPTY
:
376
{
377
while
(!_queue.empty())
378
{
379
_cond.
wait
(&ts);
380
}
381
break
;
382
}
383
}
384
}
catch
(
const
ibrcommon::Conditional::ConditionalAbortException
&ex) {
385
switch
(ex.
reason
)
386
{
387
case
ibrcommon::Conditional::ConditionalAbortException::COND_ABORT
:
388
_cond.
reset
();
389
break
;
390
391
default
:
392
break
;
393
}
394
395
throw
QueueUnblockedException
(ex,
"__wait()"
);
396
}
397
}
398
};
399
}
400
401
#endif
/* IBRCOMMON_QUEUE_H_ */
ibrcommon
ibrcommon
thread
Queue.h
Generated on Thu Mar 27 2014 09:26:21 for IBR-DTNSuite by
1.8.4