|
Boost-Commit : |
From: anthony_at_[hidden]
Date: 2007-11-19 07:29:14
Author: anthonyw
Date: 2007-11-19 07:29:14 EST (Mon, 19 Nov 2007)
New Revision: 41223
URL: http://svn.boost.org/trac/boost/changeset/41223
Log:
fixed problems with TSS cleanup when using LoadLibrary and when threads finish after thread_specific_ptr instance has been destroyed
Text files modified:
trunk/boost/thread/win32/thread_heap_alloc.hpp | 16 +-----------
trunk/boost/thread/win32/tss.hpp | 50 ++++++++++++++++++++++++++-------------
trunk/libs/thread/src/win32/thread.cpp | 40 ++++++++-----------------------
3 files changed, 46 insertions(+), 60 deletions(-)
Modified: trunk/boost/thread/win32/thread_heap_alloc.hpp
==============================================================================
--- trunk/boost/thread/win32/thread_heap_alloc.hpp (original)
+++ trunk/boost/thread/win32/thread_heap_alloc.hpp 2007-11-19 07:29:14 EST (Mon, 19 Nov 2007)
@@ -156,25 +156,13 @@
}
template<typename T>
- 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<typename T>
- do_delete<T> make_heap_deleter(T* data)
- {
- return do_delete<T>(data);
- }
}
}
Modified: trunk/boost/thread/win32/tss.hpp
==============================================================================
--- trunk/boost/thread/win32/tss.hpp (original)
+++ trunk/boost/thread/win32/tss.hpp 2007-11-19 07:29:14 EST (Mon, 19 Nov 2007)
@@ -1,13 +1,21 @@
#ifndef BOOST_THREAD_WIN32_TSS_HPP
#define BOOST_THREAD_WIN32_TSS_HPP
+#include <boost/shared_ptr.hpp>
+#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<tss_cleanup_function> func,void* tss_data,bool cleanup_existing);
BOOST_THREAD_DECL void* get_tss_data(void const* key);
}
@@ -18,31 +26,39 @@
thread_specific_ptr(thread_specific_ptr&);
thread_specific_ptr& operator=(thread_specific_ptr&);
- static void delete_data(void const* self,void* value)
- {
- static_cast<thread_specific_ptr const*>(self)->cleanup((T*)value);
- }
-
- void cleanup(T* data) const
+ struct delete_data:
+ detail::tss_cleanup_function
{
- if(func)
+ void operator()(void* data)
{
- func(data);
+ delete static_cast<T*>(data);
}
- else
+ };
+
+ 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)
{
- delete data;
+ cleanup_function(data);
}
- }
+ };
+
- void (*func)(T*);
+ boost::shared_ptr<detail::tss_cleanup_function> cleanup;
public:
thread_specific_ptr():
- func(0)
+ cleanup(detail::heap_new<delete_data>(),detail::do_heap_delete<delete_data>())
{}
explicit thread_specific_ptr(void (*func_)(T*)):
- func(func_)
+ cleanup(detail::heap_new<run_custom_cleanup_function>(func_),detail::do_heap_delete<run_custom_cleanup_function>())
{}
~thread_specific_ptr()
{
@@ -72,7 +88,7 @@
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);
}
}
};
Modified: trunk/libs/thread/src/win32/thread.cpp
==============================================================================
--- trunk/libs/thread/src/win32/thread.cpp (original)
+++ trunk/libs/thread/src/win32/thread.cpp 2007-11-19 07:29:14 EST (Mon, 19 Nov 2007)
@@ -20,28 +20,6 @@
{
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 @@
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 @@
struct tss_data_node
{
void const* key;
- boost::detail::tss_cleanup_function func;
+ boost::shared_ptr<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(void const* key_,boost::shared_ptr<boost::detail::tss_cleanup_function> func_,void* value_,
tss_data_node* next_):
key(key_),func(func_),value(value_),next(next_)
{}
@@ -173,7 +150,7 @@
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 @@
{
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<thread_exit_callback_node>(func,
current_thread_data->thread_exit_callbacks);
@@ -523,14 +505,14 @@
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<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)(current_node->value);
}
current_node->func=func;
current_node->value=tss_data;
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk