Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r56992 - in branches/release: boost boost/thread boost/thread/detail boost/thread/pthread libs/thread libs/thread/build libs/thread/example libs/thread/src/pthread libs/thread/src/win32 libs/thread/test
From: anthony_at_[hidden]
Date: 2009-10-19 05:18:16


Author: anthonyw
Date: 2009-10-19 05:18:13 EDT (Mon, 19 Oct 2009)
New Revision: 56992
URL: http://svn.boost.org/trac/boost/changeset/56992

Log:
Merged thread changes from trunk
Added:
   branches/release/libs/thread/test/test_thread_move_return.cpp
      - copied unchanged from r56991, /trunk/libs/thread/test/test_thread_move_return.cpp
   branches/release/libs/thread/test/test_thread_return_local.cpp
      - copied unchanged from r56991, /trunk/libs/thread/test/test_thread_return_local.cpp
Removed:
   branches/release/libs/thread/src/pthread/exceptions.cpp
   branches/release/libs/thread/src/win32/exceptions.cpp
Properties modified:
   branches/release/boost/thread/ (props changed)
   branches/release/boost/thread.hpp (props changed)
   branches/release/libs/thread/ (props changed)
Text files modified:
   branches/release/boost/thread/detail/move.hpp | 4
   branches/release/boost/thread/detail/thread.hpp | 18 ++
   branches/release/boost/thread/exceptions.hpp | 190 +++++++++++++++++++++++----------
   branches/release/boost/thread/locks.hpp | 11 +
   branches/release/boost/thread/pthread/thread_data.hpp | 17 ++
   branches/release/boost/thread/tss.hpp | 222 ++++++++++++++++++++--------------------
   branches/release/libs/thread/build/Jamfile.v2 | 2
   branches/release/libs/thread/example/condition.cpp | 9 +
   branches/release/libs/thread/example/tennis.cpp | 2
   branches/release/libs/thread/src/pthread/thread.cpp | 164 ++++++++---------------------
   branches/release/libs/thread/src/win32/thread.cpp | 2
   branches/release/libs/thread/test/Jamfile.v2 | 2
   branches/release/libs/thread/test/test_thread_move.cpp | 18 ---
   branches/release/libs/thread/test/test_tss.cpp | 35 ++++++
   14 files changed, 375 insertions(+), 321 deletions(-)

Modified: branches/release/boost/thread/detail/move.hpp
==============================================================================
--- branches/release/boost/thread/detail/move.hpp (original)
+++ branches/release/boost/thread/detail/move.hpp 2009-10-19 05:18:13 EDT (Mon, 19 Oct 2009)
@@ -41,9 +41,9 @@
 
 #ifndef BOOST_NO_SFINAE
     template<typename T>
- typename enable_if<boost::is_convertible<T&,detail::thread_move_t<T> >, T >::type move(T& t)
+ typename enable_if<boost::is_convertible<T&,detail::thread_move_t<T> >, detail::thread_move_t<T> >::type move(T& t)
     {
- return T(detail::thread_move_t<T>(t));
+ return detail::thread_move_t<T>(t);
     }
 #endif
     

Modified: branches/release/boost/thread/detail/thread.hpp
==============================================================================
--- branches/release/boost/thread/detail/thread.hpp (original)
+++ branches/release/boost/thread/detail/thread.hpp 2009-10-19 05:18:13 EDT (Mon, 19 Oct 2009)
@@ -144,6 +144,9 @@
         struct dummy;
 #endif
     public:
+#ifdef __SUNPRO_CC
+ thread(const volatile thread&);
+#endif
         thread();
         ~thread();
 
@@ -201,14 +204,21 @@
             thread_info=x->thread_info;
             x->thread_info.reset();
         }
-
+
+#ifdef __SUNPRO_CC
+ thread& operator=(thread x)
+ {
+ swap(x);
+ return *this;
+ }
+#else
         thread& operator=(detail::thread_move_t<thread> x)
         {
             thread new_thread(x);
             swap(new_thread);
             return *this;
         }
-
+#endif
         operator detail::thread_move_t<thread>()
         {
             return move();
@@ -339,9 +349,9 @@
         return t;
     }
 #else
