diff --git a/include/boost/thread.hpp b/include/boost/thread.hpp index b9a9ed68..625e69ec 100644 --- a/include/boost/thread.hpp +++ b/include/boost/thread.hpp @@ -4,6 +4,8 @@ // 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) +// See www.boost.org/libs/thread for documentation. + #if !defined(BOOST_THREAD_WEK01082003_HPP) #define BOOST_THREAD_WEK01082003_HPP diff --git a/include/boost/thread/win32/thread_heap_alloc.hpp b/include/boost/thread/win32/thread_heap_alloc.hpp index 1835e35e..ee47e0e6 100644 --- a/include/boost/thread/win32/thread_heap_alloc.hpp +++ b/include/boost/thread/win32/thread_heap_alloc.hpp @@ -156,25 +156,13 @@ namespace boost } template - struct do_delete + struct do_heap_delete { - T* data; - - do_delete(T* data_): - data(data_) - {} - - void operator()() const + void operator()(T* data) const { detail::heap_delete(data); } }; - - template - do_delete make_heap_deleter(T* data) - { - return do_delete(data); - } } } diff --git a/include/boost/thread/win32/tss.hpp b/include/boost/thread/win32/tss.hpp index a99dfac4..fcf792bd 100644 --- a/include/boost/thread/win32/tss.hpp +++ b/include/boost/thread/win32/tss.hpp @@ -1,13 +1,26 @@ #ifndef BOOST_THREAD_WIN32_TSS_HPP #define BOOST_THREAD_WIN32_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 Anthony Williams + +#include +#include "thread_heap_alloc.hpp" namespace boost { namespace detail { - typedef void(*tss_cleanup_function)(void const* key,void* value); + struct tss_cleanup_function + { + virtual ~tss_cleanup_function() + {} + + virtual void operator()(void* data)=0; + }; - BOOST_THREAD_DECL void set_tss_data(void const* key,tss_cleanup_function func,void* tss_data,bool cleanup_existing); + 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); } @@ -18,31 +31,39 @@ namespace boost thread_specific_ptr(thread_specific_ptr&); thread_specific_ptr& operator=(thread_specific_ptr&); - static void delete_data(void const* self,void* value) + struct delete_data: + detail::tss_cleanup_function { - static_cast(self)->cleanup((T*)value); - } + void operator()(void* data) + { + delete static_cast(data); + } + }; - void cleanup(T* data) const + struct run_custom_cleanup_function: + detail::tss_cleanup_function { - if(func) + void (*cleanup_function)(T*); + + explicit run_custom_cleanup_function(void (*cleanup_function_)(T*)): + cleanup_function(cleanup_function_) + {} + + void operator()(void* data) { - func(data); + cleanup_function(data); } - else - { - delete data; - } - } + }; - void (*func)(T*); + + boost::shared_ptr cleanup; public: thread_specific_ptr(): - func(0) + cleanup(detail::heap_new(),detail::do_heap_delete()) {} explicit thread_specific_ptr(void (*func_)(T*)): - func(func_) + cleanup(detail::heap_new(func_),detail::do_heap_delete()) {} ~thread_specific_ptr() { @@ -72,7 +93,7 @@ namespace boost T* const current_value=get(); if(current_value!=new_value) { - detail::set_tss_data(this,delete_data,new_value,true); + detail::set_tss_data(this,cleanup,new_value,true); } } }; diff --git a/src/win32/thread.cpp b/src/win32/thread.cpp index fee2b4fd..9df6a05a 100644 --- a/src/win32/thread.cpp +++ b/src/win32/thread.cpp @@ -20,28 +20,6 @@ namespace boost { namespace { -#if defined(_MSC_VER) && !defined(UNDER_CE) - __declspec(thread) detail::thread_data_base* current_thread_data=0; - detail::thread_data_base* get_current_thread_data() - { - return current_thread_data; - } - void set_current_thread_data(detail::thread_data_base* new_data) - { - current_thread_data=new_data; - } -#elif defined(__BORLANDC__) - detail::thread_data_base* __thread current_thread_data=0; - detail::thread_data_base* get_current_thread_data() - { - return current_thread_data; - } - void set_current_thread_data(detail::thread_data_base* new_data) - { - current_thread_data=new_data; - } -#else - boost::once_flag current_thread_tls_init_flag=BOOST_ONCE_INIT; DWORD current_thread_tls_key=0; @@ -62,7 +40,6 @@ namespace boost boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key); BOOST_VERIFY(TlsSetValue(current_thread_tls_key,new_data)); } -#endif #ifdef BOOST_NO_THREADEX // Windows CE doesn't define _beginthreadex @@ -135,11 +112,11 @@ namespace boost struct tss_data_node { void const* key; - boost::detail::tss_cleanup_function func; + boost::shared_ptr func; void* value; tss_data_node* next; - tss_data_node(void const* key_,boost::detail::tss_cleanup_function func_,void* value_, + tss_data_node(void const* key_,boost::shared_ptr func_,void* value_, tss_data_node* next_): key(key_),func(func_),value(value_),next(next_) {} @@ -173,7 +150,7 @@ namespace boost current_thread_data->tss_data=current_node->next; if(current_node->func) { - (*current_node->func)(current_node->key,current_node->value); + (*current_node->func)(current_node->value); } boost::detail::heap_delete(current_node); } @@ -489,7 +466,12 @@ namespace boost { void add_thread_exit_function(thread_exit_function_base* func) { - detail::thread_data_base* const current_thread_data(get_current_thread_data()); + detail::thread_data_base* current_thread_data(get_current_thread_data()); + if(!current_thread_data) + { + make_external_thread_data(); + current_thread_data=get_current_thread_data(); + } thread_exit_callback_node* const new_node= heap_new(func, current_thread_data->thread_exit_callbacks); @@ -523,14 +505,14 @@ namespace boost return NULL; } - void set_tss_data(void const* key,tss_cleanup_function func,void* tss_data,bool cleanup_existing) + void set_tss_data(void const* key,boost::shared_ptr func,void* tss_data,bool cleanup_existing) { tss_cleanup_implemented(); // if anyone uses TSS, we need the cleanup linked in if(tss_data_node* const current_node=find_tss_data(key)) { if(cleanup_existing && current_node->func) { - (current_node->func)(current_node->key,current_node->value); + (*current_node->func)(current_node->value); } current_node->func=func; current_node->value=tss_data; diff --git a/src/win32/tss_pe.cpp b/src/win32/tss_pe.cpp index 3aef63a1..4528b90f 100644 --- a/src/win32/tss_pe.cpp +++ b/src/win32/tss_pe.cpp @@ -120,6 +120,16 @@ extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata //The .CRT$Xxx information is taken from Codeguru: //http://www.codeguru.com/Cpp/misc/misc/threadsprocesses/article.php/c6945__2/ +#if (_MSC_VER >= 1400) +#pragma section(".CRT$XIU",long,read) +#pragma section(".CRT$XCU",long,read) +#pragma section(".CRT$XTU",long,read) +#pragma section(".CRT$XLC",long,read) + static __declspec(allocate(".CRT$XLC")) _TLSCB __xl_ca=on_tls_callback; + static __declspec(allocate(".CRT$XIU"))_PVFV p_tls_prepare = on_tls_prepare; + static __declspec(allocate(".CRT$XCU"))_PVFV p_process_init = on_process_init; + static __declspec(allocate(".CRT$XTU"))_PVFV p_process_term = on_process_term; +#else #if (_MSC_VER >= 1300) // 1300 == VC++ 7.0 # pragma data_seg(push, old_seg) #endif @@ -144,7 +154,6 @@ extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata #pragma data_seg(".CRT$XLB") _TLSCB p_thread_callback = on_tls_callback; #pragma data_seg() - //Callback for termination. #pragma data_seg(".CRT$XTU") @@ -153,6 +162,7 @@ extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata #if (_MSC_VER >= 1300) // 1300 == VC++ 7.0 # pragma data_seg(pop, old_seg) #endif +#endif PVAPI on_tls_prepare(void) {