2 * Copyright (c) 2005, Eric Crahen
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is furnished
9 * to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in all
12 * copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 #ifndef __ZTBLOCKINGQUEUE_H__
24 #define __ZTBLOCKINGQUEUE_H__
26 #include "zthread/Guard.h"
27 #include "zthread/Condition.h"
28 #include "zthread/Queue.h"
35 * @class BlockingQueue
36 * @author Eric Crahen <http://www.code-foo.com>
37 * @date <2003-07-16T12:01:43-0400>
40 * Like a LockedQueue, a BlockingQueue is a Queue implementation that provides
41 * serialized access to the items added to it. It differs by causing threads
42 * accessing the next() methods to block until a value becomes available.
44 template <class T
, class LockType
, typename StorageType
= std::deque
<T
> >
45 class BlockingQueue
: public Queue
<T
>, public Lockable
{
50 //! Signaled when empty
53 //! Storage backing the queue
57 volatile bool _canceled
;
61 //! Create a new BlockingQueue
62 BlockingQueue() : _notEmpty(_lock
), _canceled(false) {}
64 //! Destroy this BlockingQueue
65 virtual ~BlockingQueue() { }
68 * @see Queue::add(const T& item)
70 virtual void add(const T
& item
) {
72 Guard
<LockType
> g(_lock
);
75 throw Cancellation_Exception();
77 _queue
.push_back(item
);
84 * @see Queue::add(const T& item, unsigned long timeout)
86 virtual bool add(T item
, unsigned long timeout
) {
90 Guard
<LockType
> g(_lock
, timeout
);
93 throw Cancellation_Exception();
95 _queue
.push_back(item
);
99 } catch(Timeout_Exception
&) { return false; }
106 * Get a value from this Queue. The calling thread may block indefinitely.
108 * @return <em>T</em> next available value
110 * @exception Cancellation_Exception thrown if this Queue has been canceled.
112 * @exception Interrupted_Exception thrown if the calling thread is interrupted
113 * before a value becomes available.
115 * @pre The Queue should not have been canceled prior to the invocation of this function.
116 * @post The value returned will have been removed from the Queue.
122 Guard
<LockType
> g(_lock
);
124 while(_queue
.empty() && !_canceled
)
128 throw Cancellation_Exception();
130 T item
= _queue
.front();
139 * Get a value from this Queue. The calling thread may block indefinitely.
141 * @param timeout maximum amount of time (milliseconds) this method may block
142 * the calling thread.
144 * @return <em>T</em> next available value
146 * @exception Cancellation_Exception thrown if this Queue has been canceled.
147 * @exception Timeout_Exception thrown if the timeout expires before a value
149 * @exception Interrupted_Exception thrown if the calling thread is interrupted
150 * before a value becomes available.
152 * @pre The Queue should not have been canceled prior to the invocation of this function.
153 * @post The value returned will have been removed from the Queue.
155 * @see Queue::next(unsigned long timeout)
157 virtual T
next(unsigned long timeout
) {
159 Guard
<LockType
> g(_lock
, timeout
);
161 while(_queue
.empty() && !_canceled
) {
162 if(!_notEmpty
.wait(timeout
))
163 throw Timeout_Exception();
167 throw Cancellation_Exception();
169 T item
= _queue
.front();
178 * @see Queue::cancel()
180 * @post If threads are blocked on one of the next() functions then
181 * they will be awakened with a Cancellation_Exception.
183 virtual void cancel() {
185 Guard
<LockType
> g(_lock
);
187 _notEmpty
.broadcast();
193 * @see Queue::isCanceled()
195 virtual bool isCanceled() {
197 // Faster check since the queue will not become un-canceled
201 Guard
<LockType
> g(_lock
);
210 virtual size_t size() {
212 Guard
<LockType
> g(_lock
);
213 return _queue
.size();
218 * @see Queue::size(unsigned long timeout)
220 virtual size_t size(unsigned long timeout
) {
222 Guard
<LockType
> g(_lock
, timeout
);
223 return _queue
.size();
229 virtual void acquire() {
233 virtual bool tryAcquire(unsigned long timeout
) {
234 return _lock
.tryAcquire(timeout
);
237 virtual void release() {
241 }; /* BlockingQueue */
243 } // namespace ZThread
245 #endif // __ZTBLOCKINGQUEUE_H__