Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r81172 - in trunk: boost/thread boost/thread/detail boost/thread/pthread boost/thread/win32 libs/thread/src/pthread libs/thread/src/win32 libs/thread/test libs/thread/test/sync/futures/promise
From: vicente.botet_at_[hidden]
Date: 2012-11-04 11:47:04


Author: viboes
Date: 2012-11-04 11:47:02 EST (Sun, 04 Nov 2012)
New Revision: 81172
URL: http://svn.boost.org/trac/boost/changeset/81172

Log:
Thread: Added promise::set_..._at_thread_exit
Added:
   trunk/libs/thread/test/sync/futures/promise/set_exception_at_thread_exit_pass.cpp (contents, props changed)
   trunk/libs/thread/test/sync/futures/promise/set_lvalue_at_thread_exit_pass.cpp (contents, props changed)
   trunk/libs/thread/test/sync/futures/promise/set_rvalue_at_thread_exit_pass.cpp (contents, props changed)
   trunk/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_const_pass.cpp (contents, props changed)
   trunk/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_void_pass.cpp (contents, props changed)
Text files modified:
   trunk/boost/thread/detail/config.hpp | 4
   trunk/boost/thread/future.hpp | 434 ++++++++++++++++++++++++++++++++++++++-
   trunk/boost/thread/lockable_traits.hpp | 208 ++++++++++--------
   trunk/boost/thread/pthread/thread_data.hpp | 15 +
   trunk/boost/thread/win32/thread_data.hpp | 12 +
   trunk/libs/thread/src/pthread/thread.cpp | 40 +++
   trunk/libs/thread/src/win32/thread.cpp | 64 +++--
   trunk/libs/thread/test/Jamfile.v2 | 6
   trunk/libs/thread/test/test_4882.cpp | 17 +
   9 files changed, 656 insertions(+), 144 deletions(-)

Modified: trunk/boost/thread/detail/config.hpp
==============================================================================
--- trunk/boost/thread/detail/config.hpp (original)
+++ trunk/boost/thread/detail/config.hpp 2012-11-04 11:47:02 EST (Sun, 04 Nov 2012)
@@ -73,8 +73,8 @@
 
 // PROVIDE_PROMISE_LAZY
 #if ! defined BOOST_THREAD_DONT_PROVIDE_PROMISE_LAZY \
- && ! defined BOOST_THREAD_PROMISE_LAZY
-#define BOOST_THREAD_PROMISE_LAZY
+ && ! defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
+#define BOOST_THREAD_PROVIDES_PROMISE_LAZY
 #endif
 
 // PROVIDE_THREAD_EQ

Modified: trunk/boost/thread/future.hpp
==============================================================================
--- trunk/boost/thread/future.hpp (original)
+++ trunk/boost/thread/future.hpp 2012-11-04 11:47:02 EST (Sun, 04 Nov 2012)
@@ -39,6 +39,7 @@
 #include <boost/bind.hpp>
 #include <boost/ref.hpp>
 #include <boost/scoped_array.hpp>
+#include <boost/enable_shared_from_this.hpp>
 #include <boost/utility/enable_if.hpp>
 #include <list>
 #include <boost/next_prior.hpp>
@@ -257,11 +258,13 @@
             relocker& operator=(relocker const&);
         };
 
- struct future_object_base
+ struct future_object_base : enable_shared_from_this<future_object_base>
         {
+
             boost::exception_ptr exception;
             bool done;
             bool is_deferred;
+ bool is_constructed;
 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
             bool thread_was_interrupted;
 #endif
@@ -276,7 +279,8 @@
 
             future_object_base():
                 done(false),
- is_deferred(false)
+ is_deferred(false),
+ is_constructed(false)
 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
                , thread_was_interrupted(false)
 #endif
@@ -334,6 +338,13 @@
                 }
                 do_continuation(lock);
             }
+ void make_ready()
+ {
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ boost::unique_lock<boost::mutex> lock(mutex);
+ mark_finished_internal(lock);
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ }
 
             void do_callback(boost::unique_lock<boost::mutex>& lock)
             {
@@ -348,17 +359,24 @@
 
             void wait_internal(boost::unique_lock<boost::mutex> &lock, bool rethrow=true)
             {
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
               do_callback(lock);
- //if (!done)
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ //if (!done) // fixme why this doesn't works?
               {
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
                 if (is_deferred)
                 {
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
                   is_deferred=false;
                   execute(lock);
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+
                   //lock.unlock();
                 }
                 else
                 {
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
                   while(!done)
                   {
                       waiters.wait(lock);
@@ -366,11 +384,14 @@
 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
                   if(rethrow && thread_was_interrupted)
                   {
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
                       throw boost::thread_interrupted();
                   }
 #endif
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
                   if(rethrow && exception)
                   {
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
                       boost::rethrow_exception(exception);
                   }
                 }
@@ -378,8 +399,11 @@
             }
             void wait(bool rethrow=true)
             {
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
                 boost::unique_lock<boost::mutex> lock(mutex);
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
                 wait_internal(lock, rethrow);
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
             }
 
 #if defined BOOST_THREAD_USES_DATETIME
@@ -424,13 +448,19 @@
 #endif
             void mark_exceptional_finish_internal(boost::exception_ptr const& e, boost::unique_lock<boost::mutex>& lock)
             {
+ //std::cout << "**************"<<__FILE__ << ":" << __LINE__ <<std::endl;
                 exception=e;
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
                 mark_finished_internal(lock);
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
             }
             void mark_exceptional_finish()
             {
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
                 boost::unique_lock<boost::mutex> lock(mutex);
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
                 mark_exceptional_finish_internal(boost::current_exception(), lock);
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
             }
 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
             void mark_interrupted_finish()
@@ -440,8 +470,25 @@
                 mark_finished_internal(lock);
             }
 #endif
+ void set_exception_at_thread_exit(exception_ptr e)
+ {
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ unique_lock<boost::mutex> lk(mutex);
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ if (has_value(lk))
+ {
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ throw_exception(promise_already_satisfied());
+ }
+ //std::cout << "**************"<<__FILE__ << ":" << __LINE__ <<std::endl;
+ exception=e;
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ get_current_thread_data()->make_ready_at_thread_exit(shared_from_this());
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ }
             bool has_value()
             {
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
                 boost::lock_guard<boost::mutex> lock(mutex);
                 return done && !(exception
 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
@@ -449,6 +496,15 @@
 #endif
                 );
             }
+ bool has_value(unique_lock<boost::mutex>& )
+ {
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ return done && !(exception
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ || thread_was_interrupted
+#endif
+ );
+ }
             bool has_exception()
             {
                 boost::lock_guard<boost::mutex> lock(mutex);
@@ -458,6 +514,14 @@
 #endif
                     );
             }
+ bool has_exception(unique_lock<boost::mutex>&)
+ {
+ return done && (exception
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ || thread_was_interrupted
+#endif
+ );
+ }
 
             template<typename F,typename U>
             void set_wait_callback(F f,U* u)
@@ -596,7 +660,9 @@
 
             move_dest_type get()
             {
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
                 wait();
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
                 return static_cast<move_dest_type>(*result);
                 //return boost::move(*result); // todo check why this doesn't works (references?)
             }
@@ -621,6 +687,138 @@
                 }
             }
 
+
+ //void set_value_at_thread_exit(source_reference_type result_)
+ void set_value_at_thread_exit(const T & result_)
+ {
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ unique_lock<boost::mutex> lk(this->mutex);
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ if (this->has_value(lk))
+ {
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ throw_exception(promise_already_satisfied());
+ }
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ future_traits<T>::init(result,result_);
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ this->is_constructed = true;
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ get_current_thread_data()->make_ready_at_thread_exit(shared_from_this());
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ }
+ //void set_value_at_thread_exit(rvalue_source_type result_)
+ void set_value_at_thread_exit(BOOST_THREAD_RV_REF(T) result_)
+ {
+ unique_lock<boost::mutex> lk(this->mutex);
+ if (this->has_value(lk))
+ throw_exception(promise_already_satisfied());
+ future_traits<T>::init(result,static_cast<rvalue_source_type>(result_));
+ this->is_constructed = true;
+ get_current_thread_data()->make_ready_at_thread_exit(shared_from_this());
+ }
+
+
+ private:
+ future_object(future_object const&);
+ future_object& operator=(future_object const&);
+ };
+
+ template<typename T>
+ struct future_object<T&>:
+ detail::future_object_base
+ {
+ typedef typename future_traits<T>::storage_type storage_type;
+ typedef typename future_traits<T>::source_reference_type source_reference_type;
+ typedef typename future_traits<T>::rvalue_source_type rvalue_source_type;
+ typedef typename future_traits<T>::move_dest_type move_dest_type;
+ typedef typename future_traits<T>::shared_future_get_result_type shared_future_get_result_type;
+
+ T* result;
+
+ future_object():
+ result(0)
+ {}
+
+ ~future_object()
+ {
+ }
+
+ void mark_finished_with_result_internal(T& result_, boost::unique_lock<boost::mutex>& lock)
+ {
+ //future_traits<T>::init(result,result_);
+ result= &result_;
+ mark_finished_internal(lock);
+ }
+
+// void mark_finished_with_result_internal(rvalue_source_type result_, boost::unique_lock<boost::mutex>& lock)
+// {
+// future_traits<T>::init(result,static_cast<rvalue_source_type>(result_));
+// mark_finished_internal(lock);
+// }
+
+ void mark_finished_with_result(T& result_)
+ {
+ boost::unique_lock<boost::mutex> lock(mutex);
+ mark_finished_with_result_internal(result_, lock);
+ }
+
+// void mark_finished_with_result(rvalue_source_type result_)
+// {
+// boost::unique_lock<boost::mutex> lock(mutex);
+// mark_finished_with_result_internal(static_cast<rvalue_source_type>(result_), lock);
+// }
+
+
+ T& get()
+ {
+ wait();
+ //return static_cast<T&>(*result);
+ return *result;
+ }
+
+ T& get_sh()
+ {
+ wait();
+ //return static_cast<shared_future_get_result_type>(*result);
+ return *result;
+ }
+
+ // todo move this to detail::future_object_base
+ future_state::state get_state()
+ {
+ boost::lock_guard<boost::mutex> guard(mutex);
+ if(!done)
+ {
+ return future_state::waiting;
+ }
+ else
+ {
+ return future_state::ready;
+ }
+ }
+
+ void set_value_at_thread_exit(T& result_)
+ {
+ unique_lock<boost::mutex> lk(this->mutex);
+ if (this->has_value(lk))
+ throw_exception(promise_already_satisfied());
+ //future_traits<T>::init(result,result_);
+ result= &result_;
+ this->is_constructed = true;
+ get_current_thread_data()->make_ready_at_thread_exit(shared_from_this());
+ }
+// void set_value_at_thread_exit(rvalue_source_type result_)
+// {
+// unique_lock<boost::mutex> lk(this->mutex);
+// if (this->has_value())
+// throw_exception(promise_already_satisfied());
+// future_traits<T>::init(result,static_cast<rvalue_source_type>(result_));
+// this->is_constructed = true;
+// get_current_thread_data()->make_ready_at_thread_exit(shared_from_this());
+// }
+
+
         private:
             future_object(future_object const&);
             future_object& operator=(future_object const&);
@@ -648,7 +846,9 @@
 
             void get()
             {
- wait();
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ this->wait();
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
             }
             void get_sh()
             {
@@ -667,6 +867,22 @@
                     return future_state::ready;
                 }
             }
+ void set_value_at_thread_exit()
+ {
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ unique_lock<boost::mutex> lk(this->mutex);
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ if (this->has_value(lk))
+ {
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ throw_exception(promise_already_satisfied());
+ }
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ this->is_constructed = true;
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ get_current_thread_data()->make_ready_at_thread_exit(shared_from_this());
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ }
         private:
             future_object(future_object const&);
             future_object& operator=(future_object const&);
@@ -1275,15 +1491,22 @@
         // retrieving the value
         move_dest_type get()
         {
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
             if(!this->future_)
             {
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
                 boost::throw_exception(future_uninitialized());
             }
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
             future_ptr fut_=this->future_;
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
             this->future_.reset();
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
             return fut_->get();
 #else
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
             return this->future_->get();
 #endif
         }
@@ -1408,7 +1631,7 @@
 
         void lazy_init()
         {
-#if defined BOOST_THREAD_PROMISE_LAZY
+#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
             if(!atomic_load(&future_))
             {
                 future_ptr blank;
@@ -1432,7 +1655,7 @@
         }
 #endif
         promise():
-#if defined BOOST_THREAD_PROMISE_LAZY
+#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
             future_(),
 #else
             future_(new detail::future_object<R>()),
@@ -1526,9 +1749,31 @@
         }
 
         // setting the result with deferred notification
- //void set_value_at_thread_exit(const R& r); // NOT YET IMPLEMENTED
- //void set_value_at_thread_exit(see below); // NOT YET IMPLEMENTED
- //void set_exception_at_thread_exit(exception_ptr p); // NOT YET IMPLEMENTED
+ void set_value_at_thread_exit(const R& r)
+ {
+ if (future_.get()==0)
+ {
+ boost::throw_exception(promise_moved());
+ }
+ future_->set_value_at_thread_exit(r);
+ }
+
+ void set_value_at_thread_exit(BOOST_THREAD_RV_REF(R) r)
+ {
+ if (future_.get()==0)
+ {
+ boost::throw_exception(promise_moved());
+ }
+ future_->set_value_at_thread_exit(boost::move(r));
+ }
+ void set_exception_at_thread_exit(exception_ptr e)
+ {
+ if (future_.get()==0)
+ {
+ boost::throw_exception(promise_moved());
+ }
+ future_->set_exception_at_thread_exit(e);
+ }
 
         template<typename F>
         void set_wait_callback(F f)
@@ -1539,6 +1784,148 @@
 
     };
 
+ template <typename R>
+ class promise<R&>
+ {
+ typedef boost::shared_ptr<detail::future_object<R&> > future_ptr;
+
+ future_ptr future_;
+ bool future_obtained;
+
+ void lazy_init()
+ {
+#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
+ if(!atomic_load(&future_))
+ {
+ future_ptr blank;
+ atomic_compare_exchange(&future_,&blank,future_ptr(new detail::future_object<R&>));
+ }
+#endif
+ }
+
+ public:
+ BOOST_THREAD_MOVABLE_ONLY(promise)
+#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
+ template <class Allocator>
+ promise(boost::allocator_arg_t, Allocator a)
+ {
+ typedef typename Allocator::template rebind<detail::future_object<R&> >::other A2;
+ A2 a2(a);
+ typedef thread_detail::allocator_destructor<A2> D;
+
+ future_ = future_ptr(::new(a2.allocate(1)) detail::future_object<R&>(), D(a2, 1) );
+ future_obtained = false;
+ }
+#endif
+ promise():
+#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
+ future_(),
+#else
+ future_(new detail::future_object<R&>()),
+#endif
+ future_obtained(false)
+ {}
+
+ ~promise()
+ {
+ if(future_)
+ {
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
+
+ if(!future_->done)
+ {
+ future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
+ }
+ }
+ }
+
+ // Assignment
+ promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT :
+ future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained)
+ {
+ BOOST_THREAD_RV(rhs).future_.reset();
+ BOOST_THREAD_RV(rhs).future_obtained=false;
+ }
+ promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT
+ {
+ future_=BOOST_THREAD_RV(rhs).future_;
+ future_obtained=BOOST_THREAD_RV(rhs).future_obtained;
+ BOOST_THREAD_RV(rhs).future_.reset();
+ BOOST_THREAD_RV(rhs).future_obtained=false;
+ return *this;
+ }
+
+ void swap(promise& other)
+ {
+ future_.swap(other.future_);
+ std::swap(future_obtained,other.future_obtained);
+ }
+
+ // Result retrieval
+ BOOST_THREAD_FUTURE<R&> get_future()
+ {
+ lazy_init();
+ if (future_.get()==0)
+ {
+ boost::throw_exception(promise_moved());
+ }
+ if (future_obtained)
+ {
+ boost::throw_exception(future_already_retrieved());
+ }
+ future_obtained=true;
+ return BOOST_THREAD_FUTURE<R&>(future_);
+ }
+
+ void set_value(R& r)
+ {
+ lazy_init();
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
+ if(future_->done)
+ {
+ boost::throw_exception(promise_already_satisfied());
+ }
+ future_->mark_finished_with_result_internal(r, lock);
+ }
+
+ void set_exception(boost::exception_ptr p)
+ {
+ lazy_init();
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
+ if(future_->done)
+ {
+ boost::throw_exception(promise_already_satisfied());
+ }
+ future_->mark_exceptional_finish_internal(p, lock);
+ }
+
+ // setting the result with deferred notification
+ void set_value_at_thread_exit(R& r)
+ {
+ if (future_.get()==0)
+ {
+ boost::throw_exception(promise_moved());
+ }
+ future_->set_value_at_thread_exit(r);
+ }
+
+ void set_exception_at_thread_exit(exception_ptr e)
+ {
+ if (future_.get()==0)
+ {
+ boost::throw_exception(promise_moved());
+ }
+ future_->set_exception_at_thread_exit(e);
+ }
+
+ template<typename F>
+ void set_wait_callback(F f)
+ {
+ lazy_init();
+ future_->set_wait_callback(f,this);
+ }
+
+ };
     template <>
     class promise<void>
     {
@@ -1549,7 +1936,7 @@
 
         void lazy_init()
         {
-#if defined BOOST_THREAD_PROMISE_LAZY
+#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
             if(!atomic_load(&future_))
             {
                 future_ptr blank;
@@ -1573,7 +1960,7 @@
         }
 #endif
         promise():
-#if defined BOOST_THREAD_PROMISE_LAZY
+#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
             future_(),
 #else
             future_(new detail::future_object<void>),
@@ -1657,6 +2044,31 @@
             future_->mark_exceptional_finish_internal(p,lock);
         }
 
+ // setting the result with deferred notification
+ void set_value_at_thread_exit()
+ {
+
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+
+ if (future_.get()==0)
+ {
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ boost::throw_exception(promise_moved());
+ }
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ future_->set_value_at_thread_exit();
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ }
+
+ void set_exception_at_thread_exit(exception_ptr e)
+ {
+ if (future_.get()==0)
+ {
+ boost::throw_exception(promise_moved());
+ }
+ future_->set_exception_at_thread_exit(e);
+ }
+
         template<typename F>
         void set_wait_callback(F f)
         {

Modified: trunk/boost/thread/lockable_traits.hpp
==============================================================================
--- trunk/boost/thread/lockable_traits.hpp (original)
+++ trunk/boost/thread/lockable_traits.hpp 2012-11-04 11:47:02 EST (Sun, 04 Nov 2012)
@@ -8,26 +8,17 @@
 #define BOOST_THREAD_LOCKABLE_TRAITS_HPP
 
 #include <boost/thread/detail/config.hpp>
-#include <boost/thread/detail/move.hpp>
-#include <boost/thread/exceptions.hpp>
-//#include <boost/thread/testable_mutex.hpp>
-#include <boost/thread/thread_time.hpp>
 
 #include <boost/assert.hpp>
-#ifdef BOOST_THREAD_USES_CHRONO
-#include <boost/chrono/time_point.hpp>
-#include <boost/chrono/duration.hpp>
-#endif
 #include <boost/detail/workaround.hpp>
 #include <boost/type_traits/is_class.hpp>
 
-#include <algorithm>
-#include <iterator>
-
 #include <boost/config/abi_prefix.hpp>
 
 namespace boost
 {
+ namespace sync
+ {
 
 #if defined(BOOST_NO_SFINAE) || \
     BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) || \
@@ -72,101 +63,130 @@
                 bool, value=sizeof(has_member<derived>(0))==sizeof(true_type)); \
         }
 
- BOOST_THREAD_DEFINE_HAS_MEMBER_CALLED(lock);
- BOOST_THREAD_DEFINE_HAS_MEMBER_CALLED(unlock);
- BOOST_THREAD_DEFINE_HAS_MEMBER_CALLED(try_lock);
-
- template<typename T,bool=has_member_called_lock<T>::value >
- struct has_member_lock
- {
- BOOST_STATIC_CONSTANT(bool, value=false);
- };
-
- template<typename T>
- struct has_member_lock<T,true>
- {
- typedef char true_type;
- struct false_type
- {
- true_type dummy[2];
- };
-
- template<typename U,typename V>
- static true_type has_member(V (U::*)());
- template<typename U>
- static false_type has_member(U);
-
- BOOST_STATIC_CONSTANT(
- bool,value=sizeof(has_member_lock<T>::has_member(&T::lock))==sizeof(true_type));
- };
-
- template<typename T,bool=has_member_called_unlock<T>::value >
- struct has_member_unlock
- {
- BOOST_STATIC_CONSTANT(bool, value=false);
- };
-
- template<typename T>
- struct has_member_unlock<T,true>
- {
- typedef char true_type;
- struct false_type
- {
- true_type dummy[2];
- };
-
- template<typename U,typename V>
- static true_type has_member(V (U::*)());
- template<typename U>
- static false_type has_member(U);
-
- BOOST_STATIC_CONSTANT(
- bool,value=sizeof(has_member_unlock<T>::has_member(&T::unlock))==sizeof(true_type));
- };
-
- template<typename T,bool=has_member_called_try_lock<T>::value >
- struct has_member_try_lock
- {
- BOOST_STATIC_CONSTANT(bool, value=false);
- };
-
- template<typename T>
- struct has_member_try_lock<T,true>
- {
- typedef char true_type;
- struct false_type
- {
- true_type dummy[2];
- };
-
- template<typename U>
- static true_type has_member(bool (U::*)());
- template<typename U>
- static false_type has_member(U);
-
- BOOST_STATIC_CONSTANT(
- bool,value=sizeof(has_member_try_lock<T>::has_member(&T::try_lock))==sizeof(true_type));
- };
+ BOOST_THREAD_DEFINE_HAS_MEMBER_CALLED(lock)
+; BOOST_THREAD_DEFINE_HAS_MEMBER_CALLED(unlock);
+ BOOST_THREAD_DEFINE_HAS_MEMBER_CALLED(try_lock);
+
+ template<typename T,bool=has_member_called_lock<T>::value >
+ struct has_member_lock
+ {
+ BOOST_STATIC_CONSTANT(bool, value=false);
+ };
+
+ template<typename T>
+ struct has_member_lock<T,true>
+ {
+ typedef char true_type;
+ struct false_type
+ {
+ true_type dummy[2];
+ };
+
+ template<typename U,typename V>
+ static true_type has_member(V (U::*)());
+ template<typename U>
+ static false_type has_member(U);
+
+ BOOST_STATIC_CONSTANT(
+ bool,value=sizeof(has_member_lock<T>::has_member(&T::lock))==sizeof(true_type));
+ };
+
+ template<typename T,bool=has_member_called_unlock<T>::value >
+ struct has_member_unlock
+ {
+ BOOST_STATIC_CONSTANT(bool, value=false);
+ };
+
+ template<typename T>
+ struct has_member_unlock<T,true>
+ {
+ typedef char true_type;
+ struct false_type
+ {
+ true_type dummy[2];
+ };
+
+ template<typename U,typename V>
+ static true_type has_member(V (U::*)());
+ template<typename U>
+ static false_type has_member(U);
+
+ BOOST_STATIC_CONSTANT(
+ bool,value=sizeof(has_member_unlock<T>::has_member(&T::unlock))==sizeof(true_type));
+ };
+
+ template<typename T,bool=has_member_called_try_lock<T>::value >
+ struct has_member_try_lock
+ {
+ BOOST_STATIC_CONSTANT(bool, value=false);
+ };
+
+ template<typename T>
+ struct has_member_try_lock<T,true>
+ {
+ typedef char true_type;
+ struct false_type
+ {
+ true_type dummy[2];
+ };
+
+ template<typename U>
+ static true_type has_member(bool (U::*)());
+ template<typename U>
+ static false_type has_member(U);
+
+ BOOST_STATIC_CONSTANT(
+ bool,value=sizeof(has_member_try_lock<T>::has_member(&T::try_lock))==sizeof(true_type));
+ };
 
     }
 
