Line data Source code
1 :
2 : /* Copyright (c) 2005-2017, Stefan Eilemann <eile@equalizergraphics.com>
3 : * 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/debug.h>
23 :
24 : #include <algorithm>
25 : #include <condition_variable>
26 : #include <limits.h>
27 : #include <mutex>
28 : #include <queue>
29 : #include <string.h>
30 :
31 : namespace lunchbox
32 : {
33 : /**
34 : * A thread-safe queue with a blocking read access.
35 : *
36 : * Typically used to communicate between two execution threads.
37 : *
38 : * S is deprecated by the ctor param maxSize, and defines the initial maximum
39 : * capacity of the Queue<T>. When the capacity is reached, pushing new values
40 : * blocks until items have been consumed.
41 : *
42 : * Example: @include tests/mtQueue.cpp
43 : */
44 : template <typename T, size_t S = ULONG_MAX>
45 : class MTQueue
46 : // S = std::numeric_limits< size_t >::max() does not work:
47 : // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=6424
48 : {
49 : public:
50 : class Group;
51 : typedef T value_type;
52 :
53 : /** Construct a new queue. @version 1.0 */
54 2 : explicit MTQueue(const size_t maxSize = S)
55 2 : : _maxSize(maxSize)
56 : {
57 2 : }
58 :
59 : /** Construct a copy of a queue. @version 1.0 */
60 : MTQueue(const MTQueue<T, S>& from) { *this = from; }
61 : /** Destruct this Queue. @version 1.0 */
62 2 : ~MTQueue() {}
63 : /** Assign the values of another queue. @version 1.0 */
64 : MTQueue<T, S>& operator=(const MTQueue<T, S>& from);
65 :
66 : /**
67 : * Retrieve the requested element from the queue, may block.
68 : * @version 1.3.2
69 : */
70 : const T& operator[](const size_t index) const;
71 :
72 : /** @return true if the queue is empty, false otherwise. @version 1.0 */
73 5 : bool isEmpty() const { return _queue.empty(); }
74 : /** @return the number of items currently in the queue. @version 1.0 */
75 : size_t getSize() const { return _queue.size(); }
76 : /**
77 : * Set the new maximum size of the queue.
78 : *
79 : * If the new maximum size is less the current size of the queue, this
80 : * call will block until the queue reaches the new maximum size.
81 : *
82 : * @version 1.3.2
83 : */
84 : void setMaxSize(const size_t maxSize);
85 :
86 : /** @return the current maximum size of the queue. @version 1.3.2 */
87 : size_t getMaxSize() const { return _maxSize; }
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 : MTQueue(MTQueue<T, S>&&) = delete;
211 : MTQueue<T, S>& operator=(MTQueue<T, S>&&) = delete;
212 :
213 : std::deque<T> _queue;
214 : mutable std::mutex _mutex;
215 : mutable std::condition_variable _condition;
216 : size_t _maxSize;
217 : };
218 : }
219 :
220 : #include "mtQueue.ipp" // template implementation
221 :
222 : #endif // LUNCHBOX_MTQUEUE_H
|