Skip to content

Commit

Permalink
Thread: merge atomic linked conditionaly + future:get_exception_ptr.
Browse files Browse the repository at this point in the history
[SVN r85666]
  • Loading branch information
viboes committed Sep 14, 2013
1 parent 134c323 commit 325d8cf
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 38 deletions.
12 changes: 7 additions & 5 deletions build/Jamfile.v2
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import os ;
import feature ;
import indirect ;
import path ;
import configure ;

project boost/thread
: source-location ../src
Expand Down Expand Up @@ -140,6 +141,8 @@ local rule default_threadapi ( )
feature.feature threadapi : pthread win32 : propagated ;
feature.set-default threadapi : [ default_threadapi ] ;

exe has_atomic_flag_lockfree : ../build/has_atomic_flag_lockfree_test.cpp ;

rule tag ( name : type ? : property-set )
{
local result = $(name) ;
Expand Down Expand Up @@ -264,16 +267,15 @@ rule requirements ( properties * )
}
}
result += <define>BOOST_THREAD_DONT_USE_CHRONO ;
if ! [ configure.builds has_atomic_flag_lockfree
: $(properties) : "lockfree boost::atomic_flag" ] {
result += <library>/boost/atomic//boost_atomic ;
}
} else {
result += <define>BOOST_THREAD_USES_CHRONO ;
result += <library>/boost/chrono//boost_chrono ;
}

#if <toolset>pgi in $(properties) || <toolset>vacpp in $(properties)
#{
result += <library>/boost/atomic//boost_atomic ;
#}

return $(result) ;
}

Expand Down
13 changes: 13 additions & 0 deletions build/has_atomic_flag_lockfree_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (c) 2013, Petr Machata, Red Hat Inc.
//
// Use modification and distribution are subject to the boost Software
// License, Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt).

#include "../../../boost/atomic.hpp"
#include "../../../boost/static_assert.hpp"

int main(int argc, char *argv[])
{
BOOST_STATIC_ASSERT(BOOST_ATOMIC_FLAG_LOCK_FREE);
return 0;
}
20 changes: 13 additions & 7 deletions doc/changes.qbk
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,28 @@

[*New Features:]

