queue.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2010 Tommi Maekitalo
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * As a special exception, you may use this file as part of a free
10  * software library without restriction. Specifically, if other files
11  * instantiate templates or use macros or inline functions from this
12  * file, or you compile this file and link it with other files to
13  * produce an executable, this file does not by itself cause the
14  * resulting executable to be covered by the GNU General Public
15  * License. This exception does not however invalidate any other
16  * reasons why the executable file might be covered by the GNU Library
17  * General Public License.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22  * Lesser General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public
25  * License along with this library; if not, write to the Free Software
26  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27  */
28 
29 #ifndef CXXTOOLS_QUEUE_H
30 #define CXXTOOLS_QUEUE_H
31 
32 #include <queue>
33 #include <cxxtools/mutex.h>
34 #include <cxxtools/condition.h>
35 #include <cxxtools/timespan.h>
37 
38 namespace cxxtools
39 {
48  template <typename T>
49  class Queue
50  {
51  public:
52  typedef T value_type;
53  typedef typename std::deque<T>::size_type size_type;
54  typedef typename std::deque<T>::const_reference const_reference;
55 
56  private:
57  mutable Mutex _mutex;
58  mutable Condition _notEmpty;
59  mutable Condition _notFull;
60  std::deque<value_type> _queue;
61  size_type _maxSize;
62  size_type _numWaiting;
63 
64  public:
67  : _maxSize(0),
68  _numWaiting(0)
69  { }
70 
76  value_type get();
77 
93  std::pair<value_type, bool> get(const Milliseconds& timeout);
94 
100  std::pair<value_type, bool> tryGet();
101 
108  void put(const_reference element, bool force = false);
109 
115  bool remove(const_reference element);
116 
118  bool empty() const
119  {
120  MutexLock lock(_mutex);
121  return _queue.empty();
122  }
123 
127  bool waitEmpty(Milliseconds timeout = -1) const
128  {
129  MutexLock lock(_mutex);
130  if (timeout >= Milliseconds(0))
131  {
132  Timespan until = Timespan::gettimeofday() + timeout;
133  Timespan remaining;
134  while (!_queue.empty()
135  && (remaining = until - Timespan::gettimeofday()) > Timespan(0))
136  _notEmpty.wait(_mutex, remaining);
137  }
138  else
139  {
140  while (!_queue.empty())
141  _notEmpty.wait(lock);
142  }
143 
144  return !_queue.empty();
145  }
146 
148  size_type size() const
149  {
150  MutexLock lock(_mutex);
151  return _queue.size();
152  }
153 
160  void maxSize(size_type m);
161 
164  {
165  MutexLock lock(_mutex);
166  return _maxSize;
167  }
168 
171  {
172  MutexLock lock(_mutex);
173  return _numWaiting;
174  }
175  };
176 
177  template <typename T>
179  {
180  MutexLock lock(_mutex);
181 
182  ScopedIncrement<size_type> inc(_numWaiting);
183  while (_queue.empty())
184  _notEmpty.wait(lock);
185 
186  value_type element = _queue.front();
187  _queue.pop_front();
188 
189  if (!_queue.empty())
190  _notEmpty.signal();
191 
192  _notFull.signal();
193 
194  return element;
195  }
196 
197  template <typename T>
198  std::pair<typename Queue<T>::value_type, bool> Queue<T>::get(const Milliseconds& timeout)
199  {
200  typedef typename Queue<T>::value_type value_type;
201  typedef typename std::pair<value_type, bool> return_type;
202 
203  MutexLock lock(_mutex);
204 
205  ScopedIncrement<size_type> inc(_numWaiting);
206  if (_queue.empty())
207  {
208  if (_notEmpty.wait(lock, timeout) == false)
209  {
210  return return_type(value_type(), false);
211  }
212  }
213 
214  value_type element = _queue.front();
215  _queue.pop_front();
216 
217  if (!_queue.empty())
218  _notEmpty.signal();
219 
220  _notFull.signal();
221 
222  return return_type(element, true);
223  }
224 
225  template <typename T>
226  std::pair<typename Queue<T>::value_type, bool> Queue<T>::tryGet()
227  {
228  typedef typename Queue<T>::value_type value_type;
229  typedef typename std::pair<value_type, bool> return_type;
230 
231  MutexLock lock(_mutex);
232 
233  if (_queue.empty())
234  return return_type(value_type(), false);
235 
236  value_type element = _queue.front();
237  _queue.pop_front();
238 
239  if (!_queue.empty())
240  _notEmpty.signal();
241 
242  _notFull.signal();
243 
244  return return_type(element, true);
245  }
246 
247  template <typename T>
248  void Queue<T>::put(typename Queue<T>::const_reference element, bool force)
249  {
250  MutexLock lock(_mutex);
251 
252  if (!force)
253  while (_maxSize > 0 && _queue.size() >= _maxSize)
254  _notFull.wait(lock);
255 
256  _queue.push_back(element);
257  _notEmpty.signal();
258 
259  if (_maxSize > 0 && _queue.size() < _maxSize)
260  _notFull.signal();
261  }
262 
263  template <typename T>
265  {
266  MutexLock lock(_mutex);
267  for (typename std::deque<T>::iterator it = _queue.begin(); it != _queue.end(); ++it)
268  if (*it == element)
269  return true;
270  return false;
271  }
272 
273  template <typename T>
275  {
276  _maxSize = m;
277  MutexLock lock(_mutex);
278  if (_queue.size() < _maxSize)
279  _notFull.signal();
280  }
281 }
282 
283 #endif // CXXTOOLS_QUEUE_H
284