$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r80351 - in trunk: boost/thread/detail boost/thread/pthread boost/thread/win32 libs/thread/build libs/thread/doc libs/thread/src/pthread libs/thread/src/win32 libs/thread/test libs/thread/test/sync/conditions libs/thread/test/threads/thread/assign libs/thread/test/threads/thread/members
From: vicente.botet_at_[hidden]
Date: 2012-09-01 13:10:18
Author: viboes
Date: 2012-09-01 13:10:16 EDT (Sat, 01 Sep 2012)
New Revision: 80351
URL: http://svn.boost.org/trac/boost/changeset/80351
Log:
Thread: Added notify_all_at_thread_exit+join can throw conditionally if not joinable + detach is no more noexcept 
Added:
   trunk/libs/thread/test/sync/conditions/notify_all_at_thread_exit_pass.cpp   (contents, props changed)
   trunk/libs/thread/test/threads/thread/members/try_join_for_pass.cpp   (contents, props changed)
   trunk/libs/thread/test/threads/thread/members/try_join_until_pass.cpp   (contents, props changed)
Text files modified: 
   trunk/boost/thread/detail/config.hpp                        |    65 +++++++++++++++--------------           
   trunk/boost/thread/detail/thread.hpp                        |     7 ++                                      
   trunk/boost/thread/pthread/condition_variable_fwd.hpp       |     3 +                                       
   trunk/boost/thread/pthread/thread_data.hpp                  |    28 ++++++++++--                            
   trunk/boost/thread/win32/condition_variable.hpp             |    19 +++++---                                
   trunk/boost/thread/win32/thread_data.hpp                    |    31 +++++++++++--                           
   trunk/libs/thread/build/Jamfile.v2                          |     2                                         
   trunk/libs/thread/doc/thread_ref.qbk                        |    42 ++++++++++++------                      
   trunk/libs/thread/src/pthread/thread.cpp                    |    41 ++++++++++++++++-                       
   trunk/libs/thread/src/win32/thread.cpp                      |    58 ++++++++++++++++++++++----              
   trunk/libs/thread/src/win32/tss_dll.cpp                     |     1                                         
   trunk/libs/thread/test/Jamfile.v2                           |     3 +                                       
   trunk/libs/thread/test/threads/thread/assign/move_pass.cpp  |    16 +++---                                  
   trunk/libs/thread/test/threads/thread/members/join_pass.cpp |    88 +++++++++++++-------------------------- 
   14 files changed, 258 insertions(+), 146 deletions(-)
Modified: trunk/boost/thread/detail/config.hpp
==============================================================================
--- trunk/boost/thread/detail/config.hpp	(original)
+++ trunk/boost/thread/detail/config.hpp	2012-09-01 13:10:16 EDT (Sat, 01 Sep 2012)
@@ -12,27 +12,25 @@
 #include <boost/detail/workaround.hpp>
 
 // This compiler doesn't support Boost.Chrono
-#if defined __IBMCPP__ && (__IBMCPP__ < 1100)
-#if ! defined BOOST_THREAD_DONT_USE_CHRONO
+#if defined __IBMCPP__ && (__IBMCPP__ < 1100) && ! defined BOOST_THREAD_DONT_USE_CHRONO
 #define BOOST_THREAD_DONT_USE_CHRONO
 #endif
-#endif
 
 // This compiler doesn't support Boost.Move
-#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
+#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) && ! defined BOOST_THREAD_DONT_USE_MOVE
 #define BOOST_THREAD_DONT_USE_MOVE
 #endif
 
 // This compiler doesn't support Boost.Container Allocators files
-#if defined __SUNPRO_CC
+#if defined __SUNPRO_CC && ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS
 #define BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS
 #endif
 
-#if defined _WIN32_WCE && _WIN32_WCE==0x501
+#if defined _WIN32_WCE && _WIN32_WCE==0x501 && ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS
 #define BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS
 #endif
 
-#if ! defined BOOST_THREAD_DONT_PROVIDE_BASIC_THREAD_ID
+#if ! defined BOOST_THREAD_DONT_PROVIDE_BASIC_THREAD_ID && ! defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
 #define BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
 #endif
 
@@ -46,12 +44,12 @@
 #endif
 
 // Uses Boost.System by default if not stated the opposite defining BOOST_THREAD_DONT_USE_SYSTEM
-#if ! defined BOOST_THREAD_DONT_USE_SYSTEM
+#if ! defined BOOST_THREAD_DONT_USE_SYSTEM && ! defined BOOST_THREAD_USES_SYSTEM
 #define BOOST_THREAD_USES_SYSTEM
 #endif
 
 // Uses Boost.Chrono by default if not stated the opposite  defining BOOST_THREAD_DONT_USE_CHRONO or BOOST_THREAD_DONT_USE_SYSTEM
-#if ! defined BOOST_THREAD_DONT_USE_CHRONO && ! defined BOOST_THREAD_DONT_USE_SYSTEM
+#if ! defined BOOST_THREAD_DONT_USE_CHRONO && ! defined BOOST_THREAD_DONT_USE_SYSTEM && ! defined BOOST_THREAD_USES_CHRONO
 #define BOOST_THREAD_USES_CHRONO
 #endif
 
@@ -63,15 +61,8 @@
 #endif
 
 
-// Uses Boost.Move by default if not stated the opposite defining BOOST_THREAD_DONT_USE_MOVE
-#if ! defined BOOST_THREAD_DONT_USE_MOVE
-#if ! defined BOOST_THREAD_USES_MOVE
-//#define BOOST_THREAD_USES_MOVE
-#endif
-#endif
-
 #if BOOST_THREAD_VERSION==2