- inline thread move(detail::thread_move_t<thread> t)
+ inline detail::thread_move_t<thread> move(detail::thread_move_t<thread> t)
     {
- return thread(t);
+ return t;
     }
 #endif
 

Modified: branches/release/boost/thread/exceptions.hpp
==============================================================================
--- branches/release/boost/thread/exceptions.hpp (original)
+++ branches/release/boost/thread/exceptions.hpp 2009-10-19 05:18:13 EDT (Mon, 19 Oct 2009)
@@ -1,6 +1,6 @@
 // Copyright (C) 2001-2003
 // William E. Kempf
-// Copyright (C) 2007-8 Anthony Williams
+// Copyright (C) 2007-9 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)
@@ -24,23 +24,36 @@
 namespace boost
 {
 
- class BOOST_THREAD_DECL thread_interrupted
+ class thread_interrupted
     {};
 
-class BOOST_THREAD_DECL thread_exception : public std::exception
-{
-protected:
- thread_exception();
- thread_exception(int sys_err_code);
-
-public:
- ~thread_exception() throw();
-
- int native_error() const;
-
-private:
- int m_sys_err;
-};
+ class thread_exception:
+ public std::exception
+ {
+ protected:
+ thread_exception():
+ m_sys_err(0)
+ {}
+
+ thread_exception(int sys_err_code):
+ m_sys_err(sys_err_code)
+ {}
+
+
+ public:
+ ~thread_exception() throw()
+ {}
+
+
+ int native_error() const
+ {
+ return m_sys_err;
+ }
+
+
+ private:
+ int m_sys_err;
+ };
 
     class condition_error:
         public std::exception
@@ -53,62 +66,117 @@
     };
     
 
-class BOOST_THREAD_DECL lock_error : public thread_exception
-{
-public:
- lock_error();
- lock_error(int sys_err_code);
- ~lock_error() throw();
+ class lock_error:
+ public thread_exception
+ {
+ public:
+ lock_error()
+ {}
+
+ lock_error(int sys_err_code):
+ thread_exception(sys_err_code)
+ {}
+
+ ~lock_error() throw()
+ {}
+
 
- virtual const char* what() const throw();
-};
+ virtual const char* what() const throw()
+ {
+ return "boost::lock_error";
+ }
+ };
 
-class BOOST_THREAD_DECL thread_resource_error : public thread_exception
-{
-public:
- thread_resource_error();
- thread_resource_error(int sys_err_code);
- ~thread_resource_error() throw();
+ class thread_resource_error:
+ public thread_exception
+ {
+ public:
+ thread_resource_error()
+ {}
+
+ thread_resource_error(int sys_err_code):
+ thread_exception(sys_err_code)
+ {}
+
+ ~thread_resource_error() throw()
+ {}
+
 
- virtual const char* what() const throw();
-};
+ virtual const char* what() const throw()
+ {
+ return "boost::thread_resource_error";
+ }
+
+ };
 
-class BOOST_THREAD_DECL unsupported_thread_option : public thread_exception
-{
-public:
- unsupported_thread_option();
- unsupported_thread_option(int sys_err_code);
- ~unsupported_thread_option() throw();
+ class unsupported_thread_option:
+ public thread_exception
+ {
+ public:
+ unsupported_thread_option()
+ {}
+
+ unsupported_thread_option(int sys_err_code):
+ thread_exception(sys_err_code)
+ {}
+
+ ~unsupported_thread_option() throw()
+ {}
+
 
- virtual const char* what() const throw();
-};
+ virtual const char* what() const throw()
+ {
+ return "boost::unsupported_thread_option";
+ }
+
+ };
 
-class BOOST_THREAD_DECL invalid_thread_argument : public thread_exception
-{
-public:
- invalid_thread_argument();
- invalid_thread_argument(int sys_err_code);
- ~invalid_thread_argument() throw();
+ class invalid_thread_argument:
+ public thread_exception
+ {
+ public:
+ invalid_thread_argument()
+ {}
+
+ invalid_thread_argument(int sys_err_code):
+ thread_exception(sys_err_code)
+ {}
+
+ ~invalid_thread_argument() throw()
+ {}
+
 
- virtual const char* what() const throw();
-};
+ virtual const char* what() const throw()
+ {
+ return "boost::invalid_thread_argument";
+ }
+
+ };
 
