Equalizer 1.0

perThread.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 COBASE_PERTHREAD_H
00019 #define COBASE_PERTHREAD_H
00020 
00021 #include <errno.h>
00022 #include <string.h>
00023 
00024 #include <co/base/executionListener.h>
00025 #include <co/base/nonCopyable.h>
00026 
00027 namespace co
00028 {
00029 namespace base
00030 {
00031     class PerThreadPrivate;
00032 
00043     template<typename T> class PerThread : public ExecutionListener, 
00044                                            public NonCopyable
00045     {
00046     public:
00048         PerThread();
00050         ~PerThread();
00051 
00053         PerThread<T>& operator = ( const T* data );
00055         PerThread<T>& operator = ( const PerThread<T>& rhs );
00056 
00058         T* get();
00060         const T* get() const;
00062         T* operator->();
00064         const T* operator->() const;
00065 
00067         T& operator*()
00068             { EQASSERTINFO( get(), className( this )); return *get(); }
00070         const T& operator*() const
00071             { EQASSERTINFO( get(), className( this )); return *get(); }
00072 
00077         bool operator == ( const PerThread& rhs ) const 
00078             { return ( get() == rhs.get( )); }
00079 
00084         bool operator == ( const T* rhs ) const { return ( get()==rhs ); }
00085 
00090         bool operator != ( const T* rhs ) const { return ( get()!=rhs ); }
00091 
00096         bool operator ! () const;
00097 
00102         bool isValid() const;
00103 
00104     protected:
00105         virtual void notifyExecutionStopping();
00106 
00107     private:
00108         PerThreadPrivate* _data;
00109     };
00110 }
00111 }
00112 
00113 //----------------------------------------------------------------------
00114 // implementation
00115 //----------------------------------------------------------------------
00116 
00117 // Crude test if pthread.h was included
00118 #ifdef PTHREAD_MUTEX_INITIALIZER
00119 #  ifndef HAVE_PTHREAD_H
00120 #    define HAVE_PTHREAD_H
00121 #  endif
00122 #endif
00123 
00124 #ifdef HAVE_PTHREAD_H
00125 
00126 #include <co/base/debug.h>
00127 #include <co/base/thread.h>
00128 
00129 namespace co
00130 {
00131 namespace base
00132 {
00133 
00134 class PerThreadPrivate
00135 {
00136 public:
00137     pthread_key_t key;
00138 };
00139 
00140 template< typename T >
00141 PerThread<T>::PerThread() 
00142         : _data( new PerThreadPrivate )
00143 {
00144     const int error = pthread_key_create( &_data->key, 0 );
00145     if( error )
00146     {
00147         EQERROR << "Can't create thread-specific key: " 
00148                 << strerror( error ) << std::endl;
00149         EQASSERT( !error );
00150     }
00151 
00152     Thread::addListener( this );
00153 }
00154 
00155 template< typename T >
00156 PerThread<T>::~PerThread()
00157 {
00158     Thread::removeListener( this );
00159 
00160     T* object = get();
00161     delete object;
00162 
00163     pthread_key_delete( _data->key );
00164     delete _data;
00165     _data = 0;
00166 }
00167 
00168 template< typename T >
00169 void PerThread<T>::notifyExecutionStopping()
00170 {
00171     T* object = get();
00172     pthread_setspecific( _data->key, 0 );
00173 
00174     delete object;
00175 }
00176 
00177 template< typename T >
00178 PerThread<T>& PerThread<T>::operator = ( const T* data )
00179 { 
00180     pthread_setspecific( _data->key, static_cast<const void*>( data ));
00181     return *this; 
00182 }
00183 
00184 template< typename T >
00185 PerThread<T>& PerThread<T>::operator = ( const PerThread<T>& rhs )
00186 { 
00187     pthread_setspecific( _data->key, pthread_getspecific( rhs._data->key ));
00188     return *this;
00189 }
00190 
00191 template< typename T >
00192 T* PerThread<T>::get()
00193 {
00194     return static_cast< T* >( pthread_getspecific( _data->key )); 
00195 }
00196 template< typename T >
00197 const T* PerThread<T>::get() const
00198 {
00199     return static_cast< const T* >( pthread_getspecific( _data->key )); 
00200 }
00201 
00202 template< typename T >
00203 T* PerThread<T>::operator->() 
00204 {
00205     return static_cast< T* >( pthread_getspecific( _data->key )); 
00206 }
00207 template< typename T >
00208 const T* PerThread<T>::operator->() const 
00209 { 
00210     return static_cast< const T* >( pthread_getspecific( _data->key )); 
00211 }
00212 
00213 template< typename T >
00214 bool PerThread<T>::operator ! () const
00215 {
00216     return pthread_getspecific( _data->key ) == 0;
00217 }
00218 
00219 template< typename T >
00220 bool PerThread<T>::isValid() const
00221 {
00222     return pthread_getspecific( _data->key ) != 0;
00223 }
00224 
00225 
00226 }
00227 }
00228 #endif // HAVE_PTHREAD_H
00229 
00230 #endif //COBASE_PERTHREAD_H
Generated on Sun May 8 2011 19:11:07 for Equalizer 1.0 by  doxygen 1.7.3