Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r81023 - in trunk: boost/thread boost/thread/detail boost/thread/pthread libs/thread/doc libs/thread/example libs/thread/src/pthread libs/thread/src/win32 libs/thread/test
From: vicente.botet_at_[hidden]
Date: 2012-10-20 10:05:35


Author: viboes
Date: 2012-10-20 10:05:32 EDT (Sat, 20 Oct 2012)
New Revision: 81023
URL: http://svn.boost.org/trac/boost/changeset/81023

Log:
Thread: Added BOOST_THREAD_DONT_PROVIDE_THREAD_EQ, BOOST_THREAD_DONT_USE_DATETIME and forbid their use when defined + Added BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION and future<>::then + Go towards don't throwing from the cpp files (refactor start_thread, join + Added #define BOOST_THREAD_VERSION 2 for the tests that runs only with version 2
Added:
   trunk/libs/thread/example/future_then.cpp (contents, props changed)
Text files modified:
   trunk/boost/thread/detail/config.hpp | 49 +++++-
   trunk/boost/thread/detail/thread.hpp | 41 ++---
   trunk/boost/thread/future.hpp | 264 ++++++++++++++++++++++++++++++---------
   trunk/boost/thread/locks.hpp | 11 +
   trunk/boost/thread/pthread/condition_variable.hpp | 3
   trunk/boost/thread/pthread/condition_variable_fwd.hpp | 2
   trunk/boost/thread/pthread/mutex.hpp | 6
   trunk/boost/thread/pthread/recursive_mutex.hpp | 5
   trunk/boost/thread/pthread/shared_mutex.hpp | 8
   trunk/boost/thread/pthread/thread_data.hpp | 2
   trunk/libs/thread/doc/changes.qbk | 13 +
   trunk/libs/thread/doc/future_ref.qbk | 65 +++++++++
   trunk/libs/thread/doc/futures.qbk | 59 ++++++++
   trunk/libs/thread/src/pthread/thread.cpp | 4
   trunk/libs/thread/src/win32/thread.cpp | 54 ++++---
   trunk/libs/thread/test/Jamfile.v2 | 1
   trunk/libs/thread/test/test_2309.cpp | 2
   trunk/libs/thread/test/test_3628.cpp | 2
   trunk/libs/thread/test/test_4882.cpp | 2
   trunk/libs/thread/test/test_5542_1.cpp | 2
   trunk/libs/thread/test/test_5542_3.cpp | 2
   trunk/libs/thread/test/test_6130.cpp | 2
   trunk/libs/thread/test/test_lock_concept.cpp | 2
   trunk/libs/thread/test/test_xtime.cpp | 2
   24 files changed, 470 insertions(+), 133 deletions(-)

Modified: trunk/boost/thread/detail/config.hpp
==============================================================================
--- trunk/boost/thread/detail/config.hpp (original)
+++ trunk/boost/thread/detail/config.hpp 2012-10-20 10:05:32 EDT (Sat, 20 Oct 2012)
@@ -16,12 +16,15 @@
 #include <boost/config.hpp>
 #include <boost/detail/workaround.hpp>
 #include <boost/thread/detail/platform.hpp>
+#include <boost/detail/no_exceptions_support.hpp>
 
+#if ! defined BOOST_THREAD_NOEXCEPT_OR_THROW
 #ifdef BOOST_NO_NOEXCEPT
 # define BOOST_THREAD_NOEXCEPT_OR_THROW throw()
 #else
 # define BOOST_THREAD_NOEXCEPT_OR_THROW noexcept
 #endif
+#endif
 
 // This compiler doesn't support Boost.Chrono
 #if defined __IBMCPP__ && (__IBMCPP__ < 1100) && ! defined BOOST_THREAD_DONT_USE_CHRONO
@@ -69,12 +72,21 @@
 
 
 #if BOOST_THREAD_VERSION==2
-#if ! defined BOOST_THREAD_DONT_PROVIDE_PROMISE_LAZY && ! defined BOOST_THREAD_PROMISE_LAZY
+#if ! defined BOOST_THREAD_DONT_PROVIDE_PROMISE_LAZY \
+ && ! defined BOOST_THREAD_PROMISE_LAZY
 #define BOOST_THREAD_PROMISE_LAZY
 #endif
-#if ! defined BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0
-#define BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
+
+#if ! defined BOOST_THREAD_DONT_PROVIDE_THREAD_EQ \
+ && ! defined BOOST_THREAD_PROVIDES_THREAD_EQ
+#define BOOST_THREAD_PROVIDES_THREAD_EQ
 #endif
+
+#if ! defined BOOST_THREAD_DONT_USE_DATETIME \
+ && ! defined BOOST_THREAD_USES_DATETIME
+#define BOOST_THREAD_USES_DATETIME
+#endif
+
 #endif
 
 #if BOOST_THREAD_VERSION>=3
@@ -110,10 +122,6 @@
  && ! defined BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
 #define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
 #endif
-#if ! defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 \
- && ! defined BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_
-#define BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0
-#endif
 #if ! defined BOOST_THREAD_DONT_USE_MOVE \
  && ! defined BOOST_THREAD_USES_MOVE
 #define BOOST_THREAD_USES_MOVE
@@ -136,9 +144,16 @@
     ! defined(BOOST_NO_CXX11_DECLTYPE) && \
     ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
     ! defined(BOOST_NO_CXX11_HDR_TUPLE)
+#define BOOST_THREAD_PROVIDES_VARIADIC_THREAD
+#endif
+#endif
 
+#if ! defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION \
+ && ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_CONTINUATION
 
-#define BOOST_THREAD_PROVIDES_VARIADIC_THREAD
+#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+#define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
+#endif
 #endif
 
 #if ! defined BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET \
@@ -146,9 +161,10 @@
 #define BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
 #endif
 
+#endif // BOOST_THREAD_VERSION>=4
 
-#endif
-#endif
+
+// CORRELATIONS
 
 // BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN is defined if BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
 #if defined BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS \
@@ -158,9 +174,16 @@
 
 // BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 defined by default up to Boost 1.52
 // BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0 defined by default up to Boost 1.55
-#if ! defined BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0 \
-&& ! defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
-#define BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
+#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
+
+#if ! defined BOOST_THREAD_PROVIDES_THREAD_EQ
+#define BOOST_THREAD_PROVIDES_THREAD_EQ
+#endif
+
+#if ! defined BOOST_THREAD_USES_DATETIME
+#define defined BOOST_THREAD_USES_DATETIME
+#endif
+
 #endif
 
 #if BOOST_WORKAROUND(__BORLANDC__, < 0x600)

Modified: trunk/boost/thread/detail/thread.hpp
==============================================================================
--- trunk/boost/thread/detail/thread.hpp (original)
+++ trunk/boost/thread/detail/thread.hpp 2012-10-20 10:05:32 EDT (Sat, 20 Oct 2012)
@@ -262,10 +262,6 @@
 
         detail::thread_data_ptr thread_info;
 
