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 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 // implementation
00081 //----------------------------------------------------------------------
00082 
00083 // Crude test if pthread.h was included
00084 #ifdef PTHREAD_MUTEX_INITIALIZER
00085 #  ifndef HAVE_PTHREAD_H
00086 #    define HAVE_PTHREAD_H
00087 #  endif
00088 #endif
00089 
00090 // The application has to include pthread.h if it wants to instantiate new
00091 // types, since on Windows the use of pthreads-Win32 library includes might
00092 // create hard to resolve type conflicts with other header files.
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
Generated on Mon Aug 10 18:58:40 2009 for Equalizer 0.9 by  doxygen 1.5.8