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