Boost logo

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