monitor.h

00001 
00002 /* Copyright (c) 2006-2009, Stefan Eilemann <eile@equalizergraphics.com> 
00003  *
00004  * This library is free software; you can redistribute it and/or modify it under
00005  * the terms of the GNU Lesser General Public License version 2.1 as published
00006  * by the Free Software Foundation.
00007  *  
00008  * This library is distributed in the hope that it will be useful, but WITHOUT
00009  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00010  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00011  * details.
00012  * 
00013  * You should have received a copy of the GNU Lesser General Public License
00014  * along with this library; if not, write to the Free Software Foundation, Inc.,
00015  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00016  */
00017 
00018 #ifndef EQBASE_MONITOR_H
00019 #define EQBASE_MONITOR_H
00020 
00021 #include <eq/base/nonCopyable.h> // base class
00022 
00023 #include <errno.h>
00024 #include <string.h>
00025 #include <iostream>
00026 #include <typeinfo>
00027 
00028 
00029 namespace eq
00030 {
00031 namespace base
00032 {
00033     class MonitorPrivate;
00034 
00043     template< typename T > class Monitor : public NonCopyable
00044     {
00045     public:
00047         Monitor() : _value( static_cast<T>( 0 ))    { _construct(); }
00049         Monitor( const T& value ) : _value( value ) { _construct(); }
00050         
00052         ~Monitor();
00053 
00057         Monitor& operator++ ();
00059         Monitor& operator-- ();
00060 
00062         Monitor& operator = ( const T& value )
00063             {
00064                 set( value );
00065                 return *this;
00066             }
00067 
00069         void set( const T& value );
00071 
00078         const T& waitEQ( const T& value ) const;
00079 
00084         const T& waitNE( const T& value ) const;
00085 
00091         const T& waitGE( const T& value ) const;
00092 
00098         const T& waitLE( const T& value ) const;
00100 
00103         bool operator == ( const T& value ) const { return _value == value; }
00104         bool operator != ( const T& value ) const { return _value != value; }
00105         bool operator < ( const T& value ) const { return _value < value; }
00106         bool operator > ( const T& value ) const { return _value > value; }
00107         bool operator <= ( const T& value ) const { return _value <= value; }
00108         bool operator >= ( const T& value ) const { return _value >= value; }
00109 
00110         bool operator == ( const Monitor<T>& rhs ) const
00111             { return _value == rhs._value; }
00112         bool operator != ( const Monitor<T>& rhs ) const
00113             { return _value != rhs._value; }
00114         bool operator < ( const Monitor<T>& rhs ) const
00115             { return _value < rhs._value; }
00116         bool operator > ( const Monitor<T>& rhs ) const
00117             { return _value > rhs._value; }
00118         bool operator <= ( const Monitor<T>& rhs ) const
00119             { return _value <= rhs._value; }
00120         bool operator >= ( const Monitor<T>& rhs ) const
00121             { return _value >= rhs._value; }
00123 
00127         const T& get() const { return _value; }
00128 
00130         T operator + ( const T& value ) const { return _value + value; }
00132 
00133     private:
00134         T _value;
00135         MonitorPrivate* _data;
00136 
00137         void _construct();
00138     };
00139 
00140 typedef Monitor< bool >     Monitorb;
00141 typedef Monitor< uint32_t > Monitoru;
00142 
00144 template< typename T >
00145 std::ostream& operator << ( std::ostream& os, const Monitor<T>& monitor );
00146 }
00147 }
00148 
00149 //----------------------------------------------------------------------
00150 // implementation
00151 //----------------------------------------------------------------------
00152 
00153 // Crude test if pthread.h was included
00154 #ifdef PTHREAD_MUTEX_INITIALIZER
00155 #  ifndef HAVE_PTHREAD_H
00156 #    define HAVE_PTHREAD_H
00157 #  endif
00158 #endif
00159 
00160 // Monitor for uint32_t and bool are explicitly instantiated in monitor.cpp
00161 // Monitors for other types can be created by including pthread.h before this
00162 // file.  
00163 // The application has to include pthread.h since on Windows the use of
00164 // pthreads-Win32 library includes might create hard to resolve type conflicts
00165 // with other header files.
00166 
00167 #ifdef HAVE_PTHREAD_H
00168 
00169 #include <eq/base/debug.h>
00170 #include <eq/base/log.h>
00171 
00172 namespace eq
00173 {
00174 namespace base
00175 {
00176 class MonitorPrivate
00177 {
00178 public:
00179     pthread_cond_t  cond;
00180     pthread_mutex_t mutex;
00181 };
00182 
00183 template< typename T > 
00184 inline void Monitor<T>::_construct()
00185 {
00186     _data = new MonitorPrivate;
00187 
00188     int error = pthread_cond_init( &_data->cond, 0 );
00189     if( error )
00190     {
00191         EQERROR << "Error creating pthread condition: " 
00192                 << strerror( error ) << std::endl;
00193         return;
00194     } 
00195     
00196     error = pthread_mutex_init( &_data->mutex, 0 );
00197     if( error )
00198     {
00199         EQERROR << "Error creating pthread mutex: "
00200                 << strerror( error ) << std::endl;
00201         return;
00202     }
00203 }
00204         
00205 template< typename T > 
00206 inline Monitor<T>::~Monitor()
00207 {
00208     pthread_cond_destroy( &_data->cond );
00209     pthread_mutex_destroy( &_data->mutex );
00210     delete _data;
00211     _data = 0;
00212 }
00213 
00214 template< typename T > 
00215 inline Monitor<T>& Monitor<T>::operator++ ()
00216 {
00217     pthread_mutex_lock( &_data->mutex );
00218     ++_value;
00219     pthread_cond_broadcast( &_data->cond );
00220     pthread_mutex_unlock( &_data->mutex );
00221     return *this;
00222 }
00223 
00224 template<>  
00225 inline Monitor< bool >& Monitor< bool >::operator++ ()
00226 {
00227    pthread_mutex_lock( &_data->mutex );
00228    assert( !_value );
00229    _value = !_value;
00230    pthread_cond_broadcast( &_data->cond );
00231    pthread_mutex_unlock( &_data->mutex );
00232    return *this;
00233 }
00234 
00235 template< typename T > 
00236 inline Monitor<T>& Monitor<T>::operator-- ()
00237 {
00238     pthread_mutex_lock( &_data->mutex );
00239     --_value;
00240     pthread_cond_broadcast( &_data->cond );
00241     pthread_mutex_unlock( &_data->mutex );
00242     return *this;
00243 }
00244 
00245 template<> 
00246 inline Monitor< bool >& Monitor< bool >::operator-- ()
00247 {
00248     EQUNIMPLEMENTED;
00249     return *this;
00250 }
00251 
00252 template< typename T > 
00253 inline void Monitor<T>::set( const T& value )
00254 {
00255     pthread_mutex_lock( &_data->mutex );
00256     _value = value;
00257     pthread_cond_broadcast( &_data->cond );
00258     pthread_mutex_unlock( &_data->mutex );
00259 }
00260 
00261 template< typename T > 
00262 inline const T& Monitor<T>::waitEQ( const T& value ) const
00263 {
00264     pthread_mutex_lock( &_data->mutex );
00265     while( _value != value )
00266         pthread_cond_wait( &_data->cond, &_data->mutex);
00267     pthread_mutex_unlock( &_data->mutex );
00268     return value;
00269 }
00270 
00271 template< typename T > 
00272 inline const T& Monitor<T>::waitNE( const T& value ) const
00273 {
00274     pthread_mutex_lock( &_data->mutex );
00275     while( _value == value )
00276         pthread_cond_wait( &_data->cond, &_data->mutex);
00277     const T& newValue = _value;
00278     pthread_mutex_unlock( &_data->mutex );
00279     return newValue;
00280 }
00281 
00282 template< typename T > 
00283 inline const T& Monitor<T>::waitGE( const T& value ) const
00284 {
00285     pthread_mutex_lock( &_data->mutex );
00286     while( _value < value )
00287         pthread_cond_wait( &_data->cond, &_data->mutex);
00288     const T& newValue = _value;
00289     pthread_mutex_unlock( &_data->mutex );
00290     return newValue;
00291 }
00292 
00293 template< typename T > 
00294 inline const T& Monitor<T>::waitLE( const T& value ) const
00295 {
00296     pthread_mutex_lock( &_data->mutex );
00297     while( _value > value )
00298         pthread_cond_wait( &_data->cond, &_data->mutex);
00299     const T& newValue = _value;
00300     pthread_mutex_unlock( &_data->mutex );
00301     return newValue;
00302 }
00303 
00304 template< typename T >
00305 std::ostream& operator << ( std::ostream& os, const Monitor<T>& monitor )
00306 {
00307     os << "Monitor< " << monitor.get() << " >";
00308     return os;
00309 }
00310 }
00311 }
00312 #endif // HAVE_PTHREAD_H
00313 #endif //EQBASE_MONITOR_H
Generated on Mon Aug 10 18:58:40 2009 for Equalizer 0.9 by  doxygen 1.5.8