|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r83938 - in branches/release: boost/thread boost/thread/detail libs/thread libs/thread/build libs/thread/doc libs/thread/src libs/thread/test
From: vicente.botet_at_[hidden]
Date: 2013-04-17 00:30:49
Author: viboes
Date: 2013-04-17 00:30:48 EDT (Wed, 17 Apr 2013)
New Revision: 83938
URL: http://svn.boost.org/trac/boost/changeset/83938
Log:
Thread: merge from trunk to fix #6843,#6966.
Added:
branches/release/libs/thread/test/test_ml2.cpp
- copied unchanged from r83895, /trunk/libs/thread/test/test_ml2.cpp
Properties modified:
branches/release/boost/thread/ (props changed)
branches/release/libs/thread/ (props changed)
Text files modified:
branches/release/boost/thread/detail/move.hpp | 1
branches/release/boost/thread/future.hpp | 6
branches/release/boost/thread/lock_types.hpp | 15 +
branches/release/libs/thread/build/Jamfile.v2 | 4
branches/release/libs/thread/doc/changes.qbk | 10 +
branches/release/libs/thread/doc/future_ref.qbk | 62 +++++---
branches/release/libs/thread/doc/sync_queues_ref.qbk | 271 +++++++++++++++++++++++++++++----------
branches/release/libs/thread/src/future.cpp | 2
8 files changed, 272 insertions(+), 99 deletions(-)
Modified: branches/release/boost/thread/detail/move.hpp
==============================================================================
--- branches/release/boost/thread/detail/move.hpp (original)
+++ branches/release/boost/thread/detail/move.hpp 2013-04-17 00:30:48 EDT (Wed, 17 Apr 2013)
@@ -18,6 +18,7 @@
#include <boost/thread/detail/delete.hpp>
#include <boost/move/utility.hpp>
+#include <boost/move/traits.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
Modified: branches/release/boost/thread/future.hpp
==============================================================================
--- branches/release/boost/thread/future.hpp (original)
+++ branches/release/boost/thread/future.hpp 2013-04-17 00:30:48 EDT (Wed, 17 Apr 2013)
@@ -1707,11 +1707,13 @@
void lazy_init()
{
#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
- if(!atomic_load(&future_))
+#include <boost/detail/atomic_undef_macros.hpp>
+ if(!atomic_load(&future_))
{
future_ptr blank;
atomic_compare_exchange(&future_,&blank,future_ptr(new detail::future_object<R>));
}
+#include <boost/detail/atomic_redef_macros.hpp>
#endif
}
@@ -1874,11 +1876,13 @@
void lazy_init()
{
#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
+#include <boost/detail/atomic_undef_macros.hpp>
if(!atomic_load(&future_))
{
future_ptr blank;
atomic_compare_exchange(&future_,&blank,future_ptr(new detail::future_object<R&>));
}
+#include <boost/detail/atomic_redef_macros.hpp>
#endif
}
Modified: branches/release/boost/thread/lock_types.hpp
==============================================================================
--- branches/release/boost/thread/lock_types.hpp (original)
+++ branches/release/boost/thread/lock_types.hpp 2013-04-17 00:30:48 EDT (Wed, 17 Apr 2013)
@@ -174,7 +174,8 @@
BOOST_THREAD_EXPLICIT_LOCK_CONVERSION unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other);
#ifndef BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION
- unique_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT
+ //std-2104 unique_lock move-assignment should not be noexcept
+ unique_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other) //BOOST_NOEXCEPT
{
unique_lock temp(::boost::move(other));
swap(temp);
@@ -182,7 +183,8 @@
}
#endif
- unique_lock& operator=(BOOST_THREAD_RV_REF(unique_lock) other) BOOST_NOEXCEPT
+ //std-2104 unique_lock move-assignment should not be noexcept
+ unique_lock& operator=(BOOST_THREAD_RV_REF(unique_lock) other) //BOOST_NOEXCEPT
{
unique_lock temp(::boost::move(other));
swap(temp);
@@ -581,7 +583,8 @@
BOOST_THREAD_RV(other).m=0;
}
- shared_lock& operator=(BOOST_THREAD_RV_REF_BEG shared_lock<Mutex> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT
+ //std-2104 unique_lock move-assignment should not be noexcept
+ shared_lock& operator=(BOOST_THREAD_RV_REF_BEG shared_lock<Mutex> BOOST_THREAD_RV_REF_END other) //BOOST_NOEXCEPT
{
shared_lock temp(::boost::move(other));
swap(temp);
@@ -826,7 +829,8 @@
BOOST_THREAD_RV(other).m=0;
}
- upgrade_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT
+ //std-2104 unique_lock move-assignment should not be noexcept
+ upgrade_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other) //BOOST_NOEXCEPT
{
upgrade_lock temp(::boost::move(other));
swap(temp);
@@ -1073,7 +1077,8 @@
BOOST_THREAD_RV(other).source=0;
}
- upgrade_to_unique_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_to_unique_lock<Mutex> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT
+ //std-2104 unique_lock move-assignment should not be noexcept
+ upgrade_to_unique_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_to_unique_lock<Mutex> BOOST_THREAD_RV_REF_END other) //BOOST_NOEXCEPT
{
upgrade_to_unique_lock temp(other);
swap(temp);
Modified: branches/release/libs/thread/build/Jamfile.v2
==============================================================================
--- branches/release/libs/thread/build/Jamfile.v2 (original)
+++ branches/release/libs/thread/build/Jamfile.v2 2013-04-17 00:30:48 EDT (Wed, 17 Apr 2013)
@@ -279,6 +279,7 @@
win32/thread.cpp
win32/tss_dll.cpp
win32/tss_pe.cpp
+ future.cpp
: ## requirements ##
<threadapi>win32
;
@@ -287,6 +288,7 @@
: ## pthread sources ##
pthread/thread.cpp
pthread/once.cpp
+ future.cpp
: ## requirements ##
<threadapi>pthread
;
@@ -294,7 +296,7 @@
explicit thread_sources ;
lib boost_thread
- : thread_sources future.cpp
+ : thread_sources
: <conditional>@requirements
:
: <link>shared:<define>BOOST_THREAD_USE_DLL=1
Modified: branches/release/libs/thread/doc/changes.qbk
==============================================================================
--- branches/release/libs/thread/doc/changes.qbk (original)
+++ branches/release/libs/thread/doc/changes.qbk 2013-04-17 00:30:48 EDT (Wed, 17 Apr 2013)
@@ -25,14 +25,21 @@
[*New Features:]
* [@http://svn.boost.org/trac/boost/ticket/7285 #7285] C++11 compliance: Allow to pass movable arguments for call_once.
+* [@http://svn.boost.org/trac/boost/ticket/7445 #7445] Async: Add future<>.then
* [@http://svn.boost.org/trac/boost/ticket/7449 #7449] Synchro: Add a synchronized value class
[*Fixed Bugs:]
+* [@http://svn.boost.org/trac/boost/ticket/4878 #4878] MinGW 4.5.0 undefined reference to bool interruptible_wait(detail::win32::handle handle_to_wait_for,detail::t imeout target_time).
* [@http://svn.boost.org/trac/boost/ticket/4882 #4882] Win32 shared_mutex does not handle timeouts correctly.
+* [@http://svn.boost.org/trac/boost/ticket/5752 #5752] boost::call_once() is unreliable on some platforms
* [@http://svn.boost.org/trac/boost/ticket/6652 #6652] Boost.Thread shared_mutex.hpp:50:99: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
+* [@http://svn.boost.org/trac/boost/ticket/6843 #6843] [Intel C++] Compile Errors with '#include <atomic>'
+* [@http://svn.boost.org/trac/boost/ticket/6966 #6966] future boost::future_category inconsistent dll linkage
* [@http://svn.boost.org/trac/boost/ticket/7720 #7720] exception lock_error while intensive locking/unlocking of mutex
* [@http://svn.boost.org/trac/boost/ticket/7755 #7755] Thread: deadlock with shared_mutex on Windows
+* [@http://svn.boost.org/trac/boost/ticket/7980 #7980] Build error: msvc-11.0 and BOOST_THREAD_DONT_USE_DATETIME
+* [@http://svn.boost.org/trac/boost/ticket/7982 #7982] pthread_delay_np() parm compile error on AIX
* [@http://svn.boost.org/trac/boost/ticket/8027 #8027] thread library fails to compile with Visual Studio 2003
* [@http://svn.boost.org/trac/boost/ticket/8070 #8070] prefer GetTickCount64 over GetTickCount
* [@http://svn.boost.org/trac/boost/ticket/8136 #8136] boost::this_thread::sleep_for() sleeps longer than it should in Windows
@@ -41,6 +48,9 @@
* [@http://svn.boost.org/trac/boost/ticket/8239 #8239] barrier::wait() not marked as interruption_point
* [@http://svn.boost.org/trac/boost/ticket/8323 #8323] boost::thread::try_join_for/try_join_until may block indefinitely due to a combination of problems in Boost.Thread and Boost.Chrono
* [@http://svn.boost.org/trac/boost/ticket/8337 #8337] The internal representation of "std::string(this->code()->message())" escapes, but is destroyed when it exits scope.
+* [@http://svn.boost.org/trac/boost/ticket/8371 #8371] C++11 once_flag enabled when constexpr is not available
+
+
[heading Version 4.0.0 - boost 1.53]
Modified: branches/release/libs/thread/doc/future_ref.qbk
==============================================================================
--- branches/release/libs/thread/doc/future_ref.qbk (original)
+++ branches/release/libs/thread/doc/future_ref.qbk 2013-04-17 00:30:48 EDT (Wed, 17 Apr 2013)
@@ -269,7 +269,7 @@
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
+ then(launch policy, F&& func); // EXTENSION
void swap(__unique_future__& other) noexcept; // EXTENSION
@@ -686,11 +686,19 @@
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
+ 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
+
+[warning These functions are experimental and subject to change in future versions.
+There are not too much tests yet, so it is possible that you can find out some trivial bugs :(]
+
+[note These functions are based on the [@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3558.pdf [*N3558 - A Standardized Representation of Asynchronous Operations]] C++1y proposal by N. Gustafsson, A. Laksberg, H. Sutter, S. Mithani.]
+
+
+
[variablelist
[[Notes:] [The three functions differ only by input parameters. The first only takes a callable object which accepts a
@@ -717,7 +725,7 @@
]]
-[[Returns:] [An object of type future<decltype(func(*this))> that refers to the shared state created by the continuation.]]
+[[Returns:] [An object of type future<typename boost::result_of<F(__unique_future__&)> that refers to the shared state created by the continuation.]]
[[Postconditions:] [
@@ -1601,30 +1609,21 @@
[section:async Non-member function `async()`]
- template <class F>
- __unique_future__<typename result_of<typename decay<F>::type()>::type>
- async(F&& f);
- template <class F>
- __unique_future__<typename result_of<typename decay<F>::type()>::type>
- async(launch policy, F&& f);
-
- template <class F, class... Args>
- __unique_future__<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
- async(F&& f, Args&&... args);
- template <class F, class... Args>
- __unique_future__<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
- async(launch policy, F&& f, Args&&... args);
-
The function template async provides a mechanism to launch a function potentially in a new thread and
provides the result of the function in a future object with which it shares a shared state.
[warning `async(launch::deferred, F)` is NOT YET IMPLEMENTED!]
-[warning the variadic prototype is provided only on C++11 compilers supporting rvalue references, variadic templates, decltype and a standard library providing <tuple> (waiting for a boost::tuple that is move aware), and BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK is defined.]
-
[heading Non-Variadic variant]
+ template <class F>
+ __unique_future__<typename result_of<typename decay<F>::type()>::type>
+ async(F&& f);
+ template <class F>
+ __unique_future__<typename result_of<typename decay<F>::type()>::type>
+ async(launch policy, F&& f);
+
[variablelist
[[Requires:] [
@@ -1636,8 +1635,11 @@
shall be a valid expression.
]]
-[[Effects] [The first function behaves the same as a call to the second function with a policy argument of
- `launch::async | launch::deferred` and the same arguments for `F`. The second function creates a shared state that is associated with the returned future object.
+[[Effects] [
+The first function behaves the same as a call to the second function with a policy argument of
+ `launch::async | launch::deferred` and the same arguments for `F`.
+
+The second function creates a shared state that is associated with the returned future object.
The further behavior of the second function depends on the policy argument as follows (if more than one of these conditions applies, the implementation may choose any of the corresponding policies):
@@ -1645,6 +1647,8 @@
- if `policy & launch::deferred` is non-zero - Stores `decay_copy(boost::forward<F>(f))` in the shared state. This copy of `f` constitute a deferred function. Invocation of the deferred function evaluates `boost::move(g)()` where `g` is the stored value of `decay_copy(boost::forward<F>(f))`. The shared state is not made ready until the function has completed. The first call to a non-timed waiting function on an asynchronous return object referring to this shared state shall invoke the deferred function in the thread that called the waiting function. Once evaluation of `boost::move(g)()` begins, the function is no longer considered deferred. (Note: If this policy is specified together with other policies, such as when using a policy value of `launch::async | launch::deferred`, implementations should defer invocation or the selection of the policy when no more concurrency can be effectively exploited.)
+- if no valid launch policy is provided the behaviour is undefined.
+
]]
[[Returns:] [An object of type `__unique_future__<typename result_of<typename decay<F>::type()>::type>` that refers to the shared state created by this call to `async`.]]
@@ -1657,7 +1661,7 @@
If the implementation chooses the `launch::async` policy,
-- a call to a non-timed waiting function on an asynchronous return object that shares the shared state created by this async call shall block until the associated thread has completed, as if joined;
+- a call to a non-timed waiting function on an asynchronous return object that shares the shared state created by this async call shall block until the associated thread has completed, as if joined, or else time out;
- the associated thread completion synchronizes with the return from the first function that successfully detects the ready status of the shared state or with the return from the last function that releases the shared state, whichever happens first.
]]
@@ -1678,6 +1682,15 @@
[heading Variadic variant]
+ template <class F, class... Args>
+ __unique_future__<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
+ async(F&& f, Args&&... args);
+ template <class F, class... Args>
+ __unique_future__<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
+ async(launch policy, F&& f, Args&&... args);
+
+[warning the variadic prototype is provided only on C++11 compilers supporting rvalue references, variadic templates, decltype and a standard library providing <tuple> (waiting for a boost::tuple that is move aware), and BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK is defined.]
+
[variablelist
[[Requires:] [
@@ -1710,6 +1723,8 @@
an asynchronous return object referring to this shared state shall invoke the deferred function in the thread that called the waiting function.
Once evaluation of `invoke(move(g), move(xyz))` begins, the function is no longer considered deferred.
+ - if no valid launch policy is provided the behaviour is undefined.
+
]]
[[Note:] [If this policy is specified together with other policies, such as when using a policy value of `launch::async | launch::deferred`,
@@ -1723,10 +1738,11 @@
- the invocation of async synchronizes with the invocation of `f`. (Note: This statement applies even when the corresponding future object is moved to another thread.); and
- the completion of the function `f` is sequenced before the shared state is made ready. (Note: f might not be called at all, so its completion might never happen.)
+
If the implementation chooses the `launch::async` policy,
- a call to a waiting function on an asynchronous return object that shares the shared state created by this async call
-shall block until the associated thread has completed, as if joined;
+shall block until the associated thread has completed, as if joined, or else time out;
- the associated thread completion synchronizes with the return from the first function that successfully detects the ready status of the shared state or
with the return from the last function that releases the shared state, whichever happens first.
Modified: branches/release/libs/thread/doc/sync_queues_ref.qbk
==============================================================================
--- branches/release/libs/thread/doc/sync_queues_ref.qbk (original)
+++ branches/release/libs/thread/doc/sync_queues_ref.qbk 2013-04-17 00:30:48 EDT (Wed, 17 Apr 2013)
@@ -17,17 +17,57 @@
[section:sync_queue_req Synchronized Queue Model]
-The BasicConcurrentQueue concept models .
-A type `Q` meets the BasicConcurrentQueue requirements if the following expressions are well-formed and have the specified semantics
+[section:bounded_unbounded Bounded-Unbounded Queues]
-* `q` denotes a value of type `Q`,
-* `e` denotes a value of type Q::value_type,
-* `u` denotes a value of type Q::size_type,
-* `lve` denotes a lvalue referece of type Q::value_type,
-* `rve` denotes a rvalue referece of type Q::value_type:
-* `spe` denotes a shared_ptr<Q::value_type>
+One of the major features of a concurrent queue is whether it has a bounded-unbounded capacity.
-Basic expressions
+[endsect]
+
+[section:locking Locking/Lock-free Queues]
+
+Locking queues can by nature block waiting for the queue to be non-empty or non-full.
+
+Lock-free queues will have some trouble waiting for the queue to be non-empty or non-full queues. These queues can not define operations such as push (and pull for bounded queues). That is, it could have blocking operations (presumably emulated with busy wait) but not waiting operations.
+
+[endsect]
+
+[section:closed Closed Queue]
+
+Threads using a queue for communication need some mechanism to signal when the queue is no longer needed. The usual approach is add an additional out-of-band signal. However, this approach suffers from the flaw that threads waiting on either full or empty queues need to be woken up when the queue is no longer needed. Rather than require an out-of-band signal, we chose to directly support such a signal in the queue itself, which considerably simplifies coding.
+
+To achieve this signal, a thread may close a queue. Once closed, no new elements may be pushed onto the queue. Push operations on a closed queue will either return queue_op_status::closed (when they have a queue_op_status return type), set the closed parameter if it has one or throw sync_queue::closed (when they do not). Elements already on the queue may be pulled off. When a queue is empty and closed, pull operations will either return queue_op_status::closed (when they have a status return), set the closed parameter if it has one or throw sync_queue::closed (when they do not).
+
+
+[endsect]
+
+[section:exception Concurrent Queues Throw specification]
+[section:locking Locking]
+
+All the functions are defined as if we had in addition to its specific Throw specification the following:
+
+[variablelist
+[[Throws:] [Any exception thrown by the internal locking.]]
+]
+
+[endsect]
+[section:bad_alloc Allocation]
+
+All the functions that allocate a resource are defined as if we had in addition to its specific Throw specification the following:
+
+[variablelist
+[[Throws:] [Any exception due to allocation errors.]]
+]
+
+[endsect]
+[endsect]
+
+[section:BasicConcurrentQueue Basic Concurrent Queue Operations]
+
+The essential solution to the problem of concurrent queuing is to shift to value-based operations, rather than reference-based operations.
+
+The BasicConcurrentQueue concept models the basic operations of a concurrent queue.
+
+A type `Q` meets the BasicConcurrentQueue requirements if the following expressions are well-formed and have the specified semantics
* Q::value_type
* Q::size_type
@@ -39,108 +79,117 @@
* `b = q.empty();`
* `u = q.size();`
-Non-waiting operations
+where
-* `b = q.try_push(e);`
-* `b = q.try_push(rve);`
-* `b = q.try_pull(lre);`
+* `q` denotes a value of type `Q`,
+* `e` denotes a value of type Q::value_type,
+* `u` denotes a value of type Q::size_type,
+* `lve` denotes a lvalue referece of type Q::value_type,
+* `rve` denotes a rvalue referece of type Q::value_type:
+* `spe` denotes a shared_ptr<Q::value_type>
-Non-blocking operations are provided by BlockingQueues
-* `b = q.try_push(nb, e);`
-* `b = q.try_push(nb, rve);`
-* `b = q.try_pull(nb, lre);`
+[section:push `q.push(e);`]
-Bounded queues add the following valid expressions
+[variablelist
-* `Q q(u);`
-* `b = q.full();`
-* `u = q.capacity();`
+[[Effects:] [Waits until the queue is not full (for bounded queues) and then push `e` to the queue copying it (this could need an allocation for unbounded queues).]]
-Closed queues
+[[Synchronization:] [Prior pull-like operations on the same object synchronizes with this operation.]]
-Threads using a queue for communication need some mechanism to signal when the queue is no longer needed. The usual approach is add an additional out-of-band signal. However, this approach suffers from the flaw that threads waiting on either full or empty queues need to be woken up when the queue is no longer needed. Rather than require an out-of-band signal, we chose to directly support such a signal in the queue itself, which considerably simplifies coding.
+[[Postcondition:] [`! q.empty()`.]]
-To achieve this signal, a thread may close a queue. Once closed, no new elements may be pushed onto the queue. Push operations on a closed queue will either return queue_op_status::closed (when they have a queue_op_status return type), set the closed parameter if it has one or throw sync_queue::closed (when they do not). Elements already on the queue may be popped off. When a queue is empty and closed, pop operations will either return queue_op_status::closed (when they have a status return) or throw queue_op_status::closed (when they do not).
+[[Return type:] [`void`.]]
-* `q.close();`
-* `b = q.closed();`
+[[Throws:] [If the queue was closed, throws sync_queue_is_closed. Any exception thrown by the copy of `e`.]]
-Basic expressions
+[[Exception safety:] [If an exception is thrown then the queue state is unmodified.]]
-* Q::value_type
-* `q.push(e,c);`
-* `q.push(rve,c);`
-* `q.pull(lre,c);`
-* `spe = q.ptr_pull(c);`
+]
-Non-waiting operations
+[endsect]
+[section:push_m `q.push(rve);`]
-* `b = q.try_push(e, c);`
-* `b = q.try_push(rve, c);`
-* `b = q.try_pull(lre, c);`
+[variablelist
-Non-blocking operations are provided by BlockingQueues
+[[Effects:] [Waits until the queue is not full (for bounded queues) and then push `e` to the queue moving it (this could need an allocation for unbounded queues).]]
-* `b = q.try_push(nb, e, c);`
-* `b = q.try_push(nb, rve, c);`
-* `b = q.try_pull(nb, lre, c);`
+[[Synchronization:] [Prior pull-like operations on the same object synchronizes with this operation.]]
+[[Postcondition:] [`! q.empty()`.]]
-[section:exception Blocking Queues Throw specification]
+[[Return type:] [`void`.]]
-All the functions that can throw are defined as if we had in addition to its specific Throw specification the following:
+[[Throws:] [If the queue is closed, throws sync_queue_is_closed. Any exception thrown by the copy of `e`.]]
+
+[[Exception safety:] [If an exception is thrown then the queue state is unmodified.]]
-[variablelist
-[[Throws:] [Any exception thrown by the internal locking.]]
]
[endsect]
-[section:exception2 Closed Queues Throw specification]
-
-All the modifier functions that have no a specific closed parameter can throw are defined as if we had in addition to its specific Throw specification the following:
+[section:pull_lv `q.pull(lve)`]
[variablelist
-[[Throws:] [Any exception thrown by the internal locking.]]
+
+[[Effects:] [Waits until the queue is not empty and then pull the element from the queue `q` and moves the pulled element into `lve` (this could need an allocation for unbounded queues).]]
+
+[[Synchronization:] [Prior pull-like operations on the same object synchronizes with this operation.]]
+
+[[Postcondition:] [`! q.full()`.]]
+
+[[Return type:] [`void`.]]
+
+[[Throws:] [Any exception thrown by the move of `e`.]]
+
+[[Exception safety:] [If an exception is thrown then the queue state is unmodified.]]
+
]
[endsect]
-
-[section:push `q.push(e);`]
+[section:pull `e = q.pull()`]
[variablelist
-[[Effects:] [Waits until the queue is not full (for bounded queues) and then push the `e` onto the queue copying it.]]
+[[Requires:] [Q::value_type is no throw copy movable. This is needed to ensure the exception safety.]]
+
+[[Effects:] [Waits until the queue is not empty and not closed. If the queue is empty and closed throws sync_queue_is_closed. Otherwise pull the element from the queue `q` and moves the pulled element.]]
[[Synchronization:] [Prior pull-like operations on the same object synchronizes with this operation.]]
-[[Postcondition:] [`! q.empty()`.]]
+[[Postcondition:] [`! q.full()`.]]
-[[Return type:] [`void`.]]
+[[Return type:] [`Q::value_type`.]]
-[[Throws:] [If the queue was closed, throws sync_queue_is_closed. Any exception thrown by the the copy of `e`.]]
+[[Return:] [The pulled element.]]
+
+[[Throws:] [Any exception thrown by the copy of `e`.]]
[[Exception safety:] [If an exception is thrown then the queue state is unmodified.]]
]
[endsect]
-[section:push_m `q.push(rve);`]
+
+[section:ptr_pull `spe = q.ptr_pull()`]
[variablelist
-[[Effects:] [Waits until the queue is not full (for bounded queues) and then push the `e` onto the queue moving it.]]
+[/[Requires:] [Q::value_type is no throw copy movable. This is needed to ensure the exception safety. ]]
+
+[[Effects:] [Waits until the queue is not empty and not closed. If the queue is empty and closed throws sync_queue_is_closed. Otherwise pull the element from the queue `q` and moves the pulled element into a shared_ptr.]]
[[Synchronization:] [Prior pull-like operations on the same object synchronizes with this operation.]]
-[[Postcondition:] [`! q.empty()`.]]
+[[Postcondition:] [`! q.full()`.]]
-[[Return type:] [`void`.]]
+[[Return type:] [`Q::value_type`.]]
-[[Throws:] [If the queue is closed, throws sync_queue_is_closed. Any exception thrown by the the copy of `e`.]]
+[[Return:] [A shared_ptr containing the pulled element.]]
+
+[[Throws:] [Any exception thrown by the move of `e`. Any exception throw when allocation resources are missing. ]]
[[Exception safety:] [If an exception is thrown then the queue state is unmodified.]]
@@ -148,11 +197,36 @@
[endsect]
+
+
+[endsect]
+
+[section:non_waaiting Non-waiting Concurrent Queue Operations]
+
+The ConcurrentQueue concept models a queue with .
+
+
+A type `Q` meets the ConcurrentQueue requirements if the following expressions are well-formed and have the specified semantics
+
+* `b = q.try_push(e);`
+* `b = q.try_push(rve);`
+* `b = q.try_pull(lre);`
+
+where
+
+* `q` denotes a value of type `Q`,
+* `e` denotes a value of type Q::value_type,
+* `u` denotes a value of type Q::size_type,
+* `lve` denotes a lvalue referece of type Q::value_type,
+* `rve` denotes a rvalue referece of type Q::value_type:
+* `spe` denotes a shared_ptr<Q::value_type>
+
+
[section:try_push `q.try_push(e);`]
[variablelist
-[[Effects:] [If the queue `q` is not full, push the `e` onto the queue copying it.]]
+[[Effects:] [If the queue `q` is not full, push the `e` to the queue copying it.]]
[[Synchronization:] [Prior pull-like operations on the same object synchronizes with this operation when the operation succeeds. ]]
@@ -162,7 +236,7 @@
[[Postcondition:] [If the call returns `true`, `! q.empty()`.]]
-[[Throws:] [If the queue is closed, throws sync_queue_is_closed. Any exception thrown by the the copy of `e`.]]
+[[Throws:] [If the queue is closed, throws sync_queue_is_closed. Any exception thrown by the copy of `e`.]]
[[Exception safety:] [If an exception is thrown then the queue state is unmodified.]]
@@ -183,37 +257,96 @@
[[Postcondition:] [If the call returns `true`, `! q.empty()`.]]
-[[Throws:] [If the queue is closed, throws sync_queue_is_closed. Any exception thrown by the the copy of `e`.]]
+[[Throws:] [If the queue is closed, throws sync_queue_is_closed. Any exception thrown by the copy of `e`.]]
[[Exception safety:] [If an exception is thrown then the queue state is unmodified.]]
]
[endsect]
-[section:pull `e = q.pull()`]
+[section:pull_lv `b = q.try_pull(lve)`]
[variablelist
-[[Requires:] [Q::value_type is no throw copy movable. This is needed to ensure the exception safety]]
-
-[[Effects:] [Waits until the queue is not empty and then pull the element from the queue `q` and moves the pulled element.]]
+[[Effects:] [Waits until the queue is not empty and then pull the element from the queue `q` and moves the pulled element into `lve` (this could need an allocation for unbounded queues).]]
[[Synchronization:] [Prior pull-like operations on the same object synchronizes with this operation.]]
[[Postcondition:] [`! q.full()`.]]
-[[Return type:] [`Q::value_type`.]]
+[[Return type:] [`bool`.]]
-[[Return:] [The pulled element.]]
+[[Return:] [If the queue `q` is full return `false`, otherwise return `true`;]]
-[[Throws:] [Any exception thrown by the copy of `e`.]]
+[[Throws:] [Any exception thrown by the move of `e`.]]
[[Exception safety:] [If an exception is thrown then the queue state is unmodified.]]
]
[endsect]
+[endsect]
+
+[section:non_blocking Non-blocking Concurrent Queue Operations]
+
+For cases when blocking for mutual exclusion is undesirable, we have non-blocking operations. The interface is the same as the try operations but is allowed to also return queue_op_status::busy in case the operation is unable to complete without blocking.
+
+Non-blocking operations are provided only for BlockingQueues
+* `b = q.try_push(nb, e);`
+* `b = q.try_push(nb, rve);`
+* `b = q.try_pull(nb, lre);`
+
+
+where
+
+* `q` denotes a value of type `Q`,
+* `e` denotes a value of type Q::value_type,
+* `u` denotes a value of type Q::size_type,
+* `lve` denotes a lvalue referece of type Q::value_type,
+* `rve` denotes a rvalue referece of type Q::value_type:
+* `spe` denotes a shared_ptr<Q::value_type>
+
+
+[endsect]
+
+[section:bounded Bounded Concurrent Queue Operations]
+
+Bounded queues add the following valid expressions
+
+* `Q q(u);`
+* `b = q.full();`
+* `u = q.capacity();`
+
+[endsect]
+
+[section:closed_op Closed Concurrent Queue Operations]
+
+
+* `q.close();`
+* `b = q.closed();`
+
+Basic expressions
+
+* `q.push(e,c);`
+* `q.push(rve,c);`
+* `q.pull(lre,c);`
+* `spe = q.ptr_pull(c);`
+
+Non-waiting operations
+
+* `b = q.try_push(e, c);`
+* `b = q.try_push(rve, c);`
+* `b = q.try_pull(lre, c);`
+
+Non-blocking operations are provided by BlockingQueues
+
+* `b = q.try_push(nb, e, c);`
+* `b = q.try_push(nb, rve, c);`
+* `b = q.try_pull(nb, lre, c);`
+
+
+[endsect]
[endsect]
Modified: branches/release/libs/thread/src/future.cpp
==============================================================================
--- branches/release/libs/thread/src/future.cpp (original)
+++ branches/release/libs/thread/src/future.cpp 2013-04-17 00:30:48 EDT (Wed, 17 Apr 2013)
@@ -51,6 +51,7 @@
future_error_category future_error_category_var;
}
+ BOOST_THREAD_DECL
const system::error_category&
future_category() BOOST_NOEXCEPT
{
@@ -59,3 +60,4 @@
}
#endif
+
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