-#ifdef BOOST_THREAD_PLATFORM_WIN32
- void start_thread();
- void start_thread(const attributes& attr);
-#else
     private:
         bool start_thread_noexcept();
         bool start_thread_noexcept(const attributes& attr);
@@ -285,7 +281,6 @@
           }
         }
 
-#endif
         explicit thread(detail::thread_data_ptr data);
 
         detail::thread_data_ptr get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const;
@@ -542,14 +537,10 @@
 
 
         bool joinable() const BOOST_NOEXCEPT;
-#if defined(BOOST_THREAD_PLATFORM_WIN32)
- void join();
-#else
     private:
         bool join_noexcept();
     public:
         inline void join();
-#endif
 
 #ifdef BOOST_THREAD_USES_CHRONO
         template <class Rep, class Period>
@@ -574,10 +565,15 @@
         }
 #endif
 #if defined(BOOST_THREAD_PLATFORM_WIN32)
- bool timed_join(const system_time& abs_time);
     private:
- bool do_try_join_until(uintmax_t milli);
+ bool do_try_join_until_noexcept(uintmax_t milli, bool& res);
+ inline bool do_try_join_until(uintmax_t milli);
     public:
+ bool timed_join(const system_time& abs_time);
+ //{
+ // return do_try_join_until(get_milliseconds_until(wait_until));
+ //}
+
 #ifdef BOOST_THREAD_USES_CHRONO
         bool try_join_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
         {
@@ -592,7 +588,7 @@
         bool do_try_join_until_noexcept(struct timespec const &timeout, bool& res);
         inline bool do_try_join_until(struct timespec const &timeout);
     public:
-#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 || defined BOOST_THREAD_DONT_USE_CHRONO
+#if defined BOOST_THREAD_USES_DATETIME
         bool timed_join(const system_time& abs_time)
         {
           struct timespec const ts=detail::get_timespec(abs_time);
@@ -615,7 +611,7 @@
 #endif
       public:
 
-#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 || defined BOOST_THREAD_DONT_USE_CHRONO
+#if defined BOOST_THREAD_USES_DATETIME
         template<typename TimeDuration>
         inline bool timed_join(TimeDuration const& rel_time)
         {
@@ -630,7 +626,7 @@
         typedef detail::thread_data_base::native_handle_type native_handle_type;
         native_handle_type native_handle();
 
-#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
+#if defined BOOST_THREAD_PROVIDES_THREAD_EQ
         // Use thread::id when comparisions are needed
         // backwards compatibility
         bool operator==(const thread& other) const;
@@ -641,7 +637,7 @@
             this_thread::yield();
         }
 
-#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 || defined BOOST_THREAD_DONT_USE_CHRONO
+#if defined BOOST_THREAD_USES_DATETIME
         static inline void sleep(const system_time& xt)
         {
             this_thread::sleep(xt);
@@ -679,7 +675,7 @@
         bool BOOST_THREAD_DECL interruption_enabled() BOOST_NOEXCEPT;
         bool BOOST_THREAD_DECL interruption_requested() BOOST_NOEXCEPT;
 
-#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 || defined BOOST_THREAD_DONT_USE_CHRONO
+#if defined BOOST_THREAD_USES_DATETIME
         inline BOOST_SYMBOL_VISIBLE void sleep(xtime const& abs_time)
         {
             sleep(system_time(abs_time));
@@ -720,12 +716,8 @@
     public:
         id() BOOST_NOEXCEPT:
 #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
-#if defined(BOOST_THREAD_PLATFORM_WIN32)
         thread_data(0)
 #else
- thread_data(0)
-#endif
-#else
         thread_data()
 #endif
         {}
@@ -825,6 +817,7 @@
         #endif
         }
     }
+#endif
     void thread::join() {
         if (this_thread::get_id() == get_id())
         {
@@ -838,7 +831,11 @@
         }
     }
 
+#ifdef BOOST_THREAD_PLATFORM_PTHREAD
     bool thread::do_try_join_until(struct timespec const &timeout)
+#else
+ bool thread::do_try_join_until(uintmax_t timeout)
+#endif
     {
         if (this_thread::get_id() == get_id())
         {
@@ -858,8 +855,6 @@
         }
     }
 
-#endif
-
 #if !defined(BOOST_NO_IOSTREAM) && defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
     template<class charT, class traits>
     BOOST_SYMBOL_VISIBLE
@@ -870,7 +865,7 @@
     }
 #endif
 
-#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
+#if defined BOOST_THREAD_PROVIDES_THREAD_EQ
     inline bool thread::operator==(const thread& other) const
     {
         return get_id()==other.get_id();

Modified: trunk/boost/thread/future.hpp
==============================================================================
--- trunk/boost/thread/future.hpp (original)
+++ trunk/boost/thread/future.hpp 2012-10-20 10:05:32 EDT (Sat, 20 Oct 2012)
@@ -58,7 +58,6 @@
 #define BOOST_THREAD_FUTURE unique_future
 #endif
 
-
 namespace boost
 {
 
@@ -210,6 +209,50 @@
 
     namespace detail
     {
+#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
+ struct future_continuation_base
+ {
+ future_continuation_base() {}
+ virtual ~future_continuation_base() {}
+
+ virtual void do_continuation(boost::unique_lock<boost::mutex>& ) {};
+ private:
+ future_continuation_base(future_continuation_base const&);
+ future_continuation_base& operator=(future_continuation_base const&);
+ };
+
+ template <typename F, typename R, typename C>
+ struct future_continuation;
+
+#endif
+
+ struct relocker
+ {
+ boost::unique_lock<boost::mutex>& lock_;
+ bool unlocked_;
+
+ relocker(boost::unique_lock<boost::mutex>& lk):
+ lock_(lk)
+ {
+ lock_.unlock();
+ unlocked_=true;
+ }
+ ~relocker()
+ {
+ if (unlocked_) {
+ lock_.lock();
+ }
+ }
+ void lock() {
+ if (unlocked_) {
+ lock_.lock();
+ unlocked_=false;
+ }
+ }
+ private:
+ relocker& operator=(relocker const&);
+ };
+
         struct future_object_base
         {
             boost::exception_ptr exception;
@@ -220,10 +263,16 @@
             typedef std::list<boost::condition_variable_any*> waiter_list;
             waiter_list external_waiters;
             boost::function<void()> callback;
+#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
+ shared_ptr<future_continuation_base> continuation_ptr;
+#endif
 
             future_object_base():
                 done(false),
                 thread_was_interrupted(false)
+#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
+ , continuation_ptr()
+#endif
             {}
             virtual ~future_object_base()
             {}
@@ -241,7 +290,28 @@
                 external_waiters.erase(it);
             }
 
- void mark_finished_internal()
+#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
+ void do_continuation(boost::unique_lock<boost::mutex>& lock)
+ {
+ if (continuation_ptr) {
+ continuation_ptr->do_continuation(lock);
+ }
+ }
+#else
+ void do_continuation(boost::unique_lock<boost::mutex>&)
+ {
+ }
+#endif
+#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
+ void set_continuation_ptr(future_continuation_base* continuation, boost::unique_lock<boost::mutex>& lock)
+ {
+ continuation_ptr.reset(continuation);
+ if (done) {
+ do_continuation(lock);
+ }
+ }
+#endif
+ void mark_finished_internal(boost::unique_lock<boost::mutex>& lock)
             {
                 done=true;
                 waiters.notify_all();
@@ -250,25 +320,9 @@
                 {
                     (*it)->notify_all();
                 }
+ do_continuation(lock);
             }
 
- struct relocker
- {
- boost::unique_lock<boost::mutex>& lock;
-
- relocker(boost::unique_lock<boost::mutex>& lock_):
- lock(lock_)
- {
- lock.unlock();
- }
- ~relocker()
- {
- lock.lock();
- }
- private:
- relocker& operator=(relocker const&);
- };
-
             void do_callback(boost::unique_lock<boost::mutex>& lock)
             {
                 if(callback && !done)
@@ -280,9 +334,8 @@
             }
 
 
- void wait(bool rethrow=true)
+ void wait_internal(boost::unique_lock<boost::mutex> &lock, bool rethrow=true)
             {
- boost::unique_lock<boost::mutex> lock(mutex);
                 do_callback(lock);
                 while(!done)
                 {
@@ -296,8 +349,15 @@
                 {
                     boost::rethrow_exception(exception);
                 }
+
+ }
+ void wait(bool rethrow=true)
+ {
+ boost::unique_lock<boost::mutex> lock(mutex);
+ wait_internal(lock, rethrow);
             }
 
+#if defined BOOST_THREAD_USES_DATETIME
             bool timed_wait_until(boost::system_time const& target_time)
             {
                 boost::unique_lock<boost::mutex> lock(mutex);
@@ -312,7 +372,7 @@
                 }
                 return true;
             }
-
+#endif
 #ifdef BOOST_THREAD_USES_CHRONO
 
             template <class Clock, class Duration>
@@ -332,21 +392,21 @@
               return future_status::ready;
             }
 #endif
- void mark_exceptional_finish_internal(boost::exception_ptr const& e)
+ void mark_exceptional_finish_internal(boost::exception_ptr const& e, boost::unique_lock<boost::mutex>& lock)
             {
                 exception=e;
- mark_finished_internal();
+ mark_finished_internal(lock);
             }
             void mark_exceptional_finish()
             {
- boost::lock_guard<boost::mutex> lock(mutex);
- mark_exceptional_finish_internal(boost::current_exception());
+ boost::unique_lock<boost::mutex> lock(mutex);
+ mark_exceptional_finish_internal(boost::current_exception(), lock);
             }
             void mark_interrupted_finish()
             {
- boost::lock_guard<boost::mutex> lock(mutex);
+ boost::unique_lock<boost::mutex> lock(mutex);
                 thread_was_interrupted=true;
- mark_finished_internal();
+ mark_finished_internal(lock);
             }
             bool has_value()
             {
@@ -463,30 +523,35 @@
                 result(0)
             {}
 
- void mark_finished_with_result_internal(source_reference_type result_)
+ ~future_object()
+ {
+ }
+
+ void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock)
             {
                 future_traits<T>::init(result,result_);
- mark_finished_internal();
+ mark_finished_internal(lock);
             }
 
- void mark_finished_with_result_internal(rvalue_source_type result_)
+ 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();
+ mark_finished_internal(lock);
             }
 
             void mark_finished_with_result(source_reference_type result_)
             {
- boost::lock_guard<boost::mutex> lock(mutex);
- mark_finished_with_result_internal(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::lock_guard<boost::mutex> lock(mutex);
- mark_finished_with_result_internal(static_cast<rvalue_source_type>(result_));
+ boost::unique_lock<boost::mutex> lock(mutex);
+ mark_finished_with_result_internal(static_cast<rvalue_source_type>(result_), lock);
             }
 
+
             move_dest_type get()
             {
                 wait();
@@ -527,15 +592,15 @@
             future_object()
             {}
 
- void mark_finished_with_result_internal()
+ void mark_finished_with_result_internal(boost::unique_lock<boost::mutex>& lock)
             {
- mark_finished_internal();
+ mark_finished_internal(lock);
             }
 
             void mark_finished_with_result()
             {
- boost::lock_guard<boost::mutex> lock(mutex);
- mark_finished_with_result_internal();
+ boost::unique_lock<boost::mutex> lock(mutex);
+ mark_finished_with_result_internal(lock);
             }
 
             void get()
@@ -590,7 +655,6 @@
                                   count_type index_):
                     future_(a_future),wait_iterator(wait_iterator_),index(index_)
                 {}
-
             };
 
             struct all_futures_lock
@@ -812,7 +876,10 @@
 
         friend class shared_future<R>;
         friend class promise<R>;
-
+#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
+ template <typename, typename, typename>
+ friend struct detail::future_continuation;
+#endif
 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
         template <class> friend class packaged_task; // todo check if this works in windows
 #else
@@ -918,6 +985,7 @@
             future_->wait(false);
         }
 
+#if defined BOOST_THREAD_USES_DATETIME
         template<typename Duration>
         bool timed_wait(Duration const& rel_time) const
         {
@@ -932,6 +1000,7 @@
             }
             return future_->timed_wait_until(abs_time);
         }