-class BOOST_THREAD_DECL thread_permission_error : public thread_exception
-{
-public:
- thread_permission_error();
- thread_permission_error(int sys_err_code);
- ~thread_permission_error() throw();
+ class thread_permission_error:
+ public thread_exception
+ {
+ public:
+ thread_permission_error()
+ {}
+
+ thread_permission_error(int sys_err_code):
+ thread_exception(sys_err_code)
+ {}
+
+ ~thread_permission_error() throw()
+ {}
+
 
- virtual const char* what() const throw();
-};
+ virtual const char* what() const throw()
+ {
+ return "boost::thread_permission_error";
+ }
+
+ };
 
 } // namespace boost
 
 #include <boost/config/abi_suffix.hpp>
 
-#endif // BOOST_THREAD_CONFIG_PDM070801_H
-
-// Change log:
-// 3 Jan 03 WEKEMPF Modified for DLL implementation.
-
+#endif

Modified: branches/release/boost/thread/locks.hpp
==============================================================================
--- branches/release/boost/thread/locks.hpp (original)
+++ branches/release/boost/thread/locks.hpp 2009-10-19 05:18:13 EDT (Mon, 19 Oct 2009)
@@ -214,6 +214,9 @@
         unique_lock& operator=(unique_lock&);
         unique_lock& operator=(upgrade_lock<Mutex>& other);
     public:
+#ifdef __SUNPRO_CC
+ unique_lock(const volatile unique_lock&);
+#endif
         unique_lock():
             m(0),is_locked(false)
         {}
@@ -297,12 +300,20 @@
             return detail::thread_move_t<unique_lock<Mutex> >(*this);
         }
 
+#ifdef __SUNPRO_CC
+ unique_lock& operator=(unique_lock<Mutex> other)
+ {
+ swap(other);
+ return *this;
+ }
+#else
         unique_lock& operator=(detail::thread_move_t<unique_lock<Mutex> > other)
         {
             unique_lock temp(other);
             swap(temp);
             return *this;
         }