-#if ! defined BOOST_THREAD_DONT_PROVIDE_PROMISE_LAZY
+#if ! defined BOOST_THREAD_DONT_PROVIDE_PROMISE_LAZY && ! defined BOOST_THREAD_PROMISE_LAZY
 #define BOOST_THREAD_PROMISE_LAZY
 #endif
 #if ! defined BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0
@@ -80,49 +71,59 @@
 #endif
 
 #if BOOST_THREAD_VERSION==3
-#if ! defined BOOST_THREAD_DONT_PROVIDE_ONCE_CXX11
+#if ! defined BOOST_THREAD_DONT_PROVIDE_ONCE_CXX11 \
+ && ! defined BOOST_THREAD_PROVIDES_ONCE_CXX11
 #define BOOST_THREAD_PROVIDES_ONCE_CXX11
 #endif
-#if ! defined BOOST_THREAD_DONT_PROVIDE_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE
+#if ! defined BOOST_THREAD_DONT_PROVIDE_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE \
+ && ! defined BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE
 #define BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE
 #endif
-#if ! defined BOOST_THREAD_DONT_PROVIDE_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE
+#if ! defined BOOST_THREAD_DONT_PROVIDE_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE \
+ && ! defined BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE
 #define BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE
 #endif
-#if ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE
+#if ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE \
+ && ! defined BOOST_THREAD_PROVIDES_FUTURE
 #define BOOST_THREAD_PROVIDES_FUTURE
 #endif
-#if ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS
+#if ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS \
+ && ! defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
 #define BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
 #endif
-#if ! defined BOOST_THREAD_DONT_PROVIDE_SHARED_MUTEX_UPWARDS_CONVERSIONS
+#if ! defined BOOST_THREAD_DONT_PROVIDE_SHARED_MUTEX_UPWARDS_CONVERSIONS \
+ && ! defined BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
 #define BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
 #endif
-#if ! defined BOOST_THREAD_DONT_PROVIDE_EXPLICIT_LOCK_CONVERSION
+#if ! defined BOOST_THREAD_DONT_PROVIDE_EXPLICIT_LOCK_CONVERSION \
+ && ! defined BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION
 #define BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION
 #endif
-#if ! defined BOOST_THREAD_DONT_PROVIDE_GENERIC_SHARED_MUTEX_ON_WIN
+#if ! defined BOOST_THREAD_DONT_PROVIDE_GENERIC_SHARED_MUTEX_ON_WIN \
+ && ! defined BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
 #define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
 #endif
-#if ! defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
+#if ! defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 \
+ && ! defined BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_
 #define BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0
 #endif
-#if ! defined BOOST_THREAD_DONT_USE_MOVE
-#if ! defined BOOST_THREAD_USES_MOVE
+#if ! defined BOOST_THREAD_DONT_USE_MOVE \
+ && ! defined BOOST_THREAD_USES_MOVE
 #define BOOST_THREAD_USES_MOVE
 #endif
-#endif
 
 #endif
 
 // BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN is defined if BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
-#if defined BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
+#if defined BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS \
+&& ! defined BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
 #define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
 #endif
 
 // BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 defined by default up to Boost 1.52
 // BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0 defined by default up to Boost 1.55
-#if ! defined BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0
+#if ! defined BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0 \
+&& ! defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
 #define BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
 #endif
 
@@ -137,7 +138,7 @@
 
 // provided for backwards compatibility, since this
 // macro was used for several releases by mistake.
-#if defined(BOOST_THREAD_DYN_DLL)
+#if defined(BOOST_THREAD_DYN_DLL) && ! defined BOOST_THREAD_DYN_LINK
 # define BOOST_THREAD_DYN_LINK
 #endif
 
Modified: trunk/boost/thread/detail/thread.hpp
==============================================================================
--- trunk/boost/thread/detail/thread.hpp	(original)
+++ trunk/boost/thread/detail/thread.hpp	2012-09-01 13:10:16 EDT (Sat, 01 Sep 2012)
@@ -23,6 +23,8 @@
 #include <boost/bind.hpp>
 #include <stdlib.h>
 #include <memory>
+//#include <vector>
+//#include <utility>
 #include <boost/utility/enable_if.hpp>
 #include <boost/type_traits/remove_reference.hpp>
 #include <boost/io/ios_state.hpp>
@@ -69,10 +71,13 @@
                 f(f_)
             {}
 #endif
+            //thread_data() {}
+
             void run()
             {
                 f();
             }
+
         private:
             F f;
         };
@@ -406,7 +411,7 @@
             return timed_join(get_system_time()+rel_time);
         }
 
-        void detach() BOOST_NOEXCEPT;
+        void detach();
 
         static unsigned hardware_concurrency() BOOST_NOEXCEPT;
 
Modified: trunk/boost/thread/pthread/condition_variable_fwd.hpp
==============================================================================
--- trunk/boost/thread/pthread/condition_variable_fwd.hpp	(original)
+++ trunk/boost/thread/pthread/condition_variable_fwd.hpp	2012-09-01 13:10:16 EDT (Sat, 01 Sep 2012)
@@ -229,8 +229,11 @@
             unique_lock<mutex>& lock,
             struct timespec const &timeout);
     };
+
+    BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
 }
 
+
 #include <boost/config/abi_suffix.hpp>
 
 #endif
Modified: trunk/boost/thread/pthread/thread_data.hpp
==============================================================================
--- trunk/boost/thread/pthread/thread_data.hpp	(original)
+++ trunk/boost/thread/pthread/thread_data.hpp	2012-09-01 13:10:16 EDT (Sat, 01 Sep 2012)
@@ -8,18 +8,25 @@
 
 #include <boost/thread/detail/config.hpp>
 #include <boost/thread/exceptions.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/pthread/condition_variable_fwd.hpp>
+
 #include <boost/shared_ptr.hpp>
 #include <boost/enable_shared_from_this.hpp>
