Index: boost/thread/pthread/thread_heap_alloc.hpp =================================================================== --- boost/thread/pthread/thread_heap_alloc.hpp (revision 56275) +++ boost/thread/pthread/thread_heap_alloc.hpp (working copy) @@ -5,12 +5,35 @@ #ifndef THREAD_HEAP_ALLOC_PTHREAD_HPP #define THREAD_HEAP_ALLOC_PTHREAD_HPP +#include #include namespace boost { namespace detail { + template< typename T > + struct heap_allocator : + public std::allocator< T > + { + template< typename U > + struct rebind + { + typedef heap_allocator< U > other; + }; + + heap_allocator() {} + heap_allocator(heap_allocator const& that): + std::allocator< T >(static_cast< std::allocator< T > const& >(that)) + { + } + template< typename U > + heap_allocator(heap_allocator< U > const& that): + std::allocator< T >(static_cast< std::allocator< U > const& >(that)) + { + } + }; + template inline T* heap_new() { @@ -72,7 +95,7 @@ { return heap_new_impl(a1); } - + template inline T* heap_new(A1 const& a1,A2 const& a2) { @@ -218,8 +241,8 @@ { return heap_new_impl(a1,a2,a3,a4); } - -#endif + +#endif template inline void heap_delete(T* data) { Index: boost/thread/pthread/thread_data.hpp =================================================================== --- boost/thread/pthread/thread_data.hpp (revision 56275) +++ boost/thread/pthread/thread_data.hpp (working copy) @@ -5,6 +5,7 @@ // http://www.boost.org/LICENSE_1_0.txt) // (C) Copyright 2007 Anthony Williams +#include #include #include #include @@ -13,24 +14,37 @@ #include #include #include "condition_variable_fwd.hpp" +#include "thread_heap_alloc.hpp" #include namespace boost { class thread; - + namespace detail { struct thread_exit_callback_node; - struct tss_data_node; + struct tss_cleanup_function; + struct tss_data_node + { + void* value; + shared_ptr< tss_cleanup_function > cleanup; + tss_data_node(): + value(0) + { + } + }; + struct thread_data_base; typedef boost::shared_ptr thread_data_ptr; - + struct BOOST_THREAD_DECL thread_data_base: enable_shared_from_this { + typedef std::vector< tss_data_node, heap_allocator< tss_data_node > > tss_nodes; + thread_data_ptr self; pthread_t thread_handle; boost::mutex data_mutex; @@ -41,14 +55,14 @@ bool join_started; bool joined; boost::detail::thread_exit_callback_node* thread_exit_callbacks; - boost::detail::tss_data_node* tss_data; + tss_nodes tss_data; bool interrupt_enabled; bool interrupt_requested; pthread_cond_t* current_cond; thread_data_base(): done(false),join_started(false),joined(false), - thread_exit_callbacks(0),tss_data(0), + thread_exit_callbacks(0), interrupt_enabled(true), interrupt_requested(false), current_cond(0) @@ -74,7 +88,7 @@ throw thread_interrupted(); } } - + void operator=(interruption_checker&); public: explicit interruption_checker(pthread_cond_t* cond): @@ -102,9 +116,9 @@ namespace this_thread { void BOOST_THREAD_DECL yield(); - + void BOOST_THREAD_DECL sleep(system_time const& abs_time); - + template inline void sleep(TimeDuration const& rel_time) { Index: boost/thread/tss.hpp =================================================================== --- boost/thread/tss.hpp (revision 56275) +++ boost/thread/tss.hpp (working copy) @@ -1,111 +1,119 @@ -#ifndef BOOST_THREAD_TSS_HPP -#define BOOST_THREAD_TSS_HPP -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// (C) Copyright 2007-8 Anthony Williams - -#include -#include -#include - -#include - -namespace boost -{ - namespace detail - { - struct tss_cleanup_function - { - virtual ~tss_cleanup_function() - {} - - virtual void operator()(void* data)=0; - }; - - BOOST_THREAD_DECL void set_tss_data(void const* key,boost::shared_ptr func,void* tss_data,bool cleanup_existing); - BOOST_THREAD_DECL void* get_tss_data(void const* key); - } - - template - class thread_specific_ptr - { - private: - thread_specific_ptr(thread_specific_ptr&); - thread_specific_ptr& operator=(thread_specific_ptr&); - - struct delete_data: - detail::tss_cleanup_function - { - void operator()(void* data) - { - delete static_cast(data); - } - }; - - struct run_custom_cleanup_function: - detail::tss_cleanup_function - { - void (*cleanup_function)(T*); - - explicit run_custom_cleanup_function(void (*cleanup_function_)(T*)): - cleanup_function(cleanup_function_) - {} - - void operator()(void* data) - { - cleanup_function(static_cast(data)); - } - }; - - - boost::shared_ptr cleanup; - - public: - thread_specific_ptr(): - cleanup(detail::heap_new(),detail::do_heap_delete()) - {} - explicit thread_specific_ptr(void (*func_)(T*)) - { - if(func_) - { - cleanup.reset(detail::heap_new(func_),detail::do_heap_delete()); - } - } - ~thread_specific_ptr() - { - reset(); - } - - T* get() const - { - return static_cast(detail::get_tss_data(this)); - } - T* operator->() const - { - return get(); - } - T& operator*() const - { - return *get(); - } - T* release() - { - T* const temp=get(); - detail::set_tss_data(this,boost::shared_ptr(),0,false); - return temp; - } - void reset(T* new_value=0) - { - T* const current_value=get(); - if(current_value!=new_value) - { - detail::set_tss_data(this,cleanup,new_value,true); - } - } - }; -} - -#include - -#endif +#ifndef BOOST_THREAD_TSS_HPP +#define BOOST_THREAD_TSS_HPP +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2007-8 Anthony Williams + +#include +#include +#include +#include + +#include + +namespace boost +{ + namespace detail + { + typedef unsigned int tss_key_t; + + struct tss_cleanup_function + { + virtual ~tss_cleanup_function() + {} + + virtual void operator()(void* data)=0; + }; + + BOOST_THREAD_DECL tss_key_t allocate_tss_key(); + BOOST_THREAD_DECL void set_tss_data(tss_key_t key,boost::shared_ptr const& func,void* tss_data,bool call_cleanup); + BOOST_THREAD_DECL void* get_tss_data(tss_key_t key); + } + + template + class thread_specific_ptr + { + private: + thread_specific_ptr(thread_specific_ptr&); + thread_specific_ptr& operator=(thread_specific_ptr&); + + struct delete_data: + detail::tss_cleanup_function + { + void operator()(void* data) + { + delete static_cast(data); + } + }; + + struct run_custom_cleanup_function: + detail::tss_cleanup_function + { + void (*cleanup_function)(T*); + + explicit run_custom_cleanup_function(void (*cleanup_function_)(T*)): + cleanup_function(cleanup_function_) + {} + + void operator()(void* data) + { + cleanup_function(static_cast(data)); + } + }; + + + detail::tss_key_t key; + boost::shared_ptr cleanup; + + public: + thread_specific_ptr(): + key(detail::allocate_tss_key()), + cleanup(boost::allocate_shared< delete_data >(detail::heap_allocator< delete_data >())) + {} + explicit thread_specific_ptr(void (*func_)(T*)): + key(detail::allocate_tss_key()) + { + if(func_) + { + cleanup = boost::allocate_shared< run_custom_cleanup_function >( + detail::heap_allocator< run_custom_cleanup_function >(), func_); + } + } + ~thread_specific_ptr() + { + detail::set_tss_data(key,boost::shared_ptr(),0,true); + } + + T* get() const + { + return static_cast(detail::get_tss_data(key)); + } + T* operator->() const + { + return get(); + } + T& operator*() const + { + return *get(); + } + T* release() + { + T* const temp=get(); + detail::set_tss_data(key,boost::shared_ptr(),0,false); + return temp; + } + void reset(T* new_value=0) + { + T* const current_value=get(); + if(current_value!=new_value) + { + detail::set_tss_data(key,cleanup,new_value,true); + } + } + }; +} + +#include + +#endif Index: boost/thread/win32/thread_heap_alloc.hpp =================================================================== --- boost/thread/win32/thread_heap_alloc.hpp (revision 56275) +++ boost/thread/win32/thread_heap_alloc.hpp (working copy) @@ -8,6 +8,7 @@ #include "thread_primitives.hpp" #include #include +#include #if defined( BOOST_USE_WINDOWS_H ) # include @@ -69,7 +70,62 @@ { BOOST_VERIFY(detail::win32::HeapFree(detail::win32::GetProcessHeap(),0,heap_memory)!=0); } - + + template< typename T > + struct heap_allocator + { + template< typename U > + struct rebind + { + typedef heap_allocator< U > other; + }; + + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + + heap_allocator() {} + heap_allocator(heap_allocator const&) {} + template< typename U > + heap_allocator(heap_allocator< U > const&) {} + + pointer address(reference x) const { return &x; } + const_pointer address(const_reference x) const { return &x; } + + pointer allocate(size_type n, const void* = 0) + { + return static_cast< pointer >( + detail::allocate_raw_heap_memory(static_cast< unsigned >(n * sizeof(value_type)))); + } + void deallocate(pointer p, size_type) + { + detail::free_raw_heap_memory(p); + } + + void construct(pointer p, const_reference val) + { + new (p) value_type(val); + } + void destroy(pointer p) + { + p->~value_type(); + } + + size_type max_size() const + { + return (~static_cast< std::size_t >(0)) / sizeof(value_type); + } + + template< typename U > + bool operator== (heap_allocator< U > const&) const { return true; } + template< typename U > + bool operator!= (heap_allocator< U > const&) const { return false; } + }; + template inline T* heap_new() { @@ -225,7 +281,7 @@ { return heap_new_impl(a1); } - + template inline T* heap_new(A1 const& a1,A2 const& a2) { @@ -371,8 +427,8 @@ { return heap_new_impl(a1,a2,a3,a4); } - -#endif + +#endif template inline void heap_delete(T* data) { Index: boost/thread/win32/thread_data.hpp =================================================================== --- boost/thread/win32/thread_data.hpp (revision 56275) +++ boost/thread/win32/thread_data.hpp (working copy) @@ -5,7 +5,9 @@ // http://www.boost.org/LICENSE_1_0.txt) // (C) Copyright 2008 Anthony Williams +#include #include +#include #include #include #include "thread_primitives.hpp" @@ -18,26 +20,38 @@ namespace detail { struct thread_exit_callback_node; - struct tss_data_node; + struct tss_cleanup_function; + struct tss_data_node + { + void* value; + shared_ptr< tss_cleanup_function > cleanup; + tss_data_node(): + value(0) + { + } + }; + struct thread_data_base; void intrusive_ptr_add_ref(thread_data_base * p); void intrusive_ptr_release(thread_data_base * p); - + struct thread_data_base { + typedef std::vector< tss_data_node, heap_allocator< tss_data_node > > tss_nodes; + long count; detail::win32::handle_manager thread_handle; detail::win32::handle_manager interruption_handle; boost::detail::thread_exit_callback_node* thread_exit_callbacks; - boost::detail::tss_data_node* tss_data; + tss_nodes tss_data; bool interruption_enabled; unsigned id; thread_data_base(): count(0),thread_handle(detail::win32::invalid_handle_value), interruption_handle(create_anonymous_event(detail::win32::manual_reset_event,detail::win32::event_initially_reset)), - thread_exit_callbacks(0),tss_data(0), + thread_exit_callbacks(0), interruption_enabled(true), id(0) {} @@ -48,7 +62,7 @@ { BOOST_INTERLOCKED_INCREMENT(&p->count); } - + friend void intrusive_ptr_release(thread_data_base * p) { if(!BOOST_INTERLOCKED_DECREMENT(&p->count)) @@ -61,7 +75,7 @@ { BOOST_VERIFY(detail::win32::SetEvent(interruption_handle)!=0); } - + typedef detail::win32::handle native_handle_type; virtual void run()=0; @@ -130,8 +144,8 @@ { return milliseconds==~uintmax_t(0); } - + static timeout sentinel() { return timeout(sentinel_type()); @@ -139,7 +153,7 @@ private: struct sentinel_type {}; - + explicit timeout(sentinel_type): start(0),milliseconds(~uintmax_t(0)),relative(true) {} @@ -170,7 +184,7 @@ interruptible_wait(abs_time); } } - + } #include Index: libs/thread/src/win32/thread.cpp =================================================================== --- libs/thread/src/win32/thread.cpp (revision 56275) +++ libs/thread/src/win32/thread.cpp (working copy) @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -76,7 +77,7 @@ delete data; return ret; } - + typedef void* uintptr_t; inline uintptr_t const _beginthreadex(void* security, unsigned stack_size, unsigned (__stdcall* start_address)(void*), @@ -107,19 +108,6 @@ {} }; - struct tss_data_node - { - void const* key; - boost::shared_ptr func; - void* value; - tss_data_node* next; - - tss_data_node(void const* key_,boost::shared_ptr func_,void* value_, - tss_data_node* next_): - key(key_),func(func_),value(value_),next(next_) - {} - }; - } namespace @@ -129,7 +117,8 @@ detail::thread_data_ptr current_thread_data(get_current_thread_data(),false); if(current_thread_data) { - while(current_thread_data->tss_data || current_thread_data->thread_exit_callbacks) + bool all_tss_released; + do { while(current_thread_data->thread_exit_callbacks) { @@ -142,22 +131,26 @@ } boost::detail::heap_delete(current_node); } - while(current_thread_data->tss_data) + + all_tss_released = true; + for (detail::tss_key_t key = 0; key < current_thread_data->tss_data.size(); ++key) { - detail::tss_data_node* const current_node=current_thread_data->tss_data; - current_thread_data->tss_data=current_node->next; - if(current_node->func) + detail::tss_data_node& node = current_thread_data->tss_data[key]; + shared_ptr< detail::tss_cleanup_function > cleanup; + cleanup.swap(node.cleanup); + if (cleanup && node.value) { - (*current_node->func)(current_node->value); + all_tss_released = false; + (*cleanup)(node.value); } - boost::detail::heap_delete(current_node); } } - + while(!all_tss_released || current_thread_data->thread_exit_callbacks); + set_current_thread_data(0); } } - + unsigned __stdcall thread_start_function(void* param) { detail::thread_data_base* const thread_info(reinterpret_cast(param)); @@ -209,7 +202,7 @@ ++count; interruption_enabled=false; } - + void run() {} private: @@ -233,14 +226,14 @@ } return current_thread_data; } - + } thread::~thread() { detach(); } - + thread::id thread::get_id() const { return thread::id(get_thread_info()); @@ -274,7 +267,7 @@ } return true; } - + void thread::detach() { release_handle(); @@ -285,7 +278,7 @@ lock_guard l1(thread_info_mutex); thread_info=0; } - + void thread::interrupt() { detail::thread_data_ptr local_thread_info=get_thread_info(); @@ -294,20 +287,20 @@ local_thread_info->interrupt(); } } - + bool thread::interruption_requested() const { detail::thread_data_ptr local_thread_info=get_thread_info(); return local_thread_info.get() && (detail::win32::WaitForSingleObject(local_thread_info->interruption_handle,0)==0); } - + unsigned thread::hardware_concurrency() { SYSTEM_INFO info={0}; GetSystemInfo(&info); return info.dwNumberOfProcessors; } - + thread::native_handle_type thread::native_handle() { detail::thread_data_ptr local_thread_info=get_thread_info(); @@ -361,8 +354,8 @@ return due_time; } } - + bool interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time) { detail::win32::handle handles[3]={0}; @@ -382,10 +375,10 @@ } detail::win32::handle_manager timer_handle; - + #ifndef UNDER_CE unsigned const min_timer_wait_period=20; - + if(!target_time.is_sentinel()) { detail::timeout::remaining_time const time_left=target_time.remaining_milliseconds(); @@ -396,7 +389,7 @@ if(timer_handle!=0) { LARGE_INTEGER due_time=get_due_time(target_time); - + bool const set_time_succeeded=SetWaitableTimer(timer_handle,&due_time,0,0,0,false)!=0; if(set_time_succeeded) { @@ -412,17 +405,17 @@ } } #endif - + bool const using_timer=timeout_index!=~0u; detail::timeout::remaining_time time_left(0); - + do { if(!using_timer) { time_left=target_time.remaining_milliseconds(); } - + if(handle_count) { unsigned long const notified_index=detail::win32::WaitForMultipleObjects(handle_count,handles,false,using_timer?INFINITE:time_left.milliseconds); @@ -469,12 +462,12 @@ throw thread_interrupted(); } } - + bool interruption_enabled() { return get_current_thread_data() && get_current_thread_data()->interruption_enabled; } - + bool interruption_requested() { return get_current_thread_data() && (detail::win32::WaitForSingleObject(get_current_thread_data()->interruption_handle,0)==0); @@ -484,7 +477,7 @@ { detail::win32::Sleep(0); } - + disable_interruption::disable_interruption(): interruption_was_enabled(interruption_enabled()) { @@ -493,7 +486,7 @@ get_current_thread_data()->interruption_enabled=false; } } - + disable_interruption::~disable_interruption() { if(get_current_thread_data()) @@ -509,7 +502,7 @@ get_current_thread_data()->interruption_enabled=true; } } - + restore_interruption::~restore_interruption() { if(get_current_thread_data()) @@ -530,50 +523,46 @@ current_thread_data->thread_exit_callbacks=new_node; } - tss_data_node* find_tss_data(void const* key) + tss_key_t allocate_tss_key() { - detail::thread_data_base* const current_thread_data(get_current_thread_data()); - if(current_thread_data) - { - detail::tss_data_node* current_node=current_thread_data->tss_data; - while(current_node) - { - if(current_node->key==key) - { - return current_node; - } - current_node=current_node->next; - } - } - return NULL; + static long counter = 0; + return static_cast< tss_key_t >(BOOST_INTERLOCKED_INCREMENT(&counter)) - 1; } - void* get_tss_data(void const* key) + void* get_tss_data(tss_key_t key) { - if(tss_data_node* const current_node=find_tss_data(key)) + detail::thread_data_base* const current_thread_data(get_current_thread_data()); + if(current_thread_data && key < current_thread_data->tss_data.size()) { - return current_node->value; + return current_thread_data->tss_data[key].value; } return NULL; } - - void set_tss_data(void const* key,boost::shared_ptr func,void* tss_data,bool cleanup_existing) + + void set_tss_data(tss_key_t key,boost::shared_ptr const& func,void* tss_data,bool call_cleanup) { - if(tss_data_node* const current_node=find_tss_data(key)) + detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data()); + if (current_thread_data) { - if(cleanup_existing && current_node->func.get()) + if (key >= current_thread_data->tss_data.size()) { - (*current_node->func)(current_node->value); + current_thread_data->tss_data.resize(key + 1); } - current_node->func=func; - current_node->value=tss_data; + + { + tss_data_node& node = current_thread_data->tss_data[key]; + if (call_cleanup && node.cleanup) + { + (*node.cleanup)(node.value); + } + } + { + // need to reload node reference since the cleanup might have called tss_data.resize + tss_data_node& node = current_thread_data->tss_data[key]; + node.cleanup = func; + node.value = tss_data; + } } - else - { - detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data()); - tss_data_node* const new_node=heap_new(key,func,tss_data,current_thread_data->tss_data); - current_thread_data->tss_data=new_node; - } } } } Index: libs/thread/src/pthread/thread.cpp =================================================================== --- libs/thread/src/pthread/thread.cpp (revision 56275) +++ libs/thread/src/pthread/thread.cpp (working copy) @@ -2,7 +2,7 @@ // William E. Kempf // Copyright (C) 2007-8 Anthony Williams // -// Distributed under the Boost Software License, Version 1.0. (See accompanying +// Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include @@ -13,6 +13,7 @@ #include #include #include +#include #ifdef __linux__ #include #elif defined(__APPLE__) || defined(__FreeBSD__) @@ -42,19 +43,6 @@ {} }; - struct tss_data_node - { - void const* key; - boost::shared_ptr func; - void* value; - tss_data_node* next; - - tss_data_node(void const* key_,boost::shared_ptr func_,void* value_, - tss_data_node* next_): - key(key_),func(func_),value(value_),next(next_) - {} - }; - namespace { boost::once_flag current_thread_tls_init_flag=BOOST_ONCE_INIT; @@ -67,7 +55,8 @@ boost::detail::thread_data_base* thread_info=static_cast(data); if(thread_info) { - while(thread_info->tss_data || thread_info->thread_exit_callbacks) + bool all_tss_released; + do { while(thread_info->thread_exit_callbacks) { @@ -80,29 +69,41 @@ } delete current_node; } - while(thread_info->tss_data) + + all_tss_released = true; + for (tss_key_t key = 0; key < thread_info->tss_data.size(); ++key) { - detail::tss_data_node* const current_node=thread_info->tss_data; - thread_info->tss_data=current_node->next; - if(current_node->func) + tss_data_node& node = thread_info->tss_data[key]; + shared_ptr< tss_cleanup_function > cleanup; + cleanup.swap(node.cleanup); + if (cleanup && node.value) { - (*current_node->func)(current_node->value); + all_tss_released = false; + (*cleanup)(node.value); } - delete current_node; } } + while(!all_tss_released || thread_info->thread_exit_callbacks); + thread_info->self.reset(); } } } - + detail::atomic_count& get_tss_key_counter() + { + static detail::atomic_count counter(0); + return counter; + } + void create_current_thread_tls_key() { BOOST_VERIFY(!pthread_key_create(¤t_thread_tls_key,&tls_destructor)); + // initialize tss key counter + get_tss_key_counter(); } } - + boost::detail::thread_data_base* get_current_thread_data() { boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key); @@ -115,7 +116,7 @@ BOOST_VERIFY(!pthread_setspecific(current_thread_tls_key,new_data)); } } - + namespace { extern "C" @@ -155,7 +156,7 @@ { interrupt_enabled=false; } - + void run() {} @@ -217,7 +218,7 @@ if(local_thread_info) { bool do_join=false; - + { unique_lock lock(local_thread_info->data_mutex); while(!local_thread_info->done) @@ -225,7 +226,7 @@ local_thread_info->done_condition.wait(lock); } do_join=!local_thread_info->join_started; - + if(do_join) { local_thread_info->join_started=true; @@ -246,7 +247,7 @@ local_thread_info->joined=true; local_thread_info->done_condition.notify_all(); } - + lock_guard l1(thread_info_mutex); if(thread_info==local_thread_info) { @@ -261,7 +262,7 @@ if(local_thread_info) { bool do_join=false; - + { unique_lock lock(local_thread_info->data_mutex); while(!local_thread_info->done) @@ -272,7 +273,7 @@ } } do_join=!local_thread_info->join_started; - + if(do_join) { local_thread_info->join_started=true; @@ -293,7 +294,7 @@ local_thread_info->joined=true; local_thread_info->done_condition.notify_all(); } - + lock_guard l1(thread_info_mutex); if(thread_info==local_thread_info) { @@ -316,7 +317,7 @@ lock_guard l1(thread_info_mutex); thread_info.swap(local_thread_info); } - + if(local_thread_info) { lock_guard lock(local_thread_info->data_mutex); @@ -331,11 +332,11 @@ namespace this_thread { - + void sleep(const system_time& st) { detail::thread_data_base* const thread_info=detail::get_current_thread_data(); - + if(thread_info) { unique_lock lk(thread_info->sleep_mutex); @@ -344,7 +345,7 @@ else { xtime const xt=get_xtime(st); - + for (int foo=0; foo < 5; ++foo) { # if defined(BOOST_HAS_PTHREAD_DELAY_NP) @@ -354,7 +355,7 @@ # elif defined(BOOST_HAS_NANOSLEEP) timespec ts; to_timespec_duration(xt, ts); - + // nanosleep takes a timespec that is an offset, not // an absolute time. nanosleep(&ts, 0); @@ -458,9 +459,9 @@ return pthread_t(); } } - - + + namespace this_thread { thread::id get_id() @@ -482,13 +483,13 @@ } } } - + bool interruption_enabled() { boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data(); return thread_info && thread_info->interrupt_enabled; } - + bool interruption_requested() { boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data(); @@ -511,7 +512,7 @@ detail::get_current_thread_data()->interrupt_enabled=false; } } - + disable_interruption::~disable_interruption() { if(detail::get_current_thread_data()) @@ -527,7 +528,7 @@ detail::get_current_thread_data()->interrupt_enabled=true; } } - + restore_interruption::~restore_interruption() { if(detail::get_current_thread_data()) @@ -547,50 +548,45 @@ current_thread_data->thread_exit_callbacks=new_node; } - tss_data_node* find_tss_data(void const* key) + tss_key_t allocate_tss_key() { - detail::thread_data_base* const current_thread_data(get_current_thread_data()); - if(current_thread_data) - { - detail::tss_data_node* current_node=current_thread_data->tss_data; - while(current_node) - { - if(current_node->key==key) - { - return current_node; - } - current_node=current_node->next; - } - } - return NULL; + return static_cast< tss_key_t >(++get_tss_key_counter()) - 1; } - void* get_tss_data(void const* key) + void* get_tss_data(tss_key_t key) { - if(tss_data_node* const current_node=find_tss_data(key)) + detail::thread_data_base* const current_thread_data(get_current_thread_data()); + if(current_thread_data && key < current_thread_data->tss_data.size()) { - return current_node->value; + return current_thread_data->tss_data[key].value; } return NULL; } - - void set_tss_data(void const* key,boost::shared_ptr func,void* tss_data,bool cleanup_existing) + + void set_tss_data(tss_key_t key,boost::shared_ptr const& func,void* tss_data,bool call_cleanup) { - if(tss_data_node* const current_node=find_tss_data(key)) + detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data()); + if (current_thread_data) { - if(cleanup_existing && current_node->func) + if (key >= current_thread_data->tss_data.size()) { - (*current_node->func)(current_node->value); + current_thread_data->tss_data.resize(key + 1); } - current_node->func=func; - current_node->value=tss_data; + + { + tss_data_node& node = current_thread_data->tss_data[key]; + if (call_cleanup && node.cleanup) + { + (*node.cleanup)(node.value); + } + } + { + // need to reload node reference since the cleanup might have called tss_data.resize + tss_data_node& node = current_thread_data->tss_data[key]; + node.cleanup = func; + node.value = tss_data; + } } - else - { - detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data()); - tss_data_node* const new_node=new tss_data_node(key,func,tss_data,current_thread_data->tss_data); - current_thread_data->tss_data=new_node; - } } } @@ -660,7 +656,7 @@ // void thread_group::interrupt_all() // { // boost::lock_guard guard(m_mutex); - + // for(std::list::iterator it=m_threads.begin(),end=m_threads.end(); // it!=end; // ++it) @@ -668,8 +664,8 @@ // (*it)->interrupt(); // } // } - + // size_t thread_group::size() const // { // return m_threads.size();