|
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