-#include <boost/thread/mutex.hpp>
 #include <boost/optional.hpp>
-#include <pthread.h>
 #include <boost/assert.hpp>
-#include <boost/thread/pthread/condition_variable_fwd.hpp>
-#include <map>
-#include <unistd.h>
 #ifdef BOOST_THREAD_USES_CHRONO
 #include <boost/chrono/system_clocks.hpp>
 #endif
+
+#include <map>
+#include <vector>
+#include <utility>
+
+#include <pthread.h>
+#include <unistd.h>
+
 #include <boost/config/abi_prefix.hpp>
 
 namespace boost
@@ -104,19 +111,28 @@
             bool interrupt_requested;
             pthread_mutex_t* cond_mutex;
             pthread_cond_t* current_cond;
+            typedef std::vector<std::pair<condition_variable*, mutex*>
+            //, hidden_allocator<std::pair<condition_variable*, mutex*> >
+            > notify_list_t;
+            notify_list_t notify;
 
             thread_data_base():
                 done(false),join_started(false),joined(false),
                 thread_exit_callbacks(0),
                 interrupt_enabled(true),
                 interrupt_requested(false),
-                current_cond(0)
+                current_cond(0),
+                notify()
             {}
             virtual ~thread_data_base();
 
             typedef pthread_t native_handle_type;
 
             virtual void run()=0;
+            void notify_all_at_thread_exit(condition_variable* cv, mutex* m)
+            {
+              notify.push_back(std::pair<condition_variable*, mutex*>(cv, m));
+            }
         };
 
         BOOST_THREAD_DECL thread_data_base* get_current_thread_data();
Modified: trunk/boost/thread/win32/condition_variable.hpp
==============================================================================
--- trunk/boost/thread/win32/condition_variable.hpp	(original)
+++ trunk/boost/thread/win32/condition_variable.hpp	2012-09-01 13:10:16 EDT (Sat, 01 Sep 2012)
@@ -6,23 +6,27 @@
 // (C) Copyright 2007-8 Anthony Williams
 // (C) Copyright 2011-2012 Vicente J. Botet Escriba
 
-#include <boost/thread/mutex.hpp>
 #include <boost/thread/win32/thread_primitives.hpp>
-#include <limits.h>
-#include <boost/assert.hpp>
-#include <algorithm>
-#include <boost/thread/cv_status.hpp>
 #include <boost/thread/win32/thread_data.hpp>
-#include <boost/thread/thread_time.hpp>
+#include <boost/thread/win32/thread_data.hpp>
 #include <boost/thread/win32/interlocked_read.hpp>
+#include <boost/thread/cv_status.hpp>
 #include <boost/thread/xtime.hpp>
-#include <vector>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/thread_time.hpp>
+
+#include <boost/assert.hpp>
 #include <boost/intrusive_ptr.hpp>
+
 #ifdef BOOST_THREAD_USES_CHRONO
 #include <boost/chrono/system_clocks.hpp>
 #include <boost/chrono/ceil.hpp>
 #endif
 
+#include <limits.h>
+#include <algorithm>
+#include <vector>
+
 #include <boost/config/abi_prefix.hpp>
 
 namespace boost
@@ -510,6 +514,7 @@
 #endif
     };
 
+        BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
 }
 
 #include <boost/config/abi_suffix.hpp>
Modified: trunk/boost/thread/win32/thread_data.hpp
==============================================================================
--- trunk/boost/thread/win32/thread_data.hpp	(original)
+++ trunk/boost/thread/win32/thread_data.hpp	2012-09-01 13:10:16 EDT (Sat, 01 Sep 2012)
@@ -7,18 +7,26 @@
 // (C) Copyright 2011-2012 Vicente J. Botet Escriba
 
 #include <boost/thread/detail/config.hpp>
-#include <boost/intrusive_ptr.hpp>
 #include <boost/thread/thread_time.hpp>
 #include <boost/thread/win32/thread_primitives.hpp>
 #include <boost/thread/win32/thread_heap_alloc.hpp>
-#include <map>
+
+#include <boost/intrusive_ptr.hpp>
 #ifdef BOOST_THREAD_USES_CHRONO
 #include <boost/chrono/system_clocks.hpp>
 #endif
