From 784ec87be16d53d0863becb6c15d5636bce54fae Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Tue, 13 Nov 2007 23:23:44 +0000 Subject: [PATCH] Merged revisions 41023-41071 via svnmerge from https://svn.boost.org/svn/boost/trunk ........ r41026 | johnmaddock | 2007-11-12 02:00:46 -0800 (Mon, 12 Nov 2007) | 1 line Adjust test logic to cope with compilers that don't underflow constants to zero when they should. ........ r41027 | burbelgruff | 2007-11-12 03:10:20 -0800 (Mon, 12 Nov 2007) | 1 line #1425 Support for Visual Studio 2008 ........ r41028 | chris_kohlhoff | 2007-11-12 04:07:39 -0800 (Mon, 12 Nov 2007) | 5 lines Cannot perform concurrent operations on the /dev/poll descriptor where the sockets descriptors involved may already be being waited on. Changed the dev_poll_reactor class to keep a vector of pending event changes and interrupt the /dev/poll ioctl() wait to apply it. ........ r41029 | garcia | 2007-11-12 05:00:41 -0800 (Mon, 12 Nov 2007) | 2 lines added a reviewer for singleton. ........ r41030 | garcia | 2007-11-12 05:04:16 -0800 (Mon, 12 Nov 2007) | 2 lines Removed review dates that passed without happening. ........ r41033 | bemandawes | 2007-11-12 07:22:24 -0800 (Mon, 12 Nov 2007) | 2 lines Add separate headers for system-specific enums, thus reducing coupling. Suggested by Emil Dotchevski. ........ r41036 | bgubenko | 2007-11-12 09:03:38 -0800 (Mon, 12 Nov 2007) | 1 line add -fno-strict-aliasing to compilation with gcc ........ r41038 | johnmaddock | 2007-11-12 09:21:47 -0800 (Mon, 12 Nov 2007) | 1 line Disable long double tests if there are no long double math functions. ........ r41040 | bemandawes | 2007-11-12 09:42:42 -0800 (Mon, 12 Nov 2007) | 1 line Include system-specific headers, change namespaces accordingly. ........ r41043 | eric_niebler | 2007-11-12 13:07:54 -0800 (Mon, 12 Nov 2007) | 1 line minor clean-up ........ r41046 | bemandawes | 2007-11-12 14:29:48 -0800 (Mon, 12 Nov 2007) | 1 line Change default to --v2 ........ r41048 | noel_belcourt | 2007-11-12 14:52:12 -0800 (Mon, 12 Nov 2007) | 3 lines Get the unix timing working correctly. ........ r41050 | bgubenko | 2007-11-12 16:51:37 -0800 (Mon, 12 Nov 2007) | 1 line when setting OSPLAT, check __ia64 macro ........ r41052 | bemandawes | 2007-11-12 18:54:32 -0800 (Mon, 12 Nov 2007) | 1 line Add tests for, and fix, current_path overloading. ........ r41054 | vladimir_prus | 2007-11-12 23:54:20 -0800 (Mon, 12 Nov 2007) | 1 line Add Google Analytics tracking code ........ r41056 | anthonyw | 2007-11-13 01:27:11 -0800 (Tue, 13 Nov 2007) | 1 line Integrated TSS with storage of thread data; cleaned up the heap allocation functions to throw bad_alloc if they run out of memory ........ r41057 | danieljames | 2007-11-13 03:51:23 -0800 (Tue, 13 Nov 2007) | 1 line Don't use fpclass because it causes a warning for long doubles. I don't know if the warning is vaild here - but I don't want to disable it as it's useful for checking other function calls. ........ r41059 | chris_kohlhoff | 2007-11-13 04:50:27 -0800 (Tue, 13 Nov 2007) | 6 lines Add a workaround for MSVC secure iterator problem where allowing the destruction of an iterator to an already-destroyed string object results in a program crash. Revert previous change to destroy buffers prior to invoking the handler since it didn't fix the problem and wasn't cleaning up all copies of the buffers anyway. ........ r41060 | bemandawes | 2007-11-13 05:54:58 -0800 (Tue, 13 Nov 2007) | 1 line Correct detection of failure to run in a boost tree, and refactor code as a separate set_boost_root function. ........ r41062 | johnmaddock | 2007-11-13 08:15:27 -0800 (Tue, 13 Nov 2007) | 1 line Ooops, disable long double overloads when there is no long double support (Borland fix). ........ r41063 | eric_niebler | 2007-11-13 08:38:11 -0800 (Tue, 13 Nov 2007) | 1 line portability fix for Intel 8.1 ........ r41064 | johnmaddock | 2007-11-13 09:15:29 -0800 (Tue, 13 Nov 2007) | 1 line Updated compiler status, and regenerated docs. ........ r41069 | davedeakins | 2007-11-13 12:19:39 -0800 (Tue, 13 Nov 2007) | 1 line Have the local_time and universal_time functions use GetSystemTime and SystemTimeToFileTime on Windows CE (since GetSystemTimeAsFileTime is not present) ........ [SVN r41072] --- build/Jamfile.v2 | 2 - include/boost/thread/detail/tss_hooks.hpp | 2 +- include/boost/thread/tss.hpp | 14 +- include/boost/thread/win32/thread.hpp | 4 +- .../boost/thread/win32/thread_heap_alloc.hpp | 93 +++++++- include/boost/thread/win32/tss.hpp | 82 +++++++ src/win32/thread.cpp | 159 +++++++++---- src/win32/tss.cpp | 211 ----------------- src/win32/tss_hooks.cpp | 218 ------------------ src/win32/tss_pe.cpp | 3 + 10 files changed, 294 insertions(+), 494 deletions(-) create mode 100644 include/boost/thread/win32/tss.hpp delete mode 100644 src/win32/tss.cpp delete mode 100644 src/win32/tss_hooks.cpp diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index 10bceabe..860542be 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -180,8 +180,6 @@ alias thread_sources : ## win32 sources ## win32/thread.cpp win32/exceptions.cpp - win32/tss.cpp - win32/tss_hooks.cpp win32/tss_dll.cpp win32/tss_pe.cpp : ## requirements ## diff --git a/include/boost/thread/detail/tss_hooks.hpp b/include/boost/thread/detail/tss_hooks.hpp index a1c1aa3b..4b18fe97 100644 --- a/include/boost/thread/detail/tss_hooks.hpp +++ b/include/boost/thread/detail/tss_hooks.hpp @@ -67,7 +67,7 @@ //Called automatically by Boost.Threads when //a method for doing so has been discovered. //Must not be omitted; may be called multiple times. - + extern "C" void tss_cleanup_implemented(void); //Dummy function used both to detect whether tss cleanup //cleanup has been implemented and to force diff --git a/include/boost/thread/tss.hpp b/include/boost/thread/tss.hpp index 0b33bda4..1870324c 100644 --- a/include/boost/thread/tss.hpp +++ b/include/boost/thread/tss.hpp @@ -1,5 +1,6 @@ // Copyright (C) 2001-2003 William E. Kempf // Copyright (C) 2006 Roland Schwarz +// Copyright (C) 2007 Anthony Williams // // 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) @@ -9,14 +10,17 @@ #include +#ifdef BOOST_HAS_WINTHREADS +#include +#include BOOST_THREAD_PLATFORM(tss.hpp) +#else + #include #include #include #if defined(BOOST_HAS_PTHREADS) # include -#elif defined(BOOST_HAS_MPTASKS) -# include #endif namespace boost { @@ -57,10 +61,6 @@ private: void init(boost::function1* pcleanup); }; -#if defined(BOOST_HAS_MPTASKS) -void thread_cleanup(); -#endif - template struct tss_adapter { @@ -112,6 +112,8 @@ private: } // namespace boost +#endif + #endif //BOOST_TSS_WEK070601_HPP // Change Log: diff --git a/include/boost/thread/win32/thread.hpp b/include/boost/thread/win32/thread.hpp index a81c6ee6..1e237791 100644 --- a/include/boost/thread/win32/thread.hpp +++ b/include/boost/thread/win32/thread.hpp @@ -27,6 +27,7 @@ namespace boost namespace detail { struct thread_exit_callback_node; + struct tss_data_node; struct thread_data_base { @@ -34,13 +35,14 @@ namespace boost 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; 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), + thread_exit_callbacks(0),tss_data(0), interruption_enabled(true), id(0) {} diff --git a/include/boost/thread/win32/thread_heap_alloc.hpp b/include/boost/thread/win32/thread_heap_alloc.hpp index eed7d4b3..1835e35e 100644 --- a/include/boost/thread/win32/thread_heap_alloc.hpp +++ b/include/boost/thread/win32/thread_heap_alloc.hpp @@ -6,6 +6,8 @@ #define THREAD_HEAP_ALLOC_HPP #include #include "thread_primitives.hpp" +#include +#include #if defined( BOOST_USE_WINDOWS_H ) # include @@ -51,35 +53,106 @@ namespace boost { namespace detail { + inline BOOST_THREAD_DECL void* allocate_raw_heap_memory(unsigned size) + { + void* const heap_memory=detail::win32::HeapAlloc(detail::win32::GetProcessHeap(),0,size); + if(!heap_memory) + { + throw std::bad_alloc(); + } + return heap_memory; + } + + inline BOOST_THREAD_DECL void free_raw_heap_memory(void* heap_memory) + { + BOOST_VERIFY(detail::win32::HeapFree(detail::win32::GetProcessHeap(),0,heap_memory)!=0); + } + template T* heap_new() { - void* const heap_memory=detail::win32::HeapAlloc(detail::win32::GetProcessHeap(),0,sizeof(T)); - T* const data=new (heap_memory) T(); - return data; + void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); + try + { + T* const data=new (heap_memory) T(); + return data; + } + catch(...) + { + free_raw_heap_memory(heap_memory); + throw; + } } template T* heap_new(A1 a1) { - void* const heap_memory=detail::win32::HeapAlloc(detail::win32::GetProcessHeap(),0,sizeof(T)); - T* const data=new (heap_memory) T(a1); - return data; + void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); + try + { + T* const data=new (heap_memory) T(a1); + return data; + } + catch(...) + { + free_raw_heap_memory(heap_memory); + throw; + } } template T* heap_new(A1 a1,A2 a2) { - void* const heap_memory=detail::win32::HeapAlloc(detail::win32::GetProcessHeap(),0,sizeof(T)); - T* const data=new (heap_memory) T(a1,a2); - return data; + void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); + try + { + T* const data=new (heap_memory) T(a1,a2); + return data; + } + catch(...) + { + free_raw_heap_memory(heap_memory); + throw; + } + } + + template + T* heap_new(A1 a1,A2 a2,A3 a3) + { + void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); + try + { + T* const data=new (heap_memory) T(a1,a2,a3); + return data; + } + catch(...) + { + free_raw_heap_memory(heap_memory); + throw; + } + } + + template + T* heap_new(A1 a1,A2 a2,A3 a3,A4 a4) + { + void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); + try + { + T* const data=new (heap_memory) T(a1,a2,a3,a4); + return data; + } + catch(...) + { + free_raw_heap_memory(heap_memory); + throw; + } } template void heap_delete(T* data) { data->~T(); - detail::win32::HeapFree(detail::win32::GetProcessHeap(),0,data); + free_raw_heap_memory(data); } template diff --git a/include/boost/thread/win32/tss.hpp b/include/boost/thread/win32/tss.hpp new file mode 100644 index 00000000..a99dfac4 --- /dev/null +++ b/include/boost/thread/win32/tss.hpp @@ -0,0 +1,82 @@ +#ifndef BOOST_THREAD_WIN32_TSS_HPP +#define BOOST_THREAD_WIN32_TSS_HPP + +namespace boost +{ + namespace detail + { + typedef void(*tss_cleanup_function)(void const* key,void* value); + + BOOST_THREAD_DECL void set_tss_data(void const* key,tss_cleanup_function 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&); + + static void delete_data(void const* self,void* value) + { + static_cast(self)->cleanup((T*)value); + } + + void cleanup(T* data) const + { + if(func) + { + func(data); + } + else + { + delete data; + } + } + + void (*func)(T*); + + public: + thread_specific_ptr(): + func(0) + {} + explicit thread_specific_ptr(void (*func_)(T*)): + func(func_) + {} + ~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,0,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,delete_data,new_value,true); + } + } + }; +} + + +#endif diff --git a/src/win32/thread.cpp b/src/win32/thread.cpp index 54636dcc..fee2b4fd 100644 --- a/src/win32/thread.cpp +++ b/src/win32/thread.cpp @@ -12,7 +12,9 @@ #endif #include #include +#include #include +#include namespace boost { @@ -130,6 +132,19 @@ namespace boost {} }; + struct tss_data_node + { + void const* key; + boost::detail::tss_cleanup_function func; + void* value; + tss_data_node* next; + + tss_data_node(void const* key_,boost::detail::tss_cleanup_function func_,void* value_, + tss_data_node* next_): + key(key_),func(func_),value(value_),next(next_) + {} + }; + } namespace @@ -139,17 +154,31 @@ namespace boost boost::intrusive_ptr current_thread_data(get_current_thread_data(),false); if(current_thread_data) { - while(current_thread_data->thread_exit_callbacks) + while(current_thread_data->tss_data || current_thread_data->thread_exit_callbacks) { - detail::thread_exit_callback_node* const current_node=current_thread_data->thread_exit_callbacks; - current_thread_data->thread_exit_callbacks=current_node->next; - if(current_node->func) + while(current_thread_data->thread_exit_callbacks) { - (*current_node->func)(); - boost::detail::heap_delete(current_node->func); + detail::thread_exit_callback_node* const current_node=current_thread_data->thread_exit_callbacks; + current_thread_data->thread_exit_callbacks=current_node->next; + if(current_node->func) + { + (*current_node->func)(); + boost::detail::heap_delete(current_node->func); + } + boost::detail::heap_delete(current_node); + } + while(current_thread_data->tss_data) + { + detail::tss_data_node* const current_node=current_thread_data->tss_data; + current_thread_data->tss_data=current_node->next; + if(current_node->func) + { + (*current_node->func)(current_node->key,current_node->value); + } + boost::detail::heap_delete(current_node); } - boost::detail::heap_delete(current_node); } + } set_current_thread_data(0); } @@ -210,14 +239,20 @@ namespace boost void run() {} }; + + void make_external_thread_data() + { + externally_launched_thread* me=detail::heap_new(); + set_current_thread_data(me); + } + } thread thread::self() { if(!get_current_thread_data()) { - externally_launched_thread* me=detail::heap_new(); - set_current_thread_data(me); + make_external_thread_data(); } return thread(boost::intrusive_ptr(get_current_thread_data())); } @@ -450,49 +485,83 @@ namespace boost } } - namespace - { - void NTAPI thread_exit_func_callback(HINSTANCE, DWORD, PVOID); - typedef void (NTAPI* tls_callback)(HINSTANCE, DWORD, PVOID); - -#ifdef _MSC_VER - extern "C" - { - extern DWORD _tls_used; //the tls directory (located in .rdata segment) - extern tls_callback __xl_a[], __xl_z[]; //tls initializers */ - } - -#if (_MSC_VER >= 1300) // 1300 == VC++ 7.0 -# pragma data_seg(push, old_seg) -#endif - -#pragma data_seg(".CRT$XLB") - tls_callback p_thread_callback = thread_exit_func_callback; -#pragma data_seg() - -#if (_MSC_VER >= 1300) // 1300 == VC++ 7.0 -# pragma data_seg(pop, old_seg) -#endif -#endif - - void NTAPI thread_exit_func_callback(HINSTANCE h, DWORD dwReason, PVOID pv) - { - if((dwReason==DLL_THREAD_DETACH) || (dwReason==DLL_PROCESS_DETACH)) - { - run_thread_exit_callbacks(); - } - } - } - namespace detail { void add_thread_exit_function(thread_exit_function_base* func) { + detail::thread_data_base* const current_thread_data(get_current_thread_data()); thread_exit_callback_node* const new_node= heap_new(func, - get_current_thread_data()->thread_exit_callbacks); - get_current_thread_data()->thread_exit_callbacks=new_node; + current_thread_data->thread_exit_callbacks); + current_thread_data->thread_exit_callbacks=new_node; + } + + tss_data_node* find_tss_data(void const* 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; + } + + void* get_tss_data(void const* key) + { + if(tss_data_node* const current_node=find_tss_data(key)) + { + return current_node->value; + } + return NULL; + } + + void set_tss_data(void const* key,tss_cleanup_function 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=func; + current_node->value=tss_data; + } + else + { + 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(); + } + tss_data_node* const new_node=heap_new(key,func,tss_data,current_thread_data->tss_data); + current_thread_data->tss_data=new_node; + } } } } + +extern "C" BOOST_THREAD_DECL void on_process_enter() +{} + +extern "C" BOOST_THREAD_DECL void on_thread_enter() +{} + +extern "C" BOOST_THREAD_DECL void on_process_exit() +{} + +extern "C" BOOST_THREAD_DECL void on_thread_exit() +{ + boost::run_thread_exit_callbacks(); +} + diff --git a/src/win32/tss.cpp b/src/win32/tss.cpp deleted file mode 100644 index eb5a4d81..00000000 --- a/src/win32/tss.cpp +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright (C) 2001-2003 William E. Kempf -// Copyright (C) 2006 Roland Schwarz -// Copyright (C) 2007 Anthony Williams -// Copyright (C) 2007 David Deakins -// -// 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 - -#include -#ifndef BOOST_THREAD_NO_TSS_CLEANUP - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#if defined(UNDER_CE) && !defined(TLS_OUT_OF_INDEXES) -# define TLS_OUT_OF_INDEXES 0xFFFFFFFF -#endif - -namespace { - -typedef std::vector tss_slots; -typedef std::vector*> tss_data_cleanup_handlers_type; - -boost::once_flag tss_data_once = BOOST_ONCE_INIT; -boost::mutex* tss_data_mutex = 0; -tss_data_cleanup_handlers_type* tss_data_cleanup_handlers = 0; - DWORD tss_data_native_key=TLS_OUT_OF_INDEXES; -int tss_data_use = 0; - -void tss_data_inc_use(boost::mutex::scoped_lock& lk) -{ - ++tss_data_use; -} - -void tss_data_dec_use(boost::mutex::scoped_lock& lk) -{ - if (0 == --tss_data_use) - { - tss_data_cleanup_handlers_type::size_type i; - for (i = 0; i < tss_data_cleanup_handlers->size(); ++i) - { - delete (*tss_data_cleanup_handlers)[i]; - } - delete tss_data_cleanup_handlers; - tss_data_cleanup_handlers = 0; - lk.unlock(); - delete tss_data_mutex; - tss_data_mutex = 0; - TlsFree(tss_data_native_key); - tss_data_native_key=TLS_OUT_OF_INDEXES; - } -} - -extern "C" void cleanup_slots(void* p) -{ - tss_slots* slots = static_cast(p); - boost::mutex::scoped_lock lock(*tss_data_mutex); - for (tss_slots::size_type i = 0; i < slots->size(); ++i) - { - (*(*tss_data_cleanup_handlers)[i])((*slots)[i]); - (*slots)[i] = 0; - } - TlsSetValue(tss_data_native_key,0); - tss_data_dec_use(lock); - delete slots; -} - -void init_tss_data() -{ - std::auto_ptr - temp(new tss_data_cleanup_handlers_type); - - std::auto_ptr temp_mutex(new boost::mutex); - if (temp_mutex.get() == 0) - throw boost::thread_resource_error(); - - //Force the cleanup implementation library to be linked in - tss_cleanup_implemented(); - - //Allocate tls slot - tss_data_native_key = TlsAlloc(); - if (tss_data_native_key == TLS_OUT_OF_INDEXES) - return; - - // The life time of cleanup handlers and mutex is beeing - // managed by a reference counting technique. - // This avoids a memory leak by releasing the global data - // after last use only, since the execution order of cleanup - // handlers is unspecified on any platform with regards to - // C++ destructor ordering rules. - tss_data_cleanup_handlers = temp.release(); - tss_data_mutex = temp_mutex.release(); -} - -tss_slots* get_slots(bool alloc); - -void __cdecl tss_thread_exit() -{ - tss_slots* slots = get_slots(false); - if (slots) - cleanup_slots(slots); -} - -tss_slots* get_slots(bool alloc) -{ - tss_slots* slots = 0; - - slots = static_cast( - TlsGetValue(tss_data_native_key)); - - if (slots == 0 && alloc) - { - std::auto_ptr temp(new tss_slots); - - if (at_thread_exit(&tss_thread_exit) == -1) - return 0; - if (!TlsSetValue(tss_data_native_key, temp.get())) - return 0; - { - boost::mutex::scoped_lock lock(*tss_data_mutex); - tss_data_inc_use(lock); - } - slots = temp.release(); - } - - return slots; -} - -} // namespace - -namespace boost { - -namespace detail { -void tss::init(boost::function1* pcleanup) -{ - boost::call_once(tss_data_once, &init_tss_data); - if (tss_data_cleanup_handlers == 0) - throw thread_resource_error(); - boost::mutex::scoped_lock lock(*tss_data_mutex); - try - { - tss_data_cleanup_handlers->push_back(pcleanup); - m_slot = tss_data_cleanup_handlers->size() - 1; - tss_data_inc_use(lock); - } - catch (...) - { - throw thread_resource_error(); - } -} - -tss::~tss() -{ - boost::mutex::scoped_lock lock(*tss_data_mutex); - tss_data_dec_use(lock); -} - -void* tss::get() const -{ - tss_slots* slots = get_slots(false); - - if (!slots) - return 0; - - if (m_slot >= slots->size()) - return 0; - - return (*slots)[m_slot]; -} - -void tss::set(void* value) -{ - tss_slots* slots = get_slots(true); - - if (!slots) - throw boost::thread_resource_error(); - - if (m_slot >= slots->size()) - { - try - { - slots->resize(m_slot + 1); - } - catch (...) - { - throw boost::thread_resource_error(); - } - } - - (*slots)[m_slot] = value; -} - -void tss::cleanup(void* value) -{ - boost::mutex::scoped_lock lock(*tss_data_mutex); - (*(*tss_data_cleanup_handlers)[m_slot])(value); -} - -} // namespace detail -} // namespace boost - -#endif //BOOST_THREAD_NO_TSS_CLEANUP diff --git a/src/win32/tss_hooks.cpp b/src/win32/tss_hooks.cpp deleted file mode 100644 index 8e9f7df8..00000000 --- a/src/win32/tss_hooks.cpp +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright (C) 2004 Michael Glassford -// Copyright (C) 2006 Roland Schwarz -// Copyright (C) 2007 Anthony Williams -// Copyright (C) 2007 David Deakins -// Use, modification and distribution are subject to 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 - -#if defined(BOOST_HAS_WINTHREADS) - - #include - - #include -// #include - #include - - #include - - #define WIN32_LEAN_AND_MEAN - #include - -# if defined(UNDER_CE) && !defined(TLS_OUT_OF_INDEXES) -# define TLS_OUT_OF_INDEXES 0xFFFFFFFF -# endif - - namespace - { - class CScopedCSLock - { - public: - CScopedCSLock(LPCRITICAL_SECTION cs) : lk(true), cs(cs) { - ::EnterCriticalSection(cs); - } - ~CScopedCSLock() { - if (lk) ::LeaveCriticalSection(cs); - } - void Unlock() { - lk = false; - ::LeaveCriticalSection(cs); - } - private: - bool lk; - LPCRITICAL_SECTION cs; - }; - - typedef std::list thread_exit_handlers; - - boost::once_flag once_init_threadmon_mutex = BOOST_ONCE_INIT; - //boost::mutex* threadmon_mutex; - // We don't use boost::mutex here, to avoid a memory leak report, - // because we cannot delete it again easily. - CRITICAL_SECTION threadmon_mutex; - void init_threadmon_mutex(void) - { - //threadmon_mutex = new boost::mutex; - //if (!threadmon_mutex) - // throw boost::thread_resource_error(); - ::InitializeCriticalSection(&threadmon_mutex); - } - - const DWORD invalid_tls_key = TLS_OUT_OF_INDEXES; - DWORD tls_key = invalid_tls_key; - - unsigned long attached_thread_count = 0; - } - - /* - Calls to DllMain() and tls_callback() are serialized by the OS; - however, calls to at_thread_exit are not, so it must be protected - by a mutex. Since we already need a mutex for at_thread_exit(), - and since there is no guarantee that on_process_enter(), - on_process_exit(), on_thread_enter(), and on_thread_exit() - will be called only from DllMain() or tls_callback(), it makes - sense to protect those, too. - */ - - extern "C" BOOST_THREAD_DECL int at_thread_exit( - thread_exit_handler exit_handler - ) - { - boost::call_once(once_init_threadmon_mutex, init_threadmon_mutex); - //boost::mutex::scoped_lock lock(*threadmon_mutex); - CScopedCSLock lock(&threadmon_mutex); - - //Allocate a tls slot if necessary. - - if (tls_key == invalid_tls_key) - tls_key = TlsAlloc(); - - if (tls_key == invalid_tls_key) - return -1; - - //Get the exit handlers list for the current thread from tls. - - thread_exit_handlers* exit_handlers = - static_cast(TlsGetValue(tls_key)); - - if (!exit_handlers) - { - //No exit handlers list was created yet. - - try - { - //Attempt to create a new exit handlers list. - - exit_handlers = new thread_exit_handlers; - if (!exit_handlers) - return -1; - - //Attempt to store the list pointer in tls. - - if (TlsSetValue(tls_key, exit_handlers)) - ++attached_thread_count; - else - { - delete exit_handlers; - return -1; - } - } - catch (...) - { - return -1; - } - } - - //Like the C runtime library atexit() function, - //functions should be called in the reverse of - //the order they are added, so push them on the - //front of the list. - - try - { - exit_handlers->push_front(exit_handler); - } - catch (...) - { - return -1; - } - - //Like the atexit() function, a result of zero - //indicates success. - - return 0; - } - - extern "C" BOOST_THREAD_DECL void on_process_enter(void) - { - boost::call_once(once_init_threadmon_mutex, init_threadmon_mutex); -// boost::mutex::scoped_lock lock(*threadmon_mutex); - CScopedCSLock lock(&threadmon_mutex); - - BOOST_ASSERT(attached_thread_count == 0); - } - - extern "C" BOOST_THREAD_DECL void on_process_exit(void) - { - boost::call_once(once_init_threadmon_mutex, init_threadmon_mutex); -// boost::mutex::scoped_lock lock(*threadmon_mutex); - CScopedCSLock lock(&threadmon_mutex); - - BOOST_ASSERT(attached_thread_count == 0); - - //Free the tls slot if one was allocated. - - if (tls_key != invalid_tls_key) - { - TlsFree(tls_key); - tls_key = invalid_tls_key; - } - } - - extern "C" BOOST_THREAD_DECL void on_thread_enter(void) - { - //boost::call_once(init_threadmon_mutex, once_init_threadmon_mutex); - //boost::mutex::scoped_lock lock(*threadmon_mutex); - } - - extern "C" BOOST_THREAD_DECL void on_thread_exit(void) - { - boost::call_once(once_init_threadmon_mutex, init_threadmon_mutex); -// boost::mutex::scoped_lock lock(*threadmon_mutex); - CScopedCSLock lock(&threadmon_mutex); - - //Get the exit handlers list for the current thread from tls. - - if (tls_key == invalid_tls_key) - return; - - thread_exit_handlers* exit_handlers = - static_cast(TlsGetValue(tls_key)); - - //If a handlers list was found, use it. - - if (exit_handlers && TlsSetValue(tls_key, 0)) - { - BOOST_ASSERT(attached_thread_count > 0); - --attached_thread_count; - - //lock.unlock(); - lock.Unlock(); - - //Call each handler and remove it from the list - - while (!exit_handlers->empty()) - { - if (thread_exit_handler exit_handler = *exit_handlers->begin()) - (*exit_handler)(); - exit_handlers->pop_front(); - } - - delete exit_handlers; - exit_handlers = 0; - } - } - -#endif //defined(BOOST_HAS_WINTHREADS) diff --git a/src/win32/tss_pe.cpp b/src/win32/tss_pe.cpp index 010920f6..3aef63a1 100644 --- a/src/win32/tss_pe.cpp +++ b/src/win32/tss_pe.cpp @@ -220,10 +220,13 @@ extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata void NTAPI on_tls_callback(HINSTANCE h, DWORD dwReason, PVOID pv) { + OutputDebugString("on_tls_callback\n"); + switch (dwReason) { case DLL_THREAD_DETACH: { + OutputDebugString("on_tls_callback: thread_exit\n"); on_thread_exit(); break; }