+#endif
 #ifdef BOOST_THREAD_USES_CHRONO
         template <class Rep, class Period>
         future_status
@@ -951,6 +1020,14 @@
           return future_->wait_until(abs_time);
         }
 #endif
+
+#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
+// template<typename F>
+// auto then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
+ template<typename F>
+ inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE&)>::type> then(F&& func);
+
+#endif
     };
 
     BOOST_THREAD_DCL_MOVABLE_BEG(T) BOOST_THREAD_FUTURE<T> BOOST_THREAD_DCL_MOVABLE_END
@@ -1072,6 +1149,7 @@
             future_->wait(false);
         }
 
+#if defined BOOST_THREAD_USES_DATETIME
         template<typename Duration>
         bool timed_wait(Duration const& rel_time) const
         {
@@ -1086,6 +1164,7 @@
             }
             return future_->timed_wait_until(abs_time);
         }
+#endif
 #ifdef BOOST_THREAD_USES_CHRONO
 
         template <class Rep, class Period>
@@ -1156,11 +1235,11 @@
         {
             if(future_)
             {
- boost::lock_guard<boost::mutex> lock(future_->mutex);
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
 
                 if(!future_->done)
                 {
- future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()));
+ future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
                 }
             }
         }
@@ -1206,35 +1285,35 @@
         void set_value(typename detail::future_traits<R>::source_reference_type r)
         {
             lazy_init();
- boost::lock_guard<boost::mutex> lock(future_->mutex);
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
             if(future_->done)
             {
                 boost::throw_exception(promise_already_satisfied());
             }
- future_->mark_finished_with_result_internal(r);
+ future_->mark_finished_with_result_internal(r, lock);
         }
 
 // void set_value(R && r);
         void set_value(typename detail::future_traits<R>::rvalue_source_type r)
         {
             lazy_init();
- boost::lock_guard<boost::mutex> lock(future_->mutex);
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
             if(future_->done)
             {
                 boost::throw_exception(promise_already_satisfied());
             }
- future_->mark_finished_with_result_internal(static_cast<typename detail::future_traits<R>::rvalue_source_type>(r));
+ future_->mark_finished_with_result_internal(static_cast<typename detail::future_traits<R>::rvalue_source_type>(r), lock);
         }
 
         void set_exception(boost::exception_ptr p)
         {
             lazy_init();
- boost::lock_guard<boost::mutex> lock(future_->mutex);
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
             if(future_->done)
             {
                 boost::throw_exception(promise_already_satisfied());
             }
- future_->mark_exceptional_finish_internal(p);
+ future_->mark_exceptional_finish_internal(p, lock);
         }
 
         // setting the result with deferred notification