+
+#include <map>
+#include <vector>
+#include <utility>
+
 #include <boost/config/abi_prefix.hpp>
 
 namespace boost
 {
+  class condition_variable;
+  class mutex;
+
   class thread_attributes {
   public:
       thread_attributes() BOOST_NOEXCEPT {
@@ -76,7 +84,7 @@
         void intrusive_ptr_add_ref(thread_data_base * p);
         void intrusive_ptr_release(thread_data_base * p);
 
-        struct BOOST_SYMBOL_VISIBLE thread_data_base
+        struct BOOST_THREAD_DECL thread_data_base
         {
             long count;
             detail::win32::handle_manager thread_handle;
@@ -85,16 +93,21 @@
             std::map<void const*,boost::detail::tss_data_node> tss_data;
             bool interruption_enabled;
             unsigned id;
+            typedef std::vector<std::pair<condition_variable*, mutex*>
+            //, hidden_allocator<std::pair<condition_variable*, mutex*> >
+            > notify_list_t;
+            notify_list_t notify;
+
 
             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),tss_data(),
                 interruption_enabled(true),
-                id(0)
-            {}
-            virtual ~thread_data_base()
+                id(0),
+                notify()
             {}
+            virtual ~thread_data_base();
 
             friend void intrusive_ptr_add_ref(thread_data_base * p)
             {
@@ -117,6 +130,12 @@
             typedef detail::win32::handle native_handle_type;
 
             virtual void run()=0;
+
+            void notify_all_at_thread_exit(condition_variable* cv, mutex* m)
+            {
+              notify.push_back(std::pair<condition_variable*, mutex*>(cv, m));
+            }
+
         };
 
         typedef boost::intrusive_ptr<detail::thread_data_base> thread_data_ptr;
Modified: trunk/libs/thread/build/Jamfile.v2
==============================================================================
--- trunk/libs/thread/build/Jamfile.v2	(original)
+++ trunk/libs/thread/build/Jamfile.v2	2012-09-01 13:10:16 EDT (Sat, 01 Sep 2012)
@@ -47,6 +47,7 @@
       -<tag>@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag
       <tag>@$(__name__).tag
       <toolset>gcc:<cxxflags>-Wno-long-long
+      <define>BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
       <define>BOOST_SYSTEM_NO_DEPRECATED
       <library>/boost/system//boost_system
        #-pedantic -ansi -std=gnu++0x -Wextra -fpermissive
@@ -98,6 +99,7 @@
       #<link>shared:<define>BOOST_THREAD_DYN_LINK=1
       <link>static:<define>BOOST_THREAD_BUILD_LIB=1
       <link>shared:<define>BOOST_THREAD_BUILD_DLL=1
+      <define>BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
       <define>BOOST_SYSTEM_NO_DEPRECATED
       <library>/boost/system//boost_system
     ;
Modified: trunk/libs/thread/doc/thread_ref.qbk
==============================================================================
--- trunk/libs/thread/doc/thread_ref.qbk	(original)
+++ trunk/libs/thread/doc/thread_ref.qbk	2012-09-01 13:10:16 EDT (Sat, 01 Sep 2012)
@@ -391,7 +391,7 @@
         void swap(thread& x) noexcept;
 
         class id;
-        class attributes;
+        class attributes; // EXTENSION
 
         id get_id() const noexcept;
 
@@ -471,7 +471,7 @@
 
 [[Effects:] [Transfers ownership of the thread managed by `other` (if
 any) to `*this`. Version 2: If there was a thread previously associated with
-`*this` then that thread is detached, version 3: If the thread is joinable calls to std::terminate.]]
+`*this` then that thread is detached, Version 3: If the thread is joinable calls to std::terminate.]]
 
 [[Postconditions:] [`other->get_id()==thread::id()` and `get_id()` returns the value of `other.get_id()` prior to the assignment.]]
 
@@ -628,7 +628,7 @@
 
 [variablelist
 
-[[Effects:] [Version 1: If `*this` has an associated thread of execution, calls __detach__, Version 2: If the thread is joinable calls to std::terminate. Destroys `*this`.]]
+[[Effects:] [Version 2: If `*this` has an associated thread of execution, calls __detach__, Version 3: If the thread is joinable calls to std::terminate. Destroys `*this`.]]
 
 [[Throws:] [Nothing.]]
 
@@ -688,10 +688,12 @@
 
 [*resource_deadlock_would_occur]: if deadlock is detected or this->get_id() == std::this_thread::get_id().
 
+[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_TRROW_IF_PRECONDITION_NOT_SATISFIED is defined.
+
+
 [/
 [*no_such_process]: if the thread is not valid.
 
-[*invalid_argument]: if the thread is not joinable.
 ] 
 
 ]]
@@ -711,7 +713,7 @@
 
 [variablelist
 
-[[Preconditions:] [`this->get_id()!=boost::this_thread::get_id()`]]
+[[Preconditions:] [the thread is joinable.]]
 
 [[Effects:] [If `*this` refers to a thread of execution, waits for that thread of execution to complete, the time `wait_until` has
 been reach or the specified duration `rel_time` has elapsed. If `*this` doesn't refer to a thread of execution, returns immediately.]]
@@ -729,10 +731,11 @@
 
 [*resource_deadlock_would_occur]: if deadlock is detected or this->get_id() == std::this_thread::get_id().
 
+[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_TRROW_IF_PRECONDITION_NOT_SATISFIED is defined.
+
+
 [/
 [*no_such_process]: if the thread is not valid.
-
-[*invalid_argument]: if the thread is not joinable.
 ] 
 
 ]]
@@ -750,7 +753,7 @@
 
 [variablelist
 
-[[Preconditions:] [`this->get_id()!=boost::this_thread::get_id()`]]
+[[Preconditions:] [the thread is joinable.]]
 
 [[Effects:] [If `*this` refers to a thread of execution, waits for that thread of execution to complete, 
 the specified duration `rel_time` has elapsed. If `*this` doesn't refer to a thread of execution, returns immediately.]]
@@ -768,10 +771,11 @@
 
 [*resource_deadlock_would_occur]: if deadlock is detected or this->get_id() == std::this_thread::get_id().
 
+[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_TRROW_IF_PRECONDITION_NOT_SATISFIED is defined.
+
+
 [/
 [*no_such_process]: if the thread is not valid.
-
-[*invalid_argument]: if the thread is not joinable.
 ] 
 
 ]]
@@ -789,7 +793,7 @@
 
 [variablelist
 
-[[Preconditions:] [`this->get_id()!=boost::this_thread::get_id()`]]
+[[Preconditions:] [the thread is joinable.]]
 
 [[Effects:] [If `*this` refers to a thread of execution, waits for that thread of execution to complete, the time `abs_time` has
 been reach. If `*this` doesn't refer to a thread of execution, returns immediately.]]
@@ -807,10 +811,12 @@
 
 [*resource_deadlock_would_occur]: if deadlock is detected or this->get_id() == std::this_thread::get_id().
 
+[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_TRROW_IF_PRECONDITION_NOT_SATISFIED is defined.
+
+
 [/
 [*no_such_process]: if the thread is not valid.
 
-[*invalid_argument]: if the thread is not joinable.
 ] 
 
 ]]
@@ -825,7 +831,7 @@
 
 [section:detach Member function `detach()`]
 
-    void detach() noexcept;
+    void detach();
 
 [variablelist
 
@@ -835,7 +841,15 @@
 
 [[Postconditions:] [`*this` no longer refers to any thread of execution.]]
 
-[[Throws:] [Nothing]]
+[[Throws:] [`system_error`]]
+
+[[Error Conditions:] [
+
+[*no_such_process]: if the thread is not valid.
+
+[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_TRROW_IF_PRECONDITION_NOT_SATISFIED is defined.
+
+]]
 
 ]
 
Modified: trunk/libs/thread/src/pthread/thread.cpp
==============================================================================
--- trunk/libs/thread/src/pthread/thread.cpp	(original)
+++ trunk/libs/thread/src/pthread/thread.cpp	2012-09-01 13:10:16 EDT (Sat, 01 Sep 2012)
@@ -10,11 +10,12 @@
 
 #include <boost/thread/thread.hpp>
 #include <boost/thread/xtime.hpp>
-#include <boost/thread/condition.hpp>
+#include <boost/thread/condition_variable.hpp>
 #include <boost/thread/locks.hpp>
 #include <boost/thread/once.hpp>
 #include <boost/thread/tss.hpp>
 #include <boost/throw_exception.hpp>
+
 #ifdef __GLIBC__
 #include <sys/sysinfo.h>
 #elif defined(__APPLE__) || defined(__FreeBSD__)
@@ -31,7 +32,16 @@
     namespace detail
     {
         thread_data_base::~thread_data_base()
-        {}
+        {
+          {
+            for (notify_list_t::iterator i = notify.begin(), e = notify.end();
+                    i != e; ++i)
+            {
+                i->second->unlock();
+                i->first->notify_all();
+            }
+          }
+        }
 
         struct thread_exit_callback_node
         {
@@ -175,6 +185,8 @@
 
             void run()
             {}
+            void notify_all_at_thread_exit(condition_variable*, mutex*)
+            {}
 
         private:
             externally_launched_thread(externally_launched_thread&);
@@ -304,6 +316,12 @@
                 thread_info.reset();
             }
         }
+        else
+        {
+#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
+          boost::throw_exception(thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable"));
+#endif
+        }
     }
 
     bool thread::do_try_join_until(struct timespec const &timeout)
@@ -353,8 +371,14 @@
             {
                 thread_info.reset();
             }
+            return true;
+        }
+        else
+        {
+#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
+          boost::throw_exception(thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable"));
+#endif
         }
-        return true;
     }
 
     bool thread::joinable() const BOOST_NOEXCEPT
@@ -363,7 +387,7 @@
     }
 
 
-    void thread::detach() BOOST_NOEXCEPT
+    void thread::detach()
     {
         detail::thread_data_ptr local_thread_info;
         thread_info.swap(local_thread_info);
@@ -677,6 +701,15 @@
             }
         }
     }
+    BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk)
+    {
+      detail::thread_data_base* const current_thread_data(detail::get_current_thread_data());
+      if(current_thread_data)
+      {
+        current_thread_data->notify_all_at_thread_exit(&cond, lk.release());
+      }
+    }
+
 
 
 }
Modified: trunk/libs/thread/src/win32/thread.cpp
==============================================================================
--- trunk/libs/thread/src/win32/thread.cpp	(original)
+++ trunk/libs/thread/src/win32/thread.cpp	2012-09-01 13:10:16 EDT (Sat, 01 Sep 2012)
@@ -13,22 +13,39 @@
 #endif
 
 #include <boost/thread/thread.hpp>
-#include <algorithm>
-#ifndef UNDER_CE
-#include <process.h>
-#endif
-#include <stdio.h>
 #include <boost/thread/once.hpp>
 #include <boost/thread/tss.hpp>
+#include <boost/thread/condition_variable.hpp>
+#include <boost/thread/detail/tss_hooks.hpp>
+
 #include <boost/assert.hpp>
 #include <boost/throw_exception.hpp>
-#include <boost/thread/detail/tss_hooks.hpp>
 #include <boost/date_time/posix_time/conversion.hpp>
-#include <windows.h>
+
 #include <memory>
+#include <algorithm>
+#ifndef UNDER_CE
+#include <process.h>
+#endif
+#include <stdio.h>
+#include <windows.h>
 
 namespace boost
 {
+  namespace detail
+  {
+    thread_data_base::~thread_data_base()
+    {
+      {
+        for (notify_list_t::iterator i = notify.begin(), e = notify.end();
+                i != e; ++i)
+        {
+            i->second->unlock();
+            i->first->notify_all();
+        }
+      }
+    }
+  }
     namespace
     {
 #ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
@@ -240,6 +257,9 @@
 
             void run()
             {}
+            void notify_all_at_thread_exit(condition_variable*, mutex*)
+            {}
+
         private:
             externally_launched_thread(externally_launched_thread&);
             void operator=(externally_launched_thread&);
@@ -303,6 +323,12 @@
             this_thread::interruptible_wait(local_thread_info->thread_handle,detail::timeout::sentinel());
             release_handle();
         }
+        else
+        {
+#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
+          boost::throw_exception(thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable"));
+#endif
+        }
     }
 
     bool thread::timed_join(boost::system_time const& wait_until)
@@ -324,11 +350,17 @@
               return false;
           }
           release_handle();
+          return true;
+      }
+      else
+      {
+#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
+        boost::throw_exception(thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable"));
+#endif
       }
-      return true;
     }
 
-    void thread::detach() BOOST_NOEXCEPT
+    void thread::detach()
     {
         release_handle();
     }
@@ -682,6 +714,14 @@
         boost::run_thread_exit_callbacks();
     }
 
