Lunchbox
1.4.0
|
00001 00002 /* Copyright (c) 2008-2012, 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 LUNCHBOX_PERTHREADREF_H 00019 #define LUNCHBOX_PERTHREADREF_H 00020 00021 #include <lunchbox/debug.h> 00022 #include <lunchbox/refPtr.h> 00023 00024 namespace lunchbox 00025 { 00026 namespace detail { class PerThreadRef; } 00027 00036 template< typename T > class PerThreadRef : public NonCopyable 00037 { 00038 public: 00040 PerThreadRef(); 00042 ~PerThreadRef(); 00043 00045 PerThreadRef<T>& operator = ( RefPtr< T > data ); 00046 00048 PerThreadRef<T>& operator = ( const PerThreadRef<T>& rhs ); 00049 00051 RefPtr< const T > get() const; 00053 RefPtr< T > get(); 00054 00059 T* getPointer(); 00060 00065 T* operator->(); 00066 00071 const T* operator->() const; 00072 00077 bool operator == ( const PerThreadRef& rhs ) const 00078 { return ( get() == rhs.get( )); } 00079 00084 bool operator == ( const RefPtr< T >& rhs ) const 00085 { return ( get()==rhs ); } 00086 00091 bool operator != ( const RefPtr< T >& rhs ) const 00092 { return ( get()!=rhs ); } 00093 00098 bool operator ! () const; 00099 00104 bool isValid() const; 00105 00106 private: 00107 PerThreadRef* const _impl; 00108 }; 00109 00110 00111 //---------------------------------------------------------------------- 00112 // implementation 00113 //---------------------------------------------------------------------- 00114 00115 // Crude test if pthread.h was included 00116 #ifdef PTHREAD_MUTEX_INITIALIZER 00117 # ifndef HAVE_PTHREAD_H 00118 # define HAVE_PTHREAD_H 00119 # endif 00120 #endif 00121 00122 #ifdef HAVE_PTHREAD_H 00123 namespace detail 00124 { 00125 class PerThreadRef 00126 { 00127 public: 00128 pthread_key_t key; 00129 }; 00130 } 00131 00132 template< typename T > 00133 PerThreadRef<T>::PerThreadRef() 00134 : _impl( new detail::PerThreadRef ) 00135 { 00136 const int error = pthread_key_create( &_impl->key, 0 ); 00137 if( error ) 00138 { 00139 LBERROR << "Can't create thread-specific key: " 00140 << strerror( error ) << std::endl; 00141 LBASSERT( !error ); 00142 } 00143 } 00144 00145 template< typename T > 00146 PerThreadRef<T>::~PerThreadRef() 00147 { 00148 RefPtr< T > object = get(); 00149 00150 pthread_key_delete( _impl->key ); 00151 delete _impl; 00152 00153 object.unref(); 00154 } 00155 00156 template< typename T > 00157 PerThreadRef<T>& PerThreadRef<T>::operator = ( RefPtr< T > data ) 00158 { 00159 data.ref(); // ref new 00160 00161 RefPtr< T > object = get(); 00162 pthread_setspecific( _impl->key, static_cast<const void*>( data.get( ))); 00163 00164 object.unref(); // unref old 00165 return *this; 00166 } 00167 00168 template< typename T > 00169 PerThreadRef<T>& PerThreadRef<T>::operator = ( const PerThreadRef<T>& rhs ) 00170 { 00171 RefPtr< T > newObject = rhs.get(); 00172 newObject.ref(); // ref new 00173 00174 RefPtr< T > object = get(); 00175 pthread_setspecific( _impl->key, pthread_getspecific( rhs._impl->key )); 00176 00177 object.unref(); // unref old 00178 return *this; 00179 } 00180 00181 template< typename T > 00182 RefPtr< const T > PerThreadRef<T>::get() const 00183 { 00184 return static_cast< const T* >( pthread_getspecific( _impl->key )); 00185 } 00186 00187 template< typename T > 00188 RefPtr< T > PerThreadRef<T>::get() 00189 { 00190 return static_cast< T* >( pthread_getspecific( _impl->key )); 00191 } 00192 00193 template< typename T > 00194 T* PerThreadRef<T>::getPointer() 00195 { 00196 return static_cast< T* >( pthread_getspecific( _impl->key )); 00197 } 00198 00199 template< typename T > 00200 T* PerThreadRef<T>::operator->() 00201 { 00202 LBASSERT( pthread_getspecific( _impl->key )); 00203 return static_cast< T* >( pthread_getspecific( _impl->key )); 00204 } 00205 00206 template< typename T > 00207 const T* PerThreadRef<T>::operator->() const 00208 { 00209 LBASSERT( pthread_getspecific( _impl->key )); 00210 return static_cast< const T* >( pthread_getspecific( _impl->key )); 00211 } 00212 00213 template< typename T > 00214 bool PerThreadRef<T>::operator ! () const 00215 { 00216 return pthread_getspecific( _impl->key ) == 0; 00217 } 00218 00219 template< typename T > 00220 bool PerThreadRef<T>::isValid() const 00221 { 00222 return pthread_getspecific( _impl->key ) != 0; 00223 } 00224 #endif // HAVE_PTHREAD_H 00225 00226 } 00227 #endif //LUNCHBOX_PERTHREADREF_H