@@ -1297,11 +1376,11 @@
         {
             if(future_)
             {
- boost::lock_guard<boost::mutex> lock(future_->mutex);
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
 
                 if(!future_->done)
                 {
- future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()));
+ future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
                 }
             }
         }
@@ -1350,23 +1429,23 @@
         void set_value()
         {
             lazy_init();
- boost::lock_guard<boost::mutex> lock(future_->mutex);
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
             if(future_->done)
             {
                 boost::throw_exception(promise_already_satisfied());
             }
- future_->mark_finished_with_result_internal();
+ future_->mark_finished_with_result_internal(lock);
         }
 
         void set_exception(boost::exception_ptr p)
         {
             lazy_init();
- boost::lock_guard<boost::mutex> lock(future_->mutex);
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
             if(future_->done)
             {
                 boost::throw_exception(promise_already_satisfied());
             }
- future_->mark_exceptional_finish_internal(p);
+ future_->mark_exceptional_finish_internal(p,lock);
         }
 
         template<typename F>
@@ -1443,11 +1522,11 @@
 
             void owner_destroyed()
             {
- boost::lock_guard<boost::mutex> lk(this->mutex);
+ boost::unique_lock<boost::mutex> lk(this->mutex);
                 if(!started)
                 {
                     started=true;
- this->mark_exceptional_finish_internal(boost::copy_exception(boost::broken_promise()));
+ this->mark_exceptional_finish_internal(boost::copy_exception(boost::broken_promise()), lk);
                 }
             }
 
@@ -1925,7 +2004,7 @@
             {
                 boost::throw_exception(future_already_retrieved());
             }
- return BOOST_THREAD_FUTURE<R>();
+ //return BOOST_THREAD_FUTURE<R>();
 
         }
 
@@ -2178,7 +2257,7 @@
   {
     typedef typename decay<T>::type future_type;
     promise<future_type> p;
- p.set_value(value);
+ p.set_value(boost::forward<T>(value));
     return p.get_future().share();
   }
 
@@ -2190,6 +2269,71 @@
 
   }
 #endif
+
+#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
+ namespace detail
+ {
+
+ template <typename F, typename R, typename C>
+ struct future_continuation : future_continuation_base
+ {
+ F& parent;
+ C continuation;
+ promise<R> next;
+
+ future_continuation(F& f, C&& c) : parent(f), continuation(boost::forward<C>(c)), next()
+ {}
+ ~future_continuation()
+ {}
+
+ void do_continuation(boost::unique_lock<boost::mutex>& lk)
+ {
+ try
+ {
+ lk.unlock();
+ R val = continuation(parent);
+ next.set_value(boost::move(val));
+ }
+ catch (...)
+ {
+ next.set_exception(boost::current_exception());
+ }
+ }
+ private:
+
+ future_continuation(future_continuation const&);
+ future_continuation& operator=(future_continuation const&);
+ };
+ }
+
+// template<typename F>
+// auto then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
+ template <typename R>
+ template <typename F>
+ inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>&)>::type>
+ BOOST_THREAD_FUTURE<R>::then(F&& func)
+ {
+
+ typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>&)>::type future_type;
+
+ if (future_)
+ {
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
+ detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, F > *ptr =
+ new detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, F>(*this, boost::forward<F>(func));
+ if (ptr==0)
+ {
+ return BOOST_THREAD_FUTURE<future_type>();
+ }
+ future_->set_continuation_ptr(ptr, lock);
+ return ptr->next.get_future();
+ } else {
+ return BOOST_THREAD_FUTURE<future_type>();
+ }
+
+ }
+#endif
+
 }
 
 #endif // BOOST_NO_EXCEPTION

Modified: trunk/boost/thread/locks.hpp
==============================================================================
--- trunk/boost/thread/locks.hpp (original)
+++ trunk/boost/thread/locks.hpp 2012-10-20 10:05:32 EDT (Sat, 20 Oct 2012)
@@ -311,6 +311,7 @@
         {
             try_lock();
         }
+#if defined BOOST_THREAD_USES_DATETIME
         template<typename TimeDuration>
         unique_lock(Mutex& m_,TimeDuration const& target_time):
             m(&m_),is_locked(false)
@@ -322,7 +323,7 @@
         {
             timed_lock(target_time);
         }
-
+#endif
 #ifdef BOOST_THREAD_USES_CHRONO
         template <class Clock, class Duration>
         unique_lock(Mutex& mtx, const chrono::time_point<Clock, Duration>& t)
@@ -521,6 +522,7 @@
             is_locked=m->try_lock();
             return is_locked;
         }
+#if defined BOOST_THREAD_USES_DATETIME
         template<typename TimeDuration>
         bool timed_lock(TimeDuration const& relative_time)
         {
@@ -562,7 +564,7 @@
             is_locked=m->timed_lock(absolute_time);
             return is_locked;
         }
-
+#endif
 #ifdef BOOST_THREAD_USES_CHRONO
 
         template <class Rep, class Period>
@@ -686,12 +688,13 @@
         {
             try_lock();
         }
+#if defined BOOST_THREAD_USES_DATETIME
         shared_lock(Mutex& m_,system_time const& target_time):
             m(&m_),is_locked(false)
         {
             timed_lock(target_time);
         }
-
+#endif
 #ifdef BOOST_THREAD_USES_CHRONO
         template <class Clock, class Duration>
         shared_lock(Mutex& mtx, const chrono::time_point<Clock, Duration>& t)
@@ -809,6 +812,7 @@
             is_locked=m->try_lock_shared();
             return is_locked;
         }