+    BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk)
+    {
+      detail::thread_data_base* const current_thread_data(get_current_thread_data());
+      if(current_thread_data)
+      {
+        current_thread_data->notify_all_at_thread_exit(&cond, lk.release());
+      }
+    }
 }
 
 
Modified: trunk/libs/thread/src/win32/tss_dll.cpp
==============================================================================
--- trunk/libs/thread/src/win32/tss_dll.cpp	(original)
+++ trunk/libs/thread/src/win32/tss_dll.cpp	2012-09-01 13:10:16 EDT (Sat, 01 Sep 2012)
@@ -5,6 +5,7 @@
 
 #include <boost/thread/detail/config.hpp>
 
+
 #if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_DLL)
 
     #include <boost/thread/detail/tss_hooks.hpp>
Modified: trunk/libs/thread/test/Jamfile.v2
==============================================================================
--- trunk/libs/thread/test/Jamfile.v2	(original)
+++ trunk/libs/thread/test/Jamfile.v2	2012-09-01 13:10:16 EDT (Sat, 01 Sep 2012)
@@ -225,6 +225,7 @@
           [ thread-run2 ./sync/conditions/condition_variable_any/wait_until_pass.cpp : condition_variable_any__wait_until_p ]
           [ thread-run2 ./sync/conditions/condition_variable_any/wait_until_pred_pass.cpp : condition_variable_any__wait_until_pred_p ]
           [ thread-run2 ./sync/conditions/cv_status/cv_status_pass.cpp : cv_status__cv_status_p ]
