Ticket #2361: tss.patch
File tss.patch, 38.4 KB (added by , 13 years ago) |
---|
-
boost/thread/pthread/thread_heap_alloc.hpp
5 5 #ifndef THREAD_HEAP_ALLOC_PTHREAD_HPP 6 6 #define THREAD_HEAP_ALLOC_PTHREAD_HPP 7 7 8 #include <memory> 8 9 #include <boost/config/abi_prefix.hpp> 9 10 10 11 namespace boost 11 12 { 12 13 namespace detail 13 14 { 15 template< typename T > 16 struct heap_allocator : 17 public std::allocator< T > 18 { 19 template< typename U > 20 struct rebind 21 { 22 typedef heap_allocator< U > other; 23 }; 24 25 heap_allocator() {} 26 heap_allocator(heap_allocator const& that): 27 std::allocator< T >(static_cast< std::allocator< T > const& >(that)) 28 { 29 } 30 template< typename U > 31 heap_allocator(heap_allocator< U > const& that): 32 std::allocator< T >(static_cast< std::allocator< U > const& >(that)) 33 { 34 } 35 }; 36 14 37 template<typename T> 15 38 inline T* heap_new() 16 39 { … … 72 95 { 73 96 return heap_new_impl<T,A1&>(a1); 74 97 } 75 98 76 99 template<typename T,typename A1,typename A2> 77 100 inline T* heap_new(A1 const& a1,A2 const& a2) 78 101 { … … 218 241 { 219 242 return heap_new_impl<T,A1&,A2&,A3&,A4&>(a1,a2,a3,a4); 220 243 } 221 222 #endif 244 245 #endif 223 246 template<typename T> 224 247 inline void heap_delete(T* data) 225 248 { -
boost/thread/pthread/thread_data.hpp
5 5 // http://www.boost.org/LICENSE_1_0.txt) 6 6 // (C) Copyright 2007 Anthony Williams 7 7 8 #include <vector> 8 9 #include <boost/thread/detail/config.hpp> 9 10 #include <boost/thread/exceptions.hpp> 10 11 #include <boost/shared_ptr.hpp> … … 13 14 #include <boost/optional.hpp> 14 15 #include <pthread.h> 15 16 #include "condition_variable_fwd.hpp" 17 #include "thread_heap_alloc.hpp" 16 18 17 19 #include <boost/config/abi_prefix.hpp> 18 20 19 21 namespace boost 20 22 { 21 23 class thread; 22 24 23 25 namespace detail 24 26 { 25 27 struct thread_exit_callback_node; 26 struct tss_data_node; 28 struct tss_cleanup_function; 29 struct tss_data_node 30 { 31 void* value; 32 shared_ptr< tss_cleanup_function > cleanup; 27 33 34 tss_data_node(): 35 value(0) 36 { 37 } 38 }; 39 28 40 struct thread_data_base; 29 41 typedef boost::shared_ptr<thread_data_base> thread_data_ptr; 30 42 31 43 struct BOOST_THREAD_DECL thread_data_base: 32 44 enable_shared_from_this<thread_data_base> 33 45 { 46 typedef std::vector< tss_data_node, heap_allocator< tss_data_node > > tss_nodes; 47 34 48 thread_data_ptr self; 35 49 pthread_t thread_handle; 36 50 boost::mutex data_mutex; … … 41 55 bool join_started; 42 56 bool joined; 43 57 boost::detail::thread_exit_callback_node* thread_exit_callbacks; 44 boost::detail::tss_data_node*tss_data;58 tss_nodes tss_data; 45 59 bool interrupt_enabled; 46 60 bool interrupt_requested; 47 61 pthread_cond_t* current_cond; 48 62 49 63 thread_data_base(): 50 64 done(false),join_started(false),joined(false), 51 thread_exit_callbacks(0), tss_data(0),65 thread_exit_callbacks(0), 52 66 interrupt_enabled(true), 53 67 interrupt_requested(false), 54 68 current_cond(0) … … 74 88 throw thread_interrupted(); 75 89 } 76 90 } 77 91 78 92 void operator=(interruption_checker&); 79 93 public: 80 94 explicit interruption_checker(pthread_cond_t* cond): … … 102 116 namespace this_thread 103 117 { 104 118 void BOOST_THREAD_DECL yield(); 105 119 106 120 void BOOST_THREAD_DECL sleep(system_time const& abs_time); 107 121 108 122 template<typename TimeDuration> 109 123 inline void sleep(TimeDuration const& rel_time) 110 124 { -
boost/thread/tss.hpp
1 #ifndef BOOST_THREAD_TSS_HPP 2 #define BOOST_THREAD_TSS_HPP 3 // Distributed under the Boost Software License, Version 1.0. (See 4 // accompanying file LICENSE_1_0.txt or copy at 5 // http://www.boost.org/LICENSE_1_0.txt) 6 // (C) Copyright 2007-8 Anthony Williams 7 8 #include <boost/thread/detail/config.hpp> 9 #include <boost/shared_ptr.hpp> 10 #include <boost/thread/detail/thread_heap_alloc.hpp> 11 12 #include <boost/config/abi_prefix.hpp> 13 14 namespace boost 15 { 16 namespace detail 17 { 18 struct tss_cleanup_function 19 { 20 virtual ~tss_cleanup_function() 21 {} 22 23 virtual void operator()(void* data)=0; 24 }; 25 26 BOOST_THREAD_DECL void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing); 27 BOOST_THREAD_DECL void* get_tss_data(void const* key); 28 } 29 30 template <typename T> 31 class thread_specific_ptr 32 { 33 private: 34 thread_specific_ptr(thread_specific_ptr&); 35 thread_specific_ptr& operator=(thread_specific_ptr&); 36 37 struct delete_data: 38 detail::tss_cleanup_function 39 { 40 void operator()(void* data) 41 { 42 delete static_cast<T*>(data); 43 } 44 }; 45 46 struct run_custom_cleanup_function: 47 detail::tss_cleanup_function 48 { 49 void (*cleanup_function)(T*); 50 51 explicit run_custom_cleanup_function(void (*cleanup_function_)(T*)): 52 cleanup_function(cleanup_function_) 53 {} 54 55 void operator()(void* data) 56 { 57 cleanup_function(static_cast<T*>(data)); 58 } 59 }; 60 61 62 boost::shared_ptr<detail::tss_cleanup_function> cleanup; 63 64 public: 65 thread_specific_ptr(): 66 cleanup(detail::heap_new<delete_data>(),detail::do_heap_delete<delete_data>()) 67 {} 68 explicit thread_specific_ptr(void (*func_)(T*)) 69 { 70 if(func_) 71 { 72 cleanup.reset(detail::heap_new<run_custom_cleanup_function>(func_),detail::do_heap_delete<run_custom_cleanup_function>()); 73 } 74 } 75 ~thread_specific_ptr() 76 { 77 reset(); 78 } 79 80 T* get() const 81 { 82 return static_cast<T*>(detail::get_tss_data(this)); 83 } 84 T* operator->() const 85 { 86 return get(); 87 } 88 T& operator*() const 89 { 90 return *get(); 91 } 92 T* release() 93 { 94 T* const temp=get(); 95 detail::set_tss_data(this,boost::shared_ptr<detail::tss_cleanup_function>(),0,false); 96 return temp; 97 } 98 void reset(T* new_value=0) 99 { 100 T* const current_value=get(); 101 if(current_value!=new_value) 102 { 103 detail::set_tss_data(this,cleanup,new_value,true); 104 } 105 } 106 }; 107 } 108 109 #include <boost/config/abi_suffix.hpp> 110 111 #endif 1 #ifndef BOOST_THREAD_TSS_HPP 2 #define BOOST_THREAD_TSS_HPP 3 // Distributed under the Boost Software License, Version 1.0. (See 4 // accompanying file LICENSE_1_0.txt or copy at 5 // http://www.boost.org/LICENSE_1_0.txt) 6 // (C) Copyright 2007-8 Anthony Williams 7 8 #include <boost/thread/detail/config.hpp> 9 #include <boost/shared_ptr.hpp> 10 #include <boost/make_shared.hpp> 11 #include <boost/thread/detail/thread_heap_alloc.hpp> 12 13 #include <boost/config/abi_prefix.hpp> 14 15 namespace boost 16 { 17 namespace detail 18 { 19 typedef unsigned int tss_key_t; 20 21 struct tss_cleanup_function 22 { 23 virtual ~tss_cleanup_function() 24 {} 25 26 virtual void operator()(void* data)=0; 27 }; 28 29 BOOST_THREAD_DECL tss_key_t allocate_tss_key(); 30 BOOST_THREAD_DECL void set_tss_data(tss_key_t key,boost::shared_ptr<tss_cleanup_function> const& func,void* tss_data,bool call_cleanup); 31 BOOST_THREAD_DECL void* get_tss_data(tss_key_t key); 32 } 33 34 template <typename T> 35 class thread_specific_ptr 36 { 37 private: 38 thread_specific_ptr(thread_specific_ptr&); 39 thread_specific_ptr& operator=(thread_specific_ptr&); 40 41 struct delete_data: 42 detail::tss_cleanup_function 43 { 44 void operator()(void* data) 45 { 46 delete static_cast<T*>(data); 47 } 48 }; 49 50 struct run_custom_cleanup_function: 51 detail::tss_cleanup_function 52 { 53 void (*cleanup_function)(T*); 54 55 explicit run_custom_cleanup_function(void (*cleanup_function_)(T*)): 56 cleanup_function(cleanup_function_) 57 {} 58 59 void operator()(void* data) 60 { 61 cleanup_function(static_cast<T*>(data)); 62 } 63 }; 64 65 66 detail::tss_key_t key; 67 boost::shared_ptr<detail::tss_cleanup_function> cleanup; 68 69 public: 70 thread_specific_ptr(): 71 key(detail::allocate_tss_key()), 72 cleanup(boost::allocate_shared< delete_data >(detail::heap_allocator< delete_data >())) 73 {} 74 explicit thread_specific_ptr(void (*func_)(T*)): 75 key(detail::allocate_tss_key()) 76 { 77 if(func_) 78 { 79 cleanup = boost::allocate_shared< run_custom_cleanup_function >( 80 detail::heap_allocator< run_custom_cleanup_function >(), func_); 81 } 82 } 83 ~thread_specific_ptr() 84 { 85 detail::set_tss_data(key,boost::shared_ptr<detail::tss_cleanup_function>(),0,true); 86 } 87 88 T* get() const 89 { 90 return static_cast<T*>(detail::get_tss_data(key)); 91 } 92 T* operator->() const 93 { 94 return get(); 95 } 96 T& operator*() const 97 { 98 return *get(); 99 } 100 T* release() 101 { 102 T* const temp=get(); 103 detail::set_tss_data(key,boost::shared_ptr<detail::tss_cleanup_function>(),0,false); 104 return temp; 105 } 106 void reset(T* new_value=0) 107 { 108 T* const current_value=get(); 109 if(current_value!=new_value) 110 { 111 detail::set_tss_data(key,cleanup,new_value,true); 112 } 113 } 114 }; 115 } 116 117 #include <boost/config/abi_suffix.hpp> 118 119 #endif -
boost/thread/win32/thread_heap_alloc.hpp
8 8 #include "thread_primitives.hpp" 9 9 #include <stdexcept> 10 10 #include <boost/assert.hpp> 11 #include <boost/compatibility/cpp_c_headers/cstddef> 11 12 12 13 #if defined( BOOST_USE_WINDOWS_H ) 13 14 # include <windows.h> … … 69 70 { 70 71 BOOST_VERIFY(detail::win32::HeapFree(detail::win32::GetProcessHeap(),0,heap_memory)!=0); 71 72 } 72 73 74 template< typename T > 75 struct heap_allocator 76 { 77 template< typename U > 78 struct rebind 79 { 80 typedef heap_allocator< U > other; 81 }; 82 83 typedef std::size_t size_type; 84 typedef std::ptrdiff_t difference_type; 85 typedef T value_type; 86 typedef value_type* pointer; 87 typedef const value_type* const_pointer; 88 typedef value_type& reference; 89 typedef const value_type& const_reference; 90 91 heap_allocator() {} 92 heap_allocator(heap_allocator const&) {} 93 template< typename U > 94 heap_allocator(heap_allocator< U > const&) {} 95 96 pointer address(reference x) const { return &x; } 97 const_pointer address(const_reference x) const { return &x; } 98 99 pointer allocate(size_type n, const void* = 0) 100 { 101 return static_cast< pointer >( 102 detail::allocate_raw_heap_memory(static_cast< unsigned >(n * sizeof(value_type)))); 103 } 104 void deallocate(pointer p, size_type) 105 { 106 detail::free_raw_heap_memory(p); 107 } 108 109 void construct(pointer p, const_reference val) 110 { 111 new (p) value_type(val); 112 } 113 void destroy(pointer p) 114 { 115 p->~value_type(); 116 } 117 118 size_type max_size() const 119 { 120 return (~static_cast< std::size_t >(0)) / sizeof(value_type); 121 } 122 123 template< typename U > 124 bool operator== (heap_allocator< U > const&) const { return true; } 125 template< typename U > 126 bool operator!= (heap_allocator< U > const&) const { return false; } 127 }; 128 73 129 template<typename T> 74 130 inline T* heap_new() 75 131 { … … 225 281 { 226 282 return heap_new_impl<T,A1&>(a1); 227 283 } 228 284 229 285 template<typename T,typename A1,typename A2> 230 286 inline T* heap_new(A1 const& a1,A2 const& a2) 231 287 { … … 371 427 { 372 428 return heap_new_impl<T,A1&,A2&,A3&,A4&>(a1,a2,a3,a4); 373 429 } 374 375 #endif 430 431 #endif 376 432 template<typename T> 377 433 inline void heap_delete(T* data) 378 434 { -
boost/thread/win32/thread_data.hpp
5 5 // http://www.boost.org/LICENSE_1_0.txt) 6 6 // (C) Copyright 2008 Anthony Williams 7 7 8 #include <vector> 8 9 #include <boost/thread/detail/config.hpp> 10 #include <boost/shared_ptr.hpp> 9 11 #include <boost/intrusive_ptr.hpp> 10 12 #include <boost/thread/thread_time.hpp> 11 13 #include "thread_primitives.hpp" … … 18 20 namespace detail 19 21 { 20 22 struct thread_exit_callback_node; 21 struct tss_data_node; 23 struct tss_cleanup_function; 24 struct tss_data_node 25 { 26 void* value; 27 shared_ptr< tss_cleanup_function > cleanup; 22 28 29 tss_data_node(): 30 value(0) 31 { 32 } 33 }; 34 23 35 struct thread_data_base; 24 36 void intrusive_ptr_add_ref(thread_data_base * p); 25 37 void intrusive_ptr_release(thread_data_base * p); 26 38 27 39 struct thread_data_base 28 40 { 41 typedef std::vector< tss_data_node, heap_allocator< tss_data_node > > tss_nodes; 42 29 43 long count; 30 44 detail::win32::handle_manager thread_handle; 31 45 detail::win32::handle_manager interruption_handle; 32 46 boost::detail::thread_exit_callback_node* thread_exit_callbacks; 33 boost::detail::tss_data_node*tss_data;47 tss_nodes tss_data; 34 48 bool interruption_enabled; 35 49 unsigned id; 36 50 37 51 thread_data_base(): 38 52 count(0),thread_handle(detail::win32::invalid_handle_value), 39 53 interruption_handle(create_anonymous_event(detail::win32::manual_reset_event,detail::win32::event_initially_reset)), 40 thread_exit_callbacks(0), tss_data(0),54 thread_exit_callbacks(0), 41 55 interruption_enabled(true), 42 56 id(0) 43 57 {} … … 48 62 { 49 63 BOOST_INTERLOCKED_INCREMENT(&p->count); 50 64 } 51 65 52 66 friend void intrusive_ptr_release(thread_data_base * p) 53 67 { 54 68 if(!BOOST_INTERLOCKED_DECREMENT(&p->count)) … … 61 75 { 62 76 BOOST_VERIFY(detail::win32::SetEvent(interruption_handle)!=0); 63 77 } 64 78 65 79 typedef detail::win32::handle native_handle_type; 66 80 67 81 virtual void run()=0; … … 130 144 { 131 145 return milliseconds==~uintmax_t(0); 132 146 } 133 134 147 148 135 149 static timeout sentinel() 136 150 { 137 151 return timeout(sentinel_type()); … … 139 153 private: 140 154 struct sentinel_type 141 155 {}; 142 156 143 157 explicit timeout(sentinel_type): 144 158 start(0),milliseconds(~uintmax_t(0)),relative(true) 145 159 {} … … 170 184 interruptible_wait(abs_time); 171 185 } 172 186 } 173 187 174 188 } 175 189 176 190 #include <boost/config/abi_suffix.hpp> -
libs/thread/src/win32/thread.cpp
17 17 #include <boost/thread/once.hpp> 18 18 #include <boost/thread/tss.hpp> 19 19 #include <boost/assert.hpp> 20 #include <boost/detail/interlocked.hpp> 20 21 #include <boost/thread/detail/tss_hooks.hpp> 21 22 #include <boost/date_time/posix_time/conversion.hpp> 22 23 … … 76 77 delete data; 77 78 return ret; 78 79 } 79 80 80 81 typedef void* uintptr_t; 81 82 82 83 inline uintptr_t const _beginthreadex(void* security, unsigned stack_size, unsigned (__stdcall* start_address)(void*), … … 107 108 {} 108 109 }; 109 110 110 struct tss_data_node111 {112 void const* key;113 boost::shared_ptr<boost::detail::tss_cleanup_function> func;114 void* value;115 tss_data_node* next;116 117 tss_data_node(void const* key_,boost::shared_ptr<boost::detail::tss_cleanup_function> func_,void* value_,118 tss_data_node* next_):119 key(key_),func(func_),value(value_),next(next_)120 {}121 };122 123 111 } 124 112 125 113 namespace … … 129 117 detail::thread_data_ptr current_thread_data(get_current_thread_data(),false); 130 118 if(current_thread_data) 131 119 { 132 while(current_thread_data->tss_data || current_thread_data->thread_exit_callbacks) 120 bool all_tss_released; 121 do 133 122 { 134 123 while(current_thread_data->thread_exit_callbacks) 135 124 { … … 142 131 } 143 132 boost::detail::heap_delete(current_node); 144 133 } 145 while(current_thread_data->tss_data) 134 135 all_tss_released = true; 136 for (detail::tss_key_t key = 0; key < current_thread_data->tss_data.size(); ++key) 146 137 { 147 detail::tss_data_node* const current_node=current_thread_data->tss_data; 148 current_thread_data->tss_data=current_node->next; 149 if(current_node->func) 138 detail::tss_data_node& node = current_thread_data->tss_data[key]; 139 shared_ptr< detail::tss_cleanup_function > cleanup; 140 cleanup.swap(node.cleanup); 141 if (cleanup && node.value) 150 142 { 151 (*current_node->func)(current_node->value); 143 all_tss_released = false; 144 (*cleanup)(node.value); 152 145 } 153 boost::detail::heap_delete(current_node);154 146 } 155 147 } 156 148 while(!all_tss_released || current_thread_data->thread_exit_callbacks); 149 157 150 set_current_thread_data(0); 158 151 } 159 152 } 160 153 161 154 unsigned __stdcall thread_start_function(void* param) 162 155 { 163 156 detail::thread_data_base* const thread_info(reinterpret_cast<detail::thread_data_base*>(param)); … … 209 202 ++count; 210 203 interruption_enabled=false; 211 204 } 212 205 213 206 void run() 214 207 {} 215 208 private: … … 233 226 } 234 227 return current_thread_data; 235 228 } 236 229 237 230 } 238 231 239 232 thread::~thread() 240 233 { 241 234 detach(); 242 235 } 243 236 244 237 thread::id thread::get_id() const 245 238 { 246 239 return thread::id(get_thread_info()); … … 274 267 } 275 268 return true; 276 269 } 277 270 278 271 void thread::detach() 279 272 { 280 273 release_handle(); … … 285 278 lock_guard<mutex> l1(thread_info_mutex); 286 279 thread_info=0; 287 280 } 288 281 289 282 void thread::interrupt() 290 283 { 291 284 detail::thread_data_ptr local_thread_info=get_thread_info(); … … 294 287 local_thread_info->interrupt(); 295 288 } 296 289 } 297 290 298 291 bool thread::interruption_requested() const 299 292 { 300 293 detail::thread_data_ptr local_thread_info=get_thread_info(); 301 294 return local_thread_info.get() && (detail::win32::WaitForSingleObject(local_thread_info->interruption_handle,0)==0); 302 295 } 303 296 304 297 unsigned thread::hardware_concurrency() 305 298 { 306 299 SYSTEM_INFO info={0}; 307 300 GetSystemInfo(&info); 308 301 return info.dwNumberOfProcessors; 309 302 } 310 303 311 304 thread::native_handle_type thread::native_handle() 312 305 { 313 306 detail::thread_data_ptr local_thread_info=get_thread_info(); … … 361 354 return due_time; 362 355 } 363 356 } 364 365 357 358 366 359 bool interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time) 367 360 { 368 361 detail::win32::handle handles[3]={0}; … … 382 375 } 383 376 384 377 detail::win32::handle_manager timer_handle; 385 378 386 379 #ifndef UNDER_CE 387 380 unsigned const min_timer_wait_period=20; 388 381 389 382 if(!target_time.is_sentinel()) 390 383 { 391 384 detail::timeout::remaining_time const time_left=target_time.remaining_milliseconds(); … … 396 389 if(timer_handle!=0) 397 390 { 398 391 LARGE_INTEGER due_time=get_due_time(target_time); 399 392 400 393 bool const set_time_succeeded=SetWaitableTimer(timer_handle,&due_time,0,0,0,false)!=0; 401 394 if(set_time_succeeded) 402 395 { … … 412 405 } 413 406 } 414 407 #endif 415 408 416 409 bool const using_timer=timeout_index!=~0u; 417 410 detail::timeout::remaining_time time_left(0); 418 411 419 412 do 420 413 { 421 414 if(!using_timer) 422 415 { 423 416 time_left=target_time.remaining_milliseconds(); 424 417 } 425 418 426 419 if(handle_count) 427 420 { 428 421 unsigned long const notified_index=detail::win32::WaitForMultipleObjects(handle_count,handles,false,using_timer?INFINITE:time_left.milliseconds); … … 469 462 throw thread_interrupted(); 470 463 } 471 464 } 472 465 473 466 bool interruption_enabled() 474 467 { 475 468 return get_current_thread_data() && get_current_thread_data()->interruption_enabled; 476 469 } 477 470 478 471 bool interruption_requested() 479 472 { 480 473 return get_current_thread_data() && (detail::win32::WaitForSingleObject(get_current_thread_data()->interruption_handle,0)==0); … … 484 477 { 485 478 detail::win32::Sleep(0); 486 479 } 487 480 488 481 disable_interruption::disable_interruption(): 489 482 interruption_was_enabled(interruption_enabled()) 490 483 { … … 493 486 get_current_thread_data()->interruption_enabled=false; 494 487 } 495 488 } 496 489 497 490 disable_interruption::~disable_interruption() 498 491 { 499 492 if(get_current_thread_data()) … … 509 502 get_current_thread_data()->interruption_enabled=true; 510 503 } 511 504 } 512 505 513 506 restore_interruption::~restore_interruption() 514 507 { 515 508 if(get_current_thread_data()) … … 530 523 current_thread_data->thread_exit_callbacks=new_node; 531 524 } 532 525 533 tss_ data_node* find_tss_data(void const* key)526 tss_key_t allocate_tss_key() 534 527 { 535 detail::thread_data_base* const current_thread_data(get_current_thread_data()); 536 if(current_thread_data) 537 { 538 detail::tss_data_node* current_node=current_thread_data->tss_data; 539 while(current_node) 540 { 541 if(current_node->key==key) 542 { 543 return current_node; 544 } 545 current_node=current_node->next; 546 } 547 } 548 return NULL; 528 static long counter = 0; 529 return static_cast< tss_key_t >(BOOST_INTERLOCKED_INCREMENT(&counter)) - 1; 549 530 } 550 531 551 void* get_tss_data( void const*key)532 void* get_tss_data(tss_key_t key) 552 533 { 553 if(tss_data_node* const current_node=find_tss_data(key)) 534 detail::thread_data_base* const current_thread_data(get_current_thread_data()); 535 if(current_thread_data && key < current_thread_data->tss_data.size()) 554 536 { 555 return current_ node->value;537 return current_thread_data->tss_data[key].value; 556 538 } 557 539 return NULL; 558 540 } 559 560 void set_tss_data( void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing)541 542 void set_tss_data(tss_key_t key,boost::shared_ptr<tss_cleanup_function> const& func,void* tss_data,bool call_cleanup) 561 543 { 562 if(tss_data_node* const current_node=find_tss_data(key)) 544 detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data()); 545 if (current_thread_data) 563 546 { 564 if (cleanup_existing && current_node->func.get())547 if (key >= current_thread_data->tss_data.size()) 565 548 { 566 (*current_node->func)(current_node->value);549 current_thread_data->tss_data.resize(key + 1); 567 550 } 568 current_node->func=func; 569 current_node->value=tss_data; 551 552 { 553 tss_data_node& node = current_thread_data->tss_data[key]; 554 if (call_cleanup && node.cleanup) 555 { 556 (*node.cleanup)(node.value); 557 } 558 } 559 { 560 // need to reload node reference since the cleanup might have called tss_data.resize 561 tss_data_node& node = current_thread_data->tss_data[key]; 562 node.cleanup = func; 563 node.value = tss_data; 564 } 570 565 } 571 else572 {573 detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data());574 tss_data_node* const new_node=heap_new<tss_data_node>(key,func,tss_data,current_thread_data->tss_data);575 current_thread_data->tss_data=new_node;576 }577 566 } 578 567 } 579 568 } -
libs/thread/src/pthread/thread.cpp
2 2 // William E. Kempf 3 3 // Copyright (C) 2007-8 Anthony Williams 4 4 // 5 // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 7 8 8 #include <boost/thread/detail/config.hpp> … … 13 13 #include <boost/thread/locks.hpp> 14 14 #include <boost/thread/once.hpp> 15 15 #include <boost/thread/tss.hpp> 16 #include <boost/detail/atomic_count.hpp> 16 17 #ifdef __linux__ 17 18 #include <sys/sysinfo.h> 18 19 #elif defined(__APPLE__) || defined(__FreeBSD__) … … 42 43 {} 43 44 }; 44 45 45 struct tss_data_node46 {47 void const* key;48 boost::shared_ptr<boost::detail::tss_cleanup_function> func;49 void* value;50 tss_data_node* next;51 52 tss_data_node(void const* key_,boost::shared_ptr<boost::detail::tss_cleanup_function> func_,void* value_,53 tss_data_node* next_):54 key(key_),func(func_),value(value_),next(next_)55 {}56 };57 58 46 namespace 59 47 { 60 48 boost::once_flag current_thread_tls_init_flag=BOOST_ONCE_INIT; … … 67 55 boost::detail::thread_data_base* thread_info=static_cast<boost::detail::thread_data_base*>(data); 68 56 if(thread_info) 69 57 { 70 while(thread_info->tss_data || thread_info->thread_exit_callbacks) 58 bool all_tss_released; 59 do 71 60 { 72 61 while(thread_info->thread_exit_callbacks) 73 62 { … … 80 69 } 81 70 delete current_node; 82 71 } 83 while(thread_info->tss_data) 72 73 all_tss_released = true; 74 for (tss_key_t key = 0; key < thread_info->tss_data.size(); ++key) 84 75 { 85 detail::tss_data_node* const current_node=thread_info->tss_data; 86 thread_info->tss_data=current_node->next; 87 if(current_node->func) 76 tss_data_node& node = thread_info->tss_data[key]; 77 shared_ptr< tss_cleanup_function > cleanup; 78 cleanup.swap(node.cleanup); 79 if (cleanup && node.value) 88 80 { 89 (*current_node->func)(current_node->value); 81 all_tss_released = false; 82 (*cleanup)(node.value); 90 83 } 91 delete current_node;92 84 } 93 85 } 86 while(!all_tss_released || thread_info->thread_exit_callbacks); 87 94 88 thread_info->self.reset(); 95 89 } 96 90 } 97 91 } 98 99 92 93 detail::atomic_count& get_tss_key_counter() 94 { 95 static detail::atomic_count counter(0); 96 return counter; 97 } 98 100 99 void create_current_thread_tls_key() 101 100 { 102 101 BOOST_VERIFY(!pthread_key_create(¤t_thread_tls_key,&tls_destructor)); 102 // initialize tss key counter 103 get_tss_key_counter(); 103 104 } 104 105 } 105 106 106 107 boost::detail::thread_data_base* get_current_thread_data() 107 108 { 108 109 boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key); … … 115 116 BOOST_VERIFY(!pthread_setspecific(current_thread_tls_key,new_data)); 116 117 } 117 118 } 118 119 119 120 namespace 120 121 { 121 122 extern "C" … … 155 156 { 156 157 interrupt_enabled=false; 157 158 } 158 159 159 160 void run() 160 161 {} 161 162 … … 217 218 if(local_thread_info) 218 219 { 219 220 bool do_join=false; 220 221 221 222 { 222 223 unique_lock<mutex> lock(local_thread_info->data_mutex); 223 224 while(!local_thread_info->done) … … 225 226 local_thread_info->done_condition.wait(lock); 226 227 } 227 228 do_join=!local_thread_info->join_started; 228 229 229 230 if(do_join) 230 231 { 231 232 local_thread_info->join_started=true; … … 246 247 local_thread_info->joined=true; 247 248 local_thread_info->done_condition.notify_all(); 248 249 } 249 250 250 251 lock_guard<mutex> l1(thread_info_mutex); 251 252 if(thread_info==local_thread_info) 252 253 { … … 261 262 if(local_thread_info) 262 263 { 263 264 bool do_join=false; 264 265 265 266 { 266 267 unique_lock<mutex> lock(local_thread_info->data_mutex); 267 268 while(!local_thread_info->done) … … 272 273 } 273 274 } 274 275 do_join=!local_thread_info->join_started; 275 276 276 277 if(do_join) 277 278 { 278 279 local_thread_info->join_started=true; … … 293 294 local_thread_info->joined=true; 294 295 local_thread_info->done_condition.notify_all(); 295 296 } 296 297 297 298 lock_guard<mutex> l1(thread_info_mutex); 298 299 if(thread_info==local_thread_info) 299 300 { … … 316 317 lock_guard<mutex> l1(thread_info_mutex); 317 318 thread_info.swap(local_thread_info); 318 319 } 319 320 320 321 if(local_thread_info) 321 322 { 322 323 lock_guard<mutex> lock(local_thread_info->data_mutex); … … 331 332 332 333 namespace this_thread 333 334 { 334 335 335 336 void sleep(const system_time& st) 336 337 { 337 338 detail::thread_data_base* const thread_info=detail::get_current_thread_data(); 338 339 339 340 if(thread_info) 340 341 { 341 342 unique_lock<mutex> lk(thread_info->sleep_mutex); … … 344 345 else 345 346 { 346 347 xtime const xt=get_xtime(st); 347 348 348 349 for (int foo=0; foo < 5; ++foo) 349 350 { 350 351 # if defined(BOOST_HAS_PTHREAD_DELAY_NP) … … 354 355 # elif defined(BOOST_HAS_NANOSLEEP) 355 356 timespec ts; 356 357 to_timespec_duration(xt, ts); 357 358 358 359 // nanosleep takes a timespec that is an offset, not 359 360 // an absolute time. 360 361 nanosleep(&ts, 0); … … 458 459 return pthread_t(); 459 460 } 460 461 } 461 462 463 462 463 464 464 465 namespace this_thread 465 466 { 466 467 thread::id get_id() … … 482 483 } 483 484 } 484 485 } 485 486 486 487 bool interruption_enabled() 487 488 { 488 489 boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data(); 489 490 return thread_info && thread_info->interrupt_enabled; 490 491 } 491 492 492 493 bool interruption_requested() 493 494 { 494 495 boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data(); … … 511 512 detail::get_current_thread_data()->interrupt_enabled=false; 512 513 } 513 514 } 514 515 515 516 disable_interruption::~disable_interruption() 516 517 { 517 518 if(detail::get_current_thread_data()) … … 527 528 detail::get_current_thread_data()->interrupt_enabled=true; 528 529 } 529 530 } 530 531 531 532 restore_interruption::~restore_interruption() 532 533 { 533 534 if(detail::get_current_thread_data()) … … 547 548 current_thread_data->thread_exit_callbacks=new_node; 548 549 } 549 550 550 tss_ data_node* find_tss_data(void const* key)551 tss_key_t allocate_tss_key() 551 552 { 552 detail::thread_data_base* const current_thread_data(get_current_thread_data()); 553 if(current_thread_data) 554 { 555 detail::tss_data_node* current_node=current_thread_data->tss_data; 556 while(current_node) 557 { 558 if(current_node->key==key) 559 { 560 return current_node; 561 } 562 current_node=current_node->next; 563 } 564 } 565 return NULL; 553 return static_cast< tss_key_t >(++get_tss_key_counter()) - 1; 566 554 } 567 555 568 void* get_tss_data( void const*key)556 void* get_tss_data(tss_key_t key) 569 557 { 570 if(tss_data_node* const current_node=find_tss_data(key)) 558 detail::thread_data_base* const current_thread_data(get_current_thread_data()); 559 if(current_thread_data && key < current_thread_data->tss_data.size()) 571 560 { 572 return current_ node->value;561 return current_thread_data->tss_data[key].value; 573 562 } 574 563 return NULL; 575 564 } 576 577 void set_tss_data( void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing)565 566 void set_tss_data(tss_key_t key,boost::shared_ptr<tss_cleanup_function> const& func,void* tss_data,bool call_cleanup) 578 567 { 579 if(tss_data_node* const current_node=find_tss_data(key)) 568 detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data()); 569 if (current_thread_data) 580 570 { 581 if (cleanup_existing && current_node->func)571 if (key >= current_thread_data->tss_data.size()) 582 572 { 583 (*current_node->func)(current_node->value);573 current_thread_data->tss_data.resize(key + 1); 584 574 } 585 current_node->func=func; 586 current_node->value=tss_data; 575 576 { 577 tss_data_node& node = current_thread_data->tss_data[key]; 578 if (call_cleanup && node.cleanup) 579 { 580 (*node.cleanup)(node.value); 581 } 582 } 583 { 584 // need to reload node reference since the cleanup might have called tss_data.resize 585 tss_data_node& node = current_thread_data->tss_data[key]; 586 node.cleanup = func; 587 node.value = tss_data; 588 } 587 589 } 588 else589 {590 detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data());591 tss_data_node* const new_node=new tss_data_node(key,func,tss_data,current_thread_data->tss_data);592 current_thread_data->tss_data=new_node;593 }594 590 } 595 591 } 596 592 … … 660 656 // void thread_group::interrupt_all() 661 657 // { 662 658 // boost::lock_guard<mutex> guard(m_mutex); 663 659 664 660 // for(std::list<thread*>::iterator it=m_threads.begin(),end=m_threads.end(); 665 661 // it!=end; 666 662 // ++it) … … 668 664 // (*it)->interrupt(); 669 665 // } 670 666 // } 671 672 667 668 673 669 // size_t thread_group::size() const 674 670 // { 675 671 // return m_threads.size();