Lunchbox  1.8.0
monitor.h
1 /* Copyright (c) 2006-2012, 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/nonCopyable.h> // base class
23 #include <lunchbox/condition.h> // member
24 #include <lunchbox/scopedMutex.h> // used inline
25 #include <lunchbox/types.h>
26 
27 #include <errno.h>
28 #include <string.h>
29 #include <iostream>
30 #include <typeinfo>
31 
32 namespace lunchbox
33 {
41  template< class T > class Monitor
42  {
43  public:
45  Monitor() : _value( T( 0 )) {}
46 
48  explicit Monitor( const T& value ) : _value( value ) {}
49 
51  Monitor( const Monitor< T >& from ) : _value( from._value ) {}
52 
54  ~Monitor() {}
55 
60  {
61  ScopedCondition mutex( _cond );
62  ++_value;
63  _cond.broadcast();
64  return *this;
65  }
66 
69  {
70  ScopedCondition mutex( _cond );
71  --_value;
72  _cond.broadcast();
73  return *this;
74  }
75 
77  Monitor& operator = ( const T& value )
78  {
79  set( value );
80  return *this;
81  }
82 
84  const Monitor& operator = ( const Monitor< T >& from )
85  {
86  set( from._value );
87  return *this;
88  }
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  void set( const T& value )
110  {
111  ScopedCondition mutex( _cond );
112  _value = value;
113  _cond.broadcast();
114  }
116 
124  const T& waitEQ( const T& value ) const
125  {
126  if( sizeof( T ) <= 8 && _value == value )
127  return value;
128  ScopedCondition mutex( _cond );
129  while( _value != value )
130  _cond.wait();
131  return value;
132  }
133 
139  const T waitNE( const T& value ) const
140  {
141  if( sizeof( T ) <= 8 ) // issue #1
142  {
143  const T current = _value;
144  if( current != value )
145  return current;
146  }
147  ScopedCondition mutex( _cond );
148  while( _value == value )
149  _cond.wait();
150  return _value;
151  }
152 
158  const T waitNE( const T& v1, const T& v2 ) const
159  {
160  if( sizeof( T ) <= 8 ) // issue #1
161  {
162  const T current = _value;
163  if( current != v1 && current != v2 )
164  return current;
165  }
166  ScopedCondition mutex( _cond );
167  while( _value == v1 || _value == v2 )
168  _cond.wait();
169  return _value;
170  }
171 
178  const T waitGE( const T& value ) const
179  {
180  if( sizeof( T ) <= 8 ) // issue #1
181  {
182  const T current = _value;
183  if( current >= value )
184  return current;
185  }
186  ScopedCondition mutex( _cond );
187  while( _value < value )
188  _cond.wait();
189  return _value;
190  }
197  const T waitLE( const T& value ) const
198  {
199  if( sizeof( T ) <= 8 ) // issue #1
200  {
201  const T current = _value;
202  if( current <= value )
203  return current;
204  }
205  ScopedCondition mutex( _cond );
206  while( _value > value )
207  _cond.wait();
208  return _value;
209  }
210 
220  bool timedWaitEQ( const T& value, const uint32_t timeout ) const
221  {
222  if( sizeof( T ) <= 8 && _value == value )
223  return true;
224 
225  ScopedCondition mutex( _cond );
226  while( _value != value )
227  {
228  if( !_cond.timedWait( timeout ) )
229  {
230  return false;
231  }
232  }
233  return true;
234  }
235 
244  bool timedWaitGE( const T& value, const uint32_t timeout ) const
245  {
246  if( sizeof( T ) <= 8 && _value >= value )
247  return true;
248 
249  ScopedCondition mutex( _cond );
250  while( _value < value )
251  {
252  if ( !_cond.timedWait( timeout ) )
253  {
254  return false;
255  }
256  }
257  return true;
258  }
259 
267  bool timedWaitNE( const T& value, const uint32_t timeout ) const
268  {
269  if( sizeof( T ) <= 8 && _value != value )
270  return true;
271 
272  ScopedCondition mutex( _cond );
273  while( _value == value )
274  {
275  if( !_cond.timedWait( timeout ) )
276  {
277  return false;
278  }
279  }
280  return true;
281  }
283 
286  bool operator == ( const T& value ) const
287  {
288  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
289  return _value == value;
290  }
291  bool operator != ( const T& value ) const
292  {
293  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
294  return _value != value;
295  }
296  bool operator < ( const T& value ) const
297  {
298  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
299  return _value < value;
300  }
301  bool operator > ( const T& value ) const
302  {
303  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
304  return _value > value;
305  }
306  bool operator <= ( const T& value ) const
307  {
308  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
309  return _value <= value;
310  }
311  bool operator >= ( const T& value ) const
312  {
313  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
314  return _value >= value;
315  }
316 
317  bool operator == ( const Monitor<T>& rhs ) const
318  {
319  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
320  return _value == rhs._value;
321  }
322  bool operator != ( const Monitor<T>& rhs ) const
323  {
324  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
325  return _value != rhs._value;
326  }
327  bool operator < ( const Monitor<T>& rhs ) const
328  {
329  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
330  return _value < rhs._value;
331  }
332  bool operator > ( const Monitor<T>& rhs ) const
333  {
334  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
335  return _value > rhs._value;
336  }
337  bool operator <= ( const Monitor<T>& rhs ) const
338  {
339  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
340  return _value <= rhs._value;
341  }
342  bool operator >= ( const Monitor<T>& rhs ) const
343  {
344  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
345  return _value >= rhs._value;
346  }
348 
352  const T& operator->() const { return _value; }
353 
355  const T& get() const { return _value; }
356 
358  T operator + ( const T& value ) const
359  {
360  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
361  return _value + value;
362  }
363 
365  T operator | ( const T& value ) const
366  {
367  ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
368  return static_cast< T >( _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  }
378 
379  private:
380  T _value;
381  mutable Condition _cond;
382  };
383 
386 
388  template< typename T >
389  inline std::ostream& operator << ( std::ostream& os,
390  const Monitor<T>& monitor )
391  {
392  os << "Monitor< " << monitor.get() << " >";
393  return os;
394  }
395 
396  template<> inline Monitor< bool >& Monitor< bool >::operator++ ()
397  {
398  ScopedCondition mutex( _cond );
399  assert( !_value );
400  _value = !_value;
401  _cond.broadcast();
402  return *this;
403  }
404 
405  template<> inline Monitor< bool >& Monitor< bool >::operator-- ()
406  {
407  ScopedCondition mutex( _cond );
408  assert( !_value );
409  _value = !_value;
410  _cond.broadcast();
411  return *this;
412  }
413 
414  template<>
415  inline Monitor< bool >& Monitor< bool >::operator |= ( const bool& value )
416  {
417  if( value )
418  {
419  ScopedCondition mutex( _cond );
420  _value = value;
421  _cond.broadcast();
422  }
423  return *this;
424  }
425 }
426 #endif //LUNCHBOX_MONITOR_H