+          [ thread-run2 ./sync/conditions/notify_all_at_thread_exit_pass.cpp : notify_all_at_thread_exit_p ]
     ;
 
     explicit ts_async ;
@@ -469,6 +470,8 @@
           [ thread-run2 ./threads/thread/members/detach_pass.cpp : thread__detach_p ]
           [ thread-run2 ./threads/thread/members/get_id_pass.cpp : thread__get_id_p ]
           [ thread-run2 ./threads/thread/members/join_pass.cpp : thread__join_p ]
+          [ thread-run2 ./threads/thread/members/try_join_until_pass.cpp : thread__join_until_p ]
+          [ thread-run2 ./threads/thread/members/try_join_for_pass.cpp : thread__join_for_p ]
           [ thread-run2 ./threads/thread/members/joinable_pass.cpp : thread__joinable_p ]
           [ thread-run2 ./threads/thread/members/native_handle_pass.cpp : thread__native_handle_p ]
           [ thread-run2 ./threads/thread/members/swap_pass.cpp : thread__swap_p ]
Added: trunk/libs/thread/test/sync/conditions/notify_all_at_thread_exit_pass.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/thread/test/sync/conditions/notify_all_at_thread_exit_pass.cpp	2012-09-01 13:10:16 EDT (Sat, 01 Sep 2012)
@@ -0,0 +1,51 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Copyright (C) 2011 Vicente J. Botet Escriba
+//
+//  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)
+
+// <boost/thread/condition_variable.hpp>
+
+// void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
+
+#define BOOST_THREAD_USES_MOVE
+#define BOOST_THREAD_VESRION 3
+
+#include <boost/thread/condition_variable.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/chrono/chrono.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+boost::condition_variable cv;
+boost::mutex mut;
+
+typedef boost::chrono::milliseconds ms;
+typedef boost::chrono::high_resolution_clock Clock;
+
+void func()
+{
+  boost::unique_lock < boost::mutex > lk(mut);
+  boost::notify_all_at_thread_exit(cv, boost::move(lk));
+  boost::this_thread::sleep_for(ms(300));
+}
+
+int main()
+{
+  boost::unique_lock < boost::mutex > lk(mut);
+  boost::thread(func).detach();
+  Clock::time_point t0 = Clock::now();
+  cv.wait(lk);
+  Clock::time_point t1 = Clock::now();
+  BOOST_TEST(t1 - t0 > ms(250));
+  return boost::report_errors();
+}
+
Modified: trunk/libs/thread/test/threads/thread/assign/move_pass.cpp
==============================================================================
--- trunk/libs/thread/test/threads/thread/assign/move_pass.cpp	(original)
+++ trunk/libs/thread/test/threads/thread/assign/move_pass.cpp	2012-09-01 13:10:16 EDT (Sat, 01 Sep 2012)
@@ -89,14 +89,14 @@
     t1.join();
     BOOST_TEST(G::op_run);
   }
-//  BOOST_TEST(G::n_alive == 0);
-//  {
-//    boost::thread t0(G(), 5, 5.5);
-//    boost::thread::id id = t0.get_id();
-//    boost::thread t1;
-//    t0 = boost::move(t1);
-//    BOOST_TEST(false);
-//  }
+  BOOST_TEST(G::n_alive == 0);
+  {
+    boost::thread t0(G(), 5, 5.5);
+    boost::thread::id id = t0.get_id();
+    boost::thread t1;
+    t0 = boost::move(t1);
+    BOOST_TEST(false);
+  }
   return boost::report_errors();
 }
 
Modified: trunk/libs/thread/test/threads/thread/members/join_pass.cpp
==============================================================================
--- trunk/libs/thread/test/threads/thread/members/join_pass.cpp	(original)
+++ trunk/libs/thread/test/threads/thread/members/join_pass.cpp	2012-09-01 13:10:16 EDT (Sat, 01 Sep 2012)
@@ -16,7 +16,6 @@
 // class thread
 
 // void join();
-
 #define BOOST_THREAD_VESRION 3
 #include <boost/thread/thread.hpp>
 #include <boost/thread/mutex.hpp>
@@ -53,7 +52,7 @@
   void operator()()
   {
     BOOST_TEST(alive_ == 1);
-    BOOST_TEST(n_alive == 1);
+    //BOOST_TEST(n_alive == 1);
     op_run = true;
   }
 };
@@ -68,8 +67,6 @@
   try
   {
     boost::unique_lock<boost::mutex> lk(resource_deadlock_would_occur_mtx);
-
-
     resource_deadlock_would_occur_th->join();
     BOOST_TEST(false);
   }
@@ -83,28 +80,6 @@
   }
 }
 
-void throws_thread_resource_error_tester()
-{
-  {
-    try {
-      boost::throw_exception(
-          boost::thread_resource_error(
-              boost::system::errc::resource_deadlock_would_occur,
-              "boost thread: trying joining itself"
-              ));
-      BOOST_TEST(false);
-    }
-    catch (boost::system::system_error& e)
-    {
-      BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur);
-    }
-    catch (...)
-    {
-      BOOST_TEST(false&&"exception thrown");
-    }
-  }
-}
-
 int main()
 {
   {
@@ -115,10 +90,6 @@
   }
 
   {
-    boost::thread t0( throws_thread_resource_error_tester );
-    t0.join();
-  }
-  {
     boost::unique_lock<boost::mutex> lk(resource_deadlock_would_occur_mtx);
     boost::thread t0( resource_deadlock_would_occur_tester );
     resource_deadlock_would_occur_th = &t0;
@@ -130,35 +101,34 @@
     BOOST_TEST(!t0.joinable());
   }
 
-//  {
-//    boost::thread t0( (G()));
-//    t0.detach();
-//    try
-//    {
-//      t0.join();
-//      BOOST_TEST(false);
-//    }
-//    catch (boost::system::system_error& e)
-//    {
-//      BOOST_TEST(e.code().value() == boost::system::errc::no_such_process);
-//    }
-//  }
-//  {
-//    boost::thread t0( (G()));
-//    BOOST_TEST(t0.joinable());
-//    t0.join();
-//    BOOST_TEST(!t0.joinable());
-//    try
-//    {
-//      t0.join();
-//      BOOST_TEST(false);
-//    }
-//    catch (boost::system::system_error& e)
-//    {
-//      BOOST_TEST(e.code().value() == boost::system::errc::invalid_argument);
-//    }
-//
-//  }
+  {
+    boost::thread t0( (G()));
+    t0.detach();
+    try
+    {
+      t0.join();
+      BOOST_TEST(false);
+    }
+    catch (boost::system::system_error& e)
+    {
+      BOOST_TEST(e.code().value() == boost::system::errc::invalid_argument);
+    }
+  }
+  {
+    boost::thread t0( (G()));
+    BOOST_TEST(t0.joinable());
+    t0.join();
+    try
+    {
+      t0.join();
+      BOOST_TEST(false);
+    }
+    catch (boost::system::system_error& e)
+    {
+      BOOST_TEST(e.code().value() == boost::system::errc::invalid_argument);
+    }
+
+  }
 
   return boost::report_errors();
 }