-
     template<typename T>
- struct is_mutex_type
+ struct is_basic_lockable
     {
- BOOST_STATIC_CONSTANT(bool, value = detail::has_member_lock<T>::value &&
- detail::has_member_unlock<T>::value &&
- detail::has_member_try_lock<T>::value);
-
+ BOOST_STATIC_CONSTANT(bool, value = detail::has_member_lock<T>::value &&
+ detail::has_member_unlock<T>::value);
     };
+ template<typename T>
+ struct is_lockable
+ {
+ BOOST_STATIC_CONSTANT(bool, value =
+ is_basic_lockable<T>::value &&
+ detail::has_member_try_lock<T>::value);
+ };
+
 #else
     template<typename T>
- struct is_mutex_type
+ struct is_basic_lockable
+ {
+ BOOST_STATIC_CONSTANT(bool, value = false);
+ };
+ template<typename T>
+ struct is_lockable
     {
- BOOST_STATIC_CONSTANT(bool, value = false);
+ BOOST_STATIC_CONSTANT(bool, value = false);
     };
 #endif
 
+ template<typename T>
+ struct is_recursive_mutex_sur_parolle
+ {
+ BOOST_STATIC_CONSTANT(bool, value = false);
+ };
+
+ template<typename T>
+ struct is_recursive_basic_lockable
+ {
+ BOOST_STATIC_CONSTANT(bool, value = is_basic_lockable<T>::value &&
+ is_recursive_mutex_sur_parolle<T>::value);
+ };
+ }
+ template<typename T>
+ struct is_mutex_type
+ {
+ BOOST_STATIC_CONSTANT(bool, value = sync::is_lockable<T>::value);
+ };
+
 }
 #include <boost/config/abi_suffix.hpp>
 

Modified: trunk/boost/thread/pthread/thread_data.hpp
==============================================================================
--- trunk/boost/thread/pthread/thread_data.hpp (original)
+++ trunk/boost/thread/pthread/thread_data.hpp 2012-11-04 11:47:02 EST (Sun, 04 Nov 2012)
@@ -78,6 +78,7 @@
 
     namespace detail
     {
+ struct future_object_base;
         struct tss_cleanup_function;
         struct thread_exit_callback_node;
         struct tss_data_node
@@ -119,6 +120,9 @@
> notify_list_t;
             notify_list_t notify;
 
+ typedef std::vector<shared_ptr<future_object_base> > async_states_t;
+ async_states_t async_states_;
+
             thread_data_base():
                 done(false),join_started(false),joined(false),
                 thread_exit_callbacks(0),
@@ -127,7 +131,8 @@
                 interrupt_requested(false),
 #endif
                 current_cond(0),
- notify()
+ notify(),
+ async_states_()
             {}
             virtual ~thread_data_base();
 
@@ -138,6 +143,14 @@
             {
               notify.push_back(std::pair<condition_variable*, mutex*>(cv, m));
             }
+
+ void make_ready_at_thread_exit(shared_ptr<future_object_base> as)
+ {
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ async_states_.push_back(as);
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ }
+
         };
 
         BOOST_THREAD_DECL thread_data_base* get_current_thread_data();

Modified: trunk/boost/thread/win32/thread_data.hpp
==============================================================================
--- trunk/boost/thread/win32/thread_data.hpp (original)
+++ trunk/boost/thread/win32/thread_data.hpp 2012-11-04 11:47:02 EST (Sun, 04 Nov 2012)
@@ -72,6 +72,7 @@
 
     namespace detail
     {
+ struct future_object_base;
         struct tss_cleanup_function;
         struct thread_exit_callback_node;
         struct tss_data_node
@@ -107,6 +108,8 @@
> notify_list_t;
             notify_list_t notify;
 
+ typedef std::vector<shared_ptr<future_object_base> > async_states_t;
+ async_states_t async_states_;
 
             thread_data_base():
                 count(0),thread_handle(detail::win32::invalid_handle_value),
@@ -118,7 +121,8 @@
                 interruption_enabled(true),
 #endif
                 id(0),
- notify()
+ notify(),
+ async_states_()
             {}
             virtual ~thread_data_base();
 
@@ -150,7 +154,13 @@
               notify.push_back(std::pair<condition_variable*, mutex*>(cv, m));
             }
 
+ void make_ready_at_thread_exit(shared_ptr<future_object_base> as)
+ {
+ async_states_.push_back(as);
+ }
+
         };
+ BOOST_THREAD_DECL thread_data_base* get_current_thread_data();
 
         typedef boost::intrusive_ptr<detail::thread_data_base> thread_data_ptr;
 

Modified: trunk/libs/thread/src/pthread/thread.cpp
==============================================================================
--- trunk/libs/thread/src/pthread/thread.cpp (original)
+++ trunk/libs/thread/src/pthread/thread.cpp 2012-11-04 11:47:02 EST (Sun, 04 Nov 2012)
@@ -16,6 +16,7 @@
 #include <boost/thread/once.hpp>
 #include <boost/thread/tss.hpp>
 #include <boost/throw_exception.hpp>
+#include <boost/thread/future.hpp>
 
 #ifdef __GLIBC__
 #include <sys/sysinfo.h>