* [@http://svn.boost.org/trac/boost/ticket/8274 #8274] Synchro: Add concurrent queue
* [@http://svn.boost.org/trac/boost/ticket/8518 #8518] Synchro: Add a latch class.
* [@http://svn.boost.org/trac/boost/ticket/8519 #8519] Synchro: Update class barrier with a completion function.

* [@http://svn.boost.org/trac/boost/ticket/8515 #8515] Async: Add shared_future::then.
* [@http://svn.boost.org/trac/boost/ticket/8615 #8615] Async: Replace make_future/make_shared_future by make_ready_future.
* [@http://svn.boost.org/trac/boost/ticket/8627 #8627] Async: Add future<>::unwrap and unwrapping constructor.
* [@http://svn.boost.org/trac/boost/ticket/8677 #8677] Async: Add future<>::get_or.
* [@http://svn.boost.org/trac/boost/ticket/8678 #8678] Async: Add future<>::fallback_to.
* [@http://svn.boost.org/trac/boost/ticket/8955 #8955] Request for more efficient way to get exception_ptr from future.

* [@http://svn.boost.org/trac/boost/ticket/8891 #8891] upgrade_to_unique_lock: missing mutex() function
* [@http://svn.boost.org/trac/boost/ticket/8891 #8891] upgrade_to_unique_lock: missing mutex() function.

[*Fixed Bugs:]

* [@http://svn.boost.org/trac/boost/ticket/8931 #8931] Typos in external_locking reference
* [@http://svn.boost.org/trac/boost/ticket/9029 #9029] Misprint in documentation
* [@http://svn.boost.org/trac/boost/ticket/9037 #9037] [thread] gcc -Wshadow gives warnings in condition_variable{,_fwd}.hpp
* [@http://svn.boost.org/trac/boost/ticket/9041 #9041] [thread] Boost.Thread DSO's may need to link with Boost.Atomic
* [@http://svn.boost.org/trac/boost/ticket/8768 #8768] win32 condition_variable::wait_until infinite wait in rare cases.
* [@http://svn.boost.org/trac/boost/ticket/8817 #8817] Boost Thread Windows CE _createthreadex handling breaks mingw w64.
* [@http://svn.boost.org/trac/boost/ticket/8943 #8943] Failed to compile code using boost::call_once with Intel C++ Composer XE 2013 on Windows.
* [@http://svn.boost.org/trac/boost/ticket/8931 #8931] Typos in external_locking reference.
* [@http://svn.boost.org/trac/boost/ticket/9029 #9029] Misprint in documentation.
* [@http://svn.boost.org/trac/boost/ticket/9037 #9037] gcc -Wshadow gives warnings in condition_variable{,_fwd}.hpp.
* [@http://svn.boost.org/trac/boost/ticket/9041 #9041] Boost.Thread DSO's may need to link with Boost.Atomic.
* [@http://svn.boost.org/trac/boost/ticket/9048 #9048] boost::scoped_thread useless ctor with variadic template arguments.
* [@http://svn.boost.org/trac/boost/ticket/9079 #9079] Condition variable will wait forever for some timepoint values (Win).

[heading Version 4.1.0 - boost 1.54]

Expand Down Expand Up @@ -421,6 +425,8 @@ The following features will be included in next releases.
* [@http://svn.boost.org/trac/boost/ticket/7589 #7589] Synchro: Add polymorphic lockables.

# Add some features based on C++ proposals, in particular
* [@http://svn.boost.org/trac/boost/ticket/8274 #8274] Synchro: Add concurrent queue
* [@http://svn.boost.org/trac/boost/ticket/8518 #8518] Synchro: Add a latch class.
* [@http://svn.boost.org/trac/boost/ticket/8273 #8273] Synchro: Add externally locked streams.
* [@http://svn.boost.org/trac/boost/ticket/8513 #8513] Async: Add a basic thread_pool executor.
* [@http://svn.boost.org/trac/boost/ticket/8514 #8514] Async: Add a thread_pool executor with work stealing.
Expand Down
46 changes: 42 additions & 4 deletions doc/future_ref.qbk
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,8 @@ The object's `name` virtual function returns a pointer to the string "future".]]
// retrieving the value
see below get();
see below get_or(see below); // EXTENSION

exception_ptr get_exception_ptr(); // EXTENSION

// functions to check state
bool valid() const noexcept;
Expand Down Expand Up @@ -758,6 +760,23 @@ stored exception, `false` otherwise.]]

]

[endsect]
[/////////////////////////////////////////////////////////////////]
[section:get_exception_ptr Member function `get_exception_ptr()` EXTENSION]

exception_ptr get_exception_ptr();

[variablelist

[[Effects:] [If `*this` is associated with a shared state, waits until the result is ready. If the result is not ready on
entry, and the result has a ['wait callback] set, that callback is invoked prior to waiting.]]

[[Returns:] [a exception_ptr, storring or not an exception.]]

[[Throws:] [Whatever `mutex::lock()/mutex::unlock()` can throw.]]

]

[endsect]
[/////////////////////////////////////////////////////////]
[section:get_state Member function `get_state()` EXTENSION]
Expand Down Expand Up @@ -925,6 +944,8 @@ There are not too much tests yet, so it is possible that you can find out some t
// retrieving the value
see below get();

exception_ptr get_exception_ptr(); // EXTENSION

// functions to check state, and wait for ready
bool valid() const noexcept;
bool is_ready() const noexcept; // EXTENSION
Expand Down Expand Up @@ -1185,7 +1206,7 @@ otherwise.]]
[[Returns:] [`true` if `*this` is associated with a shared state, and that result is ready for retrieval, `false`
otherwise.]]

[[Throws:] [Nothing.]]
[[Throws:] [Whatever `mutex::lock()/mutex::unlock()` can throw.]]

]

Expand All @@ -1200,7 +1221,7 @@ otherwise.]]
[[Returns:] [`true` if `*this` is associated with a shared state, that result is ready for retrieval, and the result is a
stored value, `false` otherwise.]]

[[Throws:] [Nothing.]]
[[Throws:] [Whatever `mutex::lock()/mutex::unlock()` can throw.]]

]

Expand All @@ -1215,7 +1236,24 @@ stored value, `false` otherwise.]]
[[Returns:] [`true` if `*this` is associated with a shared state, that result is ready for retrieval, and the result is a
stored exception, `false` otherwise.]]

[[Throws:] [Nothing.]]
[[Throws:] [Whatever `mutex::lock()/mutex::unlock()` can throw.]]

]

[endsect]
[/////////////////////////////////////////////////////////////////]
[section:get_exception_ptr Member function `get_exception_ptr()` EXTENSION]

exception_ptr get_exception_ptr();

[variablelist

[[Effects:] [If `*this` is associated with a shared state, waits until the result is ready. If the result is not ready on
entry, and the result has a ['wait callback] set, that callback is invoked prior to waiting.]]

[[Returns:] [a exception_ptr, storring or not an exception.]]

[[Throws:] [Whatever `mutex::lock()/mutex::unlock()` can throw.]]

]

Expand All @@ -1232,7 +1270,7 @@ stored exception, `false` otherwise.]]
[[Returns:] [__uninitialized__ if `*this` is not associated with a shared state. __ready__ if the shared state
associated with `*this` is ready for retrieval, __waiting__ otherwise.]]

[[Throws:] [Nothing.]]
[[Throws:] [Whatever `mutex::lock()/mutex::unlock()` can throw.]]

]

Expand Down
2 changes: 1 addition & 1 deletion doc/sync_tutorial.qbk
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ In particular, the library provides some lock factories.

that can be used as

int i = with_lock_guard(mtx, {}() -> bool
int i = with_lock_guard(mtx, []()
{
// access the protected state
return true;
Expand Down
4 changes: 2 additions & 2 deletions doc/thread.qbk
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@
[include condition_variables.qbk]
[include once.qbk]
[include barrier.qbk]
[include latch.qbk]
[/include latch.qbk]
[include futures.qbk]
[/include async_executors.qbk]
[endsect]
Expand All @@ -249,7 +249,7 @@

[section:sds Synchronized Data Structures]
[include synchronized_value.qbk]
[include sync_queues_ref.qbk]
[/include sync_queues_ref.qbk]
[/include sync_streams.qbk]
[endsect]

Expand Down
2 changes: 1 addition & 1 deletion example/scoped_thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ int main()
do_something_in_current_thread();
}
{
boost::scoped_thread<> g( f, 1, 2 );
boost::scoped_thread<> g( &f, 1, 2 );
do_something_in_current_thread();
}
return 0;
Expand Down
60 changes: 42 additions & 18 deletions include/boost/thread/future.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ namespace boost
bool is_deferred_;
launch policy_;
bool is_constructed;
boost::mutex mutex;
mutable boost::mutex mutex;
boost::condition_variable waiters;
waiter_list external_waiters;
boost::function<void()> callback;
Expand Down Expand Up @@ -434,7 +434,7 @@ namespace boost
get_current_thread_data()->make_ready_at_thread_exit(shared_from_this());
}

bool has_value()
bool has_value() const
{
boost::lock_guard<boost::mutex> lock(mutex);
return done && !(exception
Expand All @@ -444,7 +444,7 @@ namespace boost
);
}

bool has_value(unique_lock<boost::mutex>& )
bool has_value(unique_lock<boost::mutex>& ) const
{
return done && !(exception
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Expand All @@ -453,7 +453,7 @@ namespace boost
);
}

bool has_exception()
bool has_exception() const
{
boost::lock_guard<boost::mutex> lock(mutex);
return done && (exception
Expand All @@ -463,7 +463,7 @@ namespace boost
);
}

bool has_exception(unique_lock<boost::mutex>&)
bool has_exception(unique_lock<boost::mutex>&) const
{
return done && (exception
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
Expand All @@ -472,16 +472,16 @@ namespace boost
);
}

bool is_deferred() const BOOST_NOEXCEPT {
bool is_deferred(boost::lock_guard<boost::mutex>&) const {
return is_deferred_;
}

launch launch_policy() const BOOST_NOEXCEPT
launch launch_policy(boost::unique_lock<boost::mutex>&) const
{
return policy_;
}

future_state::state get_state()
future_state::state get_state() const
{
boost::lock_guard<boost::mutex> guard(mutex);
if(!done)
Expand All @@ -494,6 +494,23 @@ namespace boost
}
}

exception_ptr get_exception_ptr()
{
boost::unique_lock<boost::mutex> lock(mutex);
return get_exception_ptr(lock);
}
exception_ptr get_exception_ptr(boost::unique_lock<boost::mutex>& lock)
{
wait_internal(lock, false);
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
if(thread_was_interrupted)
{
return copy_exception(boost::thread_interrupted());
}
#endif
return exception;
}

template<typename F,typename U>
void set_wait_callback(F f,U* u)
{
Expand Down Expand Up @@ -1294,7 +1311,7 @@ namespace boost
future_.swap(that.future_);
}
// functions to check state, and wait for ready
state get_state() const BOOST_NOEXCEPT
state get_state() const
{
if(!future_)
{
Expand All @@ -1303,27 +1320,34 @@ namespace boost
return future_->get_state();
}

bool is_ready() const BOOST_NOEXCEPT
bool is_ready() const
{
return get_state()==future_state::ready;
}

bool has_exception() const BOOST_NOEXCEPT
bool has_exception() const
{
return future_ && future_->has_exception();
}

bool has_value() const BOOST_NOEXCEPT
bool has_value() const
{
return future_ && future_->has_value();
}

launch launch_policy() const BOOST_NOEXCEPT
launch launch_policy(boost::unique_lock<boost::mutex>& lk) const
{
if ( future_ ) return future_->launch_policy();
if ( future_ ) return future_->launch_policy(lk);
else return launch(launch::none);
}

exception_ptr get_exception_ptr()
{
return future_
? future_->get_exception_ptr()
: exception_ptr();
}

bool valid() const BOOST_NOEXCEPT
{
return future_ != 0;
Expand Down Expand Up @@ -3938,13 +3962,13 @@ namespace boost
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());

boost::unique_lock<boost::mutex> lock(this->future_->mutex);
if (int(this->launch_policy()) & int(launch::async))
if (int(this->launch_policy(lock)) & int(launch::async))
{
return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
lock, boost::move(*this), boost::forward<F>(func)
);
}
else if (int(this->launch_policy()) & int(launch::deferred))
else if (int(this->launch_policy(lock)) & int(launch::deferred))
{
this->future_->wait_internal(lock);
return boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
Expand Down Expand Up @@ -4056,13 +4080,13 @@ namespace boost
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());

boost::unique_lock<boost::mutex> lock(this->future_->mutex);
if (int(this->launch_policy()) & int(launch::async))
if (int(this->launch_policy(lock)) & int(launch::async))
{
return boost::detail::make_future_async_continuation_shared_state<shared_future<R>, future_type, F>(
lock, boost::move(*this), boost::forward<F>(func)
);
}
else if (int(this->launch_policy()) & int(launch::deferred))
else if (int(this->launch_policy(lock)) & int(launch::deferred))
{
this->future_->wait_internal(lock);
return boost::detail::make_future_deferred_continuation_shared_state<shared_future<R>, future_type, F>(
Expand Down

0 comments on commit 325d8cf

Please sign in to comment.