+#endif
 
         unique_lock& operator=(detail::thread_move_t<upgrade_lock<Mutex> > other)
         {

Modified: branches/release/boost/thread/pthread/thread_data.hpp
==============================================================================
--- branches/release/boost/thread/pthread/thread_data.hpp (original)
+++ branches/release/boost/thread/pthread/thread_data.hpp 2009-10-19 05:18:13 EDT (Mon, 19 Oct 2009)
@@ -13,6 +13,7 @@
 #include <boost/optional.hpp>
 #include <pthread.h>
 #include "condition_variable_fwd.hpp"
+#include <map>
 
 #include <boost/config/abi_prefix.hpp>
 
@@ -22,8 +23,18 @@
     
     namespace detail
     {
+ struct tss_cleanup_function;
         struct thread_exit_callback_node;
- struct tss_data_node;
+ struct tss_data_node
+ {
+ boost::shared_ptr<boost::detail::tss_cleanup_function> func;
+ void* value;
+
+ tss_data_node(boost::shared_ptr<boost::detail::tss_cleanup_function> func_,
+ void* value_):
+ func(func_),value(value_)
+ {}
+ };
 
         struct thread_data_base;
         typedef boost::shared_ptr<thread_data_base> thread_data_ptr;
@@ -41,14 +52,14 @@
             bool join_started;
             bool joined;
             boost::detail::thread_exit_callback_node* thread_exit_callbacks;
- boost::detail::tss_data_node* tss_data;
+ std::map<void const*,boost::detail::tss_data_node> 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)

Modified: branches/release/boost/thread/tss.hpp
==============================================================================
--- branches/release/boost/thread/tss.hpp (original)
+++ branches/release/boost/thread/tss.hpp 2009-10-19 05:18:13 EDT (Mon, 19 Oct 2009)
@@ -1,111 +1,111 @@
-#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 <boost/thread/detail/config.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/thread/detail/thread_heap_alloc.hpp>
-
-#include <boost/config/abi_prefix.hpp>
-
-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<tss_cleanup_function> func,void* tss_data,bool cleanup_existing);
- BOOST_THREAD_DECL void* get_tss_data(void const* key);
- }
-
- template <typename T>
- 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<T*>(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<T*>(data));
- }
- };
-
-
- boost::shared_ptr<detail::tss_cleanup_function> cleanup;
-
- public:
- thread_specific_ptr():
- cleanup(detail::heap_new<delete_data>(),detail::do_heap_delete<delete_data>())
- {}
- explicit thread_specific_ptr(void (*func_)(T*))
- {
- if(func_)
- {
- cleanup.reset(detail::heap_new<run_custom_cleanup_function>(func_),detail::do_heap_delete<run_custom_cleanup_function>());
- }
- }
- ~thread_specific_ptr()
- {
- reset();
- }
-
- T* get() const
- {
- return static_cast<T*>(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<detail::tss_cleanup_function>(),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 <boost/config/abi_suffix.hpp>
-
-#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 <boost/thread/detail/config.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/thread/detail/thread_heap_alloc.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+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<tss_cleanup_function> func,void* tss_data,bool cleanup_existing);
+ BOOST_THREAD_DECL void* get_tss_data(void const* key);
+ }
+
+ template <typename T>
+ 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<T*>(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<T*>(data));
+ }
+ };
+
+
+ boost::shared_ptr<detail::tss_cleanup_function> cleanup;
+
+ public:
+ thread_specific_ptr():
+ cleanup(detail::heap_new<delete_data>(),detail::do_heap_delete<delete_data>())
+ {}
+ explicit thread_specific_ptr(void (*func_)(T*))
+ {
+ if(func_)
+ {
+ cleanup.reset(detail::heap_new<run_custom_cleanup_function>(func_),detail::do_heap_delete<run_custom_cleanup_function>());
+ }
+ }
+ ~thread_specific_ptr()
+ {
+ detail::set_tss_data(this,boost::shared_ptr<detail::tss_cleanup_function>(),0,true);
+ }
+
+ T* get() const
+ {
+ return static_cast<T*>(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<detail::tss_cleanup_function>(),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 <boost/config/abi_suffix.hpp>
+
+#endif

Modified: branches/release/libs/thread/build/Jamfile.v2
==============================================================================
--- branches/release/libs/thread/build/Jamfile.v2 (original)
+++ branches/release/libs/thread/build/Jamfile.v2 2009-10-19 05:18:13 EDT (Mon, 19 Oct 2009)
@@ -180,7 +180,6 @@
 alias thread_sources
     : ## win32 sources ##
       win32/thread.cpp
- win32/exceptions.cpp
       win32/tss_dll.cpp
       win32/tss_pe.cpp
     : ## requirements ##
@@ -190,7 +189,6 @@
 alias thread_sources
     : ## pthread sources ##
       pthread/thread.cpp
- pthread/exceptions.cpp
       pthread/once.cpp
     : ## requirements ##
       <threadapi>pthread

Modified: branches/release/libs/thread/example/condition.cpp
==============================================================================
--- branches/release/libs/thread/example/condition.cpp (original)
+++ branches/release/libs/thread/example/condition.cpp 2009-10-19 05:18:13 EDT (Mon, 19 Oct 2009)
@@ -50,8 +50,9 @@
 
 void sender() {
     int n = 0;
- while (n < 100) {
+ while (n < 1000000) {
         buf.send(n);
+ if(!(n%10000))
         {
             boost::mutex::scoped_lock io_lock(io_mutex);
             std::cout << "sent: " << n << std::endl;
@@ -65,18 +66,24 @@
     int n;
     do {
         n = buf.receive();
+ if(!(n%10000))
         {
             boost::mutex::scoped_lock io_lock(io_mutex);
             std::cout << "received: " << n << std::endl;
         }
     } while (n != -1); // -1 indicates end of buffer
+ buf.send(-1);
 }
 
 int main(int, char*[])
 {
     boost::thread thrd1(&sender);
     boost::thread thrd2(&receiver);
+ boost::thread thrd3(&receiver);
+ boost::thread thrd4(&receiver);
     thrd1.join();
     thrd2.join();
+ thrd3.join();
+ thrd4.join();
     return 0;
 }

Modified: branches/release/libs/thread/example/tennis.cpp
==============================================================================
--- branches/release/libs/thread/example/tennis.cpp (original)
+++ branches/release/libs/thread/example/tennis.cpp 2009-10-19 05:18:13 EDT (Mon, 19 Oct 2009)
@@ -112,7 +112,7 @@
         std::cout << "---Noise ON..." << std::endl;
     }
 
- for (int i = 0; i < 1000000; ++i)
+ for (int i = 0; i < 1000000000; ++i)
         cond.notify_all();
 
     {

Deleted: branches/release/libs/thread/src/pthread/exceptions.cpp
==============================================================================
--- branches/release/libs/thread/src/pthread/exceptions.cpp 2009-10-19 05:18:13 EDT (Mon, 19 Oct 2009)
+++ (empty file)
@@ -1,124 +0,0 @@
-// Copyright (C) 2001-2003
-// William E. Kempf
-//
-// 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 <boost/thread/detail/config.hpp>
-
-#include <boost/thread/exceptions.hpp>
-#include <cstring>
-#include <string>
-
-namespace boost {
-
-thread_exception::thread_exception()
- : m_sys_err(0)
-{
-}
-
-thread_exception::thread_exception(int sys_err_code)
- : m_sys_err(sys_err_code)
-{
-}
-
-thread_exception::~thread_exception() throw()
-{
-}
-
-int thread_exception::native_error() const
-{
- return m_sys_err;
-}
-
-lock_error::lock_error()
-{
-}
-
-lock_error::lock_error(int sys_err_code)
- : thread_exception(sys_err_code)
-{
-}
-
-lock_error::~lock_error() throw()
-{
-}
-
-const char* lock_error::what() const throw()
-{
- return "boost::lock_error";
-}
-
-thread_resource_error::thread_resource_error()
-{
-}
-
-thread_resource_error::thread_resource_error(int sys_err_code)
- : thread_exception(sys_err_code)
-{
-}
-
-thread_resource_error::~thread_resource_error() throw()
-{
-}
-
-const char* thread_resource_error::what() const throw()
-{
- return "boost::thread_resource_error";
-}
-
-unsupported_thread_option::unsupported_thread_option()
-{
-}
-
-unsupported_thread_option::unsupported_thread_option(int sys_err_code)
- : thread_exception(sys_err_code)
-{
-}
-
-unsupported_thread_option::~unsupported_thread_option() throw()
-{
-}
-
-const char* unsupported_thread_option::what() const throw()
-{
- return "boost::unsupported_thread_option";
-}
-
-invalid_thread_argument::invalid_thread_argument()
-{
-}
-
-invalid_thread_argument::invalid_thread_argument(int sys_err_code)
- : thread_exception(sys_err_code)
-{
-}
-
-invalid_thread_argument::~invalid_thread_argument() throw()
-{
-}
-
-const char* invalid_thread_argument::what() const throw()
-{
- return "boost::invalid_thread_argument";
-}
-
-thread_permission_error::thread_permission_error()
-{
-}
-
-thread_permission_error::thread_permission_error(int sys_err_code)
- : thread_exception(sys_err_code)
-{
-}
-
-thread_permission_error::~thread_permission_error() throw()
-{
-}
-
-const char* thread_permission_error::what() const throw()
-{
- return "boost::thread_permission_error";
-}
-
-} // namespace boost

Modified: branches/release/libs/thread/src/pthread/thread.cpp
==============================================================================
--- branches/release/libs/thread/src/pthread/thread.cpp (original)
+++ branches/release/libs/thread/src/pthread/thread.cpp 2009-10-19 05:18:13 EDT (Mon, 19 Oct 2009)
@@ -42,19 +42,6 @@
             {}
         };
 
- struct tss_data_node
- {
- void const* key;
- boost::shared_ptr<boost::detail::tss_cleanup_function> func;
- void* value;
- tss_data_node* next;
-
- 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_)
- {}
- };
-
         namespace
         {
             boost::once_flag current_thread_tls_init_flag=BOOST_ONCE_INIT;
@@ -67,7 +54,7 @@
                     boost::detail::thread_data_base* thread_info=static_cast<boost::detail::thread_data_base*>(data);
                     if(thread_info)
                     {
- while(thread_info->tss_data || thread_info->thread_exit_callbacks)
+ while(!thread_info->tss_data.empty() || thread_info->thread_exit_callbacks)
                         {
                             while(thread_info->thread_exit_callbacks)
                             {
@@ -80,15 +67,18 @@
                                 }
                                 delete current_node;
                             }
- while(thread_info->tss_data)
+ for(std::map<void const*,tss_data_node>::iterator next=thread_info->tss_data.begin(),
+ current,
+ end=thread_info->tss_data.end();
+ next!=end;)
                             {
- detail::tss_data_node* const current_node=thread_info->tss_data;
- thread_info->tss_data=current_node->next;
- if(current_node->func)
+ current=next;
+ ++next;
+ if(current->second.func && current->second.value)
                                 {
- (*current_node->func)(current_node->value);
+ (*current->second.func)(current->second.value);
                                 }
- delete current_node;
+ thread_info->tss_data.erase(current);
                             }
                         }
                         thread_info->self.reset();
@@ -390,7 +380,7 @@
     {
 #if defined(PTW32_VERSION) || defined(__hpux)
         return pthread_num_processors_np();
-#elif defined(__linux__)
+#elif defined(_GNU_SOURCE)
         return get_nprocs();
 #elif defined(__APPLE__) || defined(__FreeBSD__)
         int count;
@@ -552,14 +542,11 @@
             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)
+ std::map<void const*,tss_data_node>::iterator current_node=
+ current_thread_data->tss_data.find(key);
+ if(current_node!=current_thread_data->tss_data.end())
                 {
- if(current_node->key==key)
- {
- return current_node;
- }
- current_node=current_node->next;
+ return &current_node->second;
                 }
             }
             return NULL;
@@ -573,106 +560,47 @@
             }
             return NULL;
         }
+
+ void add_new_tss_node(void const* key,
+ boost::shared_ptr<tss_cleanup_function> func,
+ void* tss_data)
+ {
+ detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data());
+ current_thread_data->tss_data.insert(std::make_pair(key,tss_data_node(func,tss_data)));
+ }
+
+ void erase_tss_node(void const* key)
+ {
+ detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data());
+ current_thread_data->tss_data.erase(key);
+ }
         
