perThreadRef.h

00001 
00002 /* Copyright (c) 2008-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_PERTHREADREF_H
00019 #define EQBASE_PERTHREADREF_H
00020 
00021 #include <eq/base/base.h>
00022 #include <eq/base/debug.h>
00023 #include <eq/base/refPtr.h>
00024 
00025 namespace eq
00026 {
00027 namespace base
00028 {
00029     class PerThreadRefPrivate;
00030 
00032     template< typename T > class PerThreadRef : public NonCopyable
00033     {
00034     public:
00036         PerThreadRef();
00038         ~PerThreadRef();
00039 
00041         PerThreadRef<T>& operator = ( RefPtr< T > data );
00043         PerThreadRef<T>& operator = ( const PerThreadRef<T>& rhs );
00044 
00046         RefPtr< const T > get() const;
00048         RefPtr< T > get();
00049 
00051         T* getPointer();
00053         T* operator->();
00055         const T* operator->() const;
00056 
00058         bool operator == ( const PerThreadRef& rhs ) const 
00059             { return ( get() == rhs.get( )); }
00061         bool operator == ( const RefPtr< T >& rhs ) const
00062             { return ( get()==rhs ); }
00064         bool operator != ( const RefPtr< T >& rhs ) const
00065             { return ( get()!=rhs ); }
00066 
00068         bool operator ! () const;
00069 
00071         bool isValid() const;
00072 
00073     private:
00074         PerThreadRefPrivate* _data;
00075     };
00076 
00077 
00078 //----------------------------------------------------------------------
00079 // implementation
00080 //----------------------------------------------------------------------
00081 
00082 // Crude test if pthread.h was included
00083 #ifdef PTHREAD_MUTEX_INITIALIZER
00084 #  ifndef HAVE_PTHREAD_H
00085 #    define HAVE_PTHREAD_H
00086 #  endif
00087 #endif
00088 
00089 // The application has to include pthread.h if it wants to instantiate new
00090 // types, since on Windows the use of pthreads-Win32 library includes might
00091 // create hard to resolve type conflicts with other header files.
00092 
00093 #ifdef HAVE_PTHREAD_H
00094 
00095 class PerThreadRefPrivate
00096 {
00097 public:
00098     pthread_key_t key;
00099 };
00100 
00101 template< typename T >
00102 PerThreadRef<T>::PerThreadRef() 
00103         : _data( new PerThreadRefPrivate )
00104 {
00105     const int error = pthread_key_create( &_data->key, 0 );
00106     if( error )
00107     {
00108         EQERROR << "Can't create thread-specific key: " 
00109                 << strerror( error ) << std::endl;
00110         EQASSERT( !error );
00111     }
00112 }
00113 
00114 template< typename T >
00115 PerThreadRef<T>::~PerThreadRef()
00116 {
00117     RefPtr< T > object = get();
00118 
00119     pthread_key_delete( _data->key );
00120     delete _data;
00121     _data = 0;
00122 
00123     object.unref();
00124 }
00125 
00126 template< typename T >
00127 PerThreadRef<T>& PerThreadRef<T>::operator = ( RefPtr< T > data )
00128 { 
00129     data.ref(); // ref new
00130 
00131     RefPtr< T > object = get();
00132     pthread_setspecific( _data->key, static_cast<const void*>( data.get( )));
00133 
00134     object.unref(); // unref old
00135     return *this; 
00136 }
00137 
00138 template< typename T >
00139 PerThreadRef<T>& PerThreadRef<T>::operator = ( const PerThreadRef<T>& rhs )
00140 {
00141     RefPtr< T > newObject = rhs.get();
00142     newObject.ref(); // ref new
00143 
00144     RefPtr< T > object = get();
00145     pthread_setspecific( _data->key, pthread_getspecific( rhs._data->key ));
00146 
00147     object.unref(); // unref old
00148     return *this;
00149 }
00150 
00151 template< typename T >
00152 RefPtr< const T > PerThreadRef<T>::get() const
00153 {
00154     return static_cast< const T* >( pthread_getspecific( _data->key )); 
00155 }
00156 
00157 template< typename T >
00158 RefPtr< T > PerThreadRef<T>::get()
00159 {
00160     return static_cast< T* >( pthread_getspecific( _data->key )); 
00161 }
00162 
00163 template< typename T >
00164 T* PerThreadRef<T>::getPointer()
00165 {
00166     return static_cast< T* >( pthread_getspecific( _data->key )); 
00167 }
00168 
00169 template< typename T >
00170 T* PerThreadRef<T>::operator->() 
00171 {
00172     EQASSERT( pthread_getspecific( _data->key ));
00173     return static_cast< T* >( pthread_getspecific( _data->key )); 
00174 }
00175 
00176 template< typename T >
00177 const T* PerThreadRef<T>::operator->() const 
00178 { 
00179     EQASSERT( pthread_getspecific( _data->key ));
00180     return static_cast< const T* >( pthread_getspecific( _data->key )); 
00181 }
00182 
00183 template< typename T >
00184 bool PerThreadRef<T>::operator ! () const
00185 {
00186     return pthread_getspecific( _data->key ) == 0;
00187 }
00188 
00189 template< typename T >
00190 bool PerThreadRef<T>::isValid() const
00191 {
00192     return pthread_getspecific( _data->key ) != 0;
00193 }
00194 
00195 #endif // HAVE_PTHREAD_H
00196 }
00197 
00198 }
00199 #endif //EQBASE_PERTHREADREF_H
Generated on Mon Aug 10 18:58:40 2009 for Equalizer 0.9 by  doxygen 1.5.8