clockUtils  1.1
DoubleBufferQueue.h
Go to the documentation of this file.
1 /*
2  * clockUtils
3  * Copyright (2015) Michael Baer, Daniel Bonrath, All rights reserved.
4  *
5  * This file is part of clockUtils; clockUtils is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
25 #ifndef __CLOCKUTILS_CONTAINER_DOUBLEBUFFERQUEUE_H__
26 #define __CLOCKUTILS_CONTAINER_DOUBLEBUFFERQUEUE_H__
27 
28 #include <mutex>
29 #include <queue>
30 
31 #include "clockUtils/errors.h"
32 
34 
35 namespace clockUtils {
36 namespace container {
37 
45  template<typename T, bool producer = true, bool consumer = true>
47  private:
48  template<bool v>
49  struct Bool2Type {
50  enum {
51  value = v
52  };
53  };
54 
55  public:
59  DoubleBufferQueue() : _queueA(), _queueB(), _queueRead(&_queueA), _queueWrite(&_queueB), _readLock(), _writeLock() {
60  }
61 
65  void push(const T & value) {
66  std::lock_guard<std::mutex> lg(_writeLock);
67  _queueWrite->push(value);
68  }
69 
74  return pop(Bool2Type<consumer>());
75  }
76 
80  ClockError front(T & value) {
81  return front(Bool2Type<consumer>(), value);
82  }
83 
87  ClockError poll(T & value) {
88  return poll(Bool2Type<consumer>(), value);
89  }
90 
94  inline bool empty() const {
95  return _queueRead->empty() && _queueWrite->empty();
96  }
97 
101  inline size_t size() const {
102  return _queueRead->size() + _queueWrite->size();
103  }
104 
108  void clear() {
109  _readLock.lock();
110  while (!_queueRead->empty()) {
111  _queueRead->pop();
112  }
113  _readLock.unlock();
114  _writeLock.lock();
115  while (!_queueWrite->empty()) {
116  _queueWrite->pop();
117  }
118  _writeLock.unlock();
119  }
120 
121  private:
125  std::queue<T> _queueA;
126  std::queue<T> _queueB;
127 
131  std::queue<T> * _queueRead;
132  std::queue<T> * _queueWrite;
133 
134  std::mutex _readLock;
135  std::mutex _writeLock;
136 
137  ClockError pop(Bool2Type<true>) {
138  static_assert(consumer, "Consumer must be true here");
139  std::lock_guard<std::mutex> lg(_readLock);
140  if (_queueRead->empty()) {
141  swap();
142  }
143 
144  if (_queueRead->empty()) {
145  return ClockError::NO_ELEMENT;
146  } else {
147  _queueRead->pop();
148  return ClockError::SUCCESS;
149  }
150  }
151 
152  ClockError pop(Bool2Type<false>) {
153  static_assert(!consumer, "Consumer must be false here");
154  if (_queueRead->empty()) {
155  swap();
156  }
157 
158  if (_queueRead->empty()) {
159  return ClockError::NO_ELEMENT;
160  } else {
161  _queueRead->pop();
162  return ClockError::SUCCESS;
163  }
164  }
165 
166  ClockError front(Bool2Type<true>, T & value) {
167  static_assert(consumer, "Consumer must be true here");
168  std::lock_guard<std::mutex> lg(_readLock);
169  if (_queueRead->empty()) {
170  swap();
171  }
172 
173  if (_queueRead->empty()) {
174  return ClockError::NO_ELEMENT;
175  } else {
176  value = _queueRead->front();
177  return ClockError::SUCCESS;
178  }
179  }
180 
181  ClockError front(Bool2Type<false>, T & value) {
182  static_assert(!consumer, "Consumer must be false here");
183  if (_queueRead->empty()) {
184  swap();
185  }
186 
187  if (_queueRead->empty()) {
188  return ClockError::NO_ELEMENT;
189  } else {
190  value = _queueRead->front();
191  return ClockError::SUCCESS;
192  }
193  }
194 
195  ClockError poll(Bool2Type<true>, T & value) {
196  static_assert(consumer, "Consumer must be true here");
197  std::lock_guard<std::mutex> lg(_readLock);
198  if (_queueRead->empty()) {
199  swap();
200  }
201 
202  if (_queueRead->empty()) {
203  return ClockError::NO_ELEMENT;
204  } else {
205  value = _queueRead->front();
206  _queueRead->pop();
207  return ClockError::SUCCESS;
208  }
209  }
210 
211  ClockError poll(Bool2Type<false>, T & value) {
212  static_assert(!consumer, "Consumer must be false here");
213  if (_queueRead->empty()) {
214  swap();
215  }
216 
217  if (_queueRead->empty()) {
218  return ClockError::NO_ELEMENT;
219  } else {
220  value = _queueRead->front();
221  _queueRead->pop();
222  return ClockError::SUCCESS;
223  }
224  }
225 
229  void swap() {
230  std::lock_guard<std::mutex> lg(_writeLock);
231  if (_queueRead == &_queueA) {
232  _queueWrite = &_queueA;
233  _queueRead = &_queueB;
234  } else {
235  _queueWrite = &_queueB;
236  _queueRead = &_queueA;
237  }
238  }
239 
243  DoubleBufferQueue(const DoubleBufferQueue &) = delete;
244  };
245 
246 } /* namespace container */
247 } /* namespace clockUtils */
248 
249 #endif /* __CLOCKUTILS_CONTAINER_DOUBLEBUFFERQUEUE_H__ */
250 
void push(const T &value)
pushes the given value into the queue
size_t size() const
returns size of the queue
void clear()
removes all elements in the queue
0x10 no element available
0x0 method call succeeded
ClockError pop()
removes first entry of the queue
ClockError poll(T &value)
removes first entry of the queue and returns its value
ClockError front(T &value)
returns first entry of the queue, but keeps it in the queue
bool empty() const
returns true if the queue is empty, otherwise false
ClockError
Definition: errors.h:30