- void set_tss_data(void const* key,boost::shared_ptr<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)
         {
             if(tss_data_node* const current_node=find_tss_data(key))
             {
- if(cleanup_existing && current_node->func)
+ if(cleanup_existing && current_node->func && current_node->value)
                 {
                     (*current_node->func)(current_node->value);
                 }
- current_node->func=func;
- current_node->value=tss_data;
+ if(func || tss_data)
+ {
+ current_node->func=func;
+ current_node->value=tss_data;
+ }
+ else
+ {
+ erase_tss_node(key);
+ }
             }
             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;
- }
- }
- }
-
-// thread_group::thread_group()
-// {
-// }
-
-// thread_group::~thread_group()
-// {
-// // We shouldn't have to scoped_lock here, since referencing this object
-// // from another thread while we're deleting it in the current thread is
-// // going to lead to undefined behavior any way.
-// for (std::list<thread*>::iterator it = m_threads.begin();
-// it != m_threads.end(); ++it)
-// {
-// delete (*it);
-// }
-// }
-
-// thread* thread_group::create_thread(const function0<void>& threadfunc)
-// {
-// // No scoped_lock required here since the only "shared data" that's
-// // modified here occurs inside add_thread which does scoped_lock.
-// std::auto_ptr<thread> thrd(new thread(threadfunc));
-// add_thread(thrd.get());
-// return thrd.release();
-// }
-
-// void thread_group::add_thread(thread* thrd)
-// {
-// mutex::scoped_lock scoped_lock(m_mutex);
-
-// // For now we'll simply ignore requests to add a thread object multiple
-// // times. Should we consider this an error and either throw or return an
-// // error value?
-// std::list<thread*>::iterator it = std::find(m_threads.begin(),
-// m_threads.end(), thrd);
-// BOOST_ASSERT(it == m_threads.end());
-// if (it == m_threads.end())
-// m_threads.push_back(thrd);
-// }
-
-// void thread_group::remove_thread(thread* thrd)
-// {
-// mutex::scoped_lock scoped_lock(m_mutex);
-
-// // For now we'll simply ignore requests to remove a thread object that's
-// // not in the group. Should we consider this an error and either throw or
-// // return an error value?
-// std::list<thread*>::iterator it = std::find(m_threads.begin(),
-// m_threads.end(), thrd);
-// BOOST_ASSERT(it != m_threads.end());
-// if (it != m_threads.end())
-// m_threads.erase(it);
-// }
-
-// void thread_group::join_all()
-// {
-// mutex::scoped_lock scoped_lock(m_mutex);
-// for (std::list<thread*>::iterator it = m_threads.begin();
-// it != m_threads.end(); ++it)
-// {
-// (*it)->join();
-// }
-// }
-
-// void thread_group::interrupt_all()
-// {
-// boost::lock_guard<mutex> guard(m_mutex);
-
-// for(std::list<thread*>::iterator it=m_threads.begin(),end=m_threads.end();
-// it!=end;
-// ++it)
-// {
-// (*it)->interrupt();
-// }
-// }
-
+ add_new_tss_node(key,func,tss_data);
+ }
+ }
+ }
 
