Lunchbox  1.9.1
 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 
31 namespace lunchbox
32 {
42 template< class T > class Monitor
43 {
44  typedef void (Monitor< T >::*bool_t)() const;
45  void bool_true() const {}
46 
47 public:
49  Monitor() : _value( T( 0 )) {}
50 
52  explicit Monitor( const T& value ) : _value( value ) {}
53 
55  Monitor( const Monitor< T >& from ) : _value( from._value ) {}
56 
58  ~Monitor() {}
59 
64  {
65  ScopedCondition mutex( _cond );
66  ++_value;
67  _cond.broadcast();
68  return *this;
69  }
70 
73  {
74  ScopedCondition mutex( _cond );
75  --_value;
76  _cond.broadcast();
77  return *this;
78  }
79 
81  Monitor& operator = ( const T& value )
82  {
83  set( value );
84  return *this;
85  }
86 
88  const Monitor& operator = ( const Monitor< T >& from )
89  {
90  set( from._value );
91  return *this;
92  }
93 
95  Monitor& operator |= ( const T& value )
96  {
97  ScopedCondition mutex( _cond );
98  _value |= value;
99  _cond.broadcast();
100  return *this;
101  }
102 
104  Monitor& operator &= ( const T& value )
105  {
106  ScopedCondition mutex( _cond );
107  _value &= value;
108  _cond.broadcast();
109  return *this;
110  }
111 
113  void set( const T& value )
114  {
115  ScopedCondition mutex( _cond );
116  _value = value;
117  _cond.broadcast();
118  }
120 
128  const T& waitEQ( const T& value ) const
129  {
130  if( sizeof( T ) <= 8 && _value == value )
131  return value;
132  ScopedCondition mutex( _cond );
133  while( _value != value )
134  _cond.wait();
135  return value;
136  }
137 
143  const T waitNE( const T& value ) const
144  {
145  if( sizeof( T ) <= 8 ) // issue #1
146  {
147  const T current = _value;
148  if( current != value )
149  return current;
150  }
151  ScopedCondition mutex( _cond );
152  while( _value == value )
153  _cond.wait();
154  return _value;
155  }
156 
162  const T waitNE( const T& v1, const T& v2 ) const
163  {
164  if( sizeof( T ) <= 8 ) // issue #1
165  {
166  const T current = _value;
167  if( current != v1 && current != v2 )
168  return current;
169  }
170  ScopedCondition mutex( _cond );
171  while( _value == v1 || _value == v2 )
172  _cond.wait();
173  return _value;
174  }
175 
181  const T waitGE( const T& value ) const
182  {
183  if( sizeof( T ) <= 8 ) // issue #1
184  {
185  const T current = _value;
186  if( current >= value )
187  return current;
188  }
189  ScopedCondition mutex( _cond );
190  while( _value < value )
191  _cond.wait();
192  return _value;
193  }
199  const T waitLE( const T& value ) const
200  {
201  if( sizeof( T ) <= 8 ) // issue #1
202  {
203  const T current = _value;
204  if( current <= value )
205  return current;
206  }
207  ScopedCondition mutex( _cond );
208  while( _value > value )
209  _cond.wait();
210  return _value;
211  }
212 
222  bool timedWaitEQ( const T& value, const uint32_t timeout ) const
223  {
224  if( sizeof( T ) <= 8 && _value == value )
225  return true;
226 
227  ScopedCondition mutex( _cond );
228  while( _value != value )
229  {
230  if( !_cond.timedWait( timeout ) )
231  {
232  return false;
233  }
234  }
235  return true;
236  }
237 
245  bool timedWaitGE( const T& value, const uint32_t timeout ) const
246  {
247  if( sizeof( T ) <= 8 && _value >= value )
248  return true;
249 
250  ScopedCondition mutex( _cond );
251  while( _value < value )
252  {
253  if ( !_cond.timedWait( timeout ) )
254  {
255  return false;
256  }
257  }
258  return true;
259  }
260 
268  bool timedWaitNE( const T& value, const uint32_t timeout ) const
269  {
270  if( sizeof( T ) <= 8 && _value != value )
271  return true;
272 
273  ScopedCondition mutex( _cond );
274  while( _value == value )
275  {
276  if( !_cond.timedWait( timeout ) )
277  {
278  return false;
279  }
280  }
281  return true;
282  }
284 
287  bool operator == ( const T& value ) const
288  {
289  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
290  return _value == value;
291  }
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 
318  bool operator == ( const Monitor<T>& rhs ) const
319  {
320  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
321  return _value == rhs._value;
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  }
349  operator bool_t()
350  {
351  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
352  return _value ? &Monitor< T >::bool_true : 0;
353  }
355 
359  const T& operator->() const { return _value; }
360 
362  const T& get() const { return _value; }
363 
365  T operator + ( const T& value ) const
366  {
367  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
368  return _value + value;
369  }
370 
372  T operator | ( const T& value ) const
373  {
374  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
375  return static_cast< T >( _value | value );
376  }
377 
379  T operator & ( const T& value ) const
380  {
381  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
382  return static_cast< T >( _value & value );
383  }
385 
386 private:
387  T _value;
388  mutable Condition _cond;
389 };
390 
393 
395 template< typename T >
396 inline std::ostream& operator << ( std::ostream& os,
397  const Monitor<T>& monitor )
398 {
399  os << "Monitor< " << monitor.get() << " >";
400  return os;
401 }
402 
403 template<> inline Monitor< bool >& Monitor< bool >::operator++ ()
404 {
405  ScopedCondition mutex( _cond );
406  assert( !_value );
407  _value = !_value;
408  _cond.broadcast();
409  return *this;
410 }
411 
412 template<> inline Monitor< bool >& Monitor< bool >::operator-- ()
413 {
414  ScopedCondition mutex( _cond );
415  assert( !_value );
416  _value = !_value;
417  _cond.broadcast();
418  return *this;
419 }
420 
421 template<> inline
422 Monitor< bool >& Monitor< bool >::operator |= ( const bool& value )
423 {
424  if( value )
425  {
426  ScopedCondition mutex( _cond );
427  _value = value;
428  _cond.broadcast();
429  }
430  return *this;
431 }
432 }
433 
434 #include <lunchbox/uint128_t.h>
435 namespace lunchbox
436 {
437 template<> inline Monitor< uint128_t >::Monitor() {}
438 }
439 
440 #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:181
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 & waitEQ(const T &value) const
Block until the monitor has the given value.
Definition: monitor.h:128
const T & operator->() const
Definition: monitor.h:359
Monitor< uint32_t > Monitoru
An unsigned 32bit integer monitor.
Definition: monitor.h:392
T operator|(const T &value) const
Definition: monitor.h:372
Monitor(const T &value)
Construct a new monitor with a given default value.
Definition: monitor.h:52
const T waitLE(const T &value) const
Block until the monitor has a value less or equal to the given value.
Definition: monitor.h:199
Monitor & operator--()
Decrement the monitored value, prefix only.
Definition: monitor.h:72
const T waitNE(const T &value) const
Block until the monitor has not the given value.
Definition: monitor.h:143
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:245
Monitor< bool > Monitorb
A boolean monitor variable.
Definition: monitor.h:391
A monitor primitive.
Definition: monitor.h:42
const T waitNE(const T &v1, const T &v2) const
Block until the monitor has none of the given values.
Definition: monitor.h:162
bool timedWaitNE(const T &value, const uint32_t timeout) const
Block until the monitor has not the given value.
Definition: monitor.h:268
Monitor(const Monitor< T > &from)
Ctor initializing with the given monitor value.
Definition: monitor.h:55
Monitor & operator|=(const T &value)
Perform an or operation on the value.
Definition: monitor.h:95
Monitor & operator=(const T &value)
Assign a new value.
Definition: monitor.h:81
Monitor & operator&=(const T &value)
Perform an and operation on the value.
Definition: monitor.h:104
T operator&(const T &value) const
Definition: monitor.h:379
Monitor()
Construct a new monitor with a default value of 0.
Definition: monitor.h:49
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:222
void set(const T &value)
Set a new value.
Definition: monitor.h:113
std::ostream & operator<<(std::ostream &os, const Array< T > &array)
Pretty-print all members of the array.
Definition: array.h:47
A scoped mutex.
Definition: scopedMutex.h:59
Monitor & operator++()
Increment the monitored value, prefix only.
Definition: monitor.h:63
T operator+(const T &value) const
Definition: monitor.h:365
~Monitor()
Destructs the monitor.
Definition: monitor.h:58
const T & get() const
Definition: monitor.h:362