@@ -34,14 +35,22 @@
     {
         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();
             }
- }
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ for (async_states_t::iterator i = async_states_.begin(), e = async_states_.end();
+ i != e; ++i)
+ {
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ (*i)->make_ready();
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ }
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+
         }
 
         struct thread_exit_callback_node
@@ -68,11 +77,16 @@
             {
                 static void tls_destructor(void* data)
                 {
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
                     boost::detail::thread_data_base* thread_info=static_cast<boost::detail::thread_data_base*>(data);
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
                     if(thread_info)
                     {
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
                         while(!thread_info->tss_data.empty() || thread_info->thread_exit_callbacks)
                         {
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+
                             while(thread_info->thread_exit_callbacks)
                             {
                                 detail::thread_exit_callback_node* const current_node=thread_info->thread_exit_callbacks;
@@ -98,8 +112,17 @@
                                 thread_info->tss_data.erase(current);
                             }
                         }
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ if (thread_info) {
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
                         thread_info->self.reset();
+ } else{
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+
+ }
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
                     }
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
                 }
             }
 
@@ -162,10 +185,13 @@
                 }
 // Removed as it stops the debugger identifying the cause of the exception
 // Unhandled exceptions still cause the application to terminate
-// BOOST_CATCH(...)
-// {
-// std::terminate();
-// }
+ BOOST_CATCH(...)
+ {
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+ throw;
+
+ std::terminate();
+ }
                 BOOST_CATCH_END
 #endif
                 detail::tls_destructor(thread_info.get());
@@ -173,6 +199,8 @@
                 boost::lock_guard<boost::mutex> lock(thread_info->data_mutex);
                 thread_info->done=true;
                 thread_info->done_condition.notify_all();
+ //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+
                 return 0;
             }
         }

Modified: trunk/libs/thread/src/win32/thread.cpp
==============================================================================
--- trunk/libs/thread/src/win32/thread.cpp (original)
+++ trunk/libs/thread/src/win32/thread.cpp 2012-11-04 11:47:02 EST (Sun, 04 Nov 2012)
@@ -18,6 +18,7 @@
 #include <boost/thread/tss.hpp>
 #include <boost/thread/condition_variable.hpp>
 #include <boost/thread/detail/tss_hooks.hpp>
+#include <boost/thread/future.hpp>
 
 #include <boost/assert.hpp>
 #include <boost/throw_exception.hpp>
@@ -37,16 +38,20 @@
   {
     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();
         }
- }
+ for (async_states_t::iterator i = async_states_.begin(), e = async_states_.end();
+ i != e; ++i)
+ {
+ (*i)->make_ready();
+ }
     }
   }
+
     namespace
     {
 #ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
@@ -76,15 +81,6 @@
             }
         }
 
- detail::thread_data_base* get_current_thread_data()
- {
- if(current_thread_tls_key==TLS_OUT_OF_INDEXES)
- {
- return 0;
- }
- return (detail::thread_data_base*)TlsGetValue(current_thread_tls_key);
- }
-
         void set_current_thread_data(detail::thread_data_base* new_data)
         {
             boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key);
@@ -99,6 +95,20 @@
             }
         }
 