-// size_t thread_group::size() const
-// {
-// return m_threads.size();
-// }
 
 }

Deleted: branches/release/libs/thread/src/win32/exceptions.cpp
==============================================================================
--- branches/release/libs/thread/src/win32/exceptions.cpp 2009-10-19 05:18:13 EDT (Mon, 19 Oct 2009)
+++ (empty file)
@@ -1,124 +0,0 @@
-// Copyright (C) 2001-2003
-// William E. Kempf
-//
-// 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 <boost/thread/detail/config.hpp>
-
-#include <boost/thread/exceptions.hpp>
-#include <cstring>
-#include <string>
-
-namespace boost {
-
-thread_exception::thread_exception()
- : m_sys_err(0)
-{
-}
-
-thread_exception::thread_exception(int sys_err_code)
- : m_sys_err(sys_err_code)
-{
-}
-
-thread_exception::~thread_exception() throw()
-{
-}
-
-int thread_exception::native_error() const
-{
- return m_sys_err;
-}
-
-lock_error::lock_error()
-{
-}
-
-lock_error::lock_error(int sys_err_code)
- : thread_exception(sys_err_code)
-{
-}
-
-lock_error::~lock_error() throw()
-{
-}
-
-const char* lock_error::what() const throw()
-{
- return "boost::lock_error";
-}
-
-thread_resource_error::thread_resource_error()
-{
-}
-
-thread_resource_error::thread_resource_error(int sys_err_code)
- : thread_exception(sys_err_code)
-{
-}
-
-thread_resource_error::~thread_resource_error() throw()
-{
-}
-
-const char* thread_resource_error::what() const throw()
-{
- return "boost::thread_resource_error";
-}
-
-unsupported_thread_option::unsupported_thread_option()
-{
-}
-
-unsupported_thread_option::unsupported_thread_option(int sys_err_code)
- : thread_exception(sys_err_code)
-{
-}
-
-unsupported_thread_option::~unsupported_thread_option() throw()
-{
-}
-
-const char* unsupported_thread_option::what() const throw()
-{
- return "boost::unsupported_thread_option";
-}
-
-invalid_thread_argument::invalid_thread_argument()
-{
-}
-
-invalid_thread_argument::invalid_thread_argument(int sys_err_code)
- : thread_exception(sys_err_code)
-{
-}
-
-invalid_thread_argument::~invalid_thread_argument() throw()
-{
-}
-
-const char* invalid_thread_argument::what() const throw()
-{
- return "boost::invalid_thread_argument";
-}
-
-thread_permission_error::thread_permission_error()
-{
-}
-
-thread_permission_error::thread_permission_error(int sys_err_code)
- : thread_exception(sys_err_code)
-{
-}
-
-thread_permission_error::~thread_permission_error() throw()
-{
-}
-
-const char* thread_permission_error::what() const throw()
-{
- return "boost::thread_permission_error";
-}
-
-} // namespace boost

