Equalizer  1.2.1
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/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
Generated on Fri Jun 8 2012 15:44:32 for Equalizer 1.2.1 by  doxygen 1.8.0