mtQueue.h

00001 
00002 /* Copyright (c) 2005-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_MTQUEUE_H
00019 #define EQBASE_MTQUEUE_H
00020 
00021 #include <eq/base/base.h>
00022 #include <eq/base/debug.h>
00023 #include <queue>
00024 
00025 #include <string.h>
00026 
00027 namespace eq
00028 {
00029 namespace base
00030 {
00031     class MTQueuePrivate;
00032 
00037     template< typename T > class MTQueue
00038     {
00039     public:
00041         MTQueue();
00042 
00044         MTQueue( const MTQueue< T >& from );
00045 
00047         ~MTQueue();
00048 
00050         MTQueue< T >& operator = ( const MTQueue< T >& from ); 
00051 
00053         bool isEmpty() const { return _queue.empty(); }
00054 
00056         size_t getSize() const { return _queue.size(); }
00057 
00059         T pop();
00060 
00065         T tryPop();
00066 
00071         T back() const;
00072 
00074         void push( const T& element );
00075 
00077         void pushFront( const T& element );
00078 
00080         static const T NONE;
00081 
00082     private:
00083         std::deque< T > _queue;
00084         MTQueuePrivate* _data;
00085 
00086         void _init();
00087     };
00088 
00089 //----------------------------------------------------------------------
00090 // implementation
00091 //----------------------------------------------------------------------
00092 
00093 // Crude test if pthread.h was included
00094 #ifdef PTHREAD_MUTEX_INITIALIZER
00095 #  ifndef HAVE_PTHREAD_H
00096 #    define HAVE_PTHREAD_H
00097 #  endif
00098 #endif
00099 
00100 // The application has to include pthread.h if it wants to instantiate new queue
00101 // types, since on Windows the use of pthreads-Win32 includes might create 
00102 // hard-to-resolve type conflicts with other header files.
00103 
00104 #ifdef HAVE_PTHREAD_H
00105 
00106 class MTQueuePrivate
00107 {
00108 public:
00109     pthread_mutex_t mutex;
00110     pthread_cond_t  cond;
00111 };
00112 
00113 template< typename T > const T MTQueue<T>::NONE = 0;
00114 
00115 template< typename T >
00116 MTQueue<T>::MTQueue()
00117         : _data( new MTQueuePrivate )
00118 {
00119     _init();
00120 }
00121 
00122 template< typename T >
00123 MTQueue< T >::MTQueue( const MTQueue< T >& from )
00124         : _queue( from._queue )
00125         , _data( new MTQueuePrivate )
00126 {
00127     _init();
00128 }
00129 
00130 template< typename T >
00131 void MTQueue< T >::_init()
00132 {
00133     // mutex init
00134     int error = pthread_mutex_init( &_data->mutex, 0 );
00135     if( error )
00136     {
00137         EQERROR << "Error creating pthread mutex: " 
00138                 << strerror( error ) << std::endl;
00139         return;
00140     }
00141     // condvar init
00142     error = pthread_cond_init( &_data->cond, 0 );
00143     if( error )
00144     {
00145         EQERROR << "Error creating pthread condition: " 
00146                 << strerror( error ) << std::endl;
00147         return;
00148     }
00149 }
00150 
00151 template< typename T >
00152 MTQueue< T >& MTQueue< T >::operator = ( const MTQueue< T >& from )
00153 {
00154     pthread_mutex_lock( &_data->mutex );
00155     _queue = from._queue;
00156     pthread_cond_signal( &_data->cond );
00157     pthread_mutex_unlock( &_data->mutex );
00158     return *this;
00159 }
00160 
00161 
00162 template< typename T >
00163 MTQueue<T>::~MTQueue()
00164 {
00165     pthread_mutex_destroy( &_data->mutex );
00166     pthread_cond_destroy( &_data->cond );
00167     delete _data;
00168     _data = 0;
00169 }
00170 
00171 template< typename T >
00172 T MTQueue<T>::pop()
00173 {
00174     pthread_mutex_lock( &_data->mutex );
00175     while( _queue.empty( ))
00176         pthread_cond_wait( &_data->cond, &_data->mutex );
00177                 
00178     EQASSERT( !_queue.empty( ));
00179     T element = _queue.front();
00180     _queue.pop_front();
00181     pthread_mutex_unlock( &_data->mutex );
00182     return element;
00183 }
00184 
00185 template< typename T >
00186 T MTQueue<T>::tryPop()
00187 {
00188     if( _queue.empty( ))
00189         return NONE;
00190     
00191     pthread_mutex_lock( &_data->mutex );
00192     if( _queue.empty( ))
00193     {
00194         pthread_mutex_unlock( &_data->mutex );
00195         return NONE;
00196     }
00197     
00198     T element = _queue.front();
00199     _queue.pop_front();
00200     pthread_mutex_unlock( &_data->mutex );
00201     return element;
00202 }   
00203 
00204 template< typename T >
00205 T MTQueue<T>::back() const
00206 {
00207     pthread_mutex_lock( &_data->mutex );
00208     if( _queue.empty( ))
00209     {
00210         pthread_mutex_unlock( &_data->mutex );
00211         return NONE;
00212     }
00213     // else
00214     T element = _queue.back();
00215     pthread_mutex_unlock( &_data->mutex );
00216     return element;
00217 }
00218 
00219 template< typename T >
00220 void MTQueue<T>::push( const T& element )
00221 {
00222     pthread_mutex_lock( &_data->mutex );
00223     _queue.push_back( element );
00224     pthread_cond_signal( &_data->cond );
00225     pthread_mutex_unlock( &_data->mutex );
00226 }
00227 
00228 template< typename T >
00229 void MTQueue<T>::pushFront( const T& element )
00230 {
00231     pthread_mutex_lock( &_data->mutex );
00232     _queue.push_front( element );
00233     pthread_cond_signal( &_data->cond );
00234     pthread_mutex_unlock( &_data->mutex );
00235 }
00236 #endif //HAVE_PTHREAD_H
00237 }
00238 
00239 }
00240 #endif //EQBASE_MTQUEUE_H
Generated on Mon Aug 10 18:58:40 2009 for Equalizer 0.9 by  doxygen 1.5.8