LCOV - code coverage report
Current view: top level - lunchbox - monitor.h (source / functions) Hit Total Coverage
Test: lcov2.info Lines: 52 55 94.5 %
Date: 2014-10-01 Functions: 27 32 84.4 %

          Line data    Source code
       1             : /* Copyright (c) 2006-2013, 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/condition.h>   // member
      23             : #include <lunchbox/scopedMutex.h> // used inline
      24             : #include <lunchbox/types.h>
      25             : 
      26             : #include <errno.h>
      27             : #include <string.h>
      28             : #include <iostream>
      29             : #include <typeinfo>
      30             : 
      31             : namespace lunchbox
      32             : {
      33             : /**
      34             :  * A monitor primitive.
      35             :  *
      36             :  * A monitor has a value, which can be monitored to reach a certain state. The
      37             :  * caller is blocked until the condition is fulfilled. The concept is similar to
      38             :  * a pthread condition, with more usage convenience.
      39             :  *
      40             :  * Example: @include tests/monitor.cpp
      41             :  */
      42             : template< class T > class Monitor
      43             : {
      44             :     typedef void (Monitor< T >::*bool_t)() const;
      45           0 :     void bool_true() const {}
      46             : 
      47             : public:
      48             :     /** Construct a new monitor with a default value of 0. @version 1.0 */
      49           3 :     Monitor() : _value( T( 0 )) {}
      50             : 
      51             :     /** Construct a new monitor with a given default value. @version 1.0 */
      52        4179 :     explicit Monitor( const T& value ) : _value( value ) {}
      53             : 
      54             :     /** Ctor initializing with the given monitor value. @version 1.1.5 */
      55             :     Monitor( const Monitor< T >& from ) : _value( from._value ) {}
      56             : 
      57             :     /** Destructs the monitor. @version 1.0 */
      58        4179 :     ~Monitor() {}
      59             : 
      60             :     /** @name Changing the monitored value. */
      61             :     //@{
      62             :     /** Increment the monitored value, prefix only. @version 1.0 */
      63        3885 :     Monitor& operator++ ()
      64             :         {
      65        3885 :             ScopedCondition mutex( _cond );
      66        3888 :             ++_value;
      67        3888 :             _cond.broadcast();
      68        3888 :             return *this;
      69             :         }
      70             : 
      71             :     /** Decrement the monitored value, prefix only. @version 1.0 */
      72             :     Monitor& operator-- ()
      73             :         {
      74             :             ScopedCondition mutex( _cond );
      75             :             --_value;
      76             :             _cond.broadcast();
      77             :             return *this;
      78             :         }
      79             : 
      80             :     /** Assign a new value. @version 1.0 */
      81      813974 :     Monitor& operator = ( const T& value )
      82             :         {
      83      813974 :             set( value );
      84      813981 :             return *this;
      85             :         }
      86             : 
      87             :     /** Assign a new value. @version 1.1.5 */
      88             :     const Monitor& operator = ( const Monitor< T >& from )
      89             :         {
      90             :             set( from._value );
      91             :             return *this;
      92             :         }
      93             : 
      94             :     /** Perform an or operation on the value. @version 1.0 */
      95             :     Monitor& operator |= ( const T& value )
      96             :         {
      97             :             ScopedCondition mutex( _cond );
      98             :             _value |= value;
      99             :             _cond.broadcast();
     100             :             return *this;
     101             :         }
     102             : 
     103             :     /** Perform an and operation on the value. @version 1.7 */
     104             :     Monitor& operator &= ( const T& value )
     105             :         {
     106             :             ScopedCondition mutex( _cond );
     107             :             _value &= value;
     108             :             _cond.broadcast();
     109             :             return *this;
     110             :         }
     111             : 
     112             :     /** Set a new value. @version 1.0 */
     113      813974 :     void set( const T& value )
     114             :         {
     115      813974 :             ScopedCondition mutex( _cond );
     116      813980 :             _value = value;
     117      813980 :             _cond.broadcast();
     118      813983 :         }
     119             :     //@}
     120             : 
     121             :     /** @name Monitor the value. */
     122             :     //@{
     123             :     /**
     124             :      * Block until the monitor has the given value.
     125             :      * @return the value when reaching the condition.
     126             :      * @version 1.0
     127             :      */
     128      400036 :     const T& waitEQ( const T& value ) const
     129             :         {
     130      400036 :             if( sizeof( T ) <= 8 && _value == value )
     131           7 :                 return value;
     132      400029 :             ScopedCondition mutex( _cond );
     133     1200927 :             while( _value != value )
     134      400869 :                 _cond.wait();
     135      400029 :             return value;
     136             :         }
     137             : 
     138             :     /**
     139             :      * Block until the monitor has not the given value.
     140             :      * @return the value when reaching the condition.
     141             :      * @version 1.0
     142             :      */
     143        6961 :     const T waitNE( const T& value ) const
     144             :         {
     145             :             if( sizeof( T ) <= 8 ) // issue #1
     146             :             {
     147        6961 :                 const T current = _value;
     148        6961 :                 if( current != value )
     149        3067 :                     return current;
     150             :             }
     151        3894 :             ScopedCondition mutex( _cond );
     152       11682 :             while( _value == value )
     153        3894 :                 _cond.wait();
     154        3894 :             return _value;
     155             :         }
     156             : 
     157             :     /**
     158             :      * Block until the monitor has none of the given values.
     159             :      * @return the value when reaching the condition.
     160             :      * @version 1.0
     161             :      */
     162             :     const T waitNE( const T& v1, const T& v2 ) const
     163             :         {
     164             :             if( sizeof( T ) <= 8 ) // issue #1
     165             :             {
     166             :                 const T current = _value;
     167             :                 if( current != v1 && current != v2 )
     168             :                     return current;
     169             :             }
     170             :             ScopedCondition mutex( _cond );
     171             :             while( _value == v1 || _value == v2 )
     172             :                 _cond.wait();
     173             :             return _value;
     174             :         }
     175             : 
     176             :     /**
     177             :      * Block until the monitor has a value greater or equal to the given value.
     178             :      * @return the value when reaching the condition.
     179             :      * @version 1.0
     180             :      */
     181        3996 :     const T waitGE( const T& value ) const
     182             :         {
     183             :             if( sizeof( T ) <= 8 ) // issue #1
     184             :             {
     185        3996 :                 const T current = _value;
     186        3996 :                 if( current >= value )
     187           0 :                     return current;
     188             :             }
     189        3996 :             ScopedCondition mutex( _cond );
     190       88288 :             while( _value < value )
     191       80296 :                 _cond.wait();
     192        3996 :             return _value;
     193             :         }
     194             :     /**
     195             :      * Block until the monitor has a value less or equal to the given value.
     196             :      * @return the value when reaching the condition.
     197             :      * @version 1.0
     198             :      */
     199       76731 :     const T waitLE( const T& value ) const
     200             :         {
     201             :             if( sizeof( T ) <= 8 ) // issue #1
     202             :             {
     203             :                 const T current = _value;
     204             :                 if( current <= value )
     205             :                     return current;
     206             :             }
     207       76731 :             ScopedCondition mutex( _cond );
     208      153462 :             while( _value > value )
     209           0 :                 _cond.wait();
     210       76731 :             return _value;
     211             :         }
     212             : 
     213             :     /** @name Monitor the value with a timeout. */
     214             :     //@{
     215             :     /**
     216             :      * Block until the monitor has the given value.
     217             :      * @param value the exact value to monitor.
     218             :      * @param timeout the timeout in milliseconds to wait for the value.
     219             :      * @return true on success, false on timeout.
     220             :      * @version 1.1
     221             :      */
     222             :     bool timedWaitEQ( const T& value, const uint32_t timeout ) const
     223             :         {
     224             :             if( sizeof( T ) <= 8 && _value == value )
     225             :                 return true;
     226             : 
     227             :             ScopedCondition mutex( _cond );
     228             :             while( _value != value )
     229             :             {
     230             :                 if( !_cond.timedWait( timeout ) )
     231             :                 {
     232             :                     return false;
     233             :                 }
     234             :             }
     235             :             return true;
     236             :         }
     237             : 
     238             :     /**
     239             :      * Block until the monitor has a value greater or equal to the given value.
     240             :      * @param value the exact value to monitor.
     241             :      * @param timeout the timeout in milliseconds to wait for the value.
     242             :      * @return true on success, false on timeout.
     243             :      * @version 1.1
     244             :      */
     245             :     bool timedWaitGE( const T& value, const uint32_t timeout ) const
     246             :         {
     247             :             if( sizeof( T ) <= 8 && _value >= value )
     248             :                 return true;
     249             : 
     250             :             ScopedCondition mutex( _cond );
     251             :             while( _value < value )
     252             :             {
     253             :                 if ( !_cond.timedWait( timeout ) )
     254             :                 {
     255             :                     return false;
     256             :                 }
     257             :             }
     258             :             return true;
     259             :         }
     260             : 
     261             :     /**
     262             :      * Block until the monitor has not the given value.
     263             :      * @param value the exact value to monitor.
     264             :      * @param timeout the timeout in milliseconds to wait for not the value.
     265             :      * @return true on success, false on timeout.
     266             :      * @version 1.3.3
     267             :      */
     268             :     bool timedWaitNE( const T& value, const uint32_t timeout ) const
     269             :         {
     270             :             if( sizeof( T ) <= 8 && _value != value )
     271             :                 return true;
     272             : 
     273             :             ScopedCondition mutex( _cond );
     274             :             while( _value == value )
     275             :             {
     276             :                 if( !_cond.timedWait( timeout ) )
     277             :                 {
     278             :                     return false;
     279             :                 }
     280             :             }
     281             :             return true;
     282             :         }
     283             :     //@}
     284             : 
     285             :     /** @name Comparison Operators. @version 1.0 */
     286             :     //@{
     287        7976 :     bool operator == ( const T& value ) const
     288             :         {
     289        7976 :             ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
     290        7976 :             return _value == value;
     291             :         }
     292      237186 :     bool operator != ( const T& value ) const
     293             :         {
     294      237186 :             ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
     295      237186 :             return _value != value;
     296             :         }
     297             :     bool operator < ( const T& value ) const
     298             :         {
     299             :             ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
     300             :             return _value < value;
     301             :         }
     302             :     bool operator > ( const T& value ) const
     303             :         {
     304             :             ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
     305             :             return _value > value;
     306             :         }
     307             :     bool operator <= ( const T& value ) const
     308             :         {
     309             :             ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
     310             :             return _value <= value;
     311             :         }
     312             :     bool operator >= ( const T& value ) const
     313             :         {
     314             :             ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
     315             :             return _value >= value;
     316             :         }
     317             : 
     318             :     bool operator == ( const Monitor<T>& rhs ) const
     319             :         {
     320             :             ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
     321             :             return _value == rhs._value;
     322             :         }
     323             :     bool operator != ( const Monitor<T>& rhs ) const
     324             :         {
     325             :             ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
     326             :             return _value != rhs._value;
     327             :         }
     328             :     bool operator < ( const Monitor<T>& rhs ) const
     329             :         {
     330             :             ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
     331             :             return _value < rhs._value;
     332             :         }
     333             :     bool operator > ( const Monitor<T>& rhs ) const
     334             :         {
     335             :             ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
     336             :             return _value > rhs._value;
     337             :         }
     338             :     bool operator <= ( const Monitor<T>& rhs ) const
     339             :         {
     340             :             ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
     341             :             return _value <= rhs._value;
     342             :         }
     343             :     bool operator >= ( const Monitor<T>& rhs ) const
     344             :         {
     345             :             ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
     346             :             return _value >= rhs._value;
     347             :         }
     348             :     /** @return a bool conversion of the result. @version 1.9.1 */
     349           2 :     operator bool_t()
     350             :         {
     351           2 :             ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
     352           2 :             return _value ? &Monitor< T >::bool_true : 0;
     353             :         }
     354             :     //@}
     355             : 
     356             :     /** @name Data Access. */
     357             :     //@{
     358             :     /** @return the current value. @version 1.0 */
     359             :     const T& operator->() const { return _value; }
     360             : 
     361             :     /** @return the current value. @version 1.0 */
     362             :     const T& get() const { return _value; }
     363             : 
     364             :     /** @return the current plus the given value. @version 1.0 */
     365             :     T operator + ( const T& value ) const
     366             :         {
     367             :             ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
     368             :             return _value + value;
     369             :         }
     370             : 
     371             :     /** @return the current or'ed with the given value. @version 1.0 */
     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             :         }
     377             : 
     378             :     /** @return the current and the given value. @version 1.0 */
     379             :     T operator & ( const T& value ) const
     380             :         {
     381             :             ScopedCondition mutex( sizeof(T)>8 ? &_cond : 0 ); // issue #1
     382             :             return static_cast< T >( _value & value );
     383             :         }
     384             :     //@}
     385             : 
     386             : private:
     387             :     T _value;
     388             :     mutable Condition _cond;
     389             : };
     390             : 
     391             : typedef Monitor< bool >     Monitorb; //!< A boolean monitor variable
     392             : typedef Monitor< uint32_t > Monitoru; //!< An unsigned 32bit integer monitor
     393             : 
     394             : /** Print the monitor to the given output stream. @version 1.0 */
     395             : template< typename T >
     396             : inline std::ostream& operator << ( std::ostream& os,
     397             :                                    const Monitor<T>& monitor )
     398             : {
     399             :     os << "Monitor< " << monitor.get() << " >";
     400             :     return os;
     401             : }
     402             : 
     403             : template<> inline Monitor< bool >& Monitor< bool >::operator++ ()
     404             : {
     405             :     ScopedCondition mutex( _cond );
     406             :     assert( !_value );
     407             :     _value = !_value;
     408             :     _cond.broadcast();
     409             :     return *this;
     410             : }
     411             : 
     412             : template<> inline Monitor< bool >& Monitor< bool >::operator-- ()
     413             : {
     414             :     ScopedCondition mutex( _cond );
     415             :     assert( !_value );
     416             :     _value = !_value;
     417             :     _cond.broadcast();
     418             :     return *this;
     419             : }
     420             : 
     421             : template<> inline
     422             : Monitor< bool >& Monitor< bool >::operator |= ( const bool& value )
     423             : {
     424             :     if( value )
     425             :     {
     426             :         ScopedCondition mutex( _cond );
     427             :         _value = value;
     428             :         _cond.broadcast();
     429             :     }
     430             :     return *this;
     431             : }
     432             : }
     433             : 
     434             : #include <lunchbox/uint128_t.h>
     435             : namespace lunchbox
     436             : {
     437           1 : template<> inline Monitor< uint128_t >::Monitor() {}
     438             : }
     439             : 
     440             : #endif //LUNCHBOX_MONITOR_H

Generated by: LCOV version 1.10