Lunchbox
1.4.0
|
00001 00002 /* Copyright (c) 2006-2012, Stefan Eilemann <eile@equalizergraphics.com> 00003 * 2011, Cedric Stalder <cedric.stalder@gmail.com> 00004 * 00005 * This library is free software; you can redistribute it and/or modify it under 00006 * the terms of the GNU Lesser General Public License version 2.1 as published 00007 * by the Free Software Foundation. 00008 * 00009 * This library is distributed in the hope that it will be useful, but WITHOUT 00010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00011 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 00012 * details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public License 00015 * along with this library; if not, write to the Free Software Foundation, Inc., 00016 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00017 */ 00018 00019 #ifndef LUNCHBOX_MONITOR_H 00020 #define LUNCHBOX_MONITOR_H 00021 00022 #include <lunchbox/nonCopyable.h> // base class 00023 #include <lunchbox/condition.h> // member 00024 #include <lunchbox/scopedMutex.h> // used inline 00025 #include <lunchbox/types.h> 00026 00027 #include <errno.h> 00028 #include <string.h> 00029 #include <iostream> 00030 #include <typeinfo> 00031 00032 namespace lunchbox 00033 { 00041 template< class T > class Monitor 00042 { 00043 public: 00045 Monitor() : _value( T( 0 )) {} 00046 00048 explicit Monitor( const T& value ) : _value( value ) {} 00049 00051 Monitor( const Monitor< T >& from ) : _value( from._value ) {} 00052 00054 ~Monitor() {} 00055 00059 Monitor& operator++ () 00060 { 00061 ScopedCondition mutex( _cond ); 00062 ++_value; 00063 _cond.broadcast(); 00064 return *this; 00065 } 00066 00068 Monitor& operator-- () 00069 { 00070 ScopedCondition mutex( _cond ); 00071 --_value; 00072 _cond.broadcast(); 00073 return *this; 00074 } 00075 00077 Monitor& operator = ( const T& value ) 00078 { 00079 set( value ); 00080 return *this; 00081 } 00082 00084 const Monitor& operator = ( const Monitor< T >& from ) 00085 { 00086 set( from._value ); 00087 return *this; 00088 } 00089 00091 Monitor& operator |= ( const T& value ) 00092 { 00093 ScopedCondition mutex( _cond ); 00094 _value |= value; 00095 _cond.broadcast(); 00096 return *this; 00097 } 00098 00100 void set( const T& value ) 00101 { 00102 ScopedCondition mutex( _cond ); 00103 _value = value; 00104 _cond.broadcast(); 00105 } 00107 00115 const T& waitEQ( const T& value ) const 00116 { 00117 if( sizeof( T ) <= 8 && _value == value ) 00118 return value; 00119 ScopedCondition mutex( _cond ); 00120 while( _value != value ) 00121 _cond.wait(); 00122 return value; 00123 } 00124 00130 const T waitNE( const T& value ) const 00131 { 00132 if( sizeof( T ) <= 8 ) // issue #1 00133 { 00134 const T current = _value; 00135 if( current != value ) 00136 return current; 00137 } 00138 ScopedCondition mutex( _cond ); 00139 while( _value == value ) 00140 _cond.wait(); 00141 return _value; 00142 } 00143 00149 const T waitNE( const T& v1, const T& v2 ) const 00150 { 00151 if( sizeof( T ) <= 8 ) // issue #1 00152 { 00153 const T current = _value; 00154 if( current != v1 && current != v2 ) 00155 return current; 00156 } 00157 ScopedCondition mutex( _cond ); 00158 while( _value == v1 || _value == v2 ) 00159 _cond.wait(); 00160 return _value; 00161 } 00162 00169 const T waitGE( const T& value ) const 00170 { 00171 if( sizeof( T ) <= 8 ) // issue #1 00172 { 00173 const T current = _value; 00174 if( current >= value ) 00175 return current; 00176 } 00177 ScopedCondition mutex( _cond ); 00178 while( _value < value ) 00179 _cond.wait(); 00180 return _value; 00181 } 00188 const T waitLE( const T& value ) const 00189 { 00190 if( sizeof( T ) <= 8 ) // issue #1 00191 { 00192 const T current = _value; 00193 if( current <= value ) 00194 return current; 00195 } 00196 ScopedCondition mutex( _cond ); 00197 while( _value > value ) 00198 _cond.wait(); 00199 return _value; 00200 } 00201 00211 bool timedWaitEQ( const T& value, const uint32_t timeout ) const 00212 { 00213 if( sizeof( T ) <= 8 && _value == value ) 00214 return true; 00215 00216 ScopedCondition mutex( _cond ); 00217 while( _value != value ) 00218 { 00219 if( !_cond.timedWait( timeout ) ) 00220 { 00221 return false; 00222 } 00223 } 00224 return true; 00225 } 00226 00235 bool timedWaitGE( const T& value, const uint32_t timeout ) const 00236 { 00237 if( sizeof( T ) <= 8 && _value >= value ) 00238 return true; 00239 00240 ScopedCondition mutex( _cond ); 00241 while( _value < value ) 00242 { 00243 if ( !_cond.timedWait( timeout ) ) 00244 { 00245 return false; 00246 } 00247 } 00248 return true; 00249 } 00250 00258 bool timedWaitNE( const T& value, const uint32_t timeout ) const 00259 { 00260 if( sizeof( T ) <= 8 && _value != value ) 00261 return true; 00262 00263 ScopedCondition mutex( _cond ); 00264 while( _value == value ) 00265 { 00266 if( !_cond.timedWait( timeout ) ) 00267 { 00268 return false; 00269 } 00270 } 00271 return true; 00272 } 00274 00277 bool operator == ( const T& value ) const 00278 { 00279 ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1 00280 return _value == value; 00281 } 00282 bool operator != ( const T& value ) const 00283 { 00284 ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1 00285 return _value != value; 00286 } 00287 bool operator < ( const T& value ) const 00288 { 00289 ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1 00290 return _value < value; 00291 } 00292 bool operator > ( const T& value ) const 00293 { 00294 ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1 00295 return _value > value; 00296 } 00297 bool operator <= ( const T& value ) const 00298 { 00299 ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1 00300 return _value <= value; 00301 } 00302 bool operator >= ( const T& value ) const 00303 { 00304 ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1 00305 return _value >= value; 00306 } 00307 00308 bool operator == ( const Monitor<T>& rhs ) const 00309 { 00310 ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1 00311 return _value == rhs._value; 00312 } 00313 bool operator != ( const Monitor<T>& rhs ) const 00314 { 00315 ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1 00316 return _value != rhs._value; 00317 } 00318 bool operator < ( const Monitor<T>& rhs ) const 00319 { 00320 ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1 00321 return _value < rhs._value; 00322 } 00323 bool operator > ( const Monitor<T>& rhs ) const 00324 { 00325 ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1 00326 return _value > rhs._value; 00327 } 00328 bool operator <= ( const Monitor<T>& rhs ) const 00329 { 00330 ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1 00331 return _value <= rhs._value; 00332 } 00333 bool operator >= ( const Monitor<T>& rhs ) const 00334 { 00335 ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1 00336 return _value >= rhs._value; 00337 } 00339 00343 const T& operator->() const { return _value; } 00344 00346 const T& get() const { return _value; } 00347 00349 T operator + ( const T& value ) const 00350 { 00351 ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1 00352 return _value + value; 00353 } 00354 00356 T operator | ( const T& value ) const 00357 { 00358 ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1 00359 return static_cast< T >( _value | value ); 00360 } 00361 00363 T operator & ( const T& value ) const 00364 { 00365 ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1 00366 return static_cast< T >( _value & value ); 00367 } 00369 00370 private: 00371 T _value; 00372 mutable Condition _cond; 00373 }; 00374 00375 typedef Monitor< bool > Monitorb; 00376 typedef Monitor< uint32_t > Monitoru; 00377 00379 template< typename T > 00380 inline std::ostream& operator << ( std::ostream& os, 00381 const Monitor<T>& monitor ) 00382 { 00383 os << "Monitor< " << monitor.get() << " >"; 00384 return os; 00385 } 00386 00387 template<> inline Monitor< bool >& Monitor< bool >::operator++ () 00388 { 00389 ScopedCondition mutex( _cond ); 00390 assert( !_value ); 00391 _value = !_value; 00392 _cond.broadcast(); 00393 return *this; 00394 } 00395 00396 template<> inline Monitor< bool >& Monitor< bool >::operator-- () 00397 { 00398 ScopedCondition mutex( _cond ); 00399 assert( !_value ); 00400 _value = !_value; 00401 _cond.broadcast(); 00402 return *this; 00403 } 00404 00405 template<> 00406 inline Monitor< bool >& Monitor< bool >::operator |= ( const bool& value ) 00407 { 00408 if( value ) 00409 { 00410 ScopedCondition mutex( _cond ); 00411 _value = value; 00412 _cond.broadcast(); 00413 } 00414 return *this; 00415 } 00416 } 00417 #endif //LUNCHBOX_MONITOR_H