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