+ }
+ namespace detail
+ {
+ thread_data_base* get_current_thread_data()
+ {
+ if(current_thread_tls_key==TLS_OUT_OF_INDEXES)
+ {
+ return 0;
+ }
+ return (detail::thread_data_base*)TlsGetValue(current_thread_tls_key);
+ }
+ }
+ namespace
+ {
 #ifndef BOOST_HAS_THREADEX
 // Windows CE doesn't define _beginthreadex
 
@@ -157,7 +167,7 @@
     {
         void run_thread_exit_callbacks()
         {
- detail::thread_data_ptr current_thread_data(get_current_thread_data(),false);
+ detail::thread_data_ptr current_thread_data(detail::get_current_thread_data(),false);
             if(current_thread_data)
             {
                 while(! current_thread_data->tss_data.empty() || current_thread_data->thread_exit_callbacks)
@@ -295,11 +305,11 @@
 
         detail::thread_data_base* get_or_make_current_thread_data()
         {
- detail::thread_data_base* current_thread_data(get_current_thread_data());
+ detail::thread_data_base* current_thread_data(detail::get_current_thread_data());
             if(!current_thread_data)
             {
                 make_external_thread_data();
- current_thread_data=get_current_thread_data();
+ current_thread_data=detail::get_current_thread_data();
             }
             return current_thread_data;
         }
@@ -487,10 +497,10 @@
                 handles[handle_count++]=handle_to_wait_for;
             }
 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- if(get_current_thread_data() && get_current_thread_data()->interruption_enabled)
+ if(detail::get_current_thread_data() && detail::get_current_thread_data()->interruption_enabled)
             {
                 interruption_index=handle_count;
- handles[handle_count++]=get_current_thread_data()->interruption_handle;
+ handles[handle_count++]=detail::get_current_thread_data()->interruption_handle;
             }
 #endif
             detail::win32::handle_manager timer_handle;
@@ -547,7 +557,7 @@
 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
                         else if(notified_index==interruption_index)
                         {
- detail::win32::ResetEvent(get_current_thread_data()->interruption_handle);
+ detail::win32::ResetEvent(detail::get_current_thread_data()->interruption_handle);
                             throw thread_interrupted();
                         }
 #endif
@@ -584,19 +594,19 @@
         {
             if(interruption_enabled() && interruption_requested())
             {
- detail::win32::ResetEvent(get_current_thread_data()->interruption_handle);
+ detail::win32::ResetEvent(detail::get_current_thread_data()->interruption_handle);
                 throw thread_interrupted();
             }
         }
 
         bool interruption_enabled() BOOST_NOEXCEPT
         {
- return get_current_thread_data() && get_current_thread_data()->interruption_enabled;
+ return detail::get_current_thread_data() && detail::get_current_thread_data()->interruption_enabled;
         }
 
         bool interruption_requested() BOOST_NOEXCEPT
         {
- return get_current_thread_data() && (detail::win32::WaitForSingleObject(get_current_thread_data()->interruption_handle,0)==0);
+ return detail::get_current_thread_data() && (detail::win32::WaitForSingleObject(detail::get_current_thread_data()->interruption_handle,0)==0);
         }
 #endif
 
@@ -611,15 +621,15 @@
         {
             if(interruption_was_enabled)
             {
- get_current_thread_data()->interruption_enabled=false;
+ detail::get_current_thread_data()->interruption_enabled=false;
             }
         }
 
         disable_interruption::~disable_interruption() BOOST_NOEXCEPT
         {
- if(get_current_thread_data())
+ if(detail::get_current_thread_data())
             {
- get_current_thread_data()->interruption_enabled=interruption_was_enabled;
+ detail::get_current_thread_data()->interruption_enabled=interruption_was_enabled;
             }
         }
 
@@ -627,15 +637,15 @@
         {
             if(d.interruption_was_enabled)
             {
- get_current_thread_data()->interruption_enabled=true;
+ detail::get_current_thread_data()->interruption_enabled=true;
             }
         }
 
         restore_interruption::~restore_interruption() BOOST_NOEXCEPT
         {
- if(get_current_thread_data())
+ if(detail::get_current_thread_data())
             {
- get_current_thread_data()->interruption_enabled=false;
+ detail::get_current_thread_data()->interruption_enabled=false;
             }
         }
     }
@@ -734,7 +744,7 @@
 
     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());
+ 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/test/Jamfile.v2
==============================================================================
--- trunk/libs/thread/test/Jamfile.v2 (original)
+++ trunk/libs/thread/test/Jamfile.v2 2012-11-04 11:47:02 EST (Sun, 04 Nov 2012)
@@ -267,6 +267,11 @@
           [ thread-run2 ./sync/futures/promise/set_value_const_pass.cpp : promise__set_value_const_p ]
           [ thread-run2 ./sync/futures/promise/set_value_void_pass.cpp : promise__set_value_void_p ]
           [ thread-run2 ./sync/futures/promise/use_allocator_pass.cpp : promise__use_allocator_p ]
+ [ thread-run2 ./sync/futures/promise/set_exception_at_thread_exit_pass.cpp : promise__set_exception_at_thread_exit_p ]
+ [ thread-run2 ./sync/futures/promise/set_lvalue_at_thread_exit_pass.cpp : promise__set_lvalue_at_thread_exit_p ]
+ [ thread-run2 ./sync/futures/promise/set_rvalue_at_thread_exit_pass.cpp : promise__set_rvalue_at_thread_exit_p ]
+ [ thread-run2 ./sync/futures/promise/set_value_at_thread_exit_const_pass.cpp : promise__set_value_at_thread_exit_const_p ]
+ [ thread-run2 ./sync/futures/promise/set_value_at_thread_exit_void_pass.cpp : promise__set_value_at_thread_exit_void_p ]
     ;
 
     #explicit ts_future ;
@@ -582,6 +587,7 @@
     explicit ts_ ;
     test-suite ts_
     :
+
           #[ thread-run ../example/unwrap.cpp ]
     ;
 

Added: trunk/libs/thread/test/sync/futures/promise/set_exception_at_thread_exit_pass.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/thread/test/sync/futures/promise/set_exception_at_thread_exit_pass.cpp 2012-11-04 11:47:02 EST (Sun, 04 Nov 2012)
@@ -0,0 +1,78 @@
+//===----------------------------------------------------------------------===//
+//
+// 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/future.hpp>
+
+// class promise<R>
+
+// void promise::set_exception_at_thread_exit(exception_ptr p);
+
+#define BOOST_THREAD_VERSION 4
+
+#include <boost/thread/future.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/static_assert.hpp>
+
+namespace boost
+{
+ template <typename T>
+ struct wrap
+ {
+ wrap(T const& v) :
+ value(v)
+ {
+ }
+ T value;
+
+ };
+
+ template <typename T>
+ exception_ptr make_exception_ptr(T v)
+ {
+ return copy_exception(wrap<T> (v));
+ }
+}
+
+//void func(boost::promise<int> p)
+boost::promise<int> p;
+void func()
+{
+ p.set_exception_at_thread_exit(boost::make_exception_ptr(3));
+}
+
+int main()
+{
+ {
+ typedef int T;
+ //boost::promise<T> p;
+ boost::future<T> f = p.get_future();
+ //boost::thread(func, boost::move(p)).detach();
+ boost::thread(func).detach();
+ try
+ {
+ f.get();
+ BOOST_TEST(false);
+ }
+ catch (boost::wrap<int> i)
+ {
+ BOOST_TEST(i.value == 3);
+ }
+ catch (...)
+ {
+ BOOST_TEST(false);
+ }
+ }
+ return boost::report_errors();
+}
+

Added: trunk/libs/thread/test/sync/futures/promise/set_lvalue_at_thread_exit_pass.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/thread/test/sync/futures/promise/set_lvalue_at_thread_exit_pass.cpp 2012-11-04 11:47:02 EST (Sun, 04 Nov 2012)
@@ -0,0 +1,49 @@
+//===----------------------------------------------------------------------===//
+//
+// 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/future.hpp>
+
+// class promise<R>
+
+// void promise<R&>::set_value_at_thread_exit(R& r);
+
+#define BOOST_THREAD_VERSION 4
+
+#include <boost/thread/future.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <memory>
+
+int i = 0;
+
+//void func(boost::promise<int&> p)
+boost::promise<int&> p;
+void func()
+{
+ p.set_value_at_thread_exit(i);
+ i = 4;
+}
+
+int main()
+{
+ {
+ //boost::promise<int&> p;
+ boost::future<int&> f = p.get_future();
+ //boost::thread(func, boost::move(p)).detach();
+ boost::thread(func).detach();
+ int r = f.get();
+ BOOST_TEST(r == 4);
+ }
+ return boost::report_errors();
+}
+

Added: trunk/libs/thread/test/sync/futures/promise/set_rvalue_at_thread_exit_pass.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/thread/test/sync/futures/promise/set_rvalue_at_thread_exit_pass.cpp 2012-11-04 11:47:02 EST (Sun, 04 Nov 2012)
@@ -0,0 +1,48 @@
+//===----------------------------------------------------------------------===//
+//
+// 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/future.hpp>
+
+// class promise<R>
+
+// void promise::set_exception_at_thread_exit(exception_ptr p);
+
+#define BOOST_THREAD_VERSION 3
+
+#include <boost/thread/future.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/thread/detail/memory.hpp>
+#include <boost/interprocess/smart_ptr/unique_ptr.hpp>
+
+//void func(boost::promise<boost::interprocess::unique_ptr<int, boost::default_delete<int> > > p)
+boost::promise<boost::interprocess::unique_ptr<int, boost::default_delete<int> > > p;
+void func()
+{
+ boost::interprocess::unique_ptr<int, boost::default_delete<int> > uptr(new int(5));
+ p.set_value_at_thread_exit(boost::move(uptr));
+}
+
+int main()
+{
+ {
+ //boost::promise<boost::interprocess::unique_ptr<int, boost::default_delete<int>> > p;
+ boost::future<boost::interprocess::unique_ptr<int, boost::default_delete<int> > > f = p.get_future();
+ //boost::thread(func, boost::move(p)).detach();
+ boost::thread(func).detach();
+ BOOST_TEST(*f.get() == 5);
+ }
+
+ return boost::report_errors();
+}
+

Added: trunk/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_const_pass.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_const_pass.cpp 2012-11-04 11:47:02 EST (Sun, 04 Nov 2012)
@@ -0,0 +1,45 @@
+//===----------------------------------------------------------------------===//
+//
+// 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/future.hpp>
+
+// class promise<R>
+
+// void promise::set_value_at_thread_exit(const R& r);
+
+#define BOOST_THREAD_VERSION 4
+
+#include <boost/thread/future.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+boost::promise<int> p;
+//void func(boost::promise<int> p)
+void func()
+{
+ const int i = 5;
+ p.set_value_at_thread_exit(i);
+}
+
+int main()
+{
+ {
+ //boost::promise<int> p;
+ boost::future<int> f = p.get_future();
+ //boost::thread(func, boost::move(p)).detach();
+ boost::thread(func).detach();
+ BOOST_TEST(f.get() == 5);
+ }
+ return boost::report_errors();
+}
+

Added: trunk/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_void_pass.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_void_pass.cpp 2012-11-04 11:47:02 EST (Sun, 04 Nov 2012)
@@ -0,0 +1,87 @@
+//===----------------------------------------------------------------------===//
+//
+// 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/future.hpp>
+
+// class promise<R>
+
+// void promise<void>::set_value_at_thread_exit();
+
+#define BOOST_THREAD_VERSION 4
+
+#include <boost/thread/future.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+int i = 0;
+
+boost::promise<void> p;
+void func()
+{
+ p.set_value_at_thread_exit();
+ i = 1;
+}
+
+void func2(boost::promise<void> p2)
+{
+ p2.set_value_at_thread_exit();
+ i = 1;
+}
+
+int main()
+{
+ try
+ {
+ boost::future<void> f = p.get_future();
+ boost::thread(func).detach();
+ f.get();
+ BOOST_TEST(i == 1);
+
+ }
+ catch(std::exception ex)
+ {
+ BOOST_TEST(false);
+ }
+ catch(...)
+ {
+ BOOST_TEST(false);
+ }
+
+ // BUG when moving promise. fixme
+// try
+// {
+// std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+// boost::promise<void> p2; // BUG
+// std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+// boost::future<void> f = p2.get_future();
+// std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+// boost::thread(func2, boost::move(p2)).detach(); // BUG
+// std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+// f.get();
+// std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+// BOOST_TEST(i == 1);
+// std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
+//
+// }
+// catch(std::exception ex)
+// {
+// std::cout << __FILE__ << ":" << __LINE__ << " " << ex.what() << std::endl;
+// BOOST_TEST(false);
+// }
+// catch(...)
+// {
+// BOOST_TEST(false);
+// }
+ return boost::report_errors();
+}
+

Modified: trunk/libs/thread/test/test_4882.cpp
==============================================================================
--- trunk/libs/thread/test/test_4882.cpp (original)
+++ trunk/libs/thread/test/test_4882.cpp 2012-11-04 11:47:02 EST (Sun, 04 Nov 2012)
@@ -20,15 +20,28 @@
   {
     for (int i =0; i<10; ++i)
     {
+#if 0
       boost::system_time timeout = boost::get_system_time() + boost::posix_time::milliseconds(50);
 
       if (mutex.timed_lock(timeout))
       {
- std::cout << __FILE__ << ":" << __LINE__ << std::endl;
+ std::cout << __FILE__ << ":" << __LINE__ << " i="<<i << std::endl;
         boost::this_thread::sleep(boost::posix_time::milliseconds(10));
         mutex.unlock();
- std::cout << __FILE__ << ":" << __LINE__ << std::endl;
+ std::cout << __FILE__ << ":" << __LINE__ << " i="<<i << std::endl;
       }
+#else
+ boost::chrono::system_clock::time_point timeout = boost::chrono::system_clock::now() + boost::chrono::milliseconds(50);
+
+ std::cout << __FILE__ << ":" << __LINE__ << " i="<<i << std::endl;
+ if (mutex.try_lock_until(timeout))
+ {
+ std::cout << __FILE__ << ":" << __LINE__ << " i="<<i << std::endl;
+ boost::this_thread::sleep_for(boost::chrono::milliseconds(10));
+ mutex.unlock();
+ std::cout << __FILE__ << ":" << __LINE__ << " i="<<i << std::endl;
+ }
+#endif
     }
   }
   BOOST_CATCH (boost::lock_error& le)


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