Lunchbox  1.11.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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  {
85  set( value );
86  return *this;
87  }
88 
90  const Monitor& operator = ( const Monitor< T >& from )
91  {
92  set( from._value );
93  return *this;
94  }
95 
97  Monitor& operator |= ( const T& value )
98  {
99  ScopedCondition mutex( _cond );
100  _value |= value;
101  _cond.broadcast();
102  return *this;
103  }
104 
106  Monitor& operator &= ( const T& value )
107  {
108  ScopedCondition mutex( _cond );
109  _value &= value;
110  _cond.broadcast();
111  return *this;
112  }
113 
115  void set( const T& value )
116  {
117  ScopedCondition mutex( _cond );
118  _value = value;
119  _cond.broadcast();
120  }
122 
130  const T waitEQ( const T& value ) const
131  {
132  return _waitPredicate(
133  boost::bind( std::equal_to< T >(), value, _1 ));
134  }
135 
141  const T waitNE( const T& value ) const
142  {
143  return _waitPredicate(
144  boost::bind( std::not_equal_to< T >(), value, _1 ));
145  }
146 
152  const T waitNE( const T& v1, const T& v2 ) const
153  {
154  if( sizeof( T ) <= 8 ) // issue #1
155  {
156  const T current = _value;
157  if( current != v1 && current != v2 )
158  return current;
159  }
160  ScopedCondition mutex( _cond );
161  while( _value == v1 || _value == v2 )
162  _cond.wait();
163  return _value;
164  }
165 
171  const T waitGE( const T& value ) const
172  {
173  return _waitPredicate(
174  boost::bind( std::greater_equal< T >(), _1, value ));
175  }
181  const T waitLE( const T& value ) const
182  {
183  return _waitPredicate(
184  boost::bind( std::less_equal< T >(), _1, value ));
185  }
186 
192  const T waitGT( const T& value ) const
193  {
194  return _waitPredicate(
195  boost::bind( std::greater< T >(), _1, value ));
196  }
202  const T waitLT( const T& value ) const
203  {
204  return _waitPredicate(
205  boost::bind( std::less< T >(), _1, value ));
206  }
207 
217  bool timedWaitEQ( const T& value, const uint32_t timeout ) const
218  {
219  return _timedWaitPredicate(
220  boost::bind( std::equal_to< T >(), _1, value ), timeout);
221  }
222 
230  bool timedWaitNE( const T& value, const uint32_t timeout ) const
231  {
232  return _timedWaitPredicate(
233  boost::bind( std::not_equal_to< T >(), _1, value ), timeout);
234  }
235 
243  bool timedWaitGE( const T& value, const uint32_t timeout ) const
244  {
245  return _timedWaitPredicate(
246  boost::bind( std::greater_equal< T >(), _1, value ), timeout);
247  }
248 
256  bool timedWaitLE( const T& value, const uint32_t timeout ) const
257  {
258  return _timedWaitPredicate(
259  boost::bind( std::less_equal< T >(), _1, value ), timeout);
260  }
261 
269  bool timedWaitGT( const T& value, const uint32_t timeout ) const
270  {
271  return _timedWaitPredicate(
272  boost::bind( std::greater< T >(), _1, value ), timeout);
273  }
274 
282  bool timedWaitLT( const T& value, const uint32_t timeout ) const
283  {
284  return _timedWaitPredicate(
285  boost::bind( std::less< T >(), _1, value ), timeout);
286  }
287 
289 
292  bool operator == ( const T& value ) const
293  {
294  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
295  return _value == value;
296  }
297  bool operator != ( const T& value ) const
298  {
299  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
300  return _value != value;
301  }
302  bool operator < ( const T& value ) const
303  {
304  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
305  return _value < value;
306  }
307  bool operator > ( const T& value ) const
308  {
309  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
310  return _value > value;
311  }
312  bool operator <= ( const T& value ) const
313  {
314  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
315  return _value <= value;
316  }
317  bool operator >= ( const T& value ) const
318  {
319  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
320  return _value >= value;
321  }
322 
323  bool operator == ( const Monitor<T>& rhs ) const
324  {
325  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
326  return _value == rhs._value;
327  }
328  bool operator != ( const Monitor<T>& rhs ) const
329  {
330  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
331  return _value != rhs._value;
332  }
333  bool operator < ( const Monitor<T>& rhs ) const
334  {
335  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
336  return _value < rhs._value;
337  }
338  bool operator > ( const Monitor<T>& rhs ) const
339  {
340  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
341  return _value > rhs._value;
342  }
343  bool operator <= ( const Monitor<T>& rhs ) const
344  {
345  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
346  return _value <= rhs._value;
347  }
348  bool operator >= ( const Monitor<T>& rhs ) const
349  {
350  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
351  return _value >= rhs._value;
352  }
354  operator bool_t()
355  {
356  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
357  return _value ? &Monitor< T >::bool_true : 0;
358  }
360 
364  const T& operator->() const { return _value; }
365 
367  const T& get() const { return _value; }
368 
370  T operator + ( const T& value ) const
371  {
372  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
373  return _value + value;
374  }
375 
377  T operator | ( const T& value ) const
378  {
379  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
380  return static_cast< T >( _value | value );
381  }
382 
384  T operator & ( const T& value ) const
385  {
386  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
387  return static_cast< T >( _value & value );
388  }
390 
391 private:
392  T _value;
393  mutable Condition _cond;
394 
395  template< typename F >
396  const T _waitPredicate( const F& predicate ) const
397  {
398  if( sizeof( T ) <= 8 ) // issue #1
399  {
400  const T current = _value;
401  if( predicate( current ))
402  return current;
403  }
404  ScopedCondition mutex( _cond );
405  while( !predicate( _value ))
406  _cond.wait();
407  return _value;
408  }
409 
410  template< typename F >
411  bool _timedWaitPredicate( const F& predicate, const uint32_t timeout ) const
412  {
413  if( sizeof( T ) <= 8 ) // issue #1
414  {
415  const T current = _value;
416  if( predicate( current ))
417  return true;
418  }
419  ScopedCondition mutex( _cond );
420  while( !predicate( _value ))
421  {
422  if( !_cond.timedWait( timeout ) )
423  {
424  return false;
425  }
426  }
427  return true;
428  }
429 };
430 
433 
435 template< typename T >
436 inline std::ostream& operator << ( std::ostream& os,
437  const Monitor<T>& monitor )
438 {
439  os << "Monitor< " << monitor.get() << " >";
440  return os;
441 }
442 
443 template<> inline Monitor< bool >& Monitor< bool >::operator++ ()
444 {
445  ScopedCondition mutex( _cond );
446  assert( !_value );
447  _value = !_value;
448  _cond.broadcast();
449  return *this;
450 }
451 
452 template<> inline Monitor< bool >& Monitor< bool >::operator-- ()
453 {
454  ScopedCondition mutex( _cond );
455  assert( !_value );
456  _value = !_value;
457  _cond.broadcast();
458  return *this;
459 }
460 
461 template<> inline
462 Monitor< bool >& Monitor< bool >::operator |= ( const bool& value )
463 {
464  if( value )
465  {
466  ScopedCondition mutex( _cond );
467  _value = value;
468  _cond.broadcast();
469  }
470  return *this;
471 }
472 }
473 
474 #include <servus/uint128_t.h>
475 namespace lunchbox
476 {
477 template<> inline Monitor< servus::uint128_t >::Monitor() {}
478 }
479 
480 #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:171
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:282
LUNCHBOX_API bool timedWait(const uint32_t timeout)
Atomically unlock the mutex, wait for a signal and relock the mutex.
Basic type definitions not provided by the operating system.
A condition variable and associated lock.
Definition: condition.h:33
ScopedMutex< Condition, WriteOp > ScopedCondition
A scoped mutex for a write operation on a condition.
Definition: scopedMutex.h:126
const T & operator->() const
Definition: monitor.h:364
const T waitLT(const T &value) const
Block until the monitor has a value less than the given value.
Definition: monitor.h:202
Monitor< uint32_t > Monitoru
An unsigned 32bit integer monitor.
Definition: monitor.h:432
T operator|(const T &value) const
Definition: monitor.h:377
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:269
const T waitLE(const T &value) const
Block until the monitor has a value less or equal to the given value.
Definition: monitor.h:181
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:141
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:243
Monitor< bool > Monitorb
A boolean monitor variable.
Definition: monitor.h:431
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:152
bool timedWaitNE(const T &value, const uint32_t timeout) const
Block until the monitor has not the given value.
Definition: monitor.h:230
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:97
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:106
T operator&(const T &value) const
Definition: monitor.h:384
Monitor()
Construct a new monitor with a default value of 0.
Definition: monitor.h:51
LUNCHBOX_API void broadcast()
Broadcast the condition.
LUNCHBOX_API void wait()
Atomically unlock the mutex, wait for a signal and relock the mutex.
bool timedWaitEQ(const T &value, const uint32_t timeout) const
Block until the monitor has the given value.
Definition: monitor.h:217
void set(const T &value)
Set a new value.
Definition: monitor.h:115
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:256
A scoped mutex.
Definition: scopedMutex.h:59
const T waitGT(const T &value) const
Block until the monitor has a value greater than the given value.
Definition: monitor.h:192
Monitor & operator++()
Increment the monitored value, prefix only.
Definition: monitor.h:65
T operator+(const T &value) const
Definition: monitor.h:370
~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:130
const T & get() const
Definition: monitor.h:367