Line data Source code
1 :
2 : /* Copyright (c) 2005-2013, Stefan Eilemann <eile@equalizergraphics.com>
3 : * 2012, Daniel Nachbaur <danielnachbaur@gmail.com>
4 : *
5 : * This library is free software; you can redistribute it and/or modify it under
6 : * the terms of the GNU Lesser General Public License version 2.1 as published
7 : * by the Free Software Foundation.
8 : *
9 : * This library is distributed in the hope that it will be useful, but WITHOUT
10 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12 : * details.
13 : *
14 : * You should have received a copy of the GNU Lesser General Public License
15 : * along with this library; if not, write to the Free Software Foundation, Inc.,
16 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 : */
18 :
19 : #ifndef LUNCHBOX_MTQUEUE_H
20 : #define LUNCHBOX_MTQUEUE_H
21 :
22 : #include <lunchbox/condition.h>
23 : #include <lunchbox/debug.h>
24 :
25 : #include <algorithm>
26 : #include <limits.h>
27 : #include <queue>
28 : #include <string.h>
29 :
30 : namespace lunchbox
31 : {
32 : /**
33 : * A thread-safe queue with a blocking read access.
34 : *
35 : * Typically used to communicate between two execution threads.
36 : *
37 : * S is deprecated by the ctor param maxSize, and defines the initial maximum
38 : * capacity of the Queue<T>. When the capacity is reached, pushing new values
39 : * blocks until items have been consumed.
40 : *
41 : * Example: @include tests/mtQueue.cpp
42 : */
43 : template< typename T, size_t S = ULONG_MAX > class MTQueue
44 : // S = std::numeric_limits< size_t >::max() does not work:
45 : // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=6424
46 : {
47 : public:
48 : class Group;
49 : typedef T value_type;
50 :
51 : /** Construct a new queue. @version 1.0 */
52 2 : explicit MTQueue( const size_t maxSize = S ) : _maxSize( maxSize ) {}
53 :
54 : /** Construct a copy of a queue. @version 1.0 */
55 : MTQueue( const MTQueue< T, S >& from ) { *this = from; }
56 :
57 : /** Destruct this Queue. @version 1.0 */
58 0 : ~MTQueue() {}
59 :
60 : /** Assign the values of another queue. @version 1.0 */
61 : MTQueue< T, S >& operator = ( const MTQueue< T, S >& from );
62 :
63 : /**
64 : * Retrieve the requested element from the queue, may block.
65 : * @version 1.3.2
66 : */
67 : const T& operator[]( const size_t index ) const;
68 :
69 : /** @return true if the queue is empty, false otherwise. @version 1.0 */
70 5 : bool isEmpty() const { return _queue.empty(); }
71 :
72 : /** @return the number of items currently in the queue. @version 1.0 */
73 : size_t getSize() const { return _queue.size(); }
74 :
75 : /**
76 : * Set the new maximum size of the queue.
77 : *
78 : * If the new maximum size is less the current size of the queue, this
79 : * call will block until the queue reaches the new maximum size.
80 : *
81 : * @version 1.3.2
82 : */
83 : void setMaxSize( const size_t maxSize );
84 :
85 : /** @return the current maximum size of the queue. @version 1.3.2 */
86 : size_t getMaxSize() const { return _maxSize; }
87 :
88 : /**
89 : * Wait for the size to be at least the number of given elements.
90 : *
91 : * @return the current size when the condition was fulfilled.
92 : * @version 1.0
93 : */
94 : size_t waitSize( const size_t minSize ) const;
95 :
96 : /** Reset (empty) the queue. @version 1.0 */
97 : void clear();
98 :
99 : /**
100 : * Retrieve and pop the front element from the queue, may block.
101 : * @version 1.0
102 : */
103 : T pop();
104 :
105 : /**
106 : * Retrieve and pop the front element from the queue.
107 : *
108 : * @param timeout the timeout
109 : * @param element the element returned
110 : * @return true if an element was popped
111 : * @version 1.1
112 : */
113 : bool timedPop( const unsigned timeout, T& element );
114 :
115 : /**
116 : * Retrieve a number of items from the front of the queue.
117 : *
118 : * Between minimum and maximum number of items are returned in a vector. If
119 : * the queue has less than minimum number of elements on timeout, the result
120 : * vector is empty. The method returns as soon as there are at least minimum
121 : * elements available, i.e., it does not wait for the maximum to be reached.
122 : *
123 : * Note that this method might block up to 'minimum * timeout' milliseconds,
124 : * that is, the timeout defines the time to wait for an update on the queue.
125 : *
126 : * @param timeout the timeout to wait for an update
127 : * @param minimum the minimum number of items to retrieve
128 : * @param maximum the maximum number of items to retrieve
129 : * @return an empty vector on timeout, otherwise the result vector
130 : * containing between minimum and maximum elements.
131 : * @version 1.7.0
132 : */
133 : std::vector< T > timedPopRange( const unsigned timeout,
134 : const size_t minimum = 1,
135 : const size_t maximum = S );
136 :
137 : /**
138 : * Retrieve and pop the front element from the queue if it is not empty.
139 : *
140 : * @param result the front value or unmodified.
141 : * @return true if an element was placed in result, false if the queue
142 : * is empty.
143 : * @version 1.0
144 : */
145 : bool tryPop( T& result );
146 :
147 : /**
148 : * Try to retrieve a number of items from the front of the queue.
149 : *
150 : * Between zero and the given number of items are appended to the vector.
151 : *
152 : * @param num the maximum number of items to retrieve
153 : * @param result the front value or unmodified.
154 : * @return true if an element was placed in result, false if the queue
155 : * is empty.
156 : * @version 1.1.6
157 : */
158 : void tryPop( const size_t num, std::vector< T >& result );
159 :
160 : /**
161 : * Retrieve the front element, or abort if the barrier is reached
162 : *
163 : * Used for worker threads recursively processing data, pushing it back the
164 : * queue. Either returns an item from the queue, or aborts if num
165 : * participants are waiting in the queue.
166 : *
167 : * @param result the result element, unmodified on false return value.
168 : * @param barrier the group's barrier handle.
169 : * @return true if an element was retrieved, false if the barrier height
170 : * was reached.
171 : * @version 1.7.1
172 : */
173 : bool popBarrier( T& result, Group& barrier );
174 :
175 : /**
176 : * @param result the front value or unmodified.
177 : * @return true if an element was placed in result, false if the queue
178 : * is empty.
179 : * @version 1.0
180 : */
181 : bool getFront( T& result ) const;
182 :
183 : /**
184 : * @param result the last value or unmodified.
185 : * @return true if an element was placed in result, false if the queue
186 : * is empty.
187 : * @version 1.0
188 : */
189 : bool getBack( T& result ) const;
190 :
191 : /** Push a new element to the back of the queue. @version 1.0 */
192 : void push( const T& element );
193 :
194 : /** Push a vector of elements to the back of the queue. @version 1.0 */
195 : void push( const std::vector< T >& elements );
196 :
197 : /** Push a new element to the front of the queue. @version 1.0 */
198 : void pushFront( const T& element );
199 :
200 : /** Push a vector of elements to the front of the queue. @version 1.0 */
201 : void pushFront( const std::vector< T >& elements );
202 :
203 : /** @name STL compatibility. @version 1.7.1 */
204 : //@{
205 : void push_back( const T& element ) { push( element ); }
206 : bool empty() const { return isEmpty(); }
207 : //@}
208 :
209 : private:
210 : std::deque< T > _queue;
211 : mutable Condition _cond;
212 : size_t _maxSize;
213 : };
214 : }
215 :
216 : #include "mtQueue.ipp" // template implementation
217 :
218 : #endif //LUNCHBOX_MTQUEUE_H
|