+#if defined BOOST_THREAD_USES_DATETIME
         bool timed_lock(boost::system_time const& target_time)
         {
             if(m==0)
@@ -836,6 +840,7 @@
             is_locked=m->timed_lock_shared(target_time);
             return is_locked;
         }
+#endif
 #ifdef BOOST_THREAD_USES_CHRONO
         template <class Rep, class Period>
         bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)

Modified: trunk/boost/thread/pthread/condition_variable.hpp
==============================================================================
--- trunk/boost/thread/pthread/condition_variable.hpp (original)
+++ trunk/boost/thread/pthread/condition_variable.hpp 2012-10-20 10:05:32 EDT (Sat, 20 Oct 2012)
@@ -157,6 +157,7 @@
             while(!pred()) wait(m);
         }
 
+#if defined BOOST_THREAD_USES_DATETIME
         template<typename lock_type>
         bool timed_wait(lock_type& m,boost::system_time const& wait_until)
         {
@@ -197,7 +198,7 @@
         {
             return timed_wait(m,get_system_time()+wait_duration,pred);
         }
-
+#endif
 #ifdef BOOST_THREAD_USES_CHRONO
         template <class lock_type,class Duration>
         cv_status

Modified: trunk/boost/thread/pthread/condition_variable_fwd.hpp
==============================================================================
--- trunk/boost/thread/pthread/condition_variable_fwd.hpp (original)
+++ trunk/boost/thread/pthread/condition_variable_fwd.hpp 2012-10-20 10:05:32 EDT (Sat, 20 Oct 2012)
@@ -66,6 +66,7 @@
         }
 
 
+#if defined BOOST_THREAD_USES_DATETIME
         inline bool timed_wait(
             unique_lock<mutex>& m,
             boost::system_time const& wait_until)
@@ -121,6 +122,7 @@
         {
             return timed_wait(m,get_system_time()+wait_duration,pred);
         }
+#endif
 
 #ifdef BOOST_THREAD_USES_CHRONO
 

Modified: trunk/boost/thread/pthread/mutex.hpp
==============================================================================
--- trunk/boost/thread/pthread/mutex.hpp (original)
+++ trunk/boost/thread/pthread/mutex.hpp 2012-10-20 10:05:32 EDT (Sat, 20 Oct 2012)
@@ -146,6 +146,7 @@
 #endif
         }
 
+#if defined BOOST_THREAD_USES_DATETIME
         template<typename TimeDuration>
         bool timed_lock(TimeDuration const & relative_time)
         {
@@ -155,7 +156,7 @@
         {
             return timed_lock(system_time(absolute_time));
         }
-
+#endif
 #ifdef BOOST_PTHREAD_HAS_TIMEDLOCK
         void lock()
         {
@@ -232,12 +233,13 @@
     public:
 #endif
 
+#if defined BOOST_THREAD_USES_DATETIME
         bool timed_lock(system_time const & abs_time)
         {
             struct timespec const ts=detail::get_timespec(abs_time);
             return do_try_lock_until(ts);
         }
-
+#endif
 #ifdef BOOST_THREAD_USES_CHRONO
         template <class Rep, class Period>
         bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)

Modified: trunk/boost/thread/pthread/recursive_mutex.hpp
==============================================================================
--- trunk/boost/thread/pthread/recursive_mutex.hpp (original)
+++ trunk/boost/thread/pthread/recursive_mutex.hpp 2012-10-20 10:05:32 EDT (Sat, 20 Oct 2012)
@@ -232,11 +232,13 @@
 #endif
         }
 
+#if defined BOOST_THREAD_USES_DATETIME
         template<typename TimeDuration>
         bool timed_lock(TimeDuration const & relative_time)
         {
             return timed_lock(get_system_time()+relative_time);
         }
+#endif
 
 #ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
         void lock()
@@ -334,12 +336,13 @@
 
 #endif
 
+#if defined BOOST_THREAD_USES_DATETIME
         bool timed_lock(system_time const & abs_time)
         {
             struct timespec const ts=detail::get_timespec(abs_time);
             return do_try_lock_until(ts);
         }
-
+#endif
 #ifdef BOOST_THREAD_USES_CHRONO
         template <class Rep, class Period>
         bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)

Modified: trunk/boost/thread/pthread/shared_mutex.hpp
==============================================================================
--- trunk/boost/thread/pthread/shared_mutex.hpp (original)
+++ trunk/boost/thread/pthread/shared_mutex.hpp 2012-10-20 10:05:32 EDT (Sat, 20 Oct 2012)
@@ -88,6 +88,7 @@
             }
         }
 
+#if defined BOOST_THREAD_USES_DATETIME
         bool timed_lock_shared(system_time const& timeout)
         {
             boost::this_thread::disable_interruption do_not_disturb;
@@ -109,6 +110,7 @@
         {
             return timed_lock_shared(get_system_time()+relative_time);
         }
+#endif
 #ifdef BOOST_THREAD_USES_CHRONO
         template <class Rep, class Period>
         bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time)
@@ -166,6 +168,7 @@
             state.exclusive=true;
         }
 
+#if defined BOOST_THREAD_USES_DATETIME
         bool timed_lock(system_time const& timeout)
         {
             boost::this_thread::disable_interruption do_not_disturb;
@@ -194,7 +197,7 @@
         {
             return timed_lock(get_system_time()+relative_time);
         }
-
+#endif
 #ifdef BOOST_THREAD_USES_CHRONO
         template <class Rep, class Period>
         bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
@@ -262,6 +265,7 @@
             state.upgrade=true;
         }
 
+#if defined BOOST_THREAD_USES_DATETIME
         bool timed_lock_upgrade(system_time const& timeout)
         {
             boost::this_thread::disable_interruption do_not_disturb;
@@ -287,7 +291,7 @@
         {
             return timed_lock_upgrade(get_system_time()+relative_time);
         }
-
+#endif
 #ifdef BOOST_THREAD_USES_CHRONO
         template <class Rep, class Period>
         bool try_lock_upgrade_for(const chrono::duration<Rep, Period>& rel_time)

Modified: trunk/boost/thread/pthread/thread_data.hpp
==============================================================================
--- trunk/boost/thread/pthread/thread_data.hpp (original)
+++ trunk/boost/thread/pthread/thread_data.hpp 2012-10-20 10:05:32 EDT (Sat, 20 Oct 2012)
@@ -233,6 +233,7 @@
 #endif
         void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT;
 
+#if defined BOOST_THREAD_USES_DATETIME
 #ifdef __DECXXX
         /// Workaround of DECCXX issue of incorrect template substitution
         template<typename TimeDuration>
@@ -252,6 +253,7 @@
             this_thread::sleep(get_system_time()+rel_time);
         }
 #endif
+#endif
     }
 }
 

