perThread.h
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef EQBASE_PERTHREAD_H
00019 #define EQBASE_PERTHREAD_H
00020
00021 #include <errno.h>
00022 #include <string.h>
00023
00024 #include <eq/base/base.h>
00025 #include <eq/base/executionListener.h>
00026 #include <eq/base/nonCopyable.h>
00027
00028 namespace eq
00029 {
00030 namespace base
00031 {
00032 class PerThreadPrivate;
00033
00039 template<typename T> class PerThread : public ExecutionListener,
00040 public NonCopyable
00041 {
00042 public:
00044 PerThread();
00046 ~PerThread();
00047
00049 PerThread<T>& operator = ( const T* data );
00051 PerThread<T>& operator = ( const PerThread<T>& rhs );
00052
00054 T* get();
00056 const T* get() const;
00058 T* operator->();
00060 const T* operator->() const;
00061
00063 bool operator == ( const PerThread& rhs ) const
00064 { return ( get() == rhs.get( )); }
00066 bool operator == ( const T* rhs ) const { return ( get()==rhs ); }
00068 bool operator != ( const T* rhs ) const { return ( get()!=rhs ); }
00069
00070 protected:
00071 virtual void notifyExecutionStopping();
00072
00073 private:
00074 PerThreadPrivate* _data;
00075 };
00076 }
00077 }
00078
00079
00080
00081
00082
00083
00084 #ifdef PTHREAD_MUTEX_INITIALIZER
00085 # ifndef HAVE_PTHREAD_H
00086 # define HAVE_PTHREAD_H
00087 # endif
00088 #endif
00089
00090
00091
00092
00093
00094 #ifdef HAVE_PTHREAD_H
00095
00096 #include <eq/base/debug.h>
00097 #include <eq/base/thread.h>
00098
00099 namespace eq
00100 {
00101 namespace base
00102 {
00103
00104 class PerThreadPrivate
00105 {
00106 public:
00107 pthread_key_t key;
00108 };
00109
00110 template< typename T >
00111 PerThread<T>::PerThread()
00112 : _data( new PerThreadPrivate )
00113 {
00114 const int error = pthread_key_create( &_data->key, 0 );
00115 if( error )
00116 {
00117 EQERROR << "Can't create thread-specific key: "
00118 << strerror( error ) << std::endl;
00119 EQASSERT( !error );
00120 }
00121
00122 Thread::addListener( this );
00123 }
00124
00125 template< typename T >
00126 PerThread<T>::~PerThread()
00127 {
00128 Thread::removeListener( this );
00129
00130 T* object = get();
00131 if( object )
00132 object->notifyPerThreadDelete();
00133
00134 pthread_key_delete( _data->key );
00135 delete _data;
00136 _data = 0;
00137 }
00138
00139 template< typename T >
00140 void PerThread<T>::notifyExecutionStopping()
00141 {
00142 T* object = get();
00143 pthread_setspecific( _data->key, 0 );
00144
00145 if( object )
00146 object->notifyPerThreadDelete();
00147 }
00148
00149 template< typename T >
00150 PerThread<T>& PerThread<T>::operator = ( const T* data )
00151 {
00152 pthread_setspecific( _data->key, static_cast<const void*>( data ));
00153 return *this;
00154 }
00155
00156 template< typename T >
00157 PerThread<T>& PerThread<T>::operator = ( const PerThread<T>& rhs )
00158 {
00159 pthread_setspecific( _data->key, pthread_getspecific( rhs._data->key ));
00160 return *this;
00161 }
00162
00163 template< typename T >
00164 T* PerThread<T>::get()
00165 {
00166 return static_cast< T* >( pthread_getspecific( _data->key ));
00167 }
00168 template< typename T >
00169 const T* PerThread<T>::get() const
00170 {
00171 return static_cast< const T* >( pthread_getspecific( _data->key ));
00172 }
00173
00174 template< typename T >
00175 T* PerThread<T>::operator->()
00176 {
00177 return static_cast< T* >( pthread_getspecific( _data->key ));
00178 }
00179 template< typename T >
00180 const T* PerThread<T>::operator->() const
00181 {
00182 return static_cast< const T* >( pthread_getspecific( _data->key ));
00183 }
00184
00185 }
00186 }
00187 #endif // HAVE_PTHREAD_H
00188
00189 #endif //EQBASE_PERTHREAD_H