Modified: branches/release/libs/thread/src/win32/thread.cpp
==============================================================================
--- branches/release/libs/thread/src/win32/thread.cpp (original)
+++ branches/release/libs/thread/src/win32/thread.cpp 2009-10-19 05:18:13 EDT (Mon, 19 Oct 2009)
@@ -561,7 +561,7 @@
         {
             if(tss_data_node* const current_node=find_tss_data(key))
             {
- if(cleanup_existing && current_node->func.get())
+ if(cleanup_existing && current_node->func.get() && current_node->value)
                 {
                     (*current_node->func)(current_node->value);
                 }

Modified: branches/release/libs/thread/test/Jamfile.v2
==============================================================================
--- branches/release/libs/thread/test/Jamfile.v2 (original)
+++ branches/release/libs/thread/test/Jamfile.v2 2009-10-19 05:18:13 EDT (Mon, 19 Oct 2009)
@@ -38,6 +38,8 @@
           [ thread-run test_thread_id.cpp ]
           [ thread-run test_hardware_concurrency.cpp ]
           [ thread-run test_thread_move.cpp ]
+ [ thread-run test_thread_return_local.cpp ]
+ [ thread-run test_thread_move_return.cpp ]
           [ thread-run test_thread_launching.cpp ]
           [ thread-run test_thread_mf.cpp ]
           [ thread-run test_move_function.cpp ]

Modified: branches/release/libs/thread/test/test_thread_move.cpp
==============================================================================
--- branches/release/libs/thread/test/test_thread_move.cpp (original)
+++ branches/release/libs/thread/test/test_thread_move.cpp 2009-10-19 05:18:13 EDT (Mon, 19 Oct 2009)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007 Anthony Williams
+// Copyright (C) 2007-9 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)
@@ -33,21 +33,6 @@
     BOOST_CHECK_EQUAL(the_id,x_id);
 }
 
-boost::thread make_thread_return_lvalue(boost::thread::id* the_id)
-{
- boost::thread t(do_nothing,the_id);
- return boost::move(t);
-}
-
-void test_move_from_function_return_lvalue()
-{
- boost::thread::id the_id;
- boost::thread x=make_thread_return_lvalue(&the_id);
- boost::thread::id x_id=x.get_id();
- x.join();
- BOOST_CHECK_EQUAL(the_id,x_id);
-}
-
 void test_move_assign()
 {
     boost::thread::id the_id;
@@ -66,7 +51,6 @@
 
     test->add(BOOST_TEST_CASE(test_move_on_construction));
     test->add(BOOST_TEST_CASE(test_move_from_function_return));
- test->add(BOOST_TEST_CASE(test_move_from_function_return_lvalue));
     test->add(BOOST_TEST_CASE(test_move_assign));
     return test;
 }

Modified: branches/release/libs/thread/test/test_tss.cpp
==============================================================================
--- branches/release/libs/thread/test/test_tss.cpp (original)
+++ branches/release/libs/thread/test/test_tss.cpp 2009-10-19 05:18:13 EDT (Mon, 19 Oct 2009)
@@ -310,6 +310,39 @@
     timed_test(&do_test_tss_does_no_cleanup_with_null_cleanup_function, 2);
 }
 