Modified: trunk/libs/thread/doc/changes.qbk
==============================================================================
--- trunk/libs/thread/doc/changes.qbk (original)
+++ trunk/libs/thread/doc/changes.qbk 2012-10-20 10:05:32 EDT (Sat, 20 Oct 2012)
@@ -73,11 +73,12 @@
 * [@http://svn.boost.org/trac/boost/ticket/2797 #2797] Two problems with thread_specific_ptr.
 * [@http://svn.boost.org/trac/boost/ticket/5274 #5274] failed to compile future.hpp with stlport 5.1.5 under msvc8.1, because of undefined class.
 * [@http://svn.boost.org/trac/boost/ticket/5431 #5431] compile error in Windows CE 6.0(interlocked).
-* [@http://svn.boost.org/trac/boost/ticket/5752 #5752] boost::call_once() is unreliable on some platforms.
-[/* [@http://svn.boost.org/trac/boost/ticket/5696 #5696] win32 detail::set_tss_data does nothing when tss_cleanup_function is NULL].
+[/* [@http://svn.boost.org/trac/boost/ticket/5752 #5752] boost::call_once() is unreliable on some platforms.]
+* [@http://svn.boost.org/trac/boost/ticket/5696 #5696] win32 detail::set_tss_data does nothing when tss_cleanup_function is NULL.
+* [@http://svn.boost.org/trac/boost/ticket/6931 #6931] mutex waits forwever with Intel C++ Compiler XE 12.1.5.344 Build 20120612
 * [@http://svn.boost.org/trac/boost/ticket/7045 #7045] Thread library does not automatically compile date_time.
 * [@http://svn.boost.org/trac/boost/ticket/7173 #7173] wrong function name interrupt_point().
-* [@http://svn.boost.org/trac/boost/ticket/7200 #7200] Unable to build boost.thread modularized.
+* [@http://svn.boost.org/trac/boost/ticket/7200 #7200] Unable to build boost.thread modularized.
 * [@http://svn.boost.org/trac/boost/ticket/7220 #7220] gcc 4.6.2 warns about inline+dllimport functions.
 * [@http://svn.boost.org/trac/boost/ticket/7238 #7238] this_thread::sleep_for() does not respond to interrupt().
 * [@http://svn.boost.org/trac/boost/ticket/7245 #7245] Minor typos on documentation related to version 3.
@@ -87,6 +88,12 @@
 * [@http://svn.boost.org/trac/boost/ticket/7336 #7336] BOOST_THREAD_DONT_USE_SYSTEM doesn't work.
 * [@http://svn.boost.org/trac/boost/ticket/7329 #7349] packaged_task holds reference to temporary.
 * [@http://svn.boost.org/trac/boost/ticket/7350 #7350] allocator_destructor does not destroy object
+* [@http://svn.boost.org/trac/boost/ticket/7360 #7360] Memory leak in pthread implementation of boost::thread_specific_ptr
+* [@http://svn.boost.org/trac/boost/ticket/7370 #7370] Boost.Thread documentation
+* [@http://svn.boost.org/trac/boost/ticket/7438 #7438] Segmentation fault in test_once regression test in group.join_all();
+* [@http://svn.boost.org/trac/boost/ticket/7461 #7461] detail::win32::ReleaseSemaphore may be called with count_to_release equal to 0
+* [@http://svn.boost.org/trac/boost/ticket/7499 #7499] call_once doesn't call even once
+
          
 [heading Version 3.0.1 - boost 1.51]
 

Modified: trunk/libs/thread/doc/future_ref.qbk
==============================================================================
--- trunk/libs/thread/doc/future_ref.qbk (original)
+++ trunk/libs/thread/doc/future_ref.qbk 2012-10-20 10:05:32 EDT (Sat, 20 Oct 2012)
@@ -261,7 +261,16 @@
       __unique_future__(__unique_future__ && other) noexcept;
       __unique_future__& operator=(__unique_future__ && other) noexcept;
       shared_future<R> share();
-
+ template<typename F>
+ __unique_future__<typename boost::result_of<F(__unique_future__&)>::type>
+ then(F&& func); // EXTENSION
+ template<typename S, typename F>
+ __unique_future__<typename boost::result_of<F(__unique_future__&)>::type>
+ then(S& scheduler, F&& func); // EXTENSION NOT_YET_IMPLEMENTED
+ template<typename F>
+ __unique_future__<typename boost::result_of<F(__unique_future__&)>::type>
+ then(launch policy, F&& func); // EXTENSION NOT_YET_IMPLEMENTED
+
       void swap(__unique_future__& other) noexcept; // EXTENSION
 
       // retrieving the value
@@ -628,6 +637,60 @@
 
 [endsect]
 
+[section:then Member function `then()`]
+
+ template<typename F>
+ __unique_future__<typename boost::result_of<F(__unique_future__&)>::type>
+ then(F&& func); // EXTENSION
+ template<typename S, typename F>
+ __unique_future__<typename boost::result_of<F(__unique_future__&)>::type>
+ then(S& scheduler, F&& func); // EXTENSION
+ template<typename F>
+ __unique_future__<typename boost::result_of<F(__unique_future__&)>::type>
+ then(launch policy, F&& func); // EXTENSION
+
+[variablelist
+
+[[Notes:] [The three functions differ only by input parameters. The first only takes a callable object which accepts a
+future object as a parameter. The second function takes a scheduler as the first parameter and a callable object as
+the second parameter. The third function takes a launch policy as the first parameter and a callable object as the
+second parameter.]]
+
+[[Effects:] [
+
+- The continuation is called when the object's shared state is ready (has a value or exception stored).
+
+- The continuation launches according to the specified policy or scheduler.
+
+- When the scheduler or launch policy is not provided the continuation inherits the
+parent's launch policy or scheduler.
+
+- If the parent was created with std::promise or with a packaged_task (has no associated launch policy), the
+continuation behaves the same as the third overload with a policy argument of launch::async | launch::deferred and
+the same argument for func.
+
+- If the parent has a policy of launch::deferred and the continuation does not have a specified launch policy or
+scheduler, then the parent is filled by immediately calling .wait(), and the policy of the antecedent is
+launch::deferred
+
+]]
+
+[[Returns:] [An object of type future<decltype(func(*this))> that refers to the shared state created by the continuation.]]
+
+[[Postconditions:] [
+
+- The future object is moved to the parameter of the continuation function .
+
+- valid() == false on original future object immediately after it returns.
+
+]]
+
+]
+
+[endsect]
+
+
+
 
 [endsect]
 

Modified: trunk/libs/thread/doc/futures.qbk
==============================================================================
--- trunk/libs/thread/doc/futures.qbk (original)
+++ trunk/libs/thread/doc/futures.qbk 2012-10-20 10:05:32 EDT (Sat, 20 Oct 2012)
@@ -220,6 +220,65 @@
 
 [endsect]
 
+[section:then Associating future continuations]
+
+In asynchronous programming, it is very common for one asynchronous operation, on completion, to invoke a second
+operation and pass data to it. The current C++ standard does not allow one to register a continuation to a future.
+With .then, instead of waiting for the result, a continuation is "attached" to the asynchronous operation, which is
+invoked when the result is ready. Continuations registered using the .then function will help to avoid blocking waits
+or wasting threads on polling, greatly improving the responsiveness and scalability of an application.
+
+future.then provides the ability to sequentially compose two futures by declaring one to be the continuation of another.
+With .then the antecedent future is ready (has a value or exception stored in the shared state) before the continuation
+starts as instructed by the lambda function.
+
+In the example below the future<int> f2 is registered to be a continuation of future<int> f1 using the .then member
+function. This operation takes a lambda function which describes how f2 should proceed after f1 is ready.
+
+
+ #include <boost/thread/future.hpp>
+ using namespace boost;
+ int main()
+ {
+ future<int> f1 = async([]() { return 123; });
+ future<string> f2 = f1.then([](future<int> f) { return f.get().to_string(); // here .get() won't block });
+ }
+
+One key feature of this function is the ability to chain multiple asynchronous operations. In asynchronous programming,
+it's common to define a sequence of operations, in which each continuation executes only when the previous one completes.
+In some cases, the antecedent future produces a value that the continuation accepts as input. By using future.then,
+creating a chain of continuations becomes straightforward and intuitive:
+
+ myFuture.then(...).then(...).then(...).
+
+Some points to note are:
+
+* Each continuation will not begin until the preceding has completed.
+* If an exception is thrown, the following continuation can handle it in a try-catch block
+
+
+Input Parameters:
+
+* Lambda function2: One option which was considered was to follow JavaScript's approach and take two functions, one for
+success and one for error handling. However this option is not viable in C++ as there is no single base type for
+exceptions as there is in JavaScript. The lambda function takes a future as its input which carries the exception
+through. This makes propagating exceptions straightforward. This approach also simplifies the chaining of continuations.
+* Scheduler: Providing an overload to .then, to take a scheduler reference places great flexibility over the execution
+of the future in the programmer's hand. As described above, often taking a launch policy is not sufficient for powerful
+asynchronous operations. The lifetime of the scheduler must outlive the continuation.
+* Launch policy: if the additional flexibility that the scheduler provides is not required.
+
+
+Return values: The decision to return a future was based primarily on the ability to chain multiple continuations using
+.then. This benefit of composability gives the programmer incredible control and flexibility over their code. Returning
+a future object rather than a shared_future is also a much cheaper operation thereby improving performance. A
+shared_future object is not necessary to take advantage of the chaining feature. It is also easy to go from a future
+to a shared_future when needed using future::share().
+
+
+[endsect]
+
+
 [include future_ref.qbk]
 
 [endsect]
\ No newline at end of file

Added: trunk/libs/thread/example/future_then.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/thread/example/future_then.cpp 2012-10-20 10:05:32 EDT (Sat, 20 Oct 2012)
@@ -0,0 +1,37 @@
+// Copyright (C) 2012 Vicente Botet
+//
+// 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)
+
+#define BOOST_THREAD_VERSION 4
+#define BOOST_THREAD_DONT_PROVIDE_FUTURE_INVALID_AFTER_GET
+
+#include <boost/thread/future.hpp>
+#include <iostream>
+#include <string>
+#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
+
+int p1()
+{
+ return 123;
+}
+
+int p2(boost::future<int>& f)
+{
+ return 2 * f.get();
+}
+
+int main()
+{
+ boost::future<int> f1 = boost::async(p1);
+ boost::future<int> f2 = f1.then(p2);
+ std::cout << f2.get() << std::endl;
+ return 0;
+}
+#else
+
+int main()
+{
+ return 0;
+}
+#endif

Modified: trunk/libs/thread/src/pthread/thread.cpp
==============================================================================
--- trunk/libs/thread/src/pthread/thread.cpp (original)
+++ trunk/libs/thread/src/pthread/thread.cpp 2012-10-20 10:05:32 EDT (Sat, 20 Oct 2012)
@@ -6,6 +6,7 @@
 // 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)
 
+#define BOOST_THREAD_VERSION 2
 #include <boost/thread/detail/config.hpp>
 
 #include <boost/thread/thread.hpp>
@@ -400,6 +401,7 @@
     namespace this_thread
     {
 
+#if ! defined BOOST_THREAD_USES_DATETIME2
 #ifdef __DECXXX
         /// Workaround of DECCXX issue of incorrect template substitution
         template<>
@@ -443,7 +445,7 @@
                 }
             }
         }
-
+#endif
         void yield() BOOST_NOEXCEPT
         {
 # if defined(BOOST_HAS_SCHED_YIELD)

Modified: trunk/libs/thread/src/win32/thread.cpp
==============================================================================
--- trunk/libs/thread/src/win32/thread.cpp (original)
+++ trunk/libs/thread/src/win32/thread.cpp 2012-10-20 10:05:32 EDT (Sat, 20 Oct 2012)
@@ -11,6 +11,7 @@
 #ifndef WINVER
 #define WINVER 0x400
 #endif
+#define BOOST_THREAD_VERSION 2
 
 #include <boost/thread/thread.hpp>
 #include <boost/thread/once.hpp>
@@ -87,10 +88,15 @@
         void set_current_thread_data(detail::thread_data_base* new_data)
         {
             boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key);
- if(current_thread_tls_key!=TLS_OUT_OF_INDEXES)
+ if (current_thread_tls_key!=TLS_OUT_OF_INDEXES)
+ {
                 BOOST_VERIFY(TlsSetValue(current_thread_tls_key,new_data));
+ }
             else
- boost::throw_exception(thread_resource_error());
+ {
+ BOOST_VERIFY(false);
+ //boost::throw_exception(thread_resource_error());
+ }
         }
 
 #ifndef BOOST_HAS_THREADEX
@@ -212,29 +218,33 @@
     thread::thread() BOOST_NOEXCEPT
     {}
 
- void thread::start_thread()
+ bool thread::start_thread_noexcept()
     {
         uintptr_t const new_thread=_beginthreadex(0,0,&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id);
         if(!new_thread)
         {
- boost::throw_exception(thread_resource_error());
+ return false;
+// boost::throw_exception(thread_resource_error());
         }
         intrusive_ptr_add_ref(thread_info.get());
         thread_info->thread_handle=(detail::win32::handle)(new_thread);
         ResumeThread(thread_info->thread_handle);
+ return true;
     }
 
- void thread::start_thread(const attributes& attr)
+ bool thread::start_thread_noexcept(const attributes& attr)
     {
       //uintptr_t const new_thread=_beginthreadex(attr.get_security(),attr.get_stack_size(),&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id);
       uintptr_t const new_thread=_beginthreadex(0,static_cast<unsigned int>(attr.get_stack_size()),&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id);
       if(!new_thread)
       {
- boost::throw_exception(thread_resource_error());
+ return false;
+// boost::throw_exception(thread_resource_error());
       }
       intrusive_ptr_add_ref(thread_info.get());
       thread_info->thread_handle=(detail::win32::handle)(new_thread);
       ResumeThread(thread_info->thread_handle);
+ return true;
     }
 
     thread::thread(detail::thread_data_ptr data):
@@ -305,23 +315,22 @@
     {
         return (get_thread_info)();
     }
- void thread::join()
+ bool thread::join_noexcept()
     {
- if (this_thread::get_id() == get_id())
- {
- boost::throw_exception(thread_resource_error(system::errc::resource_deadlock_would_occur, "boost thread: trying joining itself"));
- }
+
         detail::thread_data_ptr local_thread_info=(get_thread_info)();
         if(local_thread_info)
         {
             this_thread::interruptible_wait(local_thread_info->thread_handle,detail::timeout::sentinel());
             release_handle();
+ return true;
         }
         else
         {
-#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
- boost::throw_exception(thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable"));
-#endif
+ return false;
+//#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
+// boost::throw_exception(thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable"));
+//#endif
         }
     }
 
@@ -330,27 +339,26 @@
       return do_try_join_until(get_milliseconds_until(wait_until));
     }
 
- bool thread::do_try_join_until(uintmax_t milli)
+ bool thread::do_try_join_until_noexcept(uintmax_t milli, bool& res)
     {
- if (this_thread::get_id() == get_id())
- {
- boost::throw_exception(thread_resource_error(system::errc::resource_deadlock_would_occur, "boost thread: trying joining itself"));
- }
       detail::thread_data_ptr local_thread_info=(get_thread_info)();
       if(local_thread_info)
       {
           if(!this_thread::interruptible_wait(local_thread_info->thread_handle,milli))
           {
- return false;
+ res=false;
+ return true;
           }
           release_handle();
+ res=true;
           return true;
       }
       else
       {
-#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
- boost::throw_exception(thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable"));
-#endif
+ return false;
+//#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
+// boost::throw_exception(thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable"));
+//#endif
       }
     }
 

Modified: trunk/libs/thread/test/Jamfile.v2
==============================================================================
--- trunk/libs/thread/test/Jamfile.v2 (original)
+++ trunk/libs/thread/test/Jamfile.v2 2012-10-20 10:05:32 EDT (Sat, 20 Oct 2012)
@@ -523,6 +523,7 @@
           #[ thread-run ../example/vhh_shared_monitor.cpp ]
           #[ thread-run ../example/vhh_shared_mutex.cpp ]
           [ thread-run ../example/make_future.cpp ]
+ [ thread-run ../example/future_then.cpp ]
 
     ;
 

Modified: trunk/libs/thread/test/test_2309.cpp
==============================================================================
--- trunk/libs/thread/test/test_2309.cpp (original)
+++ trunk/libs/thread/test/test_2309.cpp 2012-10-20 10:05:32 EDT (Sat, 20 Oct 2012)
@@ -3,6 +3,8 @@
 // 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)
 
+#define BOOST_THREAD_VERSION 2
+
 #include <boost/test/unit_test.hpp>
 
 #include <iostream>

Modified: trunk/libs/thread/test/test_3628.cpp
==============================================================================
--- trunk/libs/thread/test/test_3628.cpp (original)
+++ trunk/libs/thread/test/test_3628.cpp 2012-10-20 10:05:32 EDT (Sat, 20 Oct 2012)
@@ -3,6 +3,8 @@
 // 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)
 
+#define BOOST_THREAD_VERSION 2
+
 #include <boost/thread/thread.hpp>
 #include <boost/thread/condition.hpp>
 #include <boost/thread/recursive_mutex.hpp>

Modified: trunk/libs/thread/test/test_4882.cpp
==============================================================================
--- trunk/libs/thread/test/test_4882.cpp (original)
+++ trunk/libs/thread/test/test_4882.cpp 2012-10-20 10:05:32 EDT (Sat, 20 Oct 2012)
@@ -3,6 +3,8 @@
 // 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)
 
+#define BOOST_THREAD_VERSION 2
+
 #include <boost/thread/thread.hpp>
 #include <boost/thread/shared_mutex.hpp>
 #include <boost/detail/no_exceptions_support.hpp>

Modified: trunk/libs/thread/test/test_5542_1.cpp
==============================================================================
--- trunk/libs/thread/test/test_5542_1.cpp (original)
+++ trunk/libs/thread/test/test_5542_1.cpp 2012-10-20 10:05:32 EDT (Sat, 20 Oct 2012)
@@ -3,6 +3,8 @@
 // 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)
 
+#define BOOST_THREAD_VERSION 2
+
 #include <iostream>
 #include <boost/thread.hpp>
 

Modified: trunk/libs/thread/test/test_5542_3.cpp
==============================================================================
--- trunk/libs/thread/test/test_5542_3.cpp (original)
+++ trunk/libs/thread/test/test_5542_3.cpp 2012-10-20 10:05:32 EDT (Sat, 20 Oct 2012)
@@ -3,6 +3,8 @@
 // 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)
 
+#define BOOST_THREAD_VERSION 2
+
 #include <iostream>
 #include <boost/thread.hpp>
 #include <boost/date_time.hpp>

Modified: trunk/libs/thread/test/test_6130.cpp
==============================================================================
--- trunk/libs/thread/test/test_6130.cpp (original)
+++ trunk/libs/thread/test/test_6130.cpp 2012-10-20 10:05:32 EDT (Sat, 20 Oct 2012)
@@ -3,6 +3,8 @@
 // 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)
 
+#define BOOST_THREAD_VERSION 2
+
 #include <boost/thread.hpp>
 #include <boost/date_time/posix_time/posix_time_io.hpp>
 #include <assert.h>

Modified: trunk/libs/thread/test/test_lock_concept.cpp
==============================================================================
--- trunk/libs/thread/test/test_lock_concept.cpp (original)
+++ trunk/libs/thread/test/test_lock_concept.cpp 2012-10-20 10:05:32 EDT (Sat, 20 Oct 2012)
@@ -3,6 +3,8 @@
 // accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
+#define BOOST_THREAD_VERSION 2
+
 #include <boost/test/unit_test.hpp>
 #include <boost/mpl/vector.hpp>
 #include <boost/thread/mutex.hpp>

Modified: trunk/libs/thread/test/test_xtime.cpp
==============================================================================
--- trunk/libs/thread/test/test_xtime.cpp (original)
+++ trunk/libs/thread/test/test_xtime.cpp 2012-10-20 10:05:32 EDT (Sat, 20 Oct 2012)
@@ -5,6 +5,8 @@
 // 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)
 
+#define BOOST_THREAD_VERSION 2
+
 #include <boost/thread/detail/config.hpp>
 
 #include <boost/thread/xtime.hpp>


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