$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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)