+void thread_with_local_tss_ptr()
+{
+ {
+ boost::thread_specific_ptr<Dummy> local_tss(tss_custom_cleanup);
+
+ local_tss.reset(new Dummy);
+ }
+ BOOST_CHECK(tss_cleanup_called);
+ tss_cleanup_called=false;
+}
+
+
+void test_tss_does_not_call_cleanup_after_ptr_destroyed()
+{
+ boost::thread t(thread_with_local_tss_ptr);
+ t.join();
+ BOOST_CHECK(!tss_cleanup_called);
+}
+
+void test_tss_cleanup_not_called_for_null_pointer()
+{
+ boost::thread_specific_ptr<Dummy> local_tss(tss_custom_cleanup);
+ local_tss.reset(new Dummy);
+ tss_cleanup_called=false;
+ local_tss.reset(0);
+ BOOST_CHECK(tss_cleanup_called);
+ tss_cleanup_called=false;
+ local_tss.reset(new Dummy);
+ BOOST_CHECK(!tss_cleanup_called);
+}
+
+
+
 boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
 {
     boost::unit_test_framework::test_suite* test =
@@ -319,6 +352,8 @@
     test->add(BOOST_TEST_CASE(test_tss_with_custom_cleanup));
     test->add(BOOST_TEST_CASE(test_tss_does_no_cleanup_after_release));
     test->add(BOOST_TEST_CASE(test_tss_does_no_cleanup_with_null_cleanup_function));
+ test->add(BOOST_TEST_CASE(test_tss_does_not_call_cleanup_after_ptr_destroyed));
+ test->add(BOOST_TEST_CASE(test_tss_cleanup_not_called_for_null_pointer));
 
     return test;
 }


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