Equalizer 1.0
|
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