Lunchbox  1.14.0
Multi-threaded C++ toolbox library for all application developers creating high-performance multi-threaded programs.
monitor.h
1 /* Copyright (c) 2006-2013, Stefan Eilemann <eile@equalizergraphics.com>
2  * 2011, Cedric Stalder <cedric.stalder@gmail.com>
3  * 2011-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_MONITOR_H
20 #define LUNCHBOX_MONITOR_H
21 
22 #include <lunchbox/condition.h> // member
23 #include <lunchbox/scopedMutex.h> // used inline
24 #include <lunchbox/types.h>
25 
26 #include <errno.h>
27 #include <string.h>
28 #include <iostream>
29 #include <typeinfo>
30 #include <functional>
31 #include <boost/bind.hpp>
32 
33 namespace lunchbox
34 {
44 template< class T > class Monitor
45 {
46  typedef void (Monitor< T >::*bool_t)() const;
47  void bool_true() const {}
48 
49 public:
51  Monitor() : _value( T( 0 )) {}
52 
54  explicit Monitor( const T& value ) : _value( value ) {}
55 
57  Monitor( const Monitor< T >& from ) : _value( from._value ) {}
58 
60  ~Monitor() {}
61 
66  {
67  ScopedCondition mutex( _cond );
68  ++_value;
69  _cond.broadcast();
70  return *this;
71  }
72 
75  {
76  ScopedCondition mutex( _cond );
77  --_value;
78  _cond.broadcast();
79  return *this;
80  }
81 
83  Monitor& operator = ( const T& value )
84  { set( value ); return *this; }
85 
87  const Monitor& operator = ( const Monitor< T >& from )
88  { set( from._value ); return *this; }
89 
91  Monitor& operator |= ( const T& value )
92  {
93  ScopedCondition mutex( _cond );
94  _value |= value;
95  _cond.broadcast();
96  return *this;
97  }
98 
100  Monitor& operator &= ( const T& value )
101  {
102  ScopedCondition mutex( _cond );
103  _value &= value;
104  _cond.broadcast();
105  return *this;
106  }
107 
109  T set( const T& value )
110  {
111  ScopedCondition mutex( _cond );
112  const T old = _value;
113  _value = value;
114  _cond.broadcast();
115  return old;
116  }
118 
126  const T waitEQ( const T& value ) const
127  {
128  return _waitPredicate( boost::bind( std::equal_to<T>(), value, _1 ));
129  }
130 
136  const T waitNE( const T& value ) const
137  {
138  return _waitPredicate( boost::bind( std::not_equal_to<T>(), value, _1));
139  }
140 
146  const T waitNE( const T& v1, const T& v2 ) const
147  {
148  if( sizeof( T ) <= 8 ) // issue #1
149  {
150  const T current = _value;
151  if( current != v1 && current != v2 )
152  return current;
153  }
154  ScopedCondition mutex( _cond );
155  while( _value == v1 || _value == v2 )
156  _cond.wait();
157  return _value;
158  }
159 
165  const T waitGE( const T& value ) const
166  {
167  return _waitPredicate( boost::bind( std::greater_equal<T>(), _1,
168  value ));
169  }
170 
176  const T waitLE( const T& value ) const
177  { return _waitPredicate( boost::bind( std::less_equal<T>(), _1, value )); }
178 
184  const T waitGT( const T& value ) const
185  { return _waitPredicate( boost::bind( std::greater<T>(), _1, value )); }
186 
192  const T waitLT( const T& value ) const
193  { return _waitPredicate( boost::bind( std::less<T>(), _1, value )); }
194 
204  bool timedWaitEQ( const T& value, const uint32_t timeout ) const
205  {
206  return _timedWaitPredicate( boost::bind( std::equal_to<T>(), _1,
207  value ), timeout );
208  }
209 
217  bool timedWaitNE( const T& value, const uint32_t timeout ) const
218  {
219  return _timedWaitPredicate( boost::bind( std::not_equal_to<T>(), _1,
220  value ), timeout );
221  }
222 
230  bool timedWaitGE( const T& value, const uint32_t timeout ) const
231  {
232  return _timedWaitPredicate( boost::bind( std::greater_equal<T>(), _1,
233  value ), timeout );
234  }
235 
243  bool timedWaitLE( const T& value, const uint32_t timeout ) const
244  {
245  return _timedWaitPredicate( boost::bind( std::less_equal<T>(), _1,
246  value ), timeout );
247  }
248 
256  bool timedWaitGT( const T& value, const uint32_t timeout ) const
257  {
258  return _timedWaitPredicate( boost::bind( std::greater<T>(), _1,
259  value ), timeout );
260  }
261 
269  bool timedWaitLT( const T& value, const uint32_t timeout ) const
270  {
271  return _timedWaitPredicate( boost::bind( std::less<T>(), _1, value ),
272  timeout );
273  }
274 
276 
279  bool operator == ( const T& value ) const
280  {
281  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
282  return _value == value;
283  }
284  bool operator != ( const T& value ) const
285  {
286  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
287  return _value != value;
288  }
289  bool operator < ( const T& value ) const
290  {
291  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
292  return _value < value;
293  }
294  bool operator > ( const T& value ) const
295  {
296  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
297  return _value > value;
298  }
299  bool operator <= ( const T& value ) const
300  {
301  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
302  return _value <= value;
303  }
304  bool operator >= ( const T& value ) const
305  {
306  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
307  return _value >= value;
308  }
309 
310  bool operator == ( const Monitor<T>& rhs ) const
311  {
312  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
313  return _value == rhs._value;
314  }
315  bool operator != ( const Monitor<T>& rhs ) const
316  {
317  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
318  return _value != rhs._value;
319  }
320  bool operator < ( const Monitor<T>& rhs ) const
321  {
322  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
323  return _value < rhs._value;
324  }
325  bool operator > ( const Monitor<T>& rhs ) const
326  {
327  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
328  return _value > rhs._value;
329  }
330  bool operator <= ( const Monitor<T>& rhs ) const
331  {
332  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
333  return _value <= rhs._value;
334  }
335  bool operator >= ( const Monitor<T>& rhs ) const
336  {
337  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
338  return _value >= rhs._value;
339  }
341  operator bool_t()
342  {
343  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
344  return _value ? &Monitor< T >::bool_true : 0;
345  }
347 
351  const T& operator->() const { return _value; }
352 
354  const T& get() const { return _value; }
355 
357  T operator + ( const T& value ) const
358  {
359  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
360  return _value + value;
361  }
362 
364  T operator | ( const T& value ) const
365  {
366  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
367  return static_cast< T >( _value | value );
368  }
369 
371  T operator & ( const T& value ) const
372  {
373  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
374  return static_cast< T >( _value & value );
375  }
377 
378 private:
379  T _value;
380  mutable Condition _cond;
381 
382  template< typename F >
383  const T _waitPredicate( const F& predicate ) const
384  {
385  if( sizeof( T ) <= 8 ) // issue #1
386  {
387  const T current = _value;
388  if( predicate( current ))
389  return current;
390  }
391  ScopedCondition mutex( _cond );
392  while( !predicate( _value ))
393  _cond.wait();
394  return _value;
395  }
396 
397  template< typename F >
398  bool _timedWaitPredicate( const F& predicate, const uint32_t timeout ) const
399  {
400  if( sizeof( T ) <= 8 ) // issue #1
401  {
402  const T current = _value;
403  if( predicate( current ))
404  return true;
405  }
406  ScopedCondition mutex( _cond );
407  while( !predicate( _value ))
408  {
409  if( !_cond.timedWait( timeout ) )
410  {
411  return false;
412  }
413  }
414  return true;
415  }
416 };
417 
420 
422 template< typename T >
423 inline std::ostream& operator << ( std::ostream& os,
424  const Monitor<T>& monitor )
425 {
426  os << "Monitor< " << monitor.get() << " >";
427  return os;
428 }
429 
431 {
432  ScopedCondition mutex( _cond );
433  assert( !_value );
434  _value = !_value;
435  _cond.broadcast();
436  return *this;
437 }
438 
440 {
441  ScopedCondition mutex( _cond );
442  assert( !_value );
443  _value = !_value;
444  _cond.broadcast();
445  return *this;
446 }
447 
448 template<> inline
450 {
451  if( value )
452  {
453  ScopedCondition mutex( _cond );
454  _value = value;
455  _cond.broadcast();
456  }
457  return *this;
458 }
459 }
460 
461 #include <servus/uint128_t.h>
462 namespace lunchbox
463 {
464 template<> inline Monitor< servus::uint128_t >::Monitor() {}
465 }
466 
467 #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:165
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:269
Basic type definitions not provided by the operating system.
A condition variable and associated lock.
Definition: condition.h:33
const T & operator->() const
Definition: monitor.h:351
const T waitLT(const T &value) const
Block until the monitor has a value less than the given value.
Definition: monitor.h:192
Monitor< uint32_t > Monitoru
An unsigned 32bit integer monitor.
Definition: monitor.h:419
T operator|(const T &value) const
Definition: monitor.h:364
Monitor(const T &value)
Construct a new monitor with a given default value.
Definition: monitor.h:54
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:256
const T waitLE(const T &value) const
Block until the monitor has a value less or equal to the given value.
Definition: monitor.h:176
bool timedWait(const uint32_t timeout)
Atomically unlock the mutex, wait for a signal and relock the mutex.
Monitor & operator--()
Decrement the monitored value, prefix only.
Definition: monitor.h:74
const T waitNE(const T &value) const
Block until the monitor has not the given value.
Definition: monitor.h:136
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:230
Monitor< bool > Monitorb
A boolean monitor variable.
Definition: monitor.h:418
A monitor primitive.
Definition: monitor.h:44
const T waitNE(const T &v1, const T &v2) const
Block until the monitor has none of the given values.
Definition: monitor.h:146
void broadcast()
Broadcast the condition.
bool timedWaitNE(const T &value, const uint32_t timeout) const
Block until the monitor has not the given value.
Definition: monitor.h:217
Monitor(const Monitor< T > &from)
Ctor initializing with the given monitor value.
Definition: monitor.h:57
Monitor & operator|=(const T &value)
Perform an or operation on the value.
Definition: monitor.h:91
Monitor & operator=(const T &value)
Assign a new value.
Definition: monitor.h:83
Monitor & operator&=(const T &value)
Perform an and operation on the value.
Definition: monitor.h:100
T operator&(const T &value) const
Definition: monitor.h:371
Monitor()
Construct a new monitor with a default value of 0.
Definition: monitor.h:51
Abstraction layer and common utilities for multi-threaded programming.
Definition: algorithm.h:32
bool timedWaitEQ(const T &value, const uint32_t timeout) const
Block until the monitor has the given value.
Definition: monitor.h:204
std::ostream & operator<<(std::ostream &os, const Array< T > &array)
Pretty-print all members of the array.
Definition: array.h:47
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:243
A scoped mutex.
Definition: scopedMutex.h:59
void wait()
Atomically unlock the mutex, wait for a signal and relock the mutex.
const T waitGT(const T &value) const
Block until the monitor has a value greater than the given value.
Definition: monitor.h:184
Monitor & operator++()
Increment the monitored value, prefix only.
Definition: monitor.h:65
T operator+(const T &value) const
Definition: monitor.h:357
~Monitor()
Destructs the monitor.
Definition: monitor.h:60
const T waitEQ(const T &value) const
Block until the monitor has the given value.
Definition: monitor.h:126
const T & get() const
Definition: monitor.h:354