Equalizer
1.2.1
|
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/nonCopyable.h> 00025 00026 namespace co 00027 { 00028 namespace base 00029 { 00030 class PerThreadPrivate; 00031 00033 template< class T > void perThreadDelete( T* object ) { delete object; } 00034 00036 template< class T > void perThreadNoDelete( T* object ) {} 00037 00051 template< class T, void (*D)( T* ) = perThreadDelete< T > > 00052 class PerThread : public NonCopyable 00053 { 00054 public: 00056 PerThread(); 00058 ~PerThread(); 00059 00061 PerThread<T, D>& operator = ( const T* data ); 00063 PerThread<T, D>& operator = ( const PerThread<T, D>& rhs ); 00064 00066 T* get(); 00068 const T* get() const; 00070 T* operator->(); 00072 const T* operator->() const; 00073 00075 T& operator*() 00076 { EQASSERTINFO( get(), className( this )); return *get(); } 00078 const T& operator*() const 00079 { EQASSERTINFO( get(), className( this )); return *get(); } 00080 00085 bool operator == ( const PerThread& rhs ) const 00086 { return ( get() == rhs.get( )); } 00087 00092 bool operator == ( const T* rhs ) const { return ( get()==rhs ); } 00093 00098 bool operator != ( const T* rhs ) const { return ( get()!=rhs ); } 00099 00104 bool operator ! () const; 00105 00110 bool isValid() const; 00111 00112 private: 00113 PerThreadPrivate* _data; 00114 }; 00115 } 00116 } 00117 00118 //---------------------------------------------------------------------- 00119 // implementation 00120 //---------------------------------------------------------------------- 00121 00122 // Crude test if pthread.h was included 00123 #ifdef PTHREAD_MUTEX_INITIALIZER 00124 # ifndef HAVE_PTHREAD_H 00125 # define HAVE_PTHREAD_H 00126 # endif 00127 #endif 00128 00129 #ifdef HAVE_PTHREAD_H 00130 00131 #include <co/base/debug.h> 00132 #include <co/base/thread.h> 00133 00134 namespace co 00135 { 00136 namespace base 00137 { 00138 00139 class PerThreadPrivate 00140 { 00141 public: 00142 pthread_key_t key; 00143 }; 00144 00145 template< class T, void (*D)( T* ) > 00146 PerThread<T, D>::PerThread() 00147 : _data( new PerThreadPrivate ) 00148 { 00149 typedef void (*PThreadDtor_t)(void*); 00150 const int error = pthread_key_create( &_data->key, (PThreadDtor_t)( D )); 00151 if( error ) 00152 { 00153 EQERROR << "Can't create thread-specific key: " 00154 << strerror( error ) << std::endl; 00155 EQASSERT( !error ); 00156 } 00157 } 00158 00159 template< class T, void (*D)( T* ) > 00160 PerThread<T, D>::~PerThread() 00161 { 00162 T* object = get(); 00163 if( object ) 00164 D( object ); 00165 00166 pthread_key_delete( _data->key ); 00167 delete _data; 00168 _data = 0; 00169 } 00170 00171 template< class T, void (*D)( T* ) > 00172 PerThread<T, D>& PerThread<T, D>::operator = ( const T* data ) 00173 { 00174 pthread_setspecific( _data->key, static_cast<const void*>( data )); 00175 return *this; 00176 } 00177 00178 template< class T, void (*D)( T* ) > 00179 PerThread<T, D>& PerThread<T, D>::operator = ( const PerThread<T, D>& rhs ) 00180 { 00181 pthread_setspecific( _data->key, pthread_getspecific( rhs._data->key )); 00182 return *this; 00183 } 00184 00185 template< class T, void (*D)( T* ) > 00186 T* PerThread<T, D>::get() 00187 { 00188 return static_cast< T* >( pthread_getspecific( _data->key )); 00189 } 00190 template< class T, void (*D)( T* ) > 00191 const T* PerThread<T, D>::get() const 00192 { 00193 return static_cast< const T* >( pthread_getspecific( _data->key )); 00194 } 00195 00196 template< class T, void (*D)( T* ) > 00197 T* PerThread<T, D>::operator->() 00198 { 00199 return static_cast< T* >( pthread_getspecific( _data->key )); 00200 } 00201 template< class T, void (*D)( T* ) > 00202 const T* PerThread<T, D>::operator->() const 00203 { 00204 return static_cast< const T* >( pthread_getspecific( _data->key )); 00205 } 00206 00207 template< class T, void (*D)( T* ) > 00208 bool PerThread<T, D>::operator ! () const 00209 { 00210 return pthread_getspecific( _data->key ) == 0; 00211 } 00212 00213 template< class T, void (*D)( T* ) > 00214 bool PerThread<T, D>::isValid() const 00215 { 00216 return pthread_getspecific( _data->key ) != 0; 00217 } 00218 00219 00220 } 00221 } 00222 #endif // HAVE_PTHREAD_H 00223 00224 #endif //COBASE_PERTHREAD_H