Lunchbox  1.16.0
Multi-threaded C++ toolbox library for all application developers creating high-performance multi-threaded programs.
monitor.h
1 /* Copyright (c) 2006-2017, Stefan Eilemann <eile@equalizergraphics.com>
2  * Cedric Stalder <cedric.stalder@gmail.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_MONITOR_H
20 #define LUNCHBOX_MONITOR_H
21 
22 #include <lunchbox/scopedMutex.h> // used inline
23 #include <lunchbox/types.h>
24 
25 #include <boost/bind.hpp>
26 #include <condition_variable>
27 #include <errno.h>
28 #include <functional>
29 #include <iostream>
30 #include <mutex>
31 #include <string.h>
32 #include <typeinfo>
33 
34 namespace lunchbox
35 {
45 template <class T>
46 class Monitor
47 {
48  typedef void (Monitor<T>::*bool_t)() const;
49  void bool_true() const {}
50 public:
53  : _value(T(0))
54  {
55  }
56 
58  explicit Monitor(const T& value)
59  : _value(value)
60  {
61  }
62 
64  Monitor(const Monitor<T>& from)
65  : _value(from._value)
66  {
67  }
68 
70  ~Monitor() {}
75  {
76  std::unique_lock<std::mutex> lock(_mutex);
77  ++_value;
78  _condition.notify_all();
79  return *this;
80  }
81 
84  {
85  std::unique_lock<std::mutex> lock(_mutex);
86  --_value;
87  _condition.notify_all();
88  return *this;
89  }
90 
92  Monitor& operator=(const T& value)
93  {
94  set(value);
95  return *this;
96  }
97 
99  const Monitor& operator=(const Monitor<T>& from)
100  {
101  set(from._value);
102  return *this;
103  }
104 
106  Monitor& operator|=(const T& value)
107  {
108  std::unique_lock<std::mutex> lock(_mutex);
109  _value |= value;
110  _condition.notify_all();
111  return *this;
112  }
113 
115  Monitor& operator&=(const T& value)
116  {
117  std::unique_lock<std::mutex> lock(_mutex);
118  _value &= value;
119  _condition.notify_all();
120  return *this;
121  }
122 
124  T set(const T& value)
125  {
126  std::unique_lock<std::mutex> lock(_mutex);
127  const T old = _value;
128  _value = value;
129  _condition.notify_all();
130  return old;
131  }
133 
141  const T waitEQ(const T& value) const
142  {
143  return _wait([&] { return _value == value; });
144  }
145 
151  const T waitNE(const T& value) const
152  {
153  return _wait([&] { return _value != value; });
154  }
155 
161  const T waitNE(const T& v1, const T& v2) const
162  {
163  std::unique_lock<std::mutex> lock(_mutex);
164  _condition.wait(lock, [&] { return _value != v1 && _value != v2; });
165  return _value;
166  }
167 
173  const T waitGE(const T& value) const
174  {
175  return _wait([&] { return _value >= value; });
176  }
177 
183  const T waitLE(const T& value) const
184  {
185  return _wait([&] { return _value <= value; });
186  }
187 
193  const T waitGT(const T& value) const
194  {
195  return _wait([&] { return _value > value; });
196  }
197 
203  const T waitLT(const T& value) const
204  {
205  return _wait([&] { return _value < value; });
206  }
207 
217  bool timedWaitEQ(const T& value, const uint32_t timeout) const
218  {
219  return _timedWait([&] { return _value == value; }, timeout);
220  }
221 
229  bool timedWaitNE(const T& value, const uint32_t timeout) const
230  {
231  return _timedWait([&] { return _value != value; }, timeout);
232  }
233 
241  bool timedWaitGE(const T& value, const uint32_t timeout) const
242  {
243  return _timedWait([&] { return _value >= value; }, timeout);
244  }
245 
253  bool timedWaitLE(const T& value, const uint32_t timeout) const
254  {
255  return _timedWait([&] { return _value <= value; }, timeout);
256  }
257 
265  bool timedWaitGT(const T& value, const uint32_t timeout) const
266  {
267  return _timedWait([&] { return _value > value; }, timeout);
268  }
269 
277  bool timedWaitLT(const T& value, const uint32_t timeout) const
278  {
279  return _timedWait([&] { return _value < value; }, timeout);
280  }
281 
283 
286  bool operator==(const T& value) const
287  {
288  std::unique_lock<std::mutex> lock(_mutex);
289  return _value == value;
290  }
291  bool operator!=(const T& value) const
292  {
293  std::unique_lock<std::mutex> lock(_mutex);
294  return _value != value;
295  }
296  bool operator<(const T& value) const
297  {
298  std::unique_lock<std::mutex> lock(_mutex);
299  return _value < value;
300  }
301  bool operator>(const T& value) const
302  {
303  std::unique_lock<std::mutex> lock(_mutex);
304  return _value > value;
305  }
306  bool operator<=(const T& value) const
307  {
308  std::unique_lock<std::mutex> lock(_mutex);
309  return _value <= value;
310  }
311  bool operator>=(const T& value) const
312  {
313  std::unique_lock<std::mutex> lock(_mutex);
314  return _value >= value;
315  }
316 
317  bool operator==(const Monitor<T>& rhs) const
318  {
319  std::unique_lock<std::mutex> lock(_mutex);
320  return _value == rhs._value;
321  }
322  bool operator!=(const Monitor<T>& rhs) const
323  {
324  std::unique_lock<std::mutex> lock(_mutex);
325  return _value != rhs._value;
326  }
327  bool operator<(const Monitor<T>& rhs) const
328  {
329  std::unique_lock<std::mutex> lock(_mutex);
330  return _value < rhs._value;
331  }
332  bool operator>(const Monitor<T>& rhs) const
333  {
334  std::unique_lock<std::mutex> lock(_mutex);
335  return _value > rhs._value;
336  }
337  bool operator<=(const Monitor<T>& rhs) const
338  {
339  std::unique_lock<std::mutex> lock(_mutex);
340  return _value <= rhs._value;
341  }
342  bool operator>=(const Monitor<T>& rhs) const
343  {
344  std::unique_lock<std::mutex> lock(_mutex);
345  return _value >= rhs._value;
346  }
348  operator bool_t()
349  {
350  std::unique_lock<std::mutex> lock(_mutex);
351  return _value ? &Monitor<T>::bool_true : 0;
352  }
354 
358  const T& operator->() const { return _value; }
360  const T& get() const { return _value; }
362  T operator+(const T& value) const
363  {
364  std::unique_lock<std::mutex> lock(_mutex);
365  return _value + value;
366  }
367 
369  T operator|(const T& value) const
370  {
371  std::unique_lock<std::mutex> lock(_mutex);
372  return static_cast<T>(_value | value);
373  }
374 
376  T operator&(const T& value) const
377  {
378  std::unique_lock<std::mutex> lock(_mutex);
379  return static_cast<T>(_value & value);
380  }
382 
383 private:
384  T _value;
385  mutable std::mutex _mutex;
386  mutable std::condition_variable _condition;
387 
388  template <typename F>
389  const T _wait(const F& predicate) const
390  {
391  std::unique_lock<std::mutex> lock(_mutex);
392  _condition.wait(lock, predicate);
393  return _value;
394  }
395 
396  template <typename F>
397  bool _timedWait(const F& predicate, const uint32_t timeout) const
398  {
399  std::unique_lock<std::mutex> lock(_mutex);
400  return _condition.wait_for(lock, std::chrono::milliseconds(timeout),
401  predicate);
402  }
403 };
404 
407 
409 template <typename T>
410 inline std::ostream& operator<<(std::ostream& os, const Monitor<T>& monitor)
411 {
412  os << "Monitor< " << monitor.get() << " >";
413  return os;
414 }
415 
416 template <>
418 {
419  std::unique_lock<std::mutex> lock(_mutex);
420  assert(!_value);
421  _value = !_value;
422  _condition.notify_all();
423  return *this;
424 }
425 
426 template <>
428 {
429  std::unique_lock<std::mutex> lock(_mutex);
430  assert(!_value);
431  _value = !_value;
432  _condition.notify_all();
433  return *this;
434 }
435 
436 template <>
437 inline Monitor<bool>& Monitor<bool>::operator|=(const bool& value)
438 {
439  if (value)
440  {
441  std::unique_lock<std::mutex> lock(_mutex);
442  _value = value;
443  _condition.notify_all();
444  }
445  return *this;
446 }
447 }
448 
449 #include <servus/uint128_t.h>
450 namespace lunchbox
451 {
452 template <>
454 {
455 }
456 }
457 
458 #endif // LUNCHBOX_MONITOR_H
const T waitGE(const T &value) const
Block until the monitor has a value greater or equal to the given value.
Definition: monitor.h:173
bool timedWaitLT(const T &value, const uint32_t timeout) const
Block until the monitor has a value less than the given value.
Definition: monitor.h:277
Basic type definitions not provided by the operating system.
const T & operator->() const
Definition: monitor.h:358
const T waitLT(const T &value) const
Block until the monitor has a value less than the given value.
Definition: monitor.h:203
T operator|(const T &value) const
Definition: monitor.h:369
Monitor(const T &value)
Construct a new monitor with a given default value.
Definition: monitor.h:58
bool timedWaitGT(const T &value, const uint32_t timeout) const
Block until the monitor has a value greater than the given value.
Definition: monitor.h:265
const T waitLE(const T &value) const
Block until the monitor has a value less or equal to the given value.
Definition: monitor.h:183
Monitor & operator--()
Decrement the monitored value, prefix only.
Definition: monitor.h:83
const T waitNE(const T &value) const
Block until the monitor has not the given value.
Definition: monitor.h:151
bool timedWaitGE(const T &value, const uint32_t timeout) const
Block until the monitor has a value greater or equal to the given value.
Definition: monitor.h:241
A monitor primitive.
Definition: monitor.h:46
const T waitNE(const T &v1, const T &v2) const
Block until the monitor has none of the given values.
Definition: monitor.h:161
bool timedWaitNE(const T &value, const uint32_t timeout) const
Block until the monitor has not the given value.
Definition: monitor.h:229
Monitor(const Monitor< T > &from)
Ctor initializing with the given monitor value.
Definition: monitor.h:64
Monitor & operator|=(const T &value)
Perform an or operation on the value.
Definition: monitor.h:106
Monitor & operator=(const T &value)
Assign a new value.
Definition: monitor.h:92
Monitor & operator&=(const T &value)
Perform an and operation on the value.
Definition: monitor.h:115
T operator&(const T &value) const
Definition: monitor.h:376
Monitor()
Construct a new monitor with a default value of 0.
Definition: monitor.h:52
Monitor< uint32_t > Monitoru
An unsigned 32bit integer monitor.
Definition: monitor.h:406
Abstraction layer and common utilities for multi-threaded programming.
Definition: algorithm.h:29
bool timedWaitEQ(const T &value, const uint32_t timeout) const
Block until the monitor has the given value.
Definition: monitor.h:217
const Monitor & operator=(const Monitor< T > &from)
Assign a new value.
Definition: monitor.h:99
bool timedWaitLE(const T &value, const uint32_t timeout) const
Block until the monitor has a value less or equal to the given value.
Definition: monitor.h:253
const T waitGT(const T &value) const
Block until the monitor has a value greater than the given value.
Definition: monitor.h:193
Monitor & operator++()
Increment the monitored value, prefix only.
Definition: monitor.h:74
T operator+(const T &value) const
Definition: monitor.h:362
Monitor< bool > Monitorb
A boolean monitor variable.
Definition: monitor.h:405
~Monitor()
Destructs the monitor.
Definition: monitor.h:70
const T waitEQ(const T &value) const
Block until the monitor has the given value.
Definition: monitor.h:141