Lunchbox  1.6.0
monitor.h
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