Added: trunk/libs/thread/test/threads/thread/members/try_join_for_pass.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/thread/test/threads/thread/members/try_join_for_pass.cpp	2012-09-01 13:10:16 EDT (Sat, 01 Sep 2012)
@@ -0,0 +1,161 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Copyright (C) 2011 Vicente J. Botet Escriba
+//
+//  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)
+
+// <boost/thread/thread.hpp>
+
+// class thread
+
+//        template <class Rep, class Period>
+//        bool try_join_for(const chrono::duration<Rep, Period>& rel_time);
+
+#define BOOST_THREAD_VESRION 3
+#include <boost/thread/thread.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/locks.hpp>
+#include <new>
+#include <cstdlib>
+#include <cassert>
+#include <iostream>
+#include <boost/detail/lightweight_test.hpp>
+
+#if defined BOOST_THREAD_USES_CHRONO
+
+class G
+{
+  int alive_;
+public:
+  static bool op_run;
+
+  G() :
+    alive_(1)
+  {
+  }
+  G(const G& g) :
+    alive_(g.alive_)
+  {
+  }
+  ~G()
+  {
+    alive_ = 0;
+  }
+
+  void operator()()
+  {
+    BOOST_TEST(alive_ == 1);
+    op_run = true;
+  }
+};
+
+bool G::op_run = false;
+
+boost::thread* resource_deadlock_would_occur_th=0;
+boost::mutex resource_deadlock_would_occur_mtx;
+void resource_deadlock_would_occur_tester()
+{
+  try
+  {
+    boost::unique_lock<boost::mutex> lk(resource_deadlock_would_occur_mtx);
+    resource_deadlock_would_occur_th->try_join_for(boost::chrono::milliseconds(50));
+    BOOST_TEST(false);
+  }
+  catch (boost::system::system_error& e)
+  {
+    BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur);
+  }
+  catch (...)
+  {
+    BOOST_TEST(false&&"exception thrown");
+  }
+}
+
+void th_100_ms()
+{
+  boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
+}
+
+int main()
+{
+  {
+    boost::thread t0( (G()));
+    BOOST_TEST(t0.joinable());
+    BOOST_TEST(t0.try_join_for(boost::chrono::milliseconds(50)));
+    BOOST_TEST(!t0.joinable());
+  }
+  {
+    boost::thread t0( (th_100_ms));
+    BOOST_TEST(!t0.try_join_for(boost::chrono::milliseconds(50)));
+    t0.join();
+  }
+
+  {
+    boost::unique_lock<boost::mutex> lk(resource_deadlock_would_occur_mtx);
+    boost::thread t0( resource_deadlock_would_occur_tester );
+    resource_deadlock_would_occur_th = &t0;
+    BOOST_TEST(t0.joinable());
+    lk.unlock();
+    boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
+    boost::unique_lock<boost::mutex> lk2(resource_deadlock_would_occur_mtx);
+    t0.join();
+    BOOST_TEST(!t0.joinable());
+  }
+
+  {
+    boost::thread t0( (G()));
+    t0.detach();
+    try
+    {
+      t0.try_join_for(boost::chrono::milliseconds(50));
+      BOOST_TEST(false);
+    }
+    catch (boost::system::system_error& e)
+    {
+      BOOST_TEST(e.code().value() == boost::system::errc::invalid_argument);
+    }
+  }
+  {
+    boost::thread t0( (G()));
+    BOOST_TEST(t0.joinable());
+    t0.join();
+    try
+    {
+      t0.try_join_for(boost::chrono::milliseconds(50));
+      BOOST_TEST(false);
+    }
+    catch (boost::system::system_error& e)
+    {
+      BOOST_TEST(e.code().value() == boost::system::errc::invalid_argument);
+    }
+
+  }
+  {
+    boost::thread t0( (G()));
+    BOOST_TEST(t0.joinable());
+    t0.try_join_for(boost::chrono::milliseconds(50));
+    try
+    {
+      t0.join();
+      BOOST_TEST(false);
+    }
+    catch (boost::system::system_error& e)
+    {
+      BOOST_TEST(e.code().value() == boost::system::errc::invalid_argument);
+    }
+
+  }
+
+  return boost::report_errors();
+}
+
+#else
+#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported"
+#endif
Added: trunk/libs/thread/test/threads/thread/members/try_join_until_pass.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/thread/test/threads/thread/members/try_join_until_pass.cpp	2012-09-01 13:10:16 EDT (Sat, 01 Sep 2012)
@@ -0,0 +1,162 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Copyright (C) 2011 Vicente J. Botet Escriba
+//
+//  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)
+
+// <boost/thread/thread.hpp>
+
+// class thread
+
+//        template <class Clock, class Duration>
+//        bool try_join_until(const chrono::time_point<Clock, Duration>& t);
+
+#define BOOST_THREAD_VESRION 3
+#include <boost/thread/thread.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/locks.hpp>
+#include <new>
+#include <cstdlib>
+#include <cassert>
+#include <iostream>
+#include <boost/detail/lightweight_test.hpp>
+
+#if defined BOOST_THREAD_USES_CHRONO
+
+class G
+{
+  int alive_;
+public:
+  static bool op_run;
+
+  G() :
+    alive_(1)
+  {
+  }
+  G(const G& g) :
+    alive_(g.alive_)
+  {
+  }
+  ~G()
+  {
+    alive_ = 0;
+  }
+
+  void operator()()
+  {
+    BOOST_TEST(alive_ == 1);
+    op_run = true;
+  }
+};
+
+bool G::op_run = false;
+
+boost::thread* resource_deadlock_would_occur_th=0;
+boost::mutex resource_deadlock_would_occur_mtx;
+void resource_deadlock_would_occur_tester()
+{
+  try
+  {
+    boost::unique_lock<boost::mutex> lk(resource_deadlock_would_occur_mtx);
+    resource_deadlock_would_occur_th->try_join_until(boost::chrono::steady_clock::now()+boost::chrono::milliseconds(50));
+    BOOST_TEST(false);
+  }
+  catch (boost::system::system_error& e)
+  {
+    BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur);
+  }
+  catch (...)
+  {
+    BOOST_TEST(false&&"exception thrown");
+  }
+}
+
+void th_100_ms()
+{
+  boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
+}
+
+
+int main()
+{
+  {
+    boost::thread t0( (G()));
+    BOOST_TEST(t0.joinable());
+    t0.try_join_until(boost::chrono::steady_clock::now()+boost::chrono::milliseconds(50));
+    BOOST_TEST(!t0.joinable());
+  }
+  {
+    boost::thread t0( (th_100_ms));
+    BOOST_TEST(!t0.try_join_until(boost::chrono::steady_clock::now()+boost::chrono::milliseconds(50)));
+    t0.join();
+  }
+
+  {
+    boost::unique_lock<boost::mutex> lk(resource_deadlock_would_occur_mtx);
+    boost::thread t0( resource_deadlock_would_occur_tester );
+    resource_deadlock_would_occur_th = &t0;
+    BOOST_TEST(t0.joinable());
+    lk.unlock();
+    boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
+    boost::unique_lock<boost::mutex> lk2(resource_deadlock_would_occur_mtx);
+    t0.join();
+    BOOST_TEST(!t0.joinable());
+  }
+
+  {
+    boost::thread t0( (G()));
+    t0.detach();
+    try
+    {
+      t0.try_join_until(boost::chrono::steady_clock::now()+boost::chrono::milliseconds(50));
+      BOOST_TEST(false);
+    }
+    catch (boost::system::system_error& e)
+    {
+      BOOST_TEST(e.code().value() == boost::system::errc::invalid_argument);
+    }
+  }
+  {
+    boost::thread t0( (G()));
+    BOOST_TEST(t0.joinable());
+    t0.join();
+    try
+    {
+      t0.try_join_until(boost::chrono::steady_clock::now()+boost::chrono::milliseconds(50));
+      BOOST_TEST(false);
+    }
+    catch (boost::system::system_error& e)
+    {
+      BOOST_TEST(e.code().value() == boost::system::errc::invalid_argument);
+    }
+
+  }
+  {
+    boost::thread t0( (G()));
+    BOOST_TEST(t0.joinable());
+    t0.try_join_until(boost::chrono::steady_clock::now()+boost::chrono::milliseconds(50));
+    try
+    {
+      t0.join();
+      BOOST_TEST(false);
+    }
+    catch (boost::system::system_error& e)
+    {
+      BOOST_TEST(e.code().value() == boost::system::errc::invalid_argument);
+    }
+
+  }
+
+  return boost::report_errors();
+}
+
+#else
+#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported"
+#endif