mirror of
https://github.com/boostorg/thread.git
synced 2026-02-06 10:32:14 +00:00
Compare commits
1 Commits
boost-1.55
...
boost-1.54
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57bd3b0769 |
@@ -36,7 +36,6 @@ import os ;
|
||||
import feature ;
|
||||
import indirect ;
|
||||
import path ;
|
||||
import configure ;
|
||||
|
||||
project boost/thread
|
||||
: source-location ../src
|
||||
@@ -141,8 +140,6 @@ 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) ;
|
||||
@@ -239,10 +236,10 @@ rule usage-requirements ( properties * )
|
||||
}
|
||||
}
|
||||
|
||||
#if ! <toolset>vacpp in $(properties) || <toolset-vacpp:version>11.1 in $(properties) || <toolset-vacpp:version>12.1.0.1 in $(properties) || <toolset-vacpp:version>12.1 in $(properties)
|
||||
#{
|
||||
if ! <toolset>vacpp in $(properties) || <toolset-vacpp:version>11.1 in $(properties) || <toolset-vacpp:version>12.1.0.1 in $(properties) || <toolset-vacpp:version>12.1 in $(properties)
|
||||
{
|
||||
result += <library>/boost/chrono//boost_chrono ;
|
||||
#}
|
||||
}
|
||||
|
||||
return $(result) ;
|
||||
}
|
||||
@@ -267,15 +264,16 @@ 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) ;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
// 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;
|
||||
}
|
||||
@@ -1,12 +1,11 @@
|
||||
[/
|
||||
(C) Copyright 2007-8 Anthony Williams.
|
||||
(C) Copyright 2013 Vicente J. Botet Escriba.
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt).
|
||||
]
|
||||
|
||||
[section:barriers Barriers -- EXTENSION]
|
||||
[section:barriers Barriers]
|
||||
|
||||
A barrier is a simple concept. Also known as a ['rendezvous], it is a synchronization point between multiple threads. The barrier is
|
||||
configured for a particular number of threads (`n`), and as threads reach the barrier they must wait until all `n` threads have
|
||||
@@ -23,18 +22,14 @@ arrived. Once the `n`-th thread has reached the barrier, all the waiting threads
|
||||
barrier& operator=(barrier const&) = delete;
|
||||
|
||||
barrier(unsigned int count);
|
||||
template <typename F>
|
||||
barrier(unsigned int count, F&&);
|
||||
|
||||
~barrier();
|
||||
|
||||
bool wait();
|
||||
void count_down_and_wait();
|
||||
};
|
||||
|
||||
Instances of __barrier__ are not copyable or movable.
|
||||
|
||||
[section Constructor `barrier(unsigned int)`]
|
||||
[heading Constructor]
|
||||
|
||||
barrier(unsigned int count);
|
||||
|
||||
@@ -46,24 +41,7 @@ Instances of __barrier__ are not copyable or movable.
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[section Constructor `barrier(unsigned int, F&&)`]
|
||||
|
||||
barrier(unsigned int count, F&& completion);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Requires:] [The result type of the completion function call `completion()` is `void` or `unsigned int`.]]
|
||||
|
||||
[[Effects:] [Construct a barrier for `count` threads and a completion function `completion`.]]
|
||||
|
||||
[[Throws:] [__thread_resource_error__ if an error occurs.]]
|
||||
|
||||
]
|
||||
|
||||
|
||||
[endsect]
|
||||
[section Destructor `~barrier()`]
|
||||
[heading Destructor]
|
||||
|
||||
~barrier();
|
||||
|
||||
@@ -77,55 +55,24 @@ Instances of __barrier__ are not copyable or movable.
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[section Member Function `wait()`]
|
||||
[heading Member function `wait`]
|
||||
|
||||
bool wait();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Block until `count` threads have called `wait` or `count_down_and_wait` on `*this`. When the `count`-th thread calls `wait`, the barrier is reset and all waiting threads are unblocked.
|
||||
The reset depends on whether the barrier was constructed with a completion function or not. If there is no completion function or if the completion function result is void, the reset consists in restoring the original count. Otherwise the rest consist in assigning the result of the completion function (which must not be 0).]]
|
||||
[[Effects:] [Block until `count` threads have called `wait` on `*this`. When the `count`-th thread calls `wait`, all waiting threads
|
||||
are unblocked, and the barrier is reset. ]]
|
||||
|
||||
[[Returns:] [`true` for exactly one thread from each batch of waiting threads, `false` otherwise.]]
|
||||
|
||||
[[Throws:] [
|
||||
|
||||
- __thread_resource_error__ if an error occurs.
|
||||
|
||||
- __thread_interrupted__ if the wait was interrupted by a call to
|
||||
__interrupt__ on the __thread__ object associated with the current thread of execution.
|
||||
|
||||
]]
|
||||
[[Throws:] [__thread_resource_error__ if an error occurs. __thread_interrupted__ if the wait was interrupted by a call to
|
||||
__interrupt__ on the __thread__ object associated with the current thread of execution.]]
|
||||
|
||||
[[Notes:] [`wait()` is an ['interruption point].]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[section Member Function `count_down_and_wait()`]
|
||||
|
||||
void count_down_and_wait();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Block until `count` threads have called `wait` or `count_down_and_wait` on `*this`. When the `count`-th thread calls `wait`, the barrier is reset and all waiting threads are unblocked.
|
||||
The reset depends on whether the barrier was constructed with a completion function or not. If there is no completion function or if the completion function result is void, the reset consists in restoring the original count. Otherwise the rest consist in assigning the result of the completion function (which must not be 0).]]
|
||||
|
||||
[[Throws:] [
|
||||
|
||||
- __thread_resource_error__ if an error occurs.
|
||||
|
||||
- __thread_interrupted__ if the wait was interrupted by a call to
|
||||
__interrupt__ on the __thread__ object associated with the current thread of execution.
|
||||
|
||||
]]
|
||||
|
||||
[[Notes:] [`count_down_and_wait()` is an ['interruption point].]]
|
||||
|
||||
]
|
||||
|
||||
|
||||
[endsect]
|
||||
[endsect]
|
||||
[endsect]
|
||||
|
||||
@@ -8,56 +8,23 @@
|
||||
|
||||
[section:changes History]
|
||||
|
||||
[/
|
||||
[heading Version 4.2.0 - boost 1.55]
|
||||
|
||||
[*Know Bugs:]
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/2442 #2442] Application statically linked with Boost.Thread crashes when Google Desktop is installed (Windows XP)
|
||||
* [@http://svn.boost.org/trac/boost/ticket/3926 #3926] thread_specific_ptr + dlopen library causes a SIGSEGV.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/4833 #4833] MinGW/test_tss_lib: Support of automatic tss cleanup for native threading API not available
|
||||
* [@http://svn.boost.org/trac/boost/ticket/6782 #6782] call_once uses incorrect barrier intrinsic on Visual Studio
|
||||
* [@http://svn.boost.org/trac/boost/ticket/7319 #7319] Take care of c++std-lib-32966 issue
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8600 #8600] wait_for_any hangs, if called with multiple copies of shared_future referencing same task
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9307 #9307] future::fallback_to assert with ERRORRRRR boost: mutex lock failed in pthread_mutex_lock: Invalid argument
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9308 #9308] future::async fails with terminate called throwing an exception when called with a lambda - clang-darwin-asan11
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9311 #9311] ex_lambda_future fails on msvc-11.0
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9310 #9310] test_4648_lib fails on clang-darwin-asan11
|
||||
|
||||
Please take a look at [@https://svn.boost.org/trac/boost/query?status=assigned&status=new&status=reopened&component=thread&type=!Feature+Requests&col=id&col=summary&order=id thread trunk regression test] to see the current state.
|
||||
|
||||
[*Sever limitations:]
|
||||
|
||||
There are some severe bugs that prevent the use of the library on concrete contexts, in particular:
|
||||
|
||||
* on thread specific storage that prevent the library to be used with dynamic libraries,
|
||||
* The experimental features of boost::future have some severe holes that make the program crash unexpectedly.
|
||||
|
||||
[*New Features:]
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8519 #8519] Synchro: Update class barrier with a completion function.
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8273 #8273] Synchro:Add externally locked streams.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8274 #8274] Synchro:Add concurrent queue.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8515 #8515] Async: Add shared_future::then.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8519 #8519] Synchro: Update class barrier with a completion function
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8518 #8518] Synchro: Add a latch class.
|
||||
* [@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/8627 #8627] Async: Add future<>::unwrap.
|
||||
* [@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/8891 #8891] upgrade_to_unique_lock: missing mutex() function.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8955 #8955] Request for more efficient way to get exception_ptr from future.
|
||||
|
||||
[*Fixed Bugs:]
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/7461 #7461] detail::win32::ReleaseSemaphore may be called with count_to_release equal to 0 Boost 1.55.0 closed viboes Bugs
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8070 #8070] prefer GetTickCount64 over GetTickCount
|
||||
* [@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]
|
||||
|
||||
@@ -449,9 +416,10 @@ 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/8273 #8273] Add externally locked streams
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8274 #8274] Add concurrent queue
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8518 #8518] Sync: Add a latch class
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8519 #8519] Sync: Add a completion_latch class
|
||||
* [@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.
|
||||
|
||||
@@ -460,10 +428,14 @@ The following features will be included in next releases.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/7446 #7446] Async: Add when_any.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/7447 #7447] Async: Add when_all.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/7448 #7448] Async: Add async taking a scheduler parameter.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8515 #8515] Async: Add shared_future::then.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8516 #8516] Async: Add future/shared_future::then taking a scheduler as parameter.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8627 #8627] Async: Add future<>::unwrap.
|
||||
|
||||
# And some additional extensions related to futures as:
|
||||
|
||||
* [@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/8517 #8517] Async: Add a variadic shared_future::then.
|
||||
|
||||
|
||||
|
||||
@@ -78,28 +78,20 @@ When `BOOST_THREAD_VERSION>3` && defined BOOST_THREAD_PLATFORM_PTHREAD define `
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:move Boost.Atomic]
|
||||
|
||||
Boost.Thread uses by default an Boost.Atomic in POSIX platforms to implement call_once..
|
||||
[section:thread_eq `boost::thread::oprator==` deprecated]
|
||||
|
||||
Define `BOOST_THREAD_USES_ATOMIC ` if you want to use Boost.Atomic.
|
||||
Define `BOOST_THREAD_DONT_USE_ATOMIC ` if you don't want to use Boost.Atomic or if it is not supported in your platform.
|
||||
The following nested typedefs are deprecated:
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:thread_eq `boost::thread::operator==` deprecated]
|
||||
|
||||
The following operators are deprecated:
|
||||
|
||||
* `boost::thread::operator==`
|
||||
* `boost::thread::operator!=`
|
||||
* `boost::thread::oprator==`
|
||||
* `boost::thread::oprator!=`
|
||||
|
||||
When `BOOST_THREAD_PROVIDES_THREAD_EQ` is defined Boost.Thread provides these deprecated feature.
|
||||
|
||||
Use instead
|
||||
|
||||
* `boost::thread::id::operator==`
|
||||
* `boost::thread::id::operator!=`
|
||||
* `boost::thread::id::oprator==`
|
||||
* `boost::thread::id::oprator!=`
|
||||
|
||||
[warning This is a breaking change respect to version 1.x.]
|
||||
|
||||
|
||||
@@ -217,7 +217,7 @@ Silence can be sometimes louder than words-what's forbidden to do with a `strict
|
||||
* You can create a `strict_lock<T>` only starting from a valid T object. Notice that there is no other way you can create a `strict_lock<T>`.
|
||||
|
||||
BankAccount myAccount("John Doe", "123-45-6789");
|
||||
strict_lock<BankAccount> myLock(myAccount); // ok
|
||||
strict_locerk<BankAccount> myLock(myAccount); // ok
|
||||
|
||||
* You cannot copy `strict_lock`s to one another. In particular, you cannot pass `strict_lock`s by value to functions or have them returned by functions:
|
||||
|
||||
@@ -468,7 +468,7 @@ Now imagine that the AccountManager function needs to take a `unique_lock` in or
|
||||
We need a way to transfer the ownership from the `unique_lock` to a `strict_lock` the time we are working with `savingsAcct_` and then restore the ownership on `unique_lock`.
|
||||
|
||||
void AccountManager::AMoreComplicatedChecking2Savings(int amount) {
|
||||
unique_lock<AccountManager> guard1(*this, defer_lock);
|
||||
unique_lock<AccountManager> guard(*this, defer_lock);
|
||||
if (some_condition()) {
|
||||
guard1.lock();
|
||||
}
|
||||
@@ -482,7 +482,7 @@ We need a way to transfer the ownership from the `unique_lock` to a `strict_lock
|
||||
|
||||
In order to make this code compilable we need to store either a Lockable or a `unique_lock<Lockable>` reference depending on the constructor. Store which kind of reference we have stored,and in the destructor call either to the Lockable `unlock` or restore the ownership.
|
||||
|
||||
This seams too complicated to me. Another possibility is to define a nested strict lock class. The drawback is that instead of having only one strict lock we have two and we need either to duplicate every function taking a `strict_lock` or make these function templates functions. The problem with template functions is that we don't profit anymore of the C++ type system. We must add some static metafunction that check that the Locker parameter is a strict lock. The problem is that we can not really check this or can we?. The `is_strict_lock` metafunction must be specialized by the strict lock developer. We need to belive it "sur parole". The advantage is that now we can manage with more than two strict locks without changing our code. This is really nice.
|
||||
This seams too complicated to me. Another possibility is to define a nested strict lock class. The drawback is that instead of having only one strict lock we have two and we need either to duplicate every function taking a `strict_lock` or make these function templates functions. The problem with template functions is that we don't profit anymore of the C++ type system. We must add some static metafunction that check that the Locker parameter is a strict lock. The problem is that we can not really check this or can we?. The `is_strict_lock` metafunction must be specialized by the strict lock developer. We need to belive it "sur parole". The advantage is that now we can manage with more than two strict locks without changing our code. Ths is really nice.
|
||||
|
||||
Now we need to state that both classes are `strict_lock`s.
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -293,7 +293,7 @@ that is to allow multiple concurrent get operations.
|
||||
|
||||
[heading Multiple get]
|
||||
|
||||
The second `get()` call in the following example is undefined.
|
||||
The second `get()` call in the following example future
|
||||
|
||||
void bad_second_use( type arg ) {
|
||||
|
||||
@@ -369,17 +369,17 @@ and a `shared_future` that can be shared between several threads, but there were
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:make_ready_future Making immediate futures easier]
|
||||
[section:make_future Making immediate futures easier]
|
||||
|
||||
Some functions may know the value at the point of construction. In these cases the value is immediately available,
|
||||
but needs to be returned as a future or shared_future. By using make_ready_future a future
|
||||
but needs to be returned as a future or shared_future. By using make_future (make_shared_future) a future (shared_future)
|
||||
can be created which holds a pre-computed result in its shared state.
|
||||
|
||||
Without these features it is non-trivial to create a future directly from a value.
|
||||
First a promise must be created, then the promise is set, and lastly the future is retrieved from the promise.
|
||||
This can now be done with one operation.
|
||||
|
||||
[heading make_ready_future]
|
||||
[heading make_future / make_shared_future]
|
||||
|
||||
This function creates a future for a given value. If no value is given then a future<void> is returned.
|
||||
This function is primarily useful in cases where sometimes, the return value is immediately available, but sometimes
|
||||
@@ -389,14 +389,16 @@ the function must return an eventual value represented as a future.
|
||||
|
||||
boost::future<int> compute(int x)
|
||||
{
|
||||
if (x == 0) return boost::make_ready_future(0);
|
||||
if (x < 0) return boost::make_ready_future<int>(std::logic_error("Error"));
|
||||
if (x == 0) return boost::make_future(0);
|
||||
if (x < 0) return boost::make_future(-1);
|
||||
boost::future<int> f1 = boost::async([]() { return x+1; });
|
||||
return f1;
|
||||
}
|
||||
|
||||
There are two variations of this function. The first takes a value of any type, and returns a future of that type.
|
||||
The input value is passed to the shared state of the returned future. The second version takes no input and returns a future<void>.
|
||||
The input value is passed to the shared state of the returned future. The second version takes no input and returns a future<void>.
|
||||
make_shared_future has the same functionality as make_future, except has a return type of shared_future.
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
@@ -404,16 +406,16 @@ The input value is passed to the shared state of the returned future. The second
|
||||
|
||||
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
|
||||
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
|
||||
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.
|
||||
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>
|
||||
@@ -426,7 +428,7 @@ function. This operation takes a lambda function which describes how `f2` should
|
||||
|
||||
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()`,
|
||||
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(...).
|
||||
@@ -439,20 +441,21 @@ Some points to note are:
|
||||
|
||||
Input Parameters:
|
||||
|
||||
* Lambda function: One option which can be considered is to take two functions, one for
|
||||
success and one for error handling. However this option has not been retained for the moment.
|
||||
The lambda function takes a future as its input which carries the exception
|
||||
* 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
|
||||
* 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().
|
||||
.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]
|
||||
|
||||
@@ -7,19 +7,13 @@
|
||||
|
||||
[section:latches Latches -- EXPERIMENTAL]
|
||||
|
||||
[////////////////////]
|
||||
[section Introdcution]
|
||||
|
||||
Latches are a thread co-ordination mechanism that allow one or more threads to block until one or more threads have reached a point.
|
||||
|
||||
[/
|
||||
An individual latch is a reusable object; once the operation has been completed, the threads can re-use the same barrier. It is thus useful for managing repeated tasks handled by multiple threads.
|
||||
Latches are a thread co-ordination mechanism that allow one or more threads to block until one or more threads have reached a point. An individual latch is a reusable object; once the operation has been completed, the threads can re-use the same barrier. It is thus useful for managing repeated tasks handled by multiple threads.
|
||||
|
||||
A completion latch is like a latch that allows to associate a completion function which will be called once the internal counter reaches the value 0 and all the consumer threads have taken care of the notification.
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[////////////////]
|
||||
[section Examples]
|
||||
|
||||
Sample use cases for the latch include:
|
||||
@@ -44,6 +38,7 @@ An example of the first use case would be as follows:
|
||||
|
||||
An example of the second use case is shown below. We need to load data and then process it using a number of threads. Loading the data is I/O bound, whereas starting threads and creating data structures is CPU bound. By running these in parallel, throughput can be increased.
|
||||
|
||||
|
||||
void DoWork() {
|
||||
latch start_latch(1);
|
||||
vector<thread*> workers;
|
||||
@@ -62,7 +57,6 @@ An example of the second use case is shown below. We need to load data and then
|
||||
start_latch.count_down();
|
||||
}
|
||||
|
||||
[/
|
||||
The completion latches can be used to co-ordinate also a set of threads carrying out a repeated task. The number of threads can be adjusted dynamically to respond to changing requirements.
|
||||
|
||||
In the example below, a number of threads are performing a multi-stage task. Some tasks may require fewer steps than others, meaning that some threads may finish before others. We reduce the number of threads waiting on the latch when this happens.
|
||||
@@ -102,10 +96,8 @@ In the example below, a number of threads are performing a multi-stage task. Som
|
||||
GetNextStage(tasks);
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[///////////////////////////]
|
||||
[section:latch Class `latch`]
|
||||
|
||||
#include <boost/thread/latch.hpp>
|
||||
@@ -127,20 +119,16 @@ In the example below, a number of threads are performing a multi-stage task. Som
|
||||
cv_status wait_until(const chrono::time_point<Clock, Duration>& abs_time);
|
||||
void count_down();
|
||||
void count_down_and_wait();
|
||||
void reset(std::size_t count);
|
||||
|
||||
};
|
||||
|
||||
|
||||
[/
|
||||
void reset(std::size_t count);
|
||||
]
|
||||
|
||||
A latch maintains an internal counter that is initialized when the latch is created. One or more threads may block waiting until the counter is decremented to 0.
|
||||
|
||||
Instances of __latch__ are not copyable or movable.
|
||||
|
||||
[///////////////////]
|
||||
[section Constructor `latch(std::size_t)`]
|
||||
[section Constructor]
|
||||
|
||||
latch(std::size_t count);
|
||||
|
||||
@@ -148,15 +136,14 @@ Instances of __latch__ are not copyable or movable.
|
||||
|
||||
[[Effects:] [Construct a latch with is initial value for the internal counter.]]
|
||||
|
||||
[[Note:] [The counter could be zero.]]
|
||||
[[Note:] [The counter could be zero and reset later.]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[//////////////////]
|
||||
[section Destructor `~latch()`]
|
||||
[section Destructor]
|
||||
|
||||
~latch();
|
||||
|
||||
@@ -171,8 +158,7 @@ Instances of __latch__ are not copyable or movable.
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:wait Member Function `wait()`]
|
||||
[section:wait Member function `wait()`]
|
||||
|
||||
void wait();
|
||||
|
||||
@@ -192,8 +178,8 @@ are unblocked. ]]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////////////]
|
||||
[section:try_wait Member Function `try_wait()`]
|
||||
|
||||
[section:try_wait Member function `try_wait()`]
|
||||
|
||||
bool try_wait();
|
||||
|
||||
@@ -208,8 +194,8 @@ are unblocked. ]]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[//////////////////////////////////////////////]
|
||||
[section:wait_for Member Function `wait_for() `]
|
||||
|
||||
[section:wait_for Member function `wait_for() `]
|
||||
|
||||
template <class Rep, class Period>
|
||||
cv_status wait_for(const chrono::duration<Rep, Period>& rel_time);
|
||||
@@ -230,8 +216,7 @@ are unblocked. ]]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////////////////]
|
||||
[section:wait_until Member Function `wait_until()`]
|
||||
[section:wait_until Member function `wait_until()`]
|
||||
|
||||
template <class lock_type, class Clock, class Duration>
|
||||
cv_status wait_until(const chrono::time_point<Clock, Duration>& abs_time);
|
||||
@@ -252,8 +237,7 @@ are unblocked. ]]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////////////////]
|
||||
[section:count_down Member Function `count_down()`]
|
||||
[section:count_down Member function `count_down()`]
|
||||
|
||||
void count_down();
|
||||
|
||||
@@ -272,8 +256,7 @@ are unblocked. ]]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[///////////////////////////////////////////////////////////////////]
|
||||
[section:count_down_and_wait Member Function `count_down_and_wait()`]
|
||||
[section:count_down_and_wait Member function `count_down_and_wait()`]
|
||||
|
||||
void count_down_and_wait();
|
||||
|
||||
@@ -292,9 +275,8 @@ are unblocked. ]]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[///////////////////////////////////////]
|
||||
[
|
||||
[section:reset Member Function `reset()`]
|
||||
|
||||
[section:reset Member function `reset()`]
|
||||
|
||||
reset( size_t );
|
||||
|
||||
@@ -311,11 +293,9 @@ are unblocked. ]]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
]
|
||||
|
||||
[endsect] [/ latch]
|
||||
|
||||
[/
|
||||
[//////////////////////////////////////////////////]
|
||||
[section:completion_latch Class `completion_latch `]
|
||||
|
||||
#include <boost/thread/completion_latch.hpp>
|
||||
@@ -353,7 +333,6 @@ Instances of completion_latch are not copyable or movable.
|
||||
|
||||
Only the additional functions are documented.
|
||||
|
||||
[/////////////////////]
|
||||
[section:c Constructor]
|
||||
|
||||
completion_latch(std::size_t count);
|
||||
@@ -369,7 +348,6 @@ Only the additional functions are documented.
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[///////////////////////////////////////////////]
|
||||
[section:cf Constructor with completion function]
|
||||
|
||||
template <typename F>
|
||||
@@ -390,8 +368,7 @@ Only the additional functions are documented.
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[///////////////////////////////////]
|
||||
[section:then Member Function `then`]
|
||||
[section:then Member function `then`]
|
||||
|
||||
template <typename F>
|
||||
completion_function then(F&& funct);
|
||||
@@ -414,6 +391,6 @@ Only the additional functions are documented.
|
||||
[endsect]
|
||||
|
||||
[endsect] [/ completion_latch]
|
||||
]
|
||||
|
||||
|
||||
[endsect] [/ Latches]
|
||||
|
||||
@@ -1273,7 +1273,7 @@ The following classes are models of `StrictLock`:
|
||||
explicit operator bool() const noexcept;
|
||||
bool owns_lock() const noexcept;
|
||||
|
||||
mutex_type* mutex() const noexcept;
|
||||
Lockable* mutex() const noexcept;
|
||||
|
||||
#if defined BOOST_THREAD_USE_DATE_TIME || defined BOOST_THREAD_DONT_USE_CHRONO
|
||||
unique_lock(Lockable& m_,system_time const& target_time);
|
||||
@@ -1535,7 +1535,7 @@ object associated with `*this`.]]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:mutex `Lockable* mutex() const noexcept`]
|
||||
[section:mutex `Lockable* mutex() const`]
|
||||
|
||||
[variablelist
|
||||
|
||||
@@ -1907,7 +1907,7 @@ state (including the destructor) must be called by the same thread that acquired
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:upgrade_to_unique_lock Class template `upgrade_to_unique_lock` -- EXTENSION]
|
||||
[section:upgrade_to_unique_lock Class template `upgrade_to_unique_lock`]
|
||||
|
||||
// #include <boost/thread/locks.hpp>
|
||||
// #include <boost/thread/lock_types.hpp>
|
||||
@@ -1930,8 +1930,6 @@ state (including the destructor) must be called by the same thread that acquired
|
||||
|
||||
explicit operator bool() const;
|
||||
bool owns_lock() const;
|
||||
mutex_type* mutex() const;
|
||||
|
||||
};
|
||||
|
||||
__upgrade_to_unique_lock__ allows for a temporary upgrade of an __upgrade_lock__ to exclusive ownership. When constructed with a
|
||||
@@ -1941,7 +1939,7 @@ __lockable_concept_type__ is downgraded back to ['upgrade ownership].
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:scoped_try_lock Mutex-specific class `scoped_try_lock` -- DEPRECATED]
|
||||
[section:scoped_try_lock Mutex-specific class `scoped_try_lock`]
|
||||
|
||||
class MutexType::scoped_try_lock
|
||||
{
|
||||
|
||||
@@ -190,7 +190,7 @@ This wrapper can be used to join the thread before destroying it seems a natural
|
||||
|
||||
explicit scoped_thread(thread&& th) noexcept;
|
||||
template <typename F&&, typename ...Args>
|
||||
explicit scoped_thread(F&&, Args&&...);
|
||||
explicit strict_scoped_thread(F&&, Args&&...);
|
||||
|
||||
~scoped_thread();
|
||||
|
||||
@@ -323,7 +323,7 @@ any) to `*this`.
|
||||
[section:call_constructor Move Constructor from a Callable]
|
||||
|
||||
template <typename F&&, typename ...Args>
|
||||
explicit scoped_thread(F&&, Args&&...);
|
||||
explicit strict_scoped_thread(F&&, Args&&...);
|
||||
|
||||
[variablelist
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
[endsect] [/tutorial]
|
||||
|
||||
[/////////////////////]
|
||||
[section:ref Reference]
|
||||
|
||||
#include <boost/thread/externally_locked_stream.hpp>
|
||||
@@ -49,7 +48,7 @@
|
||||
operator>>(externally_locked_stream<Stream, RecursiveMutex>& mtx, T& arg);
|
||||
}
|
||||
|
||||
[/////////////////////////////////////////]
|
||||
|
||||
[section:stream_guard Class `stream_guard`]
|
||||
|
||||
#include <boost/thread/externally_locked_stream.hpp>
|
||||
@@ -79,7 +78,6 @@
|
||||
|
||||
`stream_guard` is a model of __StrictLock.
|
||||
|
||||
[//////////////////////////////////////////////////]
|
||||
[section:constructor `stream_guard(mutex_type & m)`]
|
||||
|
||||
[variablelist
|
||||
@@ -91,7 +89,7 @@
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[////////////////////////////////////////////////////////////////////////////]
|
||||
|
||||
[section:constructor_adopt `stream_guard(mutex_type & m,boost::adopt_lock_t)`]
|
||||
|
||||
[variablelist
|
||||
@@ -107,7 +105,8 @@ obtained by a call to [lock_ref_link `m.lock()`].]]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[//////////////////////////////////////////////////////////]
|
||||
|
||||
|
||||
[section:move_constructor `stream_guard(stream_guard && m)`]
|
||||
|
||||
|
||||
@@ -120,7 +119,8 @@ obtained by a call to [lock_ref_link `m.lock()`].]]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[////////////////////////////////////]
|
||||
|
||||
|
||||
[section:destructor `~stream_guard()`]
|
||||
|
||||
[variablelist
|
||||
@@ -134,8 +134,8 @@ object passed to the constructor.]]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[endsect]
|
||||
[//////////////////////////////////////////////////////////////////]
|
||||
[section:externally_locked_stream Class `externally_locked_stream `]
|
||||
|
||||
#include <boost/thread/externally_locked_stream.hpp>
|
||||
@@ -152,6 +152,7 @@ object passed to the constructor.]]
|
||||
|
||||
// Modifiers
|
||||
stream_guard<Stream, RecursiveMutex> hold();
|
||||
Stream& bypass() const;
|
||||
|
||||
};
|
||||
}
|
||||
@@ -161,7 +162,6 @@ provides full access to that object through the `get` member functions, provided
|
||||
pass a reference to a strict lock object.
|
||||
|
||||
|
||||
[////////////////////////////////////////////////////////////////////////]
|
||||
[section:constructor `externally_locked_stream(Stream&, RecursiveMutex&)`]
|
||||
|
||||
[variablelist
|
||||
@@ -172,7 +172,6 @@ pass a reference to a strict lock object.
|
||||
|
||||
[endsect]
|
||||
|
||||
[/////////////////////]
|
||||
[section:hold `hold()`]
|
||||
|
||||
[variablelist
|
||||
@@ -183,8 +182,6 @@ pass a reference to a strict lock object.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
@@ -23,16 +23,16 @@ In addition to the C++11 standard locks, Boost.Thread provides other locks and s
|
||||
In particular, the library provides some lock factories.
|
||||
|
||||
template <class Lockable, class Function>
|
||||
auto with_lock_guard(Lockable& m, Function f) -> decltype(f())
|
||||
auto with_lock_guard(Lockable& m, Function f) -> decltype(fn())
|
||||
{
|
||||
auto&& _ = boost::make_lock_guard(m);
|
||||
auto&& _ = boost::make_lock_guard(f);
|
||||
f();
|
||||
}
|
||||
|
||||
|
||||
that can be used as
|
||||
|
||||
int i = with_lock_guard(mtx, []()
|
||||
int i = with_lock_guard(mtx, {}() -> bool
|
||||
{
|
||||
// access the protected state
|
||||
return true;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/]
|
||||
|
||||
|
||||
[section:synchronized_valuesxxx Synchronized Values - EXPERIMENTAL]
|
||||
[section:synchronized_valuesxxx Synchronized values - EXPERIMENTAL]
|
||||
|
||||
[warning These features 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 :(]
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
[library Thread
|
||||
[quickbook 1.5]
|
||||
[version 4.2.0]
|
||||
[version 4.1.0]
|
||||
[authors [Williams, Anthony] [Botet Escriba, Vicente J.]]
|
||||
[copyright 2007-11 Anthony Williams]
|
||||
[copyright 2011-13 Vicente J. Botet Escriba]
|
||||
|
||||
@@ -568,7 +568,7 @@ any) to `*this`.
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Requires:] [`Callable` must be Copyable and `func()` must be a valid expression.]]
|
||||
[[Requires:] [`Callable` must by Copyable and `func()` must be a valid expression.]]
|
||||
|
||||
[[Effects:] [`func` is copied into storage managed internally by the thread library, and that copy is invoked on a newly-created
|
||||
thread of execution. If this invocation results in an exception being propagated into the internals of the thread library that is
|
||||
@@ -595,7 +595,7 @@ not of type __thread_interrupted__, then `std::terminate()` will be called. Any
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Preconditions:] [`Callable` must be copyable.]]
|
||||
[[Preconditions:] [`Callable` must by copyable.]]
|
||||
|
||||
[[Effects:] [`func` is copied into storage managed internally by the thread library, and that copy is invoked on a newly-created
|
||||
thread of execution with the specified attributes. If this invocation results in an exception being propagated into the internals of the thread library that is
|
||||
@@ -623,7 +623,7 @@ If the attributes declare the native thread as detached, the boost::thread will
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Preconditions:] [`Callable` must be Movable.]]
|
||||
[[Preconditions:] [`Callable` must by Movable.]]
|
||||
|
||||
[[Effects:] [`func` is moved into storage managed internally by the thread library, and that copy is invoked on a newly-created
|
||||
thread of execution. If this invocation results in an exception being propagated into the internals of the thread library that is
|
||||
@@ -650,7 +650,7 @@ not of type __thread_interrupted__, then `std::terminate()` will be called. Any
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Preconditions:] [`Callable` must be copyable.]]
|
||||
[[Preconditions:] [`Callable` must by copyable.]]
|
||||
|
||||
[[Effects:] [`func` is copied into storage managed internally by the thread library, and that copy is invoked on a newly-created
|
||||
thread of execution with the specified attributes. If this invocation results in an exception being propagated into the internals of the thread library that is
|
||||
@@ -679,7 +679,7 @@ If the attributes declare the native thread as detached, the boost::thread will
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Preconditions:] [`F` and each `A`n must be copyable or movable.]]
|
||||
[[Preconditions:] [`F` and each `A`n must by copyable or movable.]]
|
||||
|
||||
[[Effects:] [As if [link
|
||||
thread.thread_management.thread.callable_constructor
|
||||
|
||||
@@ -16,7 +16,7 @@ class bounded_buffer : private boost::noncopyable
|
||||
public:
|
||||
typedef boost::unique_lock<boost::mutex> lock;
|
||||
|
||||
bounded_buffer(int n) : boost::noncopyable(), begin(0), end(0), buffered(0), circular_buf(n) { }
|
||||
bounded_buffer(int n) : begin(0), end(0), buffered(0), circular_buf(n) { }
|
||||
|
||||
void send (int m) {
|
||||
lock lk(monitor);
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
// Copyright (C) 2012-2013 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_USES_LOG
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
|
||||
#include <boost/thread/detail/log.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <exception>
|
||||
#include <string>
|
||||
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
||||
|
||||
int p1_ex()
|
||||
{
|
||||
BOOST_THREAD_LOG << "P1" << BOOST_THREAD_END_LOG;
|
||||
throw std::logic_error("kk");
|
||||
}
|
||||
|
||||
int p1()
|
||||
{
|
||||
BOOST_THREAD_LOG << "P1" << BOOST_THREAD_END_LOG;
|
||||
return 1;;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
BOOST_THREAD_LOG << "<MAIN" << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
boost::future<int> f2 = f1.fallback_to(-1);
|
||||
assert(f2.get()==1);
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
|
||||
return 1;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1_ex);
|
||||
boost::future<int> f2 = f1.fallback_to(-1);
|
||||
assert(f2.get()==-1);
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
|
||||
return 1;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
BOOST_THREAD_LOG << "MAIN>" << BOOST_THREAD_END_LOG;
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -19,26 +19,7 @@ int p1()
|
||||
return 123;
|
||||
}
|
||||
|
||||
int p2(boost::future<int> f)
|
||||
{
|
||||
BOOST_THREAD_LOG << "<P2" << BOOST_THREAD_END_LOG;
|
||||
try
|
||||
{
|
||||
return 2 * f.get();
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
|
||||
BOOST_ASSERT(false);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
|
||||
BOOST_ASSERT(false);
|
||||
}
|
||||
BOOST_THREAD_LOG << "P2>" << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
int p2s(boost::shared_future<int> f)
|
||||
int p2(boost::future<int>& f)
|
||||
{
|
||||
BOOST_THREAD_LOG << "<P2" << BOOST_THREAD_END_LOG;
|
||||
try
|
||||
@@ -61,7 +42,6 @@ int p2s(boost::shared_future<int> f)
|
||||
int main()
|
||||
{
|
||||
BOOST_THREAD_LOG << "<MAIN" << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
@@ -78,25 +58,6 @@ int main()
|
||||
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share();
|
||||
boost::future<int> f2 = f1.then(&p2s);
|
||||
(void)f2.get();
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
|
||||
return 1;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
BOOST_THREAD_LOG << "MAIN>" << BOOST_THREAD_END_LOG;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
// Copyright (C) 2012-2013 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_USES_LOG
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
|
||||
#include <boost/thread/detail/log.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <string>
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
|
||||
|
||||
int p1()
|
||||
{
|
||||
BOOST_THREAD_LOG << "P1" << BOOST_THREAD_END_LOG;
|
||||
return 123;
|
||||
}
|
||||
|
||||
boost::future<int> p2()
|
||||
{
|
||||
BOOST_THREAD_LOG << "<P2" << BOOST_THREAD_END_LOG;
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
BOOST_THREAD_LOG << "P2>" << BOOST_THREAD_END_LOG;
|
||||
return boost::move(f1);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
BOOST_THREAD_LOG << "<MAIN" << BOOST_THREAD_END_LOG;
|
||||
try
|
||||
{
|
||||
boost::future<boost::future<int> > outer_future = boost::async(boost::launch::async, &p2);
|
||||
boost::future<int> inner_future = outer_future.unwrap();
|
||||
int i = inner_future.get();
|
||||
BOOST_THREAD_LOG << "i= "<< i << "" << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
|
||||
return 1;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
|
||||
return 2;
|
||||
}
|
||||
BOOST_THREAD_LOG << "MAIN>" << BOOST_THREAD_END_LOG;
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -33,7 +33,7 @@ int main()
|
||||
}
|
||||
{
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, []() {return 123;});
|
||||
boost::future<int> f2 = f1.then([](boost::future<int> f) {return 2*f.get(); });
|
||||
boost::future<int> f2 = f1.then([](boost::future<int>& f) {return 2*f.get(); });
|
||||
int result = f2.get();
|
||||
BOOST_THREAD_LOG << "f2 " << result << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
|
||||
@@ -8,16 +8,6 @@
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <iostream>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
exception_ptr make_exception_ptr(T v)
|
||||
{
|
||||
return copy_exception(v);
|
||||
}
|
||||
}
|
||||
|
||||
int p1() { return 5; }
|
||||
|
||||
void p() { }
|
||||
@@ -25,23 +15,22 @@ void p() { }
|
||||
#if defined BOOST_THREAD_USES_MOVE
|
||||
boost::future<void> void_compute()
|
||||
{
|
||||
return BOOST_THREAD_MAKE_RV_REF(boost::make_ready_future());
|
||||
return BOOST_THREAD_MAKE_RV_REF(boost::make_future());
|
||||
}
|
||||
#endif
|
||||
|
||||
boost::future<int> compute(int x)
|
||||
{
|
||||
if (x == 0) return boost::make_ready_future(0);
|
||||
//if (x < 0) return boost::make_ready_future<int>(boost::make_exception_ptr(std::logic_error("Error")));
|
||||
if (x < 0) return boost::make_ready_future<int>(std::logic_error("Error"));
|
||||
if (x == 0) return boost::make_future(0);
|
||||
if (x < 0) return boost::make_future(-1);
|
||||
//boost::future<int> f1 = boost::async([]() { return x+1; });
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, p1);
|
||||
return boost::move(f1);
|
||||
}
|
||||
boost::shared_future<int> shared_compute(int x)
|
||||
{
|
||||
if (x == 0) return boost::make_ready_future(0).share();
|
||||
if (x < 0) return boost::make_ready_future<int>(std::logic_error("Error")).share();
|
||||
if (x == 0) return boost::make_shared_future(0);
|
||||
if (x < 0) return boost::make_shared_future(-1);
|
||||
//boost::future<int> f1 = boost::async([]() { return x+1; });
|
||||
boost::shared_future<int> f1 = boost::async(p1).share();
|
||||
return boost::move(f1);
|
||||
|
||||
@@ -44,8 +44,8 @@ int main()
|
||||
externally_locked_stream<std::ostream> mcout(std::cout, terminal_mutex);
|
||||
externally_locked_stream<std::istream> mcin(std::cin, terminal_mutex);
|
||||
|
||||
scoped_thread<> t1(boost::thread(use_cerr, boost::ref(mcerr)));
|
||||
scoped_thread<> t2(boost::thread(use_cout, boost::ref(mcout)));
|
||||
scoped_thread<> t1(thread(use_cerr, boost::ref(mcerr)));
|
||||
scoped_thread<> t2(thread(use_cout, boost::ref(mcout)));
|
||||
this_thread::sleep_for(chrono::seconds(2));
|
||||
std::string nm;
|
||||
{
|
||||
|
||||
@@ -143,7 +143,7 @@ namespace
|
||||
{
|
||||
typedef SharedData<Types> S;
|
||||
|
||||
auto best_producer_time = std::numeric_limits<Stopwatch::rep>::max BOOST_PREVENT_MACRO_SUBSTITUTION ();
|
||||
auto best_producer_time = std::numeric_limits<Stopwatch::rep>::max();
|
||||
|
||||
std::vector<std::thread> consumers
|
||||
{ consumer_count };
|
||||
@@ -165,7 +165,7 @@ namespace
|
||||
for (unsigned i = 0; i < consumer_count; ++i)
|
||||
consumers[i].join();
|
||||
|
||||
best_producer_time = std::min BOOST_PREVENT_MACRO_SUBSTITUTION (best_producer_time, shared_data.producer_time);
|
||||
best_producer_time = std::min(best_producer_time, shared_data.producer_time);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ void unique()
|
||||
|
||||
int main()
|
||||
{
|
||||
boost::chrono::high_resolution_clock::duration best_time(std::numeric_limits<boost::chrono::high_resolution_clock::duration::rep>::max BOOST_PREVENT_MACRO_SUBSTITUTION ());
|
||||
boost::chrono::high_resolution_clock::duration best_time(std::numeric_limits<boost::chrono::high_resolution_clock::duration::rep>::max());
|
||||
for (int i =100; i>0; --i) {
|
||||
boost::chrono::high_resolution_clock clock;
|
||||
boost::chrono::high_resolution_clock::time_point s1 = clock.now();
|
||||
@@ -61,7 +61,7 @@ int main()
|
||||
// t13.join();
|
||||
boost::chrono::high_resolution_clock::time_point f1 = clock.now();
|
||||
//std::cout << " Time spent:" << (f1 - s1) << std::endl;
|
||||
best_time = std::min BOOST_PREVENT_MACRO_SUBSTITUTION (best_time, f1 - s1);
|
||||
best_time = std::min(best_time, f1 - s1);
|
||||
|
||||
}
|
||||
std::cout << "Best Time spent:" << best_time << std::endl;
|
||||
|
||||
@@ -110,9 +110,9 @@ int main()
|
||||
|
||||
{
|
||||
mcout << "begin of main" << std::endl;
|
||||
scoped_thread<> t11(boost::thread(producer, boost::ref(mcerr), boost::ref(sbq)));
|
||||
scoped_thread<> t12(boost::thread(producer, boost::ref(mcerr), boost::ref(sbq)));
|
||||
scoped_thread<> t2(boost::thread(consumer, boost::ref(mcout), boost::ref(sbq)));
|
||||
scoped_thread<> t11(thread(producer, boost::ref(mcerr), boost::ref(sbq)));
|
||||
scoped_thread<> t12(thread(producer, boost::ref(mcerr), boost::ref(sbq)));
|
||||
scoped_thread<> t2(thread(consumer, boost::ref(mcout), boost::ref(sbq)));
|
||||
|
||||
this_thread::sleep_for(chrono::seconds(1));
|
||||
|
||||
|
||||
@@ -110,9 +110,9 @@ int main()
|
||||
|
||||
{
|
||||
mcout << "begin of main" << std::endl;
|
||||
scoped_thread<> t11(boost::thread(producer, boost::ref(mcerr), boost::ref(sbq)));
|
||||
scoped_thread<> t12(boost::thread(producer, boost::ref(mcerr), boost::ref(sbq)));
|
||||
scoped_thread<> t2(boost::thread(consumer, boost::ref(mcout), boost::ref(sbq)));
|
||||
scoped_thread<> t11(thread(producer, boost::ref(mcerr), boost::ref(sbq)));
|
||||
scoped_thread<> t12(thread(producer, boost::ref(mcerr), boost::ref(sbq)));
|
||||
scoped_thread<> t2(thread(consumer, boost::ref(mcout), boost::ref(sbq)));
|
||||
|
||||
this_thread::sleep_for(chrono::seconds(1));
|
||||
|
||||
|
||||
@@ -13,9 +13,6 @@ void do_something(int& i)
|
||||
{
|
||||
++i;
|
||||
}
|
||||
void f(int, int)
|
||||
{
|
||||
}
|
||||
|
||||
struct func
|
||||
{
|
||||
@@ -84,10 +81,7 @@ int main()
|
||||
|
||||
do_something_in_current_thread();
|
||||
}
|
||||
{
|
||||
boost::scoped_thread<> g( &f, 1, 2 );
|
||||
do_something_in_current_thread();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
// 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)
|
||||
|
||||
#undef BOOST_THREAD_VERSION
|
||||
#define BOOST_THREAD_VERSION 2
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/condition.hpp>
|
||||
#include <boost/thread/thread_only.hpp>
|
||||
|
||||
@@ -17,197 +17,51 @@
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#ifdef BOOST_NO_CXX11_HDR_FUNCTIONAL
|
||||
#include <boost/function.hpp>
|
||||
#else
|
||||
#include <functional>
|
||||
#endif
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/is_void.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/utility/result_of.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace thread_detail
|
||||
{
|
||||
#ifdef BOOST_NO_CXX11_HDR_FUNCTIONAL
|
||||
typedef function<void()> void_completion_function;
|
||||
typedef function<size_t()> size_completion_function;
|
||||
#else
|
||||
typedef std::function<void()> void_completion_function;
|
||||
typedef std::function<size_t()> size_completion_function;
|
||||
#endif
|
||||
|
||||
struct default_barrier_reseter
|
||||
class barrier
|
||||
{
|
||||
unsigned int size_;
|
||||
default_barrier_reseter(unsigned int size) :
|
||||
size_(size)
|
||||
{
|
||||
}
|
||||
unsigned int operator()()
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
public:
|
||||
BOOST_THREAD_NO_COPYABLE( barrier )
|
||||
|
||||
barrier(unsigned int count)
|
||||
: m_threshold(count), m_count(count), m_generation(0)
|
||||
{
|
||||
if (count == 0)
|
||||
boost::throw_exception(thread_exception(system::errc::invalid_argument, "barrier constructor: count cannot be zero."));
|
||||
}
|
||||
|
||||
bool wait()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lock(m_mutex);
|
||||
unsigned int gen = m_generation;
|
||||
|
||||
if (--m_count == 0)
|
||||
{
|
||||
m_generation++;
|
||||
m_count = m_threshold;
|
||||
m_cond.notify_all();
|
||||
return true;
|
||||
}
|
||||
|
||||
while (gen == m_generation)
|
||||
m_cond.wait(lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
mutex m_mutex;
|
||||
condition_variable m_cond;
|
||||
unsigned int m_threshold;
|
||||
unsigned int m_count;
|
||||
unsigned int m_generation;
|
||||
};
|
||||
|
||||
struct void_functor_barrier_reseter
|
||||
{
|
||||
unsigned int size_;
|
||||
void_completion_function fct_;
|
||||
template <typename F>
|
||||
#ifndef BOOST_NO_CXX11_HDR_FUNCTIONAL
|
||||
void_functor_barrier_reseter(unsigned int size, BOOST_THREAD_RV_REF(F) funct)
|
||||
: size_(size), fct_(boost::move(funct))
|
||||
{}
|
||||
#else
|
||||
void_functor_barrier_reseter(unsigned int size, F funct)
|
||||
: size_(size), fct_(funct)
|
||||
{}
|
||||
#endif
|
||||
unsigned int operator()()
|
||||
{
|
||||
fct_();
|
||||
return size_;
|
||||
}
|
||||
};
|
||||
struct void_fct_ptr_barrier_reseter
|
||||
{
|
||||
unsigned int size_;
|
||||
void(*fct_)();
|
||||
void_fct_ptr_barrier_reseter(unsigned int size, void(*funct)()) :
|
||||
size_(size), fct_(funct)
|
||||
{
|
||||
}
|
||||
unsigned int operator()()
|
||||
{
|
||||
fct_();
|
||||
return size_;
|
||||
}
|
||||
};
|
||||
}
|
||||
class barrier
|
||||
{
|
||||
static inline unsigned int check_counter(unsigned int count)
|
||||
{
|
||||
if (count == 0) boost::throw_exception(
|
||||
thread_exception(system::errc::invalid_argument, "barrier constructor: count cannot be zero."));
|
||||
return count;
|
||||
}
|
||||
struct dummy
|
||||
{
|
||||
};
|
||||
|
||||
public:
|
||||
BOOST_THREAD_NO_COPYABLE( barrier)
|
||||
|
||||
explicit barrier(unsigned int count) :
|
||||
m_count(check_counter(count)), m_generation(0), fct_(thread_detail::default_barrier_reseter(count))
|
||||
{
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
barrier(
|
||||
unsigned int count,
|
||||
#ifndef BOOST_NO_CXX11_HDR_FUNCTIONAL
|
||||
BOOST_THREAD_RV_REF(F) funct,
|
||||
#else
|
||||
F funct,
|
||||
#endif
|
||||
typename enable_if<
|
||||
typename is_void<typename result_of<F>::type>::type, dummy*
|
||||
>::type=0
|
||||
)
|
||||
: m_count(check_counter(count)),
|
||||
m_generation(0),
|
||||
fct_(thread_detail::void_functor_barrier_reseter(count,
|
||||
#ifndef BOOST_NO_CXX11_HDR_FUNCTIONAL
|
||||
boost::move(funct)
|
||||
#else
|
||||
funct
|
||||
#endif
|
||||
)
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
barrier(
|
||||
unsigned int count,
|
||||
#ifndef BOOST_NO_CXX11_HDR_FUNCTIONAL
|
||||
BOOST_THREAD_RV_REF(F) funct,
|
||||
#else
|
||||
F funct,
|
||||
#endif
|
||||
typename enable_if<
|
||||
typename is_same<typename result_of<F>::type, unsigned int>::type, dummy*
|
||||
>::type=0
|
||||
)
|
||||
: m_count(check_counter(count)),
|
||||
m_generation(0),
|
||||
fct_(
|
||||
#ifndef BOOST_NO_CXX11_HDR_FUNCTIONAL
|
||||
boost::move(funct)
|
||||
#else
|
||||
funct
|
||||
#endif
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
barrier(unsigned int count, void(*funct)()) :
|
||||
m_count(check_counter(count)), m_generation(0),
|
||||
fct_(funct
|
||||
? thread_detail::size_completion_function(thread_detail::void_fct_ptr_barrier_reseter(count, funct))
|
||||
: thread_detail::size_completion_function(thread_detail::default_barrier_reseter(count))
|
||||
)
|
||||
{
|
||||
}
|
||||
barrier(unsigned int count, unsigned int(*funct)()) :
|
||||
m_count(check_counter(count)), m_generation(0),
|
||||
fct_(funct
|
||||
? thread_detail::size_completion_function(funct)
|
||||
: thread_detail::size_completion_function(thread_detail::default_barrier_reseter(count))
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
bool wait()
|
||||
{
|
||||
boost::unique_lock < boost::mutex > lock(m_mutex);
|
||||
unsigned int gen = m_generation;
|
||||
|
||||
if (--m_count == 0)
|
||||
{
|
||||
m_generation++;
|
||||
m_count = static_cast<unsigned int>(fct_());
|
||||
BOOST_ASSERT(m_count != 0);
|
||||
m_cond.notify_all();
|
||||
return true;
|
||||
}
|
||||
|
||||
while (gen == m_generation)
|
||||
m_cond.wait(lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
void count_down_and_wait()
|
||||
{
|
||||
wait();
|
||||
}
|
||||
|
||||
private:
|
||||
mutex m_mutex;
|
||||
condition_variable m_cond;
|
||||
unsigned int m_count;
|
||||
unsigned int m_generation;
|
||||
thread_detail::size_completion_function fct_;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
|
||||
@@ -264,11 +264,6 @@
|
||||
#define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
||||
#endif
|
||||
|
||||
#if ! defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP \
|
||||
&& ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_UNWRAP
|
||||
#define BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
|
||||
#endif
|
||||
|
||||
// FUTURE_INVALID_AFTER_GET
|
||||
#if ! defined BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET \
|
||||
&& ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_INVALID_AFTER_GET
|
||||
|
||||
@@ -75,28 +75,15 @@ namespace boost
|
||||
};
|
||||
struct counter_is_not_zero
|
||||
{
|
||||
counter_is_not_zero(counter const& count) : count_(count) {}
|
||||
counter_is_not_zero(const counter& count) : count_(count) {}
|
||||
bool operator()() const { return count_ != 0; }
|
||||
counter const& count_;
|
||||
const counter& count_;
|
||||
};
|
||||
struct counter_is_zero
|
||||
{
|
||||
counter_is_zero(counter const& count) : count_(count) {}
|
||||
counter_is_zero(const counter& count) : count_(count) {}
|
||||
bool operator()() const { return count_ == 0; }
|
||||
counter const& count_;
|
||||
};
|
||||
struct is_zero
|
||||
{
|
||||
is_zero(std::size_t& count) : count_(count) {}
|
||||
bool operator()() const { return count_ == 0; }
|
||||
std::size_t& count_;
|
||||
};
|
||||
struct not_equal
|
||||
{
|
||||
not_equal(std::size_t& x, std::size_t& y) : x_(x), y_(y) {}
|
||||
bool operator()() const { return x_ != y_; }
|
||||
std::size_t& x_;
|
||||
std::size_t& y_;
|
||||
const counter& count_;
|
||||
};
|
||||
}
|
||||
} // namespace boost
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2011-2013 Vicente J. Botet Escriba
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/thread for documentation.
|
||||
//
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2011-2013 Vicente J. Botet Escriba
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/thread for documentation.
|
||||
//
|
||||
|
||||
@@ -826,19 +826,6 @@ namespace boost
|
||||
};
|
||||
|
||||
void BOOST_THREAD_DECL add_thread_exit_function(thread_exit_function_base*);
|
||||
struct shared_state_base;
|
||||
#if defined(BOOST_THREAD_PLATFORM_WIN32)
|
||||
inline void make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
|
||||
{
|
||||
detail::thread_data_base* const current_thread_data(detail::get_current_thread_data());
|
||||
if(current_thread_data)
|
||||
{
|
||||
current_thread_data->make_ready_at_thread_exit(as);
|
||||
}
|
||||
}
|
||||
#else
|
||||
void BOOST_THREAD_DECL make_ready_at_thread_exit(shared_ptr<shared_state_base> as);
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace this_thread
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -23,40 +23,28 @@ namespace boost
|
||||
{
|
||||
class latch
|
||||
{
|
||||
/// @Requires: count_ must be greater than 0
|
||||
/// Effect: Decrement the count. Unlocks the lock and notify anyone waiting if we reached zero.
|
||||
/// Returns: true if count_ reached the value 0.
|
||||
/// @Requires: count_.value_ must be greater than 0
|
||||
/// Effect: Decrement the count. Unlocks the lock notify anyone waiting if we reached zero.
|
||||
/// Returns: true if count_.value_ reached the value 0.
|
||||
/// @ThreadSafe ensured by the @c lk parameter
|
||||
bool count_down(unique_lock<mutex> &lk)
|
||||
/// pre_condition (count_ > 0)
|
||||
/// pre_condition (count_.value_ > 0)
|
||||
{
|
||||
BOOST_ASSERT(count_ > 0);
|
||||
if (--count_ == 0)
|
||||
BOOST_ASSERT(count_.value_ > 0);
|
||||
if (--count_.value_ == 0)
|
||||
{
|
||||
++generation_;
|
||||
count_.cond_.notify_all();
|
||||
lk.unlock();
|
||||
cond_.notify_all();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/// Effect: Decrement the count is > 0. Unlocks the lock notify anyone waiting if we reached zero.
|
||||
/// Returns: true if count_ is 0.
|
||||
/// @ThreadSafe ensured by the @c lk parameter
|
||||
bool try_count_down(unique_lock<mutex> &lk)
|
||||
{
|
||||
if (count_ > 0)
|
||||
{
|
||||
return count_down(lk);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public:
|
||||
BOOST_THREAD_NO_COPYABLE( latch)
|
||||
|
||||
/// Constructs a latch with a given count.
|
||||
latch(std::size_t count) :
|
||||
count_(count), generation_(0)
|
||||
count_(count)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -72,8 +60,7 @@ namespace boost
|
||||
void wait()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mutex_);
|
||||
std::size_t generation(generation_);
|
||||
cond_.wait(lk, detail::not_equal(generation, generation_));
|
||||
count_.cond_.wait(lk, detail::counter_is_zero(count_));
|
||||
}
|
||||
|
||||
/// @return true if the internal counter is already 0, false otherwise
|
||||
@@ -89,8 +76,7 @@ namespace boost
|
||||
cv_status wait_for(const chrono::duration<Rep, Period>& rel_time)
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mutex_);
|
||||
std::size_t generation(generation_);
|
||||
return cond_.wait_for(lk, rel_time, detail::not_equal(generation, generation_))
|
||||
return count_.cond_.wait_for(lk, rel_time, detail::counter_is_zero(count_))
|
||||
? cv_status::no_timeout
|
||||
: cv_status::timeout;
|
||||
}
|
||||
@@ -101,8 +87,7 @@ namespace boost
|
||||
cv_status wait_until(const chrono::time_point<Clock, Duration>& abs_time)
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mutex_);
|
||||
std::size_t generation(generation_);
|
||||
return cond_.wait_until(lk, abs_time, detail::not_equal(generation, generation_))
|
||||
return count_.cond_.wait_until(lk, abs_time, detail::counter_is_zero(count_))
|
||||
? cv_status::no_timeout
|
||||
: cv_status::timeout;
|
||||
}
|
||||
@@ -114,13 +99,6 @@ namespace boost
|
||||
boost::unique_lock<boost::mutex> lk(mutex_);
|
||||
count_down(lk);
|
||||
}
|
||||
/// Effect: Decrement the count if it is > 0 and notify anyone waiting if we reached zero.
|
||||
/// Returns: true if count_ was 0 or reached 0.
|
||||
bool try_count_down()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mutex_);
|
||||
return try_count_down(lk);
|
||||
}
|
||||
void signal()
|
||||
{
|
||||
count_down();
|
||||
@@ -132,12 +110,11 @@ namespace boost
|
||||
void count_down_and_wait()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mutex_);
|
||||
std::size_t generation(generation_);
|
||||
if (count_down(lk))
|
||||
{
|
||||
return;
|
||||
}
|
||||
cond_.wait(lk, detail::not_equal(generation, generation_));
|
||||
count_.cond_.wait(lk, detail::counter_is_zero(count_));
|
||||
}
|
||||
void sync()
|
||||
{
|
||||
@@ -155,9 +132,7 @@ namespace boost
|
||||
|
||||
private:
|
||||
mutex mutex_;
|
||||
condition_variable cond_;
|
||||
std::size_t count_;
|
||||
std::size_t generation_;
|
||||
detail::counter count_;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
@@ -1112,10 +1112,6 @@ namespace boost
|
||||
{
|
||||
return exclusive.owns_lock();
|
||||
}
|
||||
Mutex* mutex() const BOOST_NOEXCEPT
|
||||
{
|
||||
return exclusive.mutex();
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) upgrade_to_unique_lock<Mutex> BOOST_THREAD_DCL_MOVABLE_END
|
||||
@@ -1191,7 +1187,7 @@ private unique_lock<Mutex>
|
||||
{
|
||||
return base::owns_lock();
|
||||
}
|
||||
Mutex* mutex() const BOOST_NOEXCEPT
|
||||
Mutex* mutex() const
|
||||
{
|
||||
return base::mutex();
|
||||
}
|
||||
|
||||
@@ -200,15 +200,15 @@ namespace boost
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
template<typename lock_type>
|
||||
bool timed_wait(lock_type& m,boost::system_time const& abs_time)
|
||||
bool timed_wait(lock_type& m,boost::system_time const& wait_until)
|
||||
{
|
||||
struct timespec const timeout=detail::to_timespec(abs_time);
|
||||
struct timespec const timeout=detail::to_timespec(wait_until);
|
||||
return do_wait_until(m, timeout);
|
||||
}
|
||||
template<typename lock_type>
|
||||
bool timed_wait(lock_type& m,xtime const& abs_time)
|
||||
bool timed_wait(lock_type& m,xtime const& wait_until)
|
||||
{
|
||||
return timed_wait(m,system_time(abs_time));
|
||||
return timed_wait(m,system_time(wait_until));
|
||||
}
|
||||
|
||||
template<typename lock_type,typename duration_type>
|
||||
@@ -218,20 +218,20 @@ namespace boost
|
||||
}
|
||||
|
||||
template<typename lock_type,typename predicate_type>
|
||||
bool timed_wait(lock_type& m,boost::system_time const& abs_time, predicate_type pred)
|
||||
bool timed_wait(lock_type& m,boost::system_time const& wait_until,predicate_type pred)
|
||||
{
|
||||
while (!pred())
|
||||
{
|
||||
if(!timed_wait(m, abs_time))
|
||||
if(!timed_wait(m, wait_until))
|
||||
return pred();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename lock_type,typename predicate_type>
|
||||
bool timed_wait(lock_type& m,xtime const& abs_time, predicate_type pred)
|
||||
bool timed_wait(lock_type& m,xtime const& wait_until,predicate_type pred)
|
||||
{
|
||||
return timed_wait(m,system_time(abs_time),pred);
|
||||
return timed_wait(m,system_time(wait_until),pred);
|
||||
}
|
||||
|
||||
template<typename lock_type,typename duration_type,typename predicate_type>
|
||||
|
||||
@@ -98,21 +98,21 @@ namespace boost
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
inline bool timed_wait(
|
||||
unique_lock<mutex>& m,
|
||||
boost::system_time const& abs_time)
|
||||
boost::system_time const& wait_until)
|
||||
{
|
||||
#if defined BOOST_THREAD_WAIT_BUG
|
||||
struct timespec const timeout=detail::to_timespec(abs_time + BOOST_THREAD_WAIT_BUG);
|
||||
struct timespec const timeout=detail::to_timespec(wait_until + BOOST_THREAD_WAIT_BUG);
|
||||
return do_wait_until(m, timeout);
|
||||
#else
|
||||
struct timespec const timeout=detail::to_timespec(abs_time);
|
||||
struct timespec const timeout=detail::to_timespec(wait_until);
|
||||
return do_wait_until(m, timeout);
|
||||
#endif
|
||||
}
|
||||
bool timed_wait(
|
||||
unique_lock<mutex>& m,
|
||||
xtime const& abs_time)
|
||||
xtime const& wait_until)
|
||||
{
|
||||
return timed_wait(m,system_time(abs_time));
|
||||
return timed_wait(m,system_time(wait_until));
|
||||
}
|
||||
|
||||
template<typename duration_type>
|
||||
@@ -126,11 +126,11 @@ namespace boost
|
||||
template<typename predicate_type>
|
||||
bool timed_wait(
|
||||
unique_lock<mutex>& m,
|
||||
boost::system_time const& abs_time,predicate_type pred)
|
||||
boost::system_time const& wait_until,predicate_type pred)
|
||||
{
|
||||
while (!pred())
|
||||
{
|
||||
if(!timed_wait(m, abs_time))
|
||||
if(!timed_wait(m, wait_until))
|
||||
return pred();
|
||||
}
|
||||
return true;
|
||||
@@ -139,9 +139,9 @@ namespace boost
|
||||
template<typename predicate_type>
|
||||
bool timed_wait(
|
||||
unique_lock<mutex>& m,
|
||||
xtime const& abs_time,predicate_type pred)
|
||||
xtime const& wait_until,predicate_type pred)
|
||||
{
|
||||
return timed_wait(m,system_time(abs_time),pred);
|
||||
return timed_wait(m,system_time(wait_until),pred);
|
||||
}
|
||||
|
||||
template<typename duration_type,typename predicate_type>
|
||||
|
||||
@@ -82,7 +82,7 @@ namespace boost
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct shared_state_base;
|
||||
struct future_object_base;
|
||||
struct tss_cleanup_function;
|
||||
struct thread_exit_callback_node;
|
||||
struct tss_data_node
|
||||
@@ -121,7 +121,7 @@ namespace boost
|
||||
> notify_list_t;
|
||||
notify_list_t notify;
|
||||
|
||||
typedef std::vector<shared_ptr<shared_state_base> > async_states_t;
|
||||
typedef std::vector<shared_ptr<future_object_base> > async_states_t;
|
||||
async_states_t async_states_;
|
||||
|
||||
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
@@ -154,7 +154,7 @@ namespace boost
|
||||
notify.push_back(std::pair<condition_variable*, mutex*>(cv, m));
|
||||
}
|
||||
|
||||
void make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
|
||||
void make_ready_at_thread_exit(shared_ptr<future_object_base> as)
|
||||
{
|
||||
async_states_.push_back(as);
|
||||
}
|
||||
|
||||
@@ -47,8 +47,9 @@ namespace boost
|
||||
*
|
||||
*/
|
||||
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template <class F, class ...Args, typename = typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type>
|
||||
explicit strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Args)... args) :
|
||||
template <class F, class ...Args>
|
||||
explicit strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Args)... args,
|
||||
typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type=0) :
|
||||
t_(boost::forward<F>(f), boost::forward<Args>(args)...) {}
|
||||
#else
|
||||
template <class F>
|
||||
@@ -137,8 +138,9 @@ namespace boost
|
||||
*/
|
||||
|
||||
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template <class F, class ...Args, typename = typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type>
|
||||
explicit scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Args)... args) :
|
||||
template <class F, class ...Args>
|
||||
explicit scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Args)... args,
|
||||
typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type=0) :
|
||||
t_(boost::forward<F>(f), boost::forward<Args>(args)...) {}
|
||||
#else
|
||||
template <class F>
|
||||
|
||||
@@ -48,31 +48,31 @@ namespace boost
|
||||
~sync_bounded_queue();
|
||||
|
||||
// Observers
|
||||
inline bool empty() const;
|
||||
inline bool full() const;
|
||||
inline size_type capacity() const;
|
||||
inline size_type size() const;
|
||||
inline bool closed() const;
|
||||
bool empty() const;
|
||||
bool full() const;
|
||||
size_type capacity() const;
|
||||
size_type size() const;
|
||||
bool closed() const;
|
||||
|
||||
// Modifiers
|
||||
inline void close();
|
||||
void close();
|
||||
|
||||
inline void push(const value_type& x);
|
||||
inline void push(BOOST_THREAD_RV_REF(value_type) x);
|
||||
inline bool try_push(const value_type& x);
|
||||
inline bool try_push(BOOST_THREAD_RV_REF(value_type) x);
|
||||
inline bool try_push(no_block_tag, const value_type& x);
|
||||
inline bool try_push(no_block_tag, BOOST_THREAD_RV_REF(value_type) x);
|
||||
void push(const value_type& x);
|
||||
void push(BOOST_THREAD_RV_REF(value_type) x);
|
||||
bool try_push(const value_type& x);
|
||||
bool try_push(BOOST_THREAD_RV_REF(value_type) x);
|
||||
bool try_push(no_block_tag, const value_type& x);
|
||||
bool try_push(no_block_tag, BOOST_THREAD_RV_REF(value_type) x);
|
||||
|
||||
// Observers/Modifiers
|
||||
inline void pull(value_type&);
|
||||
inline void pull(ValueType& elem, bool & closed);
|
||||
void pull(value_type&);
|
||||
void pull(ValueType& elem, bool & closed);
|
||||
// enable_if is_nothrow_copy_movable<value_type>
|
||||
inline value_type pull();
|
||||
inline shared_ptr<ValueType> ptr_pull();
|
||||
inline bool try_pull(value_type&);
|
||||
inline bool try_pull(no_block_tag,value_type&);
|
||||
inline shared_ptr<ValueType> try_pull();
|
||||
value_type pull();
|
||||
shared_ptr<ValueType> ptr_pull();
|
||||
bool try_pull(value_type&);
|
||||
bool try_pull(no_block_tag,value_type&);
|
||||
shared_ptr<ValueType> try_pull();
|
||||
|
||||
private:
|
||||
mutable mutex mtx_;
|
||||
@@ -86,51 +86,42 @@ namespace boost
|
||||
size_type capacity_;
|
||||
bool closed_;
|
||||
|
||||
inline size_type inc(size_type idx) const BOOST_NOEXCEPT
|
||||
size_type inc(size_type idx) const BOOST_NOEXCEPT
|
||||
{
|
||||
return (idx + 1) % capacity_;
|
||||
}
|
||||
|
||||
inline bool empty(unique_lock<mutex>& ) const BOOST_NOEXCEPT
|
||||
bool empty(unique_lock<mutex>& ) const BOOST_NOEXCEPT
|
||||
{
|
||||
return in_ == out_;
|
||||
}
|
||||
inline bool empty(lock_guard<mutex>& ) const BOOST_NOEXCEPT
|
||||
bool empty(lock_guard<mutex>& ) const BOOST_NOEXCEPT
|
||||
{
|
||||
return in_ == out_;
|
||||
}
|
||||
inline bool full(unique_lock<mutex>& ) const BOOST_NOEXCEPT
|
||||
size_type capacity(lock_guard<mutex>& ) const BOOST_NOEXCEPT
|
||||
{
|
||||
return (inc(in_) == out_);
|
||||
return capacity;
|
||||
}
|
||||
inline bool full(lock_guard<mutex>& ) const BOOST_NOEXCEPT
|
||||
size_type size(lock_guard<mutex>& ) const BOOST_NOEXCEPT
|
||||
{
|
||||
return (inc(in_) == out_);
|
||||
}
|
||||
inline size_type capacity(lock_guard<mutex>& ) const BOOST_NOEXCEPT
|
||||
{
|
||||
return capacity_-1;
|
||||
}
|
||||
inline size_type size(lock_guard<mutex>& lk) const BOOST_NOEXCEPT
|
||||
{
|
||||
if (full(lk)) return capacity(lk);
|
||||
return ((out_+capacity(lk)-in_) % capacity(lk));
|
||||
return ((out_+capacity_-in_) % capacity_)-1;
|
||||
}
|
||||
|
||||
inline void throw_if_closed(unique_lock<mutex>&);
|
||||
void throw_if_closed(unique_lock<mutex>&);
|
||||
|
||||
inline bool try_pull(value_type& x, unique_lock<mutex>& lk);
|
||||
inline bool try_push(const value_type& x, unique_lock<mutex>& lk);
|
||||
inline bool try_push(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
|
||||
inline shared_ptr<value_type> try_pull(unique_lock<mutex>& lk);
|
||||
bool try_pull(value_type& x, unique_lock<mutex>& lk);
|
||||
bool try_push(const value_type& x, unique_lock<mutex>& lk);
|
||||
bool try_push(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
|
||||
shared_ptr<value_type> try_pull(unique_lock<mutex>& lk);
|
||||
|
||||
inline void wait_until_not_empty(unique_lock<mutex>& lk);
|
||||
inline void wait_until_not_empty(unique_lock<mutex>& lk, bool&);
|
||||
inline size_type wait_until_not_full(unique_lock<mutex>& lk);
|
||||
inline size_type wait_until_not_full(unique_lock<mutex>& lk, bool&);
|
||||
void wait_until_not_empty(unique_lock<mutex>& lk);
|
||||
void wait_until_not_empty(unique_lock<mutex>& lk, bool&);
|
||||
size_type wait_until_not_full(unique_lock<mutex>& lk);
|
||||
size_type wait_until_not_full(unique_lock<mutex>& lk, bool&);
|
||||
|
||||
|
||||
inline void notify_not_empty_if_needed(unique_lock<mutex>& lk)
|
||||
void notify_not_empty_if_needed(unique_lock<mutex>& lk)
|
||||
{
|
||||
if (waiting_empty_ > 0)
|
||||
{
|
||||
@@ -139,7 +130,7 @@ namespace boost
|
||||
not_empty_.notify_one();
|
||||
}
|
||||
}
|
||||
inline void notify_not_full_if_needed(unique_lock<mutex>& lk)
|
||||
void notify_not_full_if_needed(unique_lock<mutex>& lk)
|
||||
{
|
||||
if (waiting_full_ > 0)
|
||||
{
|
||||
@@ -149,13 +140,13 @@ namespace boost
|
||||
}
|
||||
}
|
||||
|
||||
inline void pull(value_type& elem, unique_lock<mutex>& lk)
|
||||
void pull(value_type& elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
elem = boost::move(data_[out_]);
|
||||
out_ = inc(out_);
|
||||
notify_not_full_if_needed(lk);
|
||||
}
|
||||
inline boost::shared_ptr<value_type> ptr_pull(unique_lock<mutex>& lk)
|
||||
boost::shared_ptr<value_type> ptr_pull(unique_lock<mutex>& lk)
|
||||
{
|
||||
shared_ptr<value_type> res = make_shared<value_type>(boost::move(data_[out_]));
|
||||
out_ = inc(out_);
|
||||
@@ -163,23 +154,26 @@ namespace boost
|
||||
return res;
|
||||
}
|
||||
|
||||
inline void set_in(size_type in, unique_lock<mutex>& lk)
|
||||
|
||||
void set_in(size_type in, unique_lock<mutex>& lk)
|
||||
{
|
||||
in_ = in;
|
||||
notify_not_empty_if_needed(lk);
|
||||
}
|
||||
|
||||
inline void push_at(const value_type& elem, size_type in_p_1, unique_lock<mutex>& lk)
|
||||
void push_at(const value_type& elem, size_type in_p_1, unique_lock<mutex>& lk)
|
||||
{
|
||||
data_[in_] = elem;
|
||||
set_in(in_p_1, lk);
|
||||
}
|
||||
|
||||
inline void push_at(BOOST_THREAD_RV_REF(value_type) elem, size_type in_p_1, unique_lock<mutex>& lk)
|
||||
void push_at(BOOST_THREAD_RV_REF(value_type) elem, size_type in_p_1, unique_lock<mutex>& lk)
|
||||
{
|
||||
data_[in_] = boost::move(elem);
|
||||
set_in(in_p_1, lk);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
template <typename ValueType>
|
||||
|
||||
@@ -37,36 +37,37 @@ namespace boost
|
||||
|
||||
// Constructors/Assignment/Destructors
|
||||
BOOST_THREAD_NO_COPYABLE(sync_queue)
|
||||
inline sync_queue();
|
||||
//template <typename Range>
|
||||
//inline explicit sync_queue(Range range);
|
||||
inline ~sync_queue();
|
||||
sync_queue();
|
||||
template <typename Range>
|
||||
explicit sync_queue(Range range);
|
||||
~sync_queue();
|
||||
|
||||
// Observers
|
||||
inline bool empty() const;
|
||||
inline bool full() const;
|
||||
inline size_type size() const;
|
||||
inline bool closed() const;
|
||||
bool empty() const;
|
||||
bool full() const;
|
||||
size_type size() const;
|
||||
bool closed() const;
|
||||
|
||||
// Modifiers
|
||||
inline void close();
|
||||
void close();
|
||||
|
||||
inline void push(const value_type& x);
|
||||
inline void push(BOOST_THREAD_RV_REF(value_type) x);
|
||||
inline bool try_push(const value_type& x);
|
||||
inline bool try_push(BOOST_THREAD_RV_REF(value_type) x);
|
||||
inline bool try_push(no_block_tag, const value_type& x);
|
||||
inline bool try_push(no_block_tag, BOOST_THREAD_RV_REF(value_type) x);
|
||||
void push(const value_type& x);
|
||||
void push(BOOST_THREAD_RV_REF(value_type) x);
|
||||
bool try_push(const value_type& x);
|
||||
bool try_push(BOOST_THREAD_RV_REF(value_type) x);
|
||||
bool try_push(no_block_tag, const value_type& x);
|
||||
bool try_push(no_block_tag, BOOST_THREAD_RV_REF(value_type) x);
|
||||
|
||||
// Observers/Modifiers
|
||||
inline void pull(value_type&);
|
||||
inline void pull(ValueType& elem, bool & closed);
|
||||
void pull(value_type&);
|
||||
void pull(ValueType& elem, bool & closed);
|
||||
// enable_if is_nothrow_copy_movable<value_type>
|
||||
inline value_type pull();
|
||||
inline shared_ptr<ValueType> ptr_pull();
|
||||
inline bool try_pull(value_type&);
|
||||
inline bool try_pull(no_block_tag,value_type&);
|
||||
inline shared_ptr<ValueType> try_pull();
|
||||
value_type pull();
|
||||
shared_ptr<ValueType> ptr_pull();
|
||||
bool try_pull(value_type&);
|
||||
bool try_pull(no_block_tag,value_type&);
|
||||
shared_ptr<ValueType> try_pull();
|
||||
|
||||
|
||||
private:
|
||||
mutable mutex mtx_;
|
||||
@@ -75,31 +76,32 @@ namespace boost
|
||||
boost::container::deque<ValueType> data_;
|
||||
bool closed_;
|
||||
|
||||
inline bool empty(unique_lock<mutex>& ) const BOOST_NOEXCEPT
|
||||
bool empty(unique_lock<mutex>& ) const BOOST_NOEXCEPT
|
||||
{
|
||||
return data_.empty();
|
||||
}
|
||||
inline bool empty(lock_guard<mutex>& ) const BOOST_NOEXCEPT
|
||||
bool empty(lock_guard<mutex>& ) const BOOST_NOEXCEPT
|
||||
{
|
||||
return data_.empty();
|
||||
}
|
||||
|
||||
inline size_type size(lock_guard<mutex>& ) const BOOST_NOEXCEPT
|
||||
size_type size(lock_guard<mutex>& ) const BOOST_NOEXCEPT
|
||||
{
|
||||
return data_.size();
|
||||
}
|
||||
|
||||
inline void throw_if_closed(unique_lock<mutex>&);
|
||||
void throw_if_closed(unique_lock<mutex>&);
|
||||
|
||||
inline bool try_pull(value_type& x, unique_lock<mutex>& lk);
|
||||
inline bool try_push(const value_type& x, unique_lock<mutex>& lk);
|
||||
inline bool try_push(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
|
||||
inline shared_ptr<value_type> try_pull(unique_lock<mutex>& lk);
|
||||
bool try_pull(value_type& x, unique_lock<mutex>& lk);
|
||||
bool try_push(const value_type& x, unique_lock<mutex>& lk);
|
||||
bool try_push(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
|
||||
shared_ptr<value_type> try_pull(unique_lock<mutex>& lk);
|
||||
|
||||
inline void wait_until_not_empty(unique_lock<mutex>& lk);
|
||||
inline void wait_until_not_empty(unique_lock<mutex>& lk, bool&);
|
||||
void wait_until_not_empty(unique_lock<mutex>& lk);
|
||||
void wait_until_not_empty(unique_lock<mutex>& lk, bool&);
|
||||
|
||||
inline void notify_not_empty_if_needed(unique_lock<mutex>& lk)
|
||||
|
||||
void notify_not_empty_if_needed(unique_lock<mutex>& lk)
|
||||
{
|
||||
if (waiting_empty_ > 0)
|
||||
{
|
||||
@@ -109,29 +111,31 @@ namespace boost
|
||||
}
|
||||
}
|
||||
|
||||
inline void pull(value_type& elem, unique_lock<mutex>& )
|
||||
void pull(value_type& elem, unique_lock<mutex>& )
|
||||
{
|
||||
elem = boost::move(data_.front());
|
||||
data_.pop_front();
|
||||
}
|
||||
inline boost::shared_ptr<value_type> ptr_pull(unique_lock<mutex>& )
|
||||
boost::shared_ptr<value_type> ptr_pull(unique_lock<mutex>& )
|
||||
{
|
||||
shared_ptr<value_type> res = make_shared<value_type>(boost::move(data_.front()));
|
||||
data_.pop_front();
|
||||
return res;
|
||||
}
|
||||
|
||||
inline void push(const value_type& elem, unique_lock<mutex>& lk)
|
||||
void push(const value_type& elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
data_.push_back(elem);
|
||||
notify_not_empty_if_needed(lk);
|
||||
}
|
||||
|
||||
inline void push(BOOST_THREAD_RV_REF(value_type) elem, unique_lock<mutex>& lk)
|
||||
void push(BOOST_THREAD_RV_REF(value_type) elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
data_.push(boost::move(elem));
|
||||
notify_not_empty_if_needed(lk);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
template <typename ValueType>
|
||||
@@ -305,7 +309,6 @@ namespace boost
|
||||
++waiting_empty_;
|
||||
not_empty_.wait(lk);
|
||||
}
|
||||
closed=false;
|
||||
}
|
||||
|
||||
template <typename ValueType>
|
||||
|
||||
@@ -26,12 +26,10 @@
|
||||
//#endif
|
||||
|
||||
#if ! defined(BOOST_THREAD_NO_SYNCHRONIZE)
|
||||
#include <tuple> // todo change to <boost/tuple.hpp> once Boost.Tuple or Boost.Fusion provides Move semantics on C++98 compilers.
|
||||
#include <tuple> // todo change to <boost/tuple.hpp> once Boost.Tuple or Boost.Fusion provides Move semantics.
|
||||
#include <functional>
|
||||
#endif
|
||||
|
||||
#include <boost/utility/result_of.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
@@ -595,6 +593,8 @@ namespace boost
|
||||
boost::swap(value_, rhs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Essentially calling a method obj->foo(x, y, z) calls the method foo(x, y, z) inside a critical section as
|
||||
* long-lived as the call itself.
|
||||
@@ -613,81 +613,14 @@ namespace boost
|
||||
return BOOST_THREAD_MAKE_RV_REF((const_strict_lock_ptr<T,Lockable>(value_, mtx_)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Call function on a locked block.
|
||||
*
|
||||
* @requires fct(value_) is well formed.
|
||||
*
|
||||
* Example
|
||||
* void fun(synchronized_value<vector<int>> & v) {
|
||||
* v ( [](vector<int>> & vec)
|
||||
* {
|
||||
* vec.push_back(42);
|
||||
* assert(vec.back() == 42);
|
||||
* } );
|
||||
* }
|
||||
*/
|
||||
template <typename F>
|
||||
inline
|
||||
typename boost::result_of<F(value_type&)>::type
|
||||
operator()(BOOST_THREAD_RV_REF(F) fct)
|
||||
{
|
||||
strict_lock<mutex_type> lk(mtx_);
|
||||
return fct(value_);
|
||||
}
|
||||
template <typename F>
|
||||
inline
|
||||
typename boost::result_of<F(value_type const&)>::type
|
||||
operator()(BOOST_THREAD_RV_REF(F) fct) const
|
||||
{
|
||||
strict_lock<mutex_type> lk(mtx_);
|
||||
return fct(value_);
|
||||
}
|
||||
|
||||
|
||||
#if defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
template <typename F>
|
||||
inline
|
||||
typename boost::result_of<F(value_type&)>::type
|
||||
operator()(F const & fct)
|
||||
{
|
||||
strict_lock<mutex_type> lk(mtx_);
|
||||
return fct(value_);
|
||||
}
|
||||
template <typename F>
|
||||
inline
|
||||
typename boost::result_of<F(value_type const&)>::type
|
||||
operator()(F const & fct) const
|
||||
{
|
||||
strict_lock<mutex_type> lk(mtx_);
|
||||
return fct(value_);
|
||||
}
|
||||
|
||||
template <typename R>
|
||||
inline
|
||||
R operator()(R(*fct)(value_type&))
|
||||
{
|
||||
strict_lock<mutex_type> lk(mtx_);
|
||||
return fct(value_);
|
||||
}
|
||||
template <typename R>
|
||||
inline
|
||||
R operator()(R(*fct)(value_type const&)) const
|
||||
{
|
||||
strict_lock<mutex_type> lk(mtx_);
|
||||
return fct(value_);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* The synchronize() factory make easier to lock on a scope.
|
||||
* As discussed, operator-> can only lock over the duration of a call, so it is insufficient for complex operations.
|
||||
* With synchronize() you get to lock the object in a scoped and to directly access the object inside that scope.
|
||||
*
|
||||
* Example
|
||||
* void fun(synchronized_value<vector<int>> & v) {
|
||||
* auto&& vec=v.synchronize();
|
||||
* void fun(synchronized_value<vector<int>> & vec) {
|
||||
* auto&& vec=vec.synchronize();
|
||||
* vec.push_back(42);
|
||||
* assert(vec.back() == 42);
|
||||
* }
|
||||
@@ -947,9 +880,9 @@ namespace boost
|
||||
|
||||
//Hash support
|
||||
|
||||
// template <class T> struct hash;
|
||||
// template <typename T, typename L>
|
||||
// struct hash<synchronized_value<T,L> >;
|
||||
template <class T> struct hash;
|
||||
template <typename T, typename L>
|
||||
struct hash<synchronized_value<T,L> >;
|
||||
|
||||
// Comparison with T
|
||||
template <typename T, typename L>
|
||||
|
||||
@@ -48,7 +48,6 @@ namespace boost
|
||||
|
||||
void lock()
|
||||
{
|
||||
BOOST_ASSERT(! is_locked_by_this_thread());
|
||||
mtx_.lock();
|
||||
id_ = this_thread::get_id();
|
||||
}
|
||||
@@ -62,7 +61,6 @@ namespace boost
|
||||
|
||||
bool try_lock()
|
||||
{
|
||||
BOOST_ASSERT(! is_locked_by_this_thread());
|
||||
if (mtx_.try_lock())
|
||||
{
|
||||
id_ = this_thread::get_id();
|
||||
@@ -77,7 +75,6 @@ namespace boost
|
||||
template <class Rep, class Period>
|
||||
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
|
||||
{
|
||||
BOOST_ASSERT(! is_locked_by_this_thread());
|
||||
if (mtx_.try_lock_for(rel_time))
|
||||
{
|
||||
id_ = this_thread::get_id();
|
||||
@@ -91,7 +88,6 @@ namespace boost
|
||||
template <class Clock, class Duration>
|
||||
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
|
||||
{
|
||||
BOOST_ASSERT(! is_locked_by_this_thread());
|
||||
if (mtx_.try_lock_until(abs_time))
|
||||
{
|
||||
id_ = this_thread::get_id();
|
||||
|
||||
@@ -179,15 +179,15 @@ namespace boost {
|
||||
BOOST_THREAD_INLINE shared_mutex();
|
||||
BOOST_THREAD_INLINE ~shared_mutex();
|
||||
|
||||
#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS
|
||||
#ifndef BOOST_NO_DELETED_FUNCTIONS
|
||||
shared_mutex(shared_mutex const&) = delete;
|
||||
shared_mutex& operator=(shared_mutex const&) = delete;
|
||||
#else // BOOST_NO_CXX11_DELETED_FUNCTIONS
|
||||
#else // BOOST_NO_DELETED_FUNCTIONS
|
||||
private:
|
||||
shared_mutex(shared_mutex const&);
|
||||
shared_mutex& operator=(shared_mutex const&);
|
||||
public:
|
||||
#endif // BOOST_NO_CXX11_DELETED_FUNCTIONS
|
||||
#endif // BOOST_NO_DELETED_FUNCTIONS
|
||||
|
||||
// Exclusive ownership
|
||||
|
||||
@@ -381,15 +381,15 @@ namespace boost {
|
||||
BOOST_THREAD_INLINE upgrade_mutex();
|
||||
BOOST_THREAD_INLINE ~upgrade_mutex();
|
||||
|
||||
#ifndef BOOST_CXX11_NO_DELETED_FUNCTIONS
|
||||
#ifndef BOOST_NO_DELETED_FUNCTIONS
|
||||
upgrade_mutex(const upgrade_mutex&) = delete;
|
||||
upgrade_mutex& operator=(const upgrade_mutex&) = delete;
|
||||
#else // BOOST_CXX11_NO_DELETED_FUNCTIONS
|
||||
#else // BOOST_NO_DELETED_FUNCTIONS
|
||||
private:
|
||||
upgrade_mutex(const upgrade_mutex&);
|
||||
upgrade_mutex& operator=(const upgrade_mutex&);
|
||||
public:
|
||||
#endif // BOOST_CXX11_NO_DELETED_FUNCTIONS
|
||||
#endif // BOOST_NO_DELETED_FUNCTIONS
|
||||
|
||||
// Exclusive ownership
|
||||
|
||||
|
||||
@@ -191,17 +191,18 @@ namespace boost
|
||||
struct entry_manager
|
||||
{
|
||||
entry_ptr const entry;
|
||||
boost::mutex& internal_mutex;
|
||||
|
||||
BOOST_THREAD_NO_COPYABLE(entry_manager)
|
||||
entry_manager(entry_ptr const& entry_, boost::mutex& mutex_):
|
||||
entry(entry_), internal_mutex(mutex_)
|
||||
entry_manager(entry_ptr const& entry_):
|
||||
entry(entry_)
|
||||
{}
|
||||
|
||||
~entry_manager()
|
||||
{
|
||||
boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
|
||||
//if(! entry->is_notified()) // several regression #7657
|
||||
{
|
||||
entry->remove_waiter();
|
||||
}
|
||||
}
|
||||
|
||||
list_entry* operator->()
|
||||
@@ -217,7 +218,7 @@ namespace boost
|
||||
{
|
||||
relocker<lock_type> locker(lock);
|
||||
|
||||
entry_manager entry(get_wait_entry(), internal_mutex);
|
||||
entry_manager entry(get_wait_entry());
|
||||
|
||||
locker.unlock();
|
||||
|
||||
@@ -365,11 +366,7 @@ namespace boost
|
||||
const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
using namespace chrono;
|
||||
chrono::time_point<Clock, Duration> now = Clock::now();
|
||||
if (t<=now) {
|
||||
return cv_status::timeout;
|
||||
}
|
||||
do_wait(lock, ceil<milliseconds>(t-now).count());
|
||||
do_wait(lock, ceil<milliseconds>(t-Clock::now()).count());
|
||||
return Clock::now() < t ? cv_status::no_timeout :
|
||||
cv_status::timeout;
|
||||
}
|
||||
@@ -381,10 +378,6 @@ namespace boost
|
||||
const chrono::duration<Rep, Period>& d)
|
||||
{
|
||||
using namespace chrono;
|
||||
if (d<=chrono::duration<Rep, Period>::zero()) {
|
||||
return cv_status::timeout;
|
||||
}
|
||||
|
||||
steady_clock::time_point c_now = steady_clock::now();
|
||||
do_wait(lock, ceil<milliseconds>(d).count());
|
||||
return steady_clock::now() - c_now < d ? cv_status::no_timeout :
|
||||
@@ -486,11 +479,7 @@ namespace boost
|
||||
const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
using namespace chrono;
|
||||
chrono::time_point<Clock, Duration> now = Clock::now();
|
||||
if (t<=now) {
|
||||
return cv_status::timeout;
|
||||
}
|
||||
do_wait(lock, ceil<milliseconds>(t-now).count());
|
||||
do_wait(lock, ceil<milliseconds>(t-Clock::now()).count());
|
||||
return Clock::now() < t ? cv_status::no_timeout :
|
||||
cv_status::timeout;
|
||||
}
|
||||
@@ -502,9 +491,6 @@ namespace boost
|
||||
const chrono::duration<Rep, Period>& d)
|
||||
{
|
||||
using namespace chrono;
|
||||
if (d<=chrono::duration<Rep, Period>::zero()) {
|
||||
return cv_status::timeout;
|
||||
}
|
||||
steady_clock::time_point c_now = steady_clock::now();
|
||||
do_wait(lock, ceil<milliseconds>(d).count());
|
||||
return steady_clock::now() - c_now < d ? cv_status::no_timeout :
|
||||
|
||||
@@ -9,32 +9,33 @@
|
||||
|
||||
// check if we use MFC
|
||||
#ifdef _AFXDLL
|
||||
# if defined(_AFXEXT)
|
||||
# if defined(_AFXEXT)
|
||||
|
||||
// can't use ExtRawDllMain from afxdllx.h as it also defines the symbol _pRawDllMain
|
||||
extern "C"
|
||||
inline BOOL WINAPI ExtRawDllMain(HINSTANCE, DWORD dwReason, LPVOID)
|
||||
{
|
||||
if (dwReason == DLL_PROCESS_ATTACH)
|
||||
{
|
||||
// save critical data pointers before running the constructors
|
||||
AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
|
||||
pModuleState->m_pClassInit = pModuleState->m_classList;
|
||||
pModuleState->m_pFactoryInit = pModuleState->m_factoryList;
|
||||
pModuleState->m_classList.m_pHead = NULL;
|
||||
pModuleState->m_factoryList.m_pHead = NULL;
|
||||
}
|
||||
return TRUE; // ok
|
||||
if (dwReason == DLL_PROCESS_ATTACH)
|
||||
{
|
||||
// save critical data pointers before running the constructors
|
||||
AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
|
||||
pModuleState->m_pClassInit = pModuleState->m_classList;
|
||||
pModuleState->m_pFactoryInit = pModuleState->m_factoryList;
|
||||
pModuleState->m_classList.m_pHead = NULL;
|
||||
pModuleState->m_factoryList.m_pHead = NULL;
|
||||
}
|
||||
return TRUE; // ok
|
||||
}
|
||||
|
||||
extern "C" __declspec(selectany) BOOL (WINAPI * const _pRawDllMainOrig)(HANDLE, DWORD, LPVOID) = &ExtRawDllMain;
|
||||
|
||||
# elif defined(_USRDLL)
|
||||
# elif defined(_USRDLL)
|
||||
|
||||
extern "C" BOOL WINAPI RawDllMain(HANDLE, DWORD dwReason, LPVOID);
|
||||
extern "C" __declspec(selectany) BOOL (WINAPI * const _pRawDllMainOrig)(HANDLE, DWORD, LPVOID) = &RawDllMain;
|
||||
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -363,7 +363,7 @@ namespace boost
|
||||
}
|
||||
}
|
||||
#else
|
||||
#if ! defined(BOOST_MSVC) && ! defined(BOOST_INTEL)
|
||||
#ifndef BOOST_MSVC
|
||||
template<typename Function>
|
||||
void call_once(once_flag& flag,Function f)
|
||||
{
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace boost
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct shared_state_base;
|
||||
struct future_object_base;
|
||||
struct tss_cleanup_function;
|
||||
struct thread_exit_callback_node;
|
||||
struct tss_data_node
|
||||
@@ -102,7 +102,7 @@ namespace boost
|
||||
> notify_list_t;
|
||||
notify_list_t notify;
|
||||
|
||||
typedef std::vector<shared_ptr<shared_state_base> > async_states_t;
|
||||
typedef std::vector<shared_ptr<future_object_base> > async_states_t;
|
||||
async_states_t async_states_;
|
||||
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
// These data must be at the end so that the access to the other fields doesn't change
|
||||
@@ -148,12 +148,12 @@ namespace boost
|
||||
|
||||
virtual void run()=0;
|
||||
|
||||
virtual void notify_all_at_thread_exit(condition_variable* cv, mutex* m)
|
||||
void notify_all_at_thread_exit(condition_variable* cv, mutex* m)
|
||||
{
|
||||
notify.push_back(std::pair<condition_variable*, mutex*>(cv, m));
|
||||
}
|
||||
|
||||
void make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
|
||||
void make_ready_at_thread_exit(shared_ptr<future_object_base> as)
|
||||
{
|
||||
async_states_.push_back(as);
|
||||
}
|
||||
|
||||
@@ -15,11 +15,10 @@
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#include <boost/detail/interlocked.hpp>
|
||||
//#include <boost/detail/winapi/synchronization.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
#ifndef BOOST_THREAD_WIN32_HAS_GET_TICK_COUNT_64
|
||||
#if _WIN32_WINNT >= 0x0600 && ! defined _WIN32_WINNT_WS08
|
||||
#if _WIN32_WINNT >= 0x0600
|
||||
#define BOOST_THREAD_WIN32_HAS_GET_TICK_COUNT_64
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -187,9 +187,7 @@ namespace boost
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace detail
|
||||
{
|
||||
|
||||
struct externally_launched_thread:
|
||||
detail::thread_data_base
|
||||
{
|
||||
@@ -199,12 +197,7 @@ namespace boost
|
||||
interrupt_enabled=false;
|
||||
#endif
|
||||
}
|
||||
~externally_launched_thread() {
|
||||
BOOST_ASSERT(notify.empty());
|
||||
notify.clear();
|
||||
BOOST_ASSERT(async_states_.empty());
|
||||
async_states_.clear();
|
||||
}
|
||||
|
||||
void run()
|
||||
{}
|
||||
void notify_all_at_thread_exit(condition_variable*, mutex*)
|
||||
@@ -215,18 +208,18 @@ namespace boost
|
||||
void operator=(externally_launched_thread&);
|
||||
};
|
||||
|
||||
thread_data_base* make_external_thread_data()
|
||||
detail::thread_data_base* make_external_thread_data()
|
||||
{
|
||||
thread_data_base* const me(new externally_launched_thread());
|
||||
detail::thread_data_base* const me(new externally_launched_thread());
|
||||
me->self.reset(me);
|
||||
set_current_thread_data(me);
|
||||
return me;
|
||||
}
|
||||
|
||||
|
||||
thread_data_base* get_or_make_current_thread_data()
|
||||
detail::thread_data_base* get_or_make_current_thread_data()
|
||||
{
|
||||
thread_data_base* current_thread_data(get_current_thread_data());
|
||||
detail::thread_data_base* current_thread_data(detail::get_current_thread_data());
|
||||
if(!current_thread_data)
|
||||
{
|
||||
current_thread_data=make_external_thread_data();
|
||||
@@ -708,11 +701,8 @@ namespace boost
|
||||
|
||||
void erase_tss_node(void const* key)
|
||||
{
|
||||
detail::thread_data_base* const current_thread_data(get_current_thread_data());
|
||||
if(current_thread_data)
|
||||
{
|
||||
current_thread_data->tss_data.erase(key);
|
||||
}
|
||||
detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data());
|
||||
current_thread_data->tss_data.erase(key);
|
||||
}
|
||||
|
||||
void set_tss_data(void const* key,
|
||||
@@ -750,17 +740,6 @@ namespace boost
|
||||
current_thread_data->notify_all_at_thread_exit(&cond, lk.release());
|
||||
}
|
||||
}
|
||||
namespace detail {
|
||||
|
||||
void BOOST_THREAD_DECL make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
|
||||
{
|
||||
detail::thread_data_base* const current_thread_data(detail::get_current_thread_data());
|
||||
if(current_thread_data)
|
||||
{
|
||||
current_thread_data->make_ready_at_thread_exit(as);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include <boost/thread/future.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
#include <boost/date_time/posix_time/conversion.hpp>
|
||||
#endif
|
||||
@@ -129,7 +128,7 @@ namespace boost
|
||||
return ret;
|
||||
}
|
||||
|
||||
//typedef void* uintptr_t;
|
||||
typedef void* uintptr_t;
|
||||
|
||||
inline uintptr_t _beginthreadex(void* security, unsigned stack_size, unsigned (__stdcall* start_address)(void*),
|
||||
void* arglist, unsigned initflag, unsigned* thrdaddr)
|
||||
@@ -279,12 +278,6 @@ namespace boost
|
||||
interruption_enabled=false;
|
||||
#endif
|
||||
}
|
||||
~externally_launched_thread() {
|
||||
BOOST_ASSERT(notify.empty());
|
||||
notify.clear();
|
||||
BOOST_ASSERT(async_states_.empty());
|
||||
async_states_.clear();
|
||||
}
|
||||
|
||||
void run()
|
||||
{}
|
||||
@@ -436,7 +429,7 @@ namespace boost
|
||||
LARGE_INTEGER due_time={{0,0}};
|
||||
if(target_time.relative)
|
||||
{
|
||||
unsigned long const elapsed_milliseconds=detail::win32::GetTickCount64()-target_time.start;
|
||||
unsigned long const elapsed_milliseconds=GetTickCount()-target_time.start;
|
||||
LONGLONG const remaining_milliseconds=(target_time.milliseconds-elapsed_milliseconds);
|
||||
LONGLONG const hundred_nanoseconds_in_one_millisecond=10000;
|
||||
|
||||
@@ -754,16 +747,5 @@ namespace boost
|
||||
current_thread_data->notify_all_at_thread_exit(&cond, lk.release());
|
||||
}
|
||||
}
|
||||
//namespace detail {
|
||||
//
|
||||
// void BOOST_THREAD_DECL make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
|
||||
// {
|
||||
// detail::thread_data_base* const current_thread_data(detail::get_current_thread_data());
|
||||
// if(current_thread_data)
|
||||
// {
|
||||
// current_thread_data->make_ready_at_thread_exit(as);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
@@ -66,14 +66,6 @@ project
|
||||
#<toolset>darwin-4.6.2:<cxxflags>-Wno-delete-non-virtual-dtor # doesn't work
|
||||
<toolset>darwin-4.7.0:<cxxflags>-ansi
|
||||
<toolset>darwin-4.7.0:<cxxflags>-Wno-delete-non-virtual-dtor
|
||||
#<toolset>darwin-4.6.2:<cxxflags>-Wno-unused-local-typedefs
|
||||
#<toolset>darwin-4.7.1:<cxxflags>-Wno-unused-local-typedefs
|
||||
#<toolset>darwin-4.7.2:<cxxflags>-Wno-unused-local-typedefs
|
||||
#<toolset>darwin-4.8.0:<cxxflags>-Wno-unused-local-typedefs
|
||||
#<toolset>darwin-4.6.2x:<cxxflags>-Wno-unused-local-typedefs
|
||||
#<toolset>darwin-4.7.1x:<cxxflags>-Wno-unused-local-typedefs
|
||||
#<toolset>darwin-4.7.2x:<cxxflags>-Wno-unused-local-typedefs
|
||||
#<toolset>darwin-4.8.0x:<cxxflags>-Wno-unused-local-typedefs
|
||||
|
||||
#<toolset>clang-2.8:<cxxflags>-Wno-delete-non-virtual-dtor
|
||||
#<toolset>clang-2.8:<cxxflags>-Wno-unused-function
|
||||
@@ -82,8 +74,6 @@ project
|
||||
<toolset>clang-3.0:<cxxflags>-Wno-delete-non-virtual-dtor
|
||||
#<toolset>clang-3.0:<cxxflags>-Wno-unused-function
|
||||
#<toolset>clang-3.0:<cxxflags>-Wno-unused-variable
|
||||
#<toolset>clang-3.1:<cxxflags>-Wno-bind-to-temporary-copy
|
||||
#<toolset>clang-3.2:<cxxflags>-Wno-bind-to-temporary-copy
|
||||
|
||||
# Note: Some of the remarks from the Intel compiler are disabled
|
||||
# remark #193: zero used for undefined preprocessing identifier "XXX"
|
||||
@@ -231,8 +221,6 @@ rule thread-compile ( sources : reqs * : name )
|
||||
[ thread-test test_condition.cpp ]
|
||||
[ thread-test test_once.cpp ]
|
||||
[ thread-run test_barrier.cpp ]
|
||||
[ thread-run test_barrier_void_fct.cpp ]
|
||||
[ thread-run test_barrier_size_fct.cpp ]
|
||||
[ thread-test test_lock_concept.cpp ]
|
||||
[ thread-test test_generic_locks.cpp ]
|
||||
[ thread-run test_latch.cpp ]
|
||||
@@ -354,7 +342,6 @@ rule thread-compile ( sources : reqs * : name )
|
||||
[ thread-run2-noit ./sync/futures/future/default_pass.cpp : future__default_p ]
|
||||
[ thread-run2-noit ./sync/futures/future/dtor_pass.cpp : future__dtor_p ]
|
||||
[ thread-run2-noit ./sync/futures/future/get_pass.cpp : future__get_p ]
|
||||
[ thread-run2-noit ./sync/futures/future/get_or_pass.cpp : future__get_or_p ]
|
||||
[ thread-run2-noit ./sync/futures/future/move_ctor_pass.cpp : future__move_ctor_p ]
|
||||
[ thread-run2-noit ./sync/futures/future/move_assign_pass.cpp : future__move_asign_p ]
|
||||
[ thread-run2-noit ./sync/futures/future/share_pass.cpp : future__share_p ]
|
||||
@@ -377,7 +364,6 @@ rule thread-compile ( sources : reqs * : name )
|
||||
[ thread-run2-noit ./sync/futures/shared_future/wait_pass.cpp : shared_future__wait_p ]
|
||||
[ thread-run2-noit ./sync/futures/shared_future/wait_for_pass.cpp : shared_future__wait_for_p ]
|
||||
[ thread-run2-noit ./sync/futures/shared_future/wait_until_pass.cpp : shared_future__wait_until_p ]
|
||||
[ thread-run2-noit ./sync/futures/shared_future/then_pass.cpp : shared_future__then_p ]
|
||||
;
|
||||
|
||||
#explicit ts_packaged_task ;
|
||||
@@ -630,17 +616,6 @@ rule thread-compile ( sources : reqs * : name )
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/null_mutex/try_lock_until_pass.cpp : null_mutex__try_lock_until_p ]
|
||||
;
|
||||
|
||||
test-suite ts_sync_queue
|
||||
:
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/sync_queue/single_thread_pass.cpp : sync_queue__single_thread_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/sync_queue/multi_thread_pass.cpp : sync_queue__multi_thread_p ]
|
||||
;
|
||||
|
||||
test-suite ts_sync_bounded_queue
|
||||
:
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/sync_bounded_queue/single_thread_pass.cpp : sync_bounded_queue__single_thread_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/sync_bounded_queue/multi_thread_pass.cpp : sync_bounded_queue__multi_thread_p ]
|
||||
;
|
||||
|
||||
#explicit ts_this_thread ;
|
||||
test-suite ts_this_thread
|
||||
@@ -704,10 +679,8 @@ rule thread-compile ( sources : reqs * : name )
|
||||
#[ thread-run ../example/vhh_shared_mutex.cpp ]
|
||||
[ thread-run2 ../example/make_future.cpp : ex_make_future ]
|
||||
[ thread-run2 ../example/future_then.cpp : ex_future_then ]
|
||||
[ thread-run2 ../example/future_fallback_to.cpp : ex_future_fallback_to ]
|
||||
[ thread-run2 ../example/future_unwrap.cpp : ex_future_unwrap ]
|
||||
[ thread-run2-noit ../example/synchronized_value.cpp : ex_synchronized_value ]
|
||||
[ thread-run2-noit ../example/synchronized_person.cpp : ex_synchronized_person ]
|
||||
#[ thread-run2-noit ../example/synchronized_value.cpp : ex_synchronized_value ]
|
||||
#[ thread-run2-noit ../example/synchronized_person.cpp : ex_synchronized_person ]
|
||||
[ thread-run2-noit ../example/thread_guard.cpp : ex_thread_guard ]
|
||||
[ thread-run2-noit ../example/scoped_thread.cpp : ex_scoped_thread ]
|
||||
[ thread-run2-noit ../example/strict_lock.cpp : ex_strict_lock ]
|
||||
@@ -768,7 +741,6 @@ rule thread-compile ( sources : reqs * : name )
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/swap_pass.cpp : synchronized_value__swap_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/swap_T_pass.cpp : synchronized_value__swap_T_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/synchronize_pass.cpp : synchronized_value__synchronize_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/call_pass.cpp : synchronized_value__call_p ]
|
||||
|
||||
;
|
||||
|
||||
@@ -783,18 +755,11 @@ rule thread-compile ( sources : reqs * : name )
|
||||
#[ thread-run test_7720.cpp ]
|
||||
#[ thread-run test_7666.cpp ]
|
||||
#[ thread-run test_7755.cpp ]
|
||||
#[ thread-run ../example/unwrap.cpp ]
|
||||
#[ thread-run ../example/perf_condition_variable.cpp ]
|
||||
#[ thread-run ../example/perf_shared_mutex.cpp ]
|
||||
#[ thread-run ../example/std_async_test.cpp ]
|
||||
#[ thread-run test_8508.cpp ]
|
||||
#[ thread-run test_8586.cpp ]
|
||||
#[ thread-run test_8596.cpp ]
|
||||
#[ thread-run test_8600.cpp ]
|
||||
#[ thread-run test_8943.cpp ]
|
||||
#[ thread-run test_8960.cpp ]
|
||||
[ thread-run test_9079_a.cpp ]
|
||||
[ thread-run test_9079_b.cpp ]
|
||||
|
||||
[ thread-run test_8596.cpp ]
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
@@ -38,21 +38,18 @@ typedef boost::chrono::milliseconds ms;
|
||||
|
||||
class A
|
||||
{
|
||||
long data_;
|
||||
long data_;
|
||||
|
||||
public:
|
||||
typedef long result_type;
|
||||
typedef long result_type;
|
||||
|
||||
explicit A(long i) :
|
||||
data_(i)
|
||||
{
|
||||
}
|
||||
explicit A(long i) : data_(i) {}
|
||||
|
||||
long operator()() const
|
||||
{
|
||||
boost::this_thread::sleep_for(ms(200));
|
||||
return data_;
|
||||
}
|
||||
long operator()() const
|
||||
{
|
||||
boost::this_thread::sleep_for(ms(200));
|
||||
return data_;
|
||||
}
|
||||
};
|
||||
|
||||
class MoveOnly
|
||||
@@ -62,38 +59,37 @@ public:
|
||||
|
||||
int value;
|
||||
|
||||
BOOST_THREAD_MOVABLE_ONLY(MoveOnly)
|
||||
BOOST_THREAD_MOVABLE_ONLY(MoveOnly)
|
||||
MoveOnly()
|
||||
{
|
||||
value = 0;
|
||||
value=0;
|
||||
}
|
||||
MoveOnly( BOOST_THREAD_RV_REF(MoveOnly))
|
||||
{
|
||||
value = 1;
|
||||
}
|
||||
MoveOnly& operator=(BOOST_THREAD_RV_REF(MoveOnly))
|
||||
{
|
||||
value = 2;
|
||||
return *this;
|
||||
}
|
||||
|
||||
int operator()()
|
||||
{
|
||||
boost::this_thread::sleep_for(ms(200));
|
||||
return 3;
|
||||
}
|
||||
template <typename OS>
|
||||
friend OS& operator<<(OS& os, MoveOnly const& v)
|
||||
{
|
||||
os << v.value;
|
||||
return os;
|
||||
}
|
||||
};
|
||||
|
||||
namespace boost
|
||||
{
|
||||
BOOST_THREAD_DCL_MOVABLE (MoveOnly)
|
||||
MoveOnly(BOOST_THREAD_RV_REF(MoveOnly))
|
||||
{
|
||||
value=1;
|
||||
}
|
||||
MoveOnly& operator=(BOOST_THREAD_RV_REF(MoveOnly))
|
||||
{
|
||||
value=2;
|
||||
return *this;
|
||||
}
|
||||
|
||||
int operator()()
|
||||
{
|
||||
boost::this_thread::sleep_for(ms(200));
|
||||
return 3;
|
||||
}
|
||||
template <typename OS>
|
||||
friend OS& operator<<(OS& os, MoveOnly const& v)
|
||||
{
|
||||
os << v.value;
|
||||
return os;
|
||||
}
|
||||
};
|
||||
|
||||
namespace boost {
|
||||
BOOST_THREAD_DCL_MOVABLE(MoveOnly)
|
||||
}
|
||||
|
||||
int f0()
|
||||
{
|
||||
@@ -117,7 +113,7 @@ void f2()
|
||||
boost::interprocess::unique_ptr<int, boost::default_delete<int> > f3_0()
|
||||
{
|
||||
boost::this_thread::sleep_for(ms(200));
|
||||
boost::interprocess::unique_ptr<int, boost::default_delete<int> > r( (new int(3)));
|
||||
boost::interprocess::unique_ptr<int, boost::default_delete<int> > r((new int(3)));
|
||||
return boost::move(r);
|
||||
}
|
||||
MoveOnly f3_1()
|
||||
@@ -143,404 +139,299 @@ boost::interprocess::unique_ptr<int, boost::default_delete<int> > f4(
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl;
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::future<int> f = boost::async(f0);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(f.get() == 3);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(300));
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl;
|
||||
try {
|
||||
boost::future<int> f = boost::async(f0);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(f.get() == 3);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(300));
|
||||
} catch (std::exception& ex) {
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl;
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
} catch (...) {
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
|
||||
}
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl;
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::shared_future<int> f = boost::async(f0).share();
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(f.get() == 3);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(300));
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl;
|
||||
try {
|
||||
boost::future<int> f = boost::async(boost::launch::async, f0);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(f.get() == 3);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(200));
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"] "<< (t1 - t0).count() << std::endl;
|
||||
} catch (std::exception& ex) {
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl;
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
} catch (...) {
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl;
|
||||
{
|
||||
try {
|
||||
boost::future<long> f = boost::async(boost::launch::async, A(3));
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(f.get() == 3);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(200));
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"] "<< (t1 - t0).count() << std::endl;
|
||||
} catch (std::exception& ex) {
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl;
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
} catch (...) {
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
|
||||
}
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl;
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::future<int> f = boost::async(boost::launch::async, f0);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(f.get() == 3);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(300));
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "] " << (t1 - t0).count() << std::endl;
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl;
|
||||
try {
|
||||
boost::future<int> f = boost::async(boost::launch::async, BOOST_THREAD_MAKE_RV_REF(MoveOnly()));
|
||||
// boost::this_thread::sleep_for(ms(300));
|
||||
// Clock::time_point t0 = Clock::now();
|
||||
// BOOST_TEST(f.get() == 3);
|
||||
// Clock::time_point t1 = Clock::now();
|
||||
// BOOST_TEST(t1 - t0 < ms(200));
|
||||
// std::cout << __FILE__ <<"["<<__LINE__<<"] "<< (t1 - t0).count() << std::endl;
|
||||
} catch (std::exception& ex) {
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl;
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
|
||||
}
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::future<long> f = boost::async(boost::launch::async, A(3));
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(f.get() == 3);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(300));
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "] " << (t1 - t0).count() << std::endl;
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl;
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
|
||||
}
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::future<int> f = boost::async(boost::launch::async, BOOST_THREAD_MAKE_RV_REF(MoveOnly()));
|
||||
// boost::this_thread::sleep_for(ms(300));
|
||||
// Clock::time_point t0 = Clock::now();
|
||||
// BOOST_TEST(f.get() == 3);
|
||||
// Clock::time_point t1 = Clock::now();
|
||||
// BOOST_TEST(t1 - t0 < ms(300));
|
||||
// std::cout << __FILE__ <<"["<<__LINE__<<"] "<< (t1 - t0).count() << std::endl;
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl;
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
} catch (...) {
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
}
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl;
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::future<int> f = boost::async(boost::launch::any, f0);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(f.get() == 3);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(300));
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "] " << (t1 - t0).count() << std::endl;
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl;
|
||||
try {
|
||||
boost::future<int> f = boost::async(boost::launch::any, f0);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(f.get() == 3);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(200));
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"] "<< (t1 - t0).count() << std::endl;
|
||||
} catch (std::exception& ex) {
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl;
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
} catch (...) {
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
}
|
||||
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl;
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::future<int> f = boost::async(boost::launch::deferred, f0);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(f.get() == 3);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 > ms(100));
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
try {
|
||||
boost::future<int> f = boost::async(boost::launch::deferred, f0);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(f.get() == 3);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 > ms(100));
|
||||
} catch (std::exception& ex) {
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl;
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
} catch (...) {
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl;
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::future<int&> f = boost::async(f1);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(&f.get() == &i);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(300));
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "] " << (t1 - t0).count() << std::endl;
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl;
|
||||
try {
|
||||
boost::future<int&> f = boost::async(f1);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(&f.get() == &i);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(200));
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"] "<< (t1 - t0).count() << std::endl;
|
||||
} catch (std::exception& ex) {
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl;
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
} catch (...) {
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
}
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl;
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::future<int&> f = boost::async(boost::launch::async, f1);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(&f.get() == &i);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(300));
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "] " << (t1 - t0).count() << std::endl;
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl;
|
||||
try {
|
||||
boost::future<int&> f = boost::async(boost::launch::async, f1);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(&f.get() == &i);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(200));
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"] "<< (t1 - t0).count() << std::endl;
|
||||
} catch (std::exception& ex) {
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl;
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
} catch (...) {
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
}
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl;
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::future<int&> f = boost::async(boost::launch::any, f1);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(&f.get() == &i);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(300));
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "] " << (t1 - t0).count() << std::endl;
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl;
|
||||
try {
|
||||
boost::future<int&> f = boost::async(boost::launch::any, f1);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(&f.get() == &i);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(200));
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"] "<< (t1 - t0).count() << std::endl;
|
||||
} catch (std::exception& ex) {
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl;
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
} catch (...) {
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
}
|
||||
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl;
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::future<int&> f = boost::async(boost::launch::deferred, f1);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(&f.get() == &i);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 > ms(100));
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
try {
|
||||
boost::future<int&> f = boost::async(boost::launch::deferred, f1);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(&f.get() == &i);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 > ms(100));
|
||||
} catch (std::exception& ex) {
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl;
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
} catch (...) {
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl;
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::future<void> f = boost::async(f2);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
f.get();
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(300));
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "] " << (t1 - t0).count() << std::endl;
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl;
|
||||
try {
|
||||
boost::future<void> f = boost::async(f2);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
f.get();
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(200));
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"] "<< (t1 - t0).count() << std::endl;
|
||||
} catch (std::exception& ex) {
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl;
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
} catch (...) {
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
}
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl;
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::future<void> f = boost::async(boost::launch::async, f2);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
f.get();
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(300));
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "] " << (t1 - t0).count() << std::endl;
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl;
|
||||
try {
|
||||
boost::future<void> f = boost::async(boost::launch::async, f2);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
f.get();
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(200));
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"] "<< (t1 - t0).count() << std::endl;
|
||||
} catch (std::exception& ex) {
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl;
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
} catch (...) {
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
}
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl;
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::future<void> f = boost::async(boost::launch::any, f2);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
f.get();
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(300));
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "] " << (t1 - t0).count() << std::endl;
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl;
|
||||
try {
|
||||
boost::future<void> f = boost::async(boost::launch::any, f2);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
f.get();
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(200));
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"] "<< (t1 - t0).count() << std::endl;
|
||||
} catch (std::exception& ex) {
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl;
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
} catch (...) {
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
}
|
||||
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl;
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::future<void> f = boost::async(boost::launch::deferred, f2);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
f.get();
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 > ms(100));
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
try {
|
||||
boost::future<void> f = boost::async(boost::launch::deferred, f2);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
f.get();
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 > ms(100));
|
||||
} catch (std::exception& ex) {
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl;
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
} catch (...) {
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl;
|
||||
{
|
||||
try
|
||||
{
|
||||
try {
|
||||
boost::future<MoveOnly> f = boost::async(&f3_1);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(f.get().value == 1);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(300));
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl;
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(f.get().value == 1);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(200));
|
||||
} catch (std::exception& ex) {
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl;
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
} catch (...) {
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
}
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl;
|
||||
{
|
||||
try
|
||||
{
|
||||
try {
|
||||
boost::future<MoveOnly> f;
|
||||
f = boost::async(&f3_1);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(f.get().value == 1);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(300));
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl;
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(f.get().value == 1);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(200));
|
||||
} catch (std::exception& ex) {
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl;
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
} catch (...) {
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
}
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl;
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::future<boost::interprocess::unique_ptr<int, boost::default_delete<int> > > f = boost::async(&f3_0);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(*f.get() == 3);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(300));
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "] " << (t1 - t0).count() << std::endl;
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl;
|
||||
try {
|
||||
boost::future<boost::interprocess::unique_ptr<int, boost::default_delete<int> > > f = boost::async(&f3_0);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(*f.get() == 3);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(200));
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"] "<< (t1 - t0).count() << std::endl;
|
||||
} catch (std::exception& ex) {
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl;
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
} catch (...) {
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
}
|
||||
@@ -548,45 +439,35 @@ int main()
|
||||
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl;
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::future<boost::interprocess::unique_ptr<int, boost::default_delete<int> > > f = boost::async(boost::launch::async, &f3, 3);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(*f.get() == 3);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(300));
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"] "<< (t1 - t0).count() << std::endl;
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
try {
|
||||
boost::future<boost::interprocess::unique_ptr<int, boost::default_delete<int> > > f = boost::async(boost::launch::async, &f3, 3);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(*f.get() == 3);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(200));
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"] "<< (t1 - t0).count() << std::endl;
|
||||
} catch (std::exception& ex) {
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl;
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
} catch (...) {
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
}
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl;
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::future<boost::interprocess::unique_ptr<int, boost::default_delete<int> > > f = boost::async(&f3, 3);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(*f.get() == 3);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(300));
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"] "<< (t1 - t0).count() << std::endl;
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
try {
|
||||
boost::future<boost::interprocess::unique_ptr<int, boost::default_delete<int> > > f = boost::async(&f3, 3);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(*f.get() == 3);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(200));
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"] "<< (t1 - t0).count() << std::endl;
|
||||
} catch (std::exception& ex) {
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl;
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
} catch (...) {
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
}
|
||||
@@ -595,45 +476,35 @@ int main()
|
||||
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl;
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::future<boost::interprocess::unique_ptr<int, boost::default_delete<int> > > f = boost::async(boost::launch::async, &f4, boost::interprocess::unique_ptr<int, boost::default_delete<int> >(new int(3)));
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(*f.get() == 3);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(300));
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"] "<< (t1 - t0).count() << std::endl;
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
try {
|
||||
boost::future<boost::interprocess::unique_ptr<int, boost::default_delete<int> > > f = boost::async(boost::launch::async, &f4, boost::interprocess::unique_ptr<int, boost::default_delete<int> >(new int(3)));
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(*f.get() == 3);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(200));
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"] "<< (t1 - t0).count() << std::endl;
|
||||
} catch (std::exception& ex) {
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl;
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
} catch (...) {
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
}
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl;
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::future<boost::interprocess::unique_ptr<int, boost::default_delete<int> > > f = boost::async(&f4, boost::interprocess::unique_ptr<int, boost::default_delete<int> >(new int(3)));
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(*f.get() == 3);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(300));
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"] "<< (t1 - t0).count() << std::endl;
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
try {
|
||||
boost::future<boost::interprocess::unique_ptr<int, boost::default_delete<int> > > f = boost::async(&f4, boost::interprocess::unique_ptr<int, boost::default_delete<int> >(new int(3)));
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
Clock::time_point t0 = Clock::now();
|
||||
BOOST_TEST(*f.get() == 3);
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(t1 - t0 < ms(200));
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"] "<< (t1 - t0).count() << std::endl;
|
||||
} catch (std::exception& ex) {
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl;
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
} catch (...) {
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,182 +0,0 @@
|
||||
// Copyright (C) 2013 Vicente J. Botet Escriba
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// <boost/thread/future.hpp>
|
||||
|
||||
// class future<R>
|
||||
|
||||
// R future::get_or(R&&);
|
||||
// R& future<R&>::get_or(R&);
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_USES_LOG
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
#include <boost/thread/detail/log.hpp>
|
||||
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template <typename T>
|
||||
struct wrap
|
||||
{
|
||||
wrap(T const& v) : value(v){}
|
||||
T value;
|
||||
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
exception_ptr make_exception_ptr(T v) {
|
||||
return copy_exception(wrap<T>(v));
|
||||
}
|
||||
}
|
||||
|
||||
void func1(boost::promise<int> p)
|
||||
{
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
|
||||
p.set_value(3);
|
||||
}
|
||||
|
||||
void func2(boost::promise<int> p)
|
||||
{
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
|
||||
p.set_exception(boost::make_exception_ptr(3));
|
||||
}
|
||||
|
||||
int j = 0;
|
||||
|
||||
void func3(boost::promise<int&> p)
|
||||
{
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
|
||||
j = 5;
|
||||
p.set_value(j);
|
||||
}
|
||||
|
||||
void func4(boost::promise<int&> p)
|
||||
{
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
|
||||
p.set_exception(boost::make_exception_ptr(3.5));
|
||||
}
|
||||
|
||||
void func5(boost::promise<void> p)
|
||||
{
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
|
||||
p.set_value();
|
||||
}
|
||||
|
||||
void func6(boost::promise<void> p)
|
||||
{
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
|
||||
p.set_exception(boost::make_exception_ptr(4));
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
typedef int T;
|
||||
{
|
||||
boost::promise<T> p;
|
||||
boost::future<T> f = p.get_future();
|
||||
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
boost::thread(func1, boost::move(p)).detach();
|
||||
#else
|
||||
p.set_value(3);
|
||||
#endif
|
||||
BOOST_TEST(f.valid());
|
||||
BOOST_TEST(f.get_or(4) == 3);
|
||||
#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
|
||||
BOOST_TEST(!f.valid());
|
||||
#endif
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
boost::promise<T> p;
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<T> f = p.get_future();
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
boost::thread(func2, boost::move(p)).detach();
|
||||
#else
|
||||
p.set_exception(boost::make_exception_ptr(3));
|
||||
#endif
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
try
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
BOOST_TEST(f.valid());
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
BOOST_TEST(f.get_or(4) == 4);
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
BOOST_TEST(!f.valid());
|
||||
#endif
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
}
|
||||
// BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
// {
|
||||
// typedef int& T;
|
||||
// {
|
||||
// boost::promise<T> p;
|
||||
// boost::future<T> f = p.get_future();
|
||||
//#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
// boost::thread(func3, boost::move(p)).detach();
|
||||
//#else
|
||||
// int j=5;
|
||||
// p.set_value(j);
|
||||
//#endif
|
||||
// BOOST_TEST(f.valid());
|
||||
// int k=4;
|
||||
// BOOST_TEST(f.get_or(k) == 5);
|
||||
//#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
|
||||
// BOOST_TEST(!f.valid());
|
||||
//#endif
|
||||
// }
|
||||
// BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
// {
|
||||
// boost::promise<T> p;
|
||||
// boost::future<T> f = p.get_future();
|
||||
//#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
// boost::thread(func4, boost::move(p)).detach();
|
||||
//#else
|
||||
// p.set_exception(boost::make_exception_ptr(3.5));
|
||||
//#endif
|
||||
// try
|
||||
// {
|
||||
// BOOST_TEST(f.valid());
|
||||
// int j=4;
|
||||
// BOOST_TEST(f.get_or(j) == 4);
|
||||
// }
|
||||
// catch (...)
|
||||
// {
|
||||
// BOOST_TEST(false);
|
||||
// }
|
||||
//#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
|
||||
// BOOST_TEST(!f.valid());
|
||||
//#endif
|
||||
// }
|
||||
// }
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#else
|
||||
#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported"
|
||||
#endif
|
||||
@@ -189,26 +189,6 @@ int main()
|
||||
BOOST_TEST(!f.valid());
|
||||
#endif
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
boost::promise<T> p;
|
||||
boost::future<T> f = p.get_future();
|
||||
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
boost::thread(func4, boost::move(p)).detach();
|
||||
#else
|
||||
p.set_exception(boost::make_exception_ptr(3.5));
|
||||
#endif
|
||||
try
|
||||
{
|
||||
BOOST_TEST(f.valid());
|
||||
boost::exception_ptr ptr = f.get_exception_ptr();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
BOOST_TEST(f.valid());
|
||||
}
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
||||
|
||||
|
||||
int p1()
|
||||
{
|
||||
BOOST_THREAD_LOG << "p1 < " << BOOST_THREAD_END_LOG;
|
||||
@@ -29,7 +28,7 @@ int p1()
|
||||
return 1;
|
||||
}
|
||||
|
||||
int p2(boost::future<int> f)
|
||||
int p2(boost::future<int>& f)
|
||||
{
|
||||
BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG;
|
||||
BOOST_TEST(f.valid());
|
||||
@@ -39,25 +38,14 @@ int p2(boost::future<int> f)
|
||||
return 2 * i;
|
||||
}
|
||||
|
||||
void p3(boost::future<int> f)
|
||||
{
|
||||
BOOST_THREAD_LOG << "p3 <" << &f << BOOST_THREAD_END_LOG;
|
||||
BOOST_TEST(f.valid());
|
||||
int i = f.get();
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
|
||||
BOOST_THREAD_LOG << "p3 <" << &f << " " <<i << BOOST_THREAD_END_LOG;
|
||||
return;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<int> f2 = f1.then(&p2);
|
||||
BOOST_TEST(f2.valid());
|
||||
BOOST_TEST(! f1.valid());
|
||||
try
|
||||
{
|
||||
BOOST_TEST(f2.get()==2);
|
||||
@@ -74,27 +62,6 @@ int main()
|
||||
}
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<void> f2 = f1.then(&p3);
|
||||
BOOST_TEST(f2.valid());
|
||||
try
|
||||
{
|
||||
f2.wait();
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
boost::future<int> f2 = boost::async(p1).then(&p2);
|
||||
BOOST_TEST(f2.get()==2);
|
||||
|
||||
@@ -26,32 +26,23 @@
|
||||
|
||||
#if BOOST_THREAD_VERSION == 4
|
||||
#define BOOST_THREAD_DETAIL_SIGNATURE double()
|
||||
#define BOOST_THREAD_DETAIL_VOID_SIGNATURE void()
|
||||
#else
|
||||
#define BOOST_THREAD_DETAIL_SIGNATURE double
|
||||
#define BOOST_THREAD_DETAIL_VOID_SIGNATURE void
|
||||
#endif
|
||||
|
||||
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
||||
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
#define BOOST_THREAD_DETAIL_SIGNATURE_2 double(int, char)
|
||||
#define BOOST_THREAD_DETAIL_SIGNATURE_2_RES 5 + 3 +'a'
|
||||
#define BOOST_THREAD_DETAIL_VOID_SIGNATURE_2 void(int)
|
||||
#else
|
||||
#define BOOST_THREAD_DETAIL_SIGNATURE_2 double()
|
||||
#define BOOST_THREAD_DETAIL_SIGNATURE_2_RES 5
|
||||
#define BOOST_THREAD_DETAIL_VOID_SIGNATURE_2 void()
|
||||
#endif
|
||||
#else
|
||||
#define BOOST_THREAD_DETAIL_SIGNATURE_2 double
|
||||
#define BOOST_THREAD_DETAIL_SIGNATURE_2_RES 5
|
||||
#define BOOST_THREAD_DETAIL_VOID_SIGNATURE_2 void
|
||||
#endif
|
||||
|
||||
void void_fct()
|
||||
{
|
||||
return;
|
||||
}
|
||||
double fct()
|
||||
{
|
||||
return 5.0;
|
||||
@@ -104,8 +95,6 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(int) const
|
||||
{ }
|
||||
long operator()() const
|
||||
{ return data_;}
|
||||
long operator()(long i, long j) const
|
||||
@@ -145,8 +134,6 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(int) const
|
||||
{ }
|
||||
long operator()() const
|
||||
{ return data_;}
|
||||
long operator()(long i, long j) const
|
||||
@@ -183,8 +170,6 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(int) const
|
||||
{ }
|
||||
long operator()() const
|
||||
{ return data_;}
|
||||
long operator()(long i, long j) const
|
||||
@@ -195,7 +180,6 @@ int C::n_copies = 0;
|
||||
int main()
|
||||
{
|
||||
{
|
||||
A::reset();
|
||||
boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p(BOOST_THREAD_MAKE_RV_REF(A(5)));
|
||||
BOOST_TEST(p.valid());
|
||||
boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
|
||||
@@ -220,6 +204,7 @@ int main()
|
||||
BOOST_TEST_EQ(A::n_copies, 1);
|
||||
BOOST_TEST_EQ(A::n_moves, 0);
|
||||
}
|
||||
|
||||
{
|
||||
A::reset();
|
||||
const A a(5);
|
||||
@@ -232,37 +217,6 @@ int main()
|
||||
BOOST_TEST_EQ(A::n_copies, 1);
|
||||
BOOST_TEST_EQ(A::n_moves, 0);
|
||||
}
|
||||
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
{
|
||||
A::reset();
|
||||
boost::packaged_task<BOOST_THREAD_DETAIL_VOID_SIGNATURE_2> p(BOOST_THREAD_MAKE_RV_REF(A(5)));
|
||||
BOOST_TEST(p.valid());
|
||||
boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
|
||||
p(1);
|
||||
BOOST_TEST(A::n_copies == 0);
|
||||
BOOST_TEST_EQ(A::n_moves, 1);
|
||||
}
|
||||
{
|
||||
A::reset();
|
||||
A a(5);
|
||||
boost::packaged_task<BOOST_THREAD_DETAIL_VOID_SIGNATURE_2> p(a);
|
||||
BOOST_TEST(p.valid());
|
||||
boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
|
||||
p(1);
|
||||
BOOST_TEST_EQ(A::n_copies, 1);
|
||||
BOOST_TEST_EQ(A::n_moves, 0);
|
||||
}
|
||||
{
|
||||
A::reset();
|
||||
const A a(5);
|
||||
boost::packaged_task<BOOST_THREAD_DETAIL_VOID_SIGNATURE_2> p(a);
|
||||
BOOST_TEST(p.valid());
|
||||
boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
|
||||
p(1);
|
||||
BOOST_TEST_EQ(A::n_copies, 1);
|
||||
BOOST_TEST_EQ(A::n_moves, 0);
|
||||
}
|
||||
#endif
|
||||
{
|
||||
M::reset();
|
||||
boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p(BOOST_THREAD_MAKE_RV_REF(M(5)));
|
||||
@@ -287,25 +241,7 @@ int main()
|
||||
BOOST_TEST(f.get() == 5.0);
|
||||
BOOST_TEST_EQ(M::n_moves, 1);
|
||||
}
|
||||
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
{
|
||||
M::reset();
|
||||
boost::packaged_task<BOOST_THREAD_DETAIL_VOID_SIGNATURE_2> p(BOOST_THREAD_MAKE_RV_REF(M(5)));
|
||||
BOOST_TEST(p.valid());
|
||||
boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
|
||||
p(1);
|
||||
BOOST_TEST_EQ(M::n_moves, 1);
|
||||
}
|
||||
{
|
||||
M::reset();
|
||||
M a(5);
|
||||
boost::packaged_task<BOOST_THREAD_DETAIL_VOID_SIGNATURE_2> p(boost::move(a));
|
||||
BOOST_TEST(p.valid());
|
||||
boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
|
||||
p(1);
|
||||
BOOST_TEST_EQ(M::n_moves, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
C::reset();
|
||||
C a(5);
|
||||
@@ -329,33 +265,6 @@ int main()
|
||||
BOOST_TEST(f.get() == 5.0);
|
||||
BOOST_TEST_EQ(C::n_copies, 1);
|
||||
}
|
||||
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
{
|
||||
C::reset();
|
||||
C a(5);
|
||||
boost::packaged_task<BOOST_THREAD_DETAIL_VOID_SIGNATURE_2> p(a);
|
||||
BOOST_TEST(p.valid());
|
||||
boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
|
||||
p(1);
|
||||
BOOST_TEST_EQ(C::n_copies, 1);
|
||||
}
|
||||
|
||||
{
|
||||
C::reset();
|
||||
const C a(5);
|
||||
boost::packaged_task<BOOST_THREAD_DETAIL_VOID_SIGNATURE_2> p(a);
|
||||
BOOST_TEST(p.valid());
|
||||
boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
|
||||
p(1);
|
||||
BOOST_TEST_EQ(C::n_copies, 1);
|
||||
}
|
||||
#endif
|
||||
{
|
||||
boost::packaged_task<BOOST_THREAD_DETAIL_VOID_SIGNATURE> p(void_fct);
|
||||
BOOST_TEST(p.valid());
|
||||
boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
|
||||
p();
|
||||
}
|
||||
{
|
||||
boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(fct);
|
||||
BOOST_TEST(p.valid());
|
||||
|
||||
@@ -38,7 +38,9 @@ int main()
|
||||
}
|
||||
{
|
||||
boost::promise<void> p;
|
||||
std::cout << __LINE__ << std::endl;
|
||||
boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
|
||||
std::cout << __LINE__ << std::endl;
|
||||
BOOST_TEST(f.valid());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
// Copyright (C) 2012-2013 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)
|
||||
|
||||
// <boost/thread/future.hpp>
|
||||
|
||||
// class future<R>
|
||||
|
||||
// template<typename F>
|
||||
// auto then(F&& func) -> future<decltype(func(*this))>;
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_USES_LOG
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
#include <boost/thread/detail/log.hpp>
|
||||
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
||||
|
||||
int p1()
|
||||
{
|
||||
BOOST_THREAD_LOG << "p1 < " << BOOST_THREAD_END_LOG;
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
|
||||
BOOST_THREAD_LOG << "p1 >" << BOOST_THREAD_END_LOG;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int p2(boost::shared_future<int> f)
|
||||
{
|
||||
BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG;
|
||||
BOOST_TEST(f.valid());
|
||||
int i = f.get();
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
|
||||
BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG;
|
||||
return 2 * i;
|
||||
}
|
||||
|
||||
void p3(boost::shared_future<int> f)
|
||||
{
|
||||
BOOST_THREAD_LOG << "p3 <" << &f << BOOST_THREAD_END_LOG;
|
||||
BOOST_TEST(f.valid());
|
||||
int i = f.get();
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
|
||||
BOOST_THREAD_LOG << "p3 <" << &f << " " << i << BOOST_THREAD_END_LOG;
|
||||
return ;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share();
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<int> f2 = f1.then(&p2);
|
||||
BOOST_TEST(f2.valid());
|
||||
try
|
||||
{
|
||||
BOOST_TEST(f2.get()==2);
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share();
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<void> f2 = f1.then(&p3);
|
||||
BOOST_TEST(f2.valid());
|
||||
try
|
||||
{
|
||||
f2.wait();
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
boost::future<int> f2 = boost::async(p1).share().then(&p2);
|
||||
BOOST_TEST(f2.get()==2);
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
boost::shared_future<int> f1 = boost::async(p1).share();
|
||||
boost::shared_future<int> f21 = f1.then(&p2).share();
|
||||
boost::future<int> f2= f21.then(&p2);
|
||||
BOOST_TEST(f2.get()==4);
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
boost::shared_future<int> f1 = boost::async(p1).share();
|
||||
boost::future<int> f2= f1.then(&p2).share().then(&p2);
|
||||
BOOST_TEST(f2.get()==4);
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
boost::future<int> f2 = boost::async(p1).share().then(&p2).share().then(&p2);
|
||||
BOOST_TEST(f2.get()==4);
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -1,252 +0,0 @@
|
||||
// Copyright (C) 2013 Vicente J. Botet Escriba
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// <boost/thread/sync_bounded_queue.hpp>
|
||||
|
||||
// class sync_queue<T>
|
||||
|
||||
// push || pull;
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
|
||||
#include <boost/thread/sync_bounded_queue.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/thread/barrier.hpp>
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
struct call_push
|
||||
{
|
||||
boost::sync_bounded_queue<int> &q_;
|
||||
boost::barrier& go_;
|
||||
|
||||
call_push(boost::sync_bounded_queue<int> &q, boost::barrier &go) :
|
||||
q_(q), go_(go)
|
||||
{
|
||||
}
|
||||
typedef void result_type;
|
||||
void operator()()
|
||||
{
|
||||
go_.count_down_and_wait();
|
||||
q_.push(42);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
struct call_push_2
|
||||
{
|
||||
boost::sync_bounded_queue<int> &q_;
|
||||
boost::barrier& go_;
|
||||
boost::barrier& end_;
|
||||
|
||||
call_push_2(boost::sync_bounded_queue<int> &q, boost::barrier &go, boost::barrier &end) :
|
||||
q_(q), go_(go), end_(end)
|
||||
{
|
||||
}
|
||||
typedef void result_type;
|
||||
void operator()()
|
||||
{
|
||||
go_.count_down_and_wait();
|
||||
q_.push(42);
|
||||
end_.count_down_and_wait();
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
struct call_pull
|
||||
{
|
||||
boost::sync_bounded_queue<int> &q_;
|
||||
boost::barrier& go_;
|
||||
|
||||
call_pull(boost::sync_bounded_queue<int> &q, boost::barrier &go) :
|
||||
q_(q), go_(go)
|
||||
{
|
||||
}
|
||||
typedef int result_type;
|
||||
int operator()()
|
||||
{
|
||||
go_.count_down_and_wait();
|
||||
return q_.pull();
|
||||
}
|
||||
};
|
||||
|
||||
void test_concurrent_push_and_pull_on_empty_queue()
|
||||
{
|
||||
boost::sync_bounded_queue<int> q(4);
|
||||
|
||||
boost::barrier go(2);
|
||||
|
||||
boost::future<void> push_done;
|
||||
boost::future<int> pull_done;
|
||||
|
||||
try
|
||||
{
|
||||
push_done=boost::async(boost::launch::async,
|
||||
#if ! defined BOOST_NO_CXX11_LAMBDAS
|
||||
[&q,&go]()
|
||||
{
|
||||
go.wait();
|
||||
q.push(42);
|
||||
}
|
||||
#else
|
||||
call_push(q,go)
|
||||
#endif
|
||||
);
|
||||
pull_done=boost::async(boost::launch::async,
|
||||
#if ! defined BOOST_NO_CXX11_LAMBDAS
|
||||
[&q,&go]() -> int
|
||||
{
|
||||
go.wait();
|
||||
return q.pull();
|
||||
}
|
||||
#else
|
||||
call_pull(q,go)
|
||||
#endif
|
||||
);
|
||||
|
||||
push_done.get();
|
||||
BOOST_TEST_EQ(pull_done.get(), 42);
|
||||
BOOST_TEST(q.empty());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
|
||||
void test_concurrent_push_on_empty_queue()
|
||||
{
|
||||
boost::sync_bounded_queue<int> q(4);
|
||||
const unsigned int n = 3;
|
||||
boost::barrier go(n);
|
||||
boost::future<void> push_done[n];
|
||||
|
||||
try
|
||||
{
|
||||
for (unsigned int i =0; i< n; ++i)
|
||||
push_done[i]=boost::async(boost::launch::async,
|
||||
#if ! defined BOOST_NO_CXX11_LAMBDAS
|
||||
[&q,&go]()
|
||||
{
|
||||
go.wait();
|
||||
q.push(42);
|
||||
}
|
||||
#else
|
||||
call_push(q,go)
|
||||
#endif
|
||||
);
|
||||
|
||||
for (unsigned int i = 0; i < n; ++i)
|
||||
push_done[i].get();
|
||||
|
||||
BOOST_TEST(!q.empty());
|
||||
for (unsigned int i =0; i< n; ++i)
|
||||
BOOST_TEST_EQ(q.pull(), 42);
|
||||
BOOST_TEST(q.empty());
|
||||
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
|
||||
void test_concurrent_push_on_full_queue()
|
||||
{
|
||||
const unsigned int size = 2;
|
||||
boost::sync_bounded_queue<int> q(size);
|
||||
const unsigned int n = 2*size;
|
||||
boost::barrier go(n);
|
||||
boost::barrier end(size+1);
|
||||
boost::future<void> push_done[n];
|
||||
|
||||
try
|
||||
{
|
||||
for (unsigned int i =0; i< n; ++i)
|
||||
push_done[i]=boost::async(boost::launch::async,
|
||||
#if ! defined BOOST_NO_CXX11_LAMBDAS
|
||||
[&q,&go,&end]()
|
||||
{
|
||||
go.wait();
|
||||
q.push(42);
|
||||
end.wait();
|
||||
}
|
||||
#else
|
||||
call_push_2(q,go,end)
|
||||
#endif
|
||||
);
|
||||
|
||||
end.wait();
|
||||
BOOST_TEST(!q.empty());
|
||||
BOOST_TEST(q.full());
|
||||
for (unsigned int i =0; i< size; ++i)
|
||||
BOOST_TEST_EQ(q.pull(), 42);
|
||||
end.wait();
|
||||
|
||||
for (unsigned int i = 0; i < n; ++i)
|
||||
push_done[i].get();
|
||||
|
||||
BOOST_TEST(!q.empty());
|
||||
for (unsigned int i =0; i< size; ++i)
|
||||
BOOST_TEST_EQ(q.pull(), 42);
|
||||
BOOST_TEST(q.empty());
|
||||
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
void test_concurrent_pull_on_queue()
|
||||
{
|
||||
boost::sync_bounded_queue<int> q(4);
|
||||
const unsigned int n = 3;
|
||||
boost::barrier go(n);
|
||||
|
||||
boost::future<int> pull_done[n];
|
||||
|
||||
try
|
||||
{
|
||||
for (unsigned int i =0; i< n; ++i)
|
||||
q.push(42);
|
||||
|
||||
for (unsigned int i =0; i< n; ++i)
|
||||
pull_done[i]=boost::async(boost::launch::async,
|
||||
#if ! defined BOOST_NO_CXX11_LAMBDAS
|
||||
[&q,&go]() -> int
|
||||
{
|
||||
go.wait();
|
||||
return q.pull();
|
||||
}
|
||||
#else
|
||||
call_pull(q,go)
|
||||
#endif
|
||||
);
|
||||
|
||||
for (unsigned int i = 0; i < n; ++i)
|
||||
BOOST_TEST_EQ(pull_done[i].get(), 42);
|
||||
BOOST_TEST(q.empty());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_concurrent_push_and_pull_on_empty_queue();
|
||||
test_concurrent_push_on_empty_queue();
|
||||
test_concurrent_push_on_full_queue();
|
||||
test_concurrent_pull_on_queue();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
@@ -1,226 +0,0 @@
|
||||
// Copyright (C) 2013 Vicente J. Botet Escriba
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// <boost/thread/sync_bounded_queue.hpp>
|
||||
|
||||
// class sync_bounded_queue<T>
|
||||
|
||||
// sync_bounded_queue();
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
|
||||
#include <boost/thread/sync_bounded_queue.hpp>
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
{
|
||||
// default queue invariants
|
||||
boost::sync_bounded_queue<int> q(2);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST_EQ(q.capacity(), 2u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue try_pull fails
|
||||
boost::sync_bounded_queue<int> q(2);
|
||||
int i;
|
||||
BOOST_TEST(! q.try_pull(i));
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue try_pull fails
|
||||
boost::sync_bounded_queue<int> q(2);
|
||||
BOOST_TEST(! q.try_pull());
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue push rvalue succeeds
|
||||
boost::sync_bounded_queue<int> q(2);
|
||||
q.push(1);
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue push rvalue succeeds
|
||||
boost::sync_bounded_queue<int> q(2);
|
||||
q.push(1);
|
||||
q.push(2);
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST( q.full());
|
||||
BOOST_TEST_EQ(q.size(), 2u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue push value succeeds
|
||||
boost::sync_bounded_queue<int> q(2);
|
||||
int i;
|
||||
q.push(i);
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue try_push rvalue succeeds
|
||||
boost::sync_bounded_queue<int> q(2);
|
||||
BOOST_TEST(q.try_push(1));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue try_push value succeeds
|
||||
boost::sync_bounded_queue<int> q(2);
|
||||
int i;
|
||||
BOOST_TEST(q.try_push(i));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue try_push rvalue succeeds
|
||||
boost::sync_bounded_queue<int> q(2);
|
||||
BOOST_TEST(q.try_push(boost::no_block, 1));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue pull succeed
|
||||
boost::sync_bounded_queue<int> q(2);
|
||||
q.push(1);
|
||||
int i;
|
||||
q.pull(i);
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue pull succeed
|
||||
boost::sync_bounded_queue<int> q(2);
|
||||
q.push(1);
|
||||
int i = q.pull();
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue try_pull succeed
|
||||
boost::sync_bounded_queue<int> q(2);
|
||||
q.push(1);
|
||||
int i;
|
||||
BOOST_TEST(q.try_pull(i));
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue try_pull succeed
|
||||
boost::sync_bounded_queue<int> q(2);
|
||||
q.push(1);
|
||||
int i;
|
||||
BOOST_TEST(q.try_pull(boost::no_block, i));
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue try_pull succeed
|
||||
boost::sync_bounded_queue<int> q(2);
|
||||
q.push(1);
|
||||
boost::shared_ptr<int> i = q.try_pull();
|
||||
BOOST_TEST_EQ(*i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// full queue try_push rvalue fails
|
||||
boost::sync_bounded_queue<int> q(2);
|
||||
q.push(1);
|
||||
q.push(2);
|
||||
BOOST_TEST(! q.try_push(3));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST( q.full());
|
||||
BOOST_TEST_EQ(q.size(), 2u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// full queue try_push succeeds
|
||||
boost::sync_bounded_queue<int> q(2);
|
||||
q.push(1);
|
||||
q.push(2);
|
||||
BOOST_TEST(q.try_pull());
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
|
||||
{
|
||||
// closed invariants
|
||||
boost::sync_bounded_queue<int> q(2);
|
||||
q.close();
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(q.closed());
|
||||
}
|
||||
{
|
||||
// closed queue push fails
|
||||
boost::sync_bounded_queue<int> q(2);
|
||||
q.close();
|
||||
try {
|
||||
q.push(1);
|
||||
BOOST_TEST(false);
|
||||
} catch (...) {
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(q.closed());
|
||||
}
|
||||
}
|
||||
{
|
||||
// 1-element closed queue pull succeed
|
||||
boost::sync_bounded_queue<int> q(2);
|
||||
q.push(1);
|
||||
q.close();
|
||||
int i;
|
||||
q.pull(i);
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(q.closed());
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
@@ -1,185 +0,0 @@
|
||||
// Copyright (C) 2013 Vicente J. Botet Escriba
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// <boost/thread/sync_queue.hpp>
|
||||
|
||||
// class sync_queue<T>
|
||||
|
||||
// push || pull;
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
|
||||
#include <boost/thread/sync_queue.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/thread/barrier.hpp>
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
struct call_push
|
||||
{
|
||||
boost::sync_queue<int> &q_;
|
||||
boost::barrier& go_;
|
||||
|
||||
call_push(boost::sync_queue<int> &q, boost::barrier &go) :
|
||||
q_(q), go_(go)
|
||||
{
|
||||
}
|
||||
typedef void result_type;
|
||||
void operator()()
|
||||
{
|
||||
go_.count_down_and_wait();
|
||||
q_.push(42);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
struct call_pull
|
||||
{
|
||||
boost::sync_queue<int> &q_;
|
||||
boost::barrier& go_;
|
||||
|
||||
call_pull(boost::sync_queue<int> &q, boost::barrier &go) :
|
||||
q_(q), go_(go)
|
||||
{
|
||||
}
|
||||
typedef int result_type;
|
||||
int operator()()
|
||||
{
|
||||
go_.count_down_and_wait();
|
||||
return q_.pull();
|
||||
}
|
||||
};
|
||||
|
||||
void test_concurrent_push_and_pull_on_empty_queue()
|
||||
{
|
||||
boost::sync_queue<int> q;
|
||||
|
||||
boost::barrier go(2);
|
||||
|
||||
boost::future<void> push_done;
|
||||
boost::future<int> pull_done;
|
||||
|
||||
try
|
||||
{
|
||||
push_done=boost::async(boost::launch::async,
|
||||
#if ! defined BOOST_NO_CXX11_LAMBDAS
|
||||
[&q,&go]()
|
||||
{
|
||||
go.wait();
|
||||
q.push(42);
|
||||
}
|
||||
#else
|
||||
call_push(q,go)
|
||||
#endif
|
||||
);
|
||||
pull_done=boost::async(boost::launch::async,
|
||||
#if ! defined BOOST_NO_CXX11_LAMBDAS
|
||||
[&q,&go]() -> int
|
||||
{
|
||||
go.wait();
|
||||
return q.pull();
|
||||
}
|
||||
#else
|
||||
call_pull(q,go)
|
||||
#endif
|
||||
);
|
||||
|
||||
push_done.get();
|
||||
BOOST_TEST_EQ(pull_done.get(), 42);
|
||||
BOOST_TEST(q.empty());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
|
||||
void test_concurrent_push_on_empty_queue()
|
||||
{
|
||||
boost::sync_queue<int> q;
|
||||
const unsigned int n = 3;
|
||||
boost::barrier go(n);
|
||||
boost::future<void> push_done[n];
|
||||
|
||||
try
|
||||
{
|
||||
for (unsigned int i =0; i< n; ++i)
|
||||
push_done[i]=boost::async(boost::launch::async,
|
||||
#if ! defined BOOST_NO_CXX11_LAMBDAS
|
||||
[&q,&go]()
|
||||
{
|
||||
go.wait();
|
||||
q.push(42);
|
||||
}
|
||||
#else
|
||||
call_push(q,go)
|
||||
#endif
|
||||
);
|
||||
|
||||
for (unsigned int i = 0; i < n; ++i)
|
||||
push_done[i].get();
|
||||
|
||||
BOOST_TEST(!q.empty());
|
||||
for (unsigned int i =0; i< n; ++i)
|
||||
BOOST_TEST_EQ(q.pull(), 42);
|
||||
BOOST_TEST(q.empty());
|
||||
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
|
||||
void test_concurrent_pull_on_queue()
|
||||
{
|
||||
boost::sync_queue<int> q;
|
||||
const unsigned int n = 3;
|
||||
boost::barrier go(n);
|
||||
|
||||
boost::future<int> pull_done[n];
|
||||
|
||||
try
|
||||
{
|
||||
for (unsigned int i =0; i< n; ++i)
|
||||
q.push(42);
|
||||
|
||||
for (unsigned int i =0; i< n; ++i)
|
||||
pull_done[i]=boost::async(boost::launch::async,
|
||||
#if ! defined BOOST_NO_CXX11_LAMBDAS
|
||||
[&q,&go]() -> int
|
||||
{
|
||||
go.wait();
|
||||
return q.pull();
|
||||
}
|
||||
#else
|
||||
call_pull(q,go)
|
||||
#endif
|
||||
);
|
||||
|
||||
for (unsigned int i = 0; i < n; ++i)
|
||||
BOOST_TEST_EQ(pull_done[i].get(), 42);
|
||||
BOOST_TEST(q.empty());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_concurrent_push_and_pull_on_empty_queue();
|
||||
test_concurrent_push_on_empty_queue();
|
||||
test_concurrent_pull_on_queue();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
@@ -1,203 +0,0 @@
|
||||
// Copyright (C) 2013 Vicente J. Botet Escriba
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// <boost/thread/sync_queue.hpp>
|
||||
|
||||
// class sync_queue<T>
|
||||
|
||||
// sync_queue();
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
|
||||
#include <boost/thread/sync_queue.hpp>
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
{
|
||||
// default queue invariants
|
||||
boost::sync_queue<int> q;
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue try_pull fails
|
||||
boost::sync_queue<int> q;
|
||||
int i;
|
||||
BOOST_TEST(! q.try_pull(i));
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue try_pull fails
|
||||
boost::sync_queue<int> q;
|
||||
BOOST_TEST(! q.try_pull());
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue push rvalue succeeds
|
||||
boost::sync_queue<int> q;
|
||||
q.push(1);
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue push rvalue succeeds
|
||||
boost::sync_queue<int> q;
|
||||
q.push(1);
|
||||
q.push(2);
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 2u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue push value succeeds
|
||||
boost::sync_queue<int> q;
|
||||
int i;
|
||||
q.push(i);
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue try_push rvalue succeeds
|
||||
boost::sync_queue<int> q;
|
||||
BOOST_TEST(q.try_push(1));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue try_push value succeeds
|
||||
boost::sync_queue<int> q;
|
||||
int i;
|
||||
BOOST_TEST(q.try_push(i));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue try_push rvalue succeeds
|
||||
boost::sync_queue<int> q;
|
||||
BOOST_TEST(q.try_push(boost::no_block, 1));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue pull succeed
|
||||
boost::sync_queue<int> q;
|
||||
q.push(1);
|
||||
int i;
|
||||
q.pull(i);
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue pull succeed
|
||||
boost::sync_queue<int> q;
|
||||
q.push(1);
|
||||
int i = q.pull();
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue try_pull succeed
|
||||
boost::sync_queue<int> q;
|
||||
q.push(1);
|
||||
int i;
|
||||
BOOST_TEST(q.try_pull(i));
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue try_pull succeed
|
||||
boost::sync_queue<int> q;
|
||||
q.push(1);
|
||||
int i;
|
||||
BOOST_TEST(q.try_pull(boost::no_block, i));
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue try_pull succeed
|
||||
boost::sync_queue<int> q;
|
||||
q.push(1);
|
||||
boost::shared_ptr<int> i = q.try_pull();
|
||||
BOOST_TEST_EQ(*i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
|
||||
{
|
||||
// closed invariants
|
||||
boost::sync_queue<int> q;
|
||||
q.close();
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(q.closed());
|
||||
}
|
||||
{
|
||||
// closed queue push fails
|
||||
boost::sync_queue<int> q;
|
||||
q.close();
|
||||
try {
|
||||
q.push(1);
|
||||
BOOST_TEST(false);
|
||||
} catch (...) {
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(q.closed());
|
||||
}
|
||||
}
|
||||
{
|
||||
// 1-element closed queue pull succeed
|
||||
boost::sync_queue<int> q;
|
||||
q.push(1);
|
||||
q.close();
|
||||
int i;
|
||||
q.pull(i);
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(q.closed());
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
@@ -1,144 +0,0 @@
|
||||
// Copyright (C) 2013 Vicente J. Botet Escriba
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// <boost/thread/synchronized_value.hpp>
|
||||
|
||||
// class synchronized_value<T,M>
|
||||
|
||||
// template <typename F>
|
||||
// inline typename boost::result_of<F(value_type&)>::type
|
||||
// operator()(BOOST_THREAD_RV_REF(F) fct);
|
||||
// template <typename F>
|
||||
// inline typename boost::result_of<F(value_type const&)>::type
|
||||
// operator()(BOOST_THREAD_RV_REF(F) fct) const;
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
|
||||
#include <boost/thread/synchronized_value.hpp>
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
struct S {
|
||||
int f() const {return 1;}
|
||||
int g() {return 1;}
|
||||
};
|
||||
|
||||
void c(S const& s)
|
||||
{
|
||||
BOOST_TEST(s.f()==1);
|
||||
}
|
||||
|
||||
void nc(S & s)
|
||||
{
|
||||
BOOST_TEST(s.f()==1);
|
||||
BOOST_TEST(s.g()==1);
|
||||
}
|
||||
|
||||
struct cfctr {
|
||||
typedef void result_type;
|
||||
void operator()(S const& s) const {
|
||||
BOOST_TEST(s.f()==1);
|
||||
}
|
||||
};
|
||||
struct ncfctr {
|
||||
typedef void result_type;
|
||||
void operator()(S& s) const {
|
||||
BOOST_TEST(s.f()==1);
|
||||
BOOST_TEST(s.g()==1);
|
||||
}
|
||||
};
|
||||
|
||||
struct cfctr3 {
|
||||
typedef void result_type;
|
||||
BOOST_THREAD_MOVABLE_ONLY(cfctr3)
|
||||
cfctr3()
|
||||
{}
|
||||
cfctr3(BOOST_THREAD_RV_REF(cfctr3))
|
||||
{}
|
||||
void operator()(S const& s) const {
|
||||
BOOST_TEST(s.f()==1);
|
||||
}
|
||||
};
|
||||
struct ncfctr3 {
|
||||
typedef void result_type;
|
||||
BOOST_THREAD_MOVABLE_ONLY(ncfctr3)
|
||||
ncfctr3()
|
||||
{}
|
||||
ncfctr3(BOOST_THREAD_RV_REF(ncfctr3))
|
||||
{}
|
||||
void operator()(S& s) const {
|
||||
BOOST_TEST(s.f()==1);
|
||||
BOOST_TEST(s.g()==1);
|
||||
}
|
||||
};
|
||||
|
||||
cfctr3 make_cfctr3() {
|
||||
return BOOST_THREAD_MAKE_RV_REF(cfctr3());
|
||||
}
|
||||
|
||||
ncfctr3 make_ncfctr3() {
|
||||
return BOOST_THREAD_MAKE_RV_REF(ncfctr3());
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
boost::synchronized_value<S> v;
|
||||
v(&nc);
|
||||
//v(&c);
|
||||
}
|
||||
{
|
||||
const boost::synchronized_value<S> v;
|
||||
v(&c);
|
||||
}
|
||||
{
|
||||
boost::synchronized_value<S> v;
|
||||
v(ncfctr());
|
||||
}
|
||||
{
|
||||
const boost::synchronized_value<S> v;
|
||||
v(cfctr());
|
||||
}
|
||||
{
|
||||
boost::synchronized_value<S> v;
|
||||
ncfctr fct;
|
||||
v(fct);
|
||||
}
|
||||
{
|
||||
const boost::synchronized_value<S> v;
|
||||
cfctr fct;
|
||||
v(fct);
|
||||
}
|
||||
{
|
||||
boost::synchronized_value<S> v;
|
||||
v(make_ncfctr3());
|
||||
}
|
||||
{
|
||||
const boost::synchronized_value<S> v;
|
||||
v(make_cfctr3());
|
||||
}
|
||||
#if ! defined BOOST_NO_CXX11_LAMBDAS
|
||||
{
|
||||
boost::synchronized_value<S> v;
|
||||
v([](S& s) {
|
||||
BOOST_TEST(s.f()==1);
|
||||
BOOST_TEST(s.g()==1);
|
||||
});
|
||||
}
|
||||
{
|
||||
const boost::synchronized_value<S> v;
|
||||
v([](S const& s) {
|
||||
BOOST_TEST(s.f()==1);
|
||||
});
|
||||
}
|
||||
#endif
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
@@ -10,27 +10,28 @@
|
||||
|
||||
class ThreadClass
|
||||
{
|
||||
public:
|
||||
public:
|
||||
ThreadClass()
|
||||
{
|
||||
}
|
||||
{
|
||||
}
|
||||
|
||||
void operator()()
|
||||
{
|
||||
return;
|
||||
}
|
||||
void operator()()
|
||||
{
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
boost::posix_time::ptime currentTimeUTC;
|
||||
boost::posix_time::ptime currentTimeUTC;
|
||||
|
||||
ThreadClass tc;
|
||||
boost::thread t(tc);
|
||||
t.join(); //causes a runtime access violation here
|
||||
ThreadClass tc;
|
||||
boost::thread t(tc);
|
||||
t.join(); //causes a runtime access violation here
|
||||
|
||||
std::cout << "done" << std::endl;
|
||||
//system("pause");
|
||||
std::cout << "done" << std::endl;
|
||||
//system("pause");
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
#include <future>
|
||||
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
@@ -30,11 +28,6 @@ boost::packaged_task<int()>* schedule(boost::function<int ()> const& fn)
|
||||
|
||||
struct MyFunc
|
||||
{
|
||||
MyFunc(MyFunc const&) = delete;
|
||||
MyFunc& operator=(MyFunc const&) = delete;
|
||||
MyFunc() {};
|
||||
MyFunc(MyFunc &&) {};
|
||||
MyFunc& operator=(MyFunc &&) { return *this;};
|
||||
void operator()()const {}
|
||||
};
|
||||
|
||||
@@ -48,14 +41,12 @@ int main()
|
||||
std::cout << "The answer to the ultimate question: " << fut.get() << std::endl;
|
||||
|
||||
{
|
||||
boost::function<void()> f;
|
||||
//boost::function<void()> f;
|
||||
MyFunc mf;
|
||||
|
||||
boost::packaged_task<void()> t1(f);
|
||||
boost::packaged_task<void()> t2(boost::move(mf));
|
||||
//boost::packaged_task<void()> t1(f); // error 1
|
||||
boost::packaged_task<void()> t2(mf); // error 2
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
// Copyright (C) 2013 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)
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#define USE_STD 0
|
||||
#define USE_BOOST 1
|
||||
|
||||
#define USED_THREAD_API USE_BOOST
|
||||
//#define USED_THREAD_API USE_STD
|
||||
|
||||
#if USED_THREAD_API == USE_BOOST
|
||||
|
||||
# define BOOST_THREAD_VERSION 4
|
||||
# include <boost/thread/future.hpp>
|
||||
|
||||
using boost::future;
|
||||
using boost::async;
|
||||
|
||||
#endif
|
||||
#if USED_THREAD_API == USE_STD
|
||||
# include <future>
|
||||
using std::future;
|
||||
using std::async;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
future<void> do_something()
|
||||
{
|
||||
auto result = async( []{ std::cout<< "A\n"; } );
|
||||
std::cout << "B\n";
|
||||
return result; // error here
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
do_something().wait();
|
||||
std::cout << "Hello, World!" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
// Copyright (C) 2013 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)
|
||||
|
||||
// A
|
||||
|
||||
//#include <boost/log/trivial.hpp>
|
||||
#include <boost/chrono.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
|
||||
//#if !defined(BOOST_NO_CXX11_ALIGNAS)
|
||||
//#error
|
||||
//# define BOOST_ALIGNMENT2(x) alignas(x)
|
||||
//#elif defined(_MSC_VER)
|
||||
//#error
|
||||
//# define BOOST_ALIGNMENT2(x) __declspec(align(x))
|
||||
//#elif defined(__GNUC__)
|
||||
//#error
|
||||
//# define BOOST_ALIGNMENT(x) __attribute__ ((__aligned__(x)))
|
||||
//#else
|
||||
//#error
|
||||
//# define BOOST_NO_ALIGNMENT2
|
||||
//# define BOOST_ALIGNMENT2(x)
|
||||
//#endif
|
||||
|
||||
typedef boost::chrono::high_resolution_clock Clock;
|
||||
typedef Clock::time_point TimePoint;
|
||||
|
||||
inline TimePoint real_time_now()
|
||||
{
|
||||
return Clock::now();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace boost::chrono;
|
||||
|
||||
boost::condition_variable m_task_spawn_condition;
|
||||
|
||||
boost::mutex main_thread_mutex;
|
||||
boost::unique_lock < boost::mutex > main_thread_lock(main_thread_mutex);
|
||||
|
||||
//BOOST_LOG_TRIVIAL(info) << "[TaskScheduler::run_and_wait] Scheduling loop - BEGIN";
|
||||
|
||||
//while (true)
|
||||
{
|
||||
static const milliseconds TIME_BACK = milliseconds(1);
|
||||
m_task_spawn_condition.wait_until(
|
||||
main_thread_lock,
|
||||
real_time_now() - TIME_BACK); // wait forever
|
||||
m_task_spawn_condition.wait_for( main_thread_lock, - TIME_BACK ); // same problem
|
||||
//BOOST_LOG_TRIVIAL(trace) << "TICK";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
// Copyright (C) 2013 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)
|
||||
|
||||
// B
|
||||
|
||||
#include <boost/atomic.hpp>
|
||||
//#include <boost/log/trivial.hpp>
|
||||
#include <boost/chrono.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
|
||||
typedef boost::chrono::high_resolution_clock Clock;
|
||||
typedef Clock::time_point TimePoint;
|
||||
|
||||
inline TimePoint real_time_now()
|
||||
{
|
||||
return Clock::now();
|
||||
}
|
||||
|
||||
class Foo {
|
||||
boost::atomic<bool> m_is_exiting;
|
||||
TimePoint m_next_tick_time;
|
||||
|
||||
public:
|
||||
|
||||
bool is_exiting() const
|
||||
{
|
||||
return m_is_exiting;
|
||||
}
|
||||
|
||||
TimePoint spawn_tasks() // note that in my app, this call takes more time than here
|
||||
{
|
||||
using namespace boost::chrono;
|
||||
const TimePoint now = real_time_now();
|
||||
|
||||
if (m_next_tick_time < now) {
|
||||
m_next_tick_time = now + seconds(1);
|
||||
//BOOST_LOG_TRIVIAL(info) << "TICK!";
|
||||
}
|
||||
|
||||
return m_next_tick_time;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace boost::chrono;
|
||||
static const milliseconds MIN_TIME_TASKS_SPAWN_FREQUENCY = milliseconds(1);
|
||||
//microseconds(1); // THE SHORTER THE QUICKER TO REPRODUCE THE BUG
|
||||
|
||||
boost::condition_variable m_task_spawn_condition;
|
||||
Foo foo;
|
||||
|
||||
boost::mutex main_thread_mutex;
|
||||
boost::unique_lock < boost::mutex > main_thread_lock(main_thread_mutex);
|
||||
|
||||
//BOOST_LOG_TRIVIAL(info) << "[TaskScheduler::run_and_wait] Scheduling loop - BEGIN";
|
||||
|
||||
while (!foo.is_exiting()) {
|
||||
const TimePoint next_task_spawn_time = foo.spawn_tasks();
|
||||
|
||||
const TimePoint now = real_time_now();
|
||||
const TimePoint next_minimum_spawn_time = now + MIN_TIME_TASKS_SPAWN_FREQUENCY;
|
||||
const TimePoint next_spawn_time = next_task_spawn_time > TimePoint()
|
||||
&& next_task_spawn_time < next_minimum_spawn_time
|
||||
? next_task_spawn_time : next_minimum_spawn_time;
|
||||
|
||||
const TimePoint::duration wait_time = next_spawn_time - now;
|
||||
if (wait_time > wait_time.zero()) {
|
||||
// BOOST_LOG_TRIVIAL(trace) << "WAIT TIME: " << wait_time; // UNCOMMENT THIS: MAKES IT WORKS. WAT??????
|
||||
m_task_spawn_condition.wait_until(
|
||||
main_thread_lock,
|
||||
next_spawn_time); // DON'T WORK: WILL WAIT IF next_spawn_time is too close!
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,7 +18,7 @@
|
||||
namespace {
|
||||
|
||||
// Shared variables for generation barrier test
|
||||
const int N_THREADS=3;
|
||||
const int N_THREADS=10;
|
||||
boost::barrier gen_barrier(N_THREADS);
|
||||
boost::mutex mutex;
|
||||
long global_parameter;
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
// (C) Copyright 2013 Vicente J. Botet Escriba
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#define BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/barrier.hpp>
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
// Shared variables for generation barrier test
|
||||
long global_parameter;
|
||||
const int N_THREADS=3;
|
||||
|
||||
unsigned int size_fct() {
|
||||
global_parameter++;
|
||||
return N_THREADS;
|
||||
}
|
||||
|
||||
boost::barrier gen_barrier(N_THREADS, size_fct);
|
||||
|
||||
void barrier_thread()
|
||||
{
|
||||
for (int i = 0; i < 5; ++i)
|
||||
{
|
||||
gen_barrier.count_down_and_wait();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void test_barrier()
|
||||
{
|
||||
boost::thread_group g;
|
||||
global_parameter = 0;
|
||||
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < N_THREADS; ++i)
|
||||
g.create_thread(&barrier_thread);
|
||||
g.join_all();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
g.interrupt_all();
|
||||
g.join_all();
|
||||
throw;
|
||||
}
|
||||
|
||||
BOOST_TEST(global_parameter==5);
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
test_barrier();
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
// (C) Copyright 2013 Vicente J. Botet Escriba
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#define BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/barrier.hpp>
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
// Shared variables for generation barrier test
|
||||
long global_parameter;
|
||||
|
||||
void void_fct() {
|
||||
global_parameter++;
|
||||
}
|
||||
|
||||
const int N_THREADS=3;
|
||||
boost::barrier gen_barrier(N_THREADS, void_fct);
|
||||
|
||||
void barrier_thread()
|
||||
{
|
||||
for (int i = 0; i < 5; ++i)
|
||||
{
|
||||
gen_barrier.count_down_and_wait();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void test_barrier()
|
||||
{
|
||||
boost::thread_group g;
|
||||
global_parameter = 0;
|
||||
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < N_THREADS; ++i)
|
||||
g.create_thread(&barrier_thread);
|
||||
g.join_all();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
g.interrupt_all();
|
||||
g.join_all();
|
||||
throw;
|
||||
}
|
||||
|
||||
BOOST_TEST(global_parameter==5);
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
test_barrier();
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ struct non_copyable_functor:
|
||||
{
|
||||
unsigned value;
|
||||
|
||||
non_copyable_functor(): boost::noncopyable(),
|
||||
non_copyable_functor():
|
||||
value(0)
|
||||
{}
|
||||
|
||||
|
||||
@@ -63,7 +63,6 @@ void test_thread_callable_object_no_arguments()
|
||||
struct callable_noncopyable_no_args:
|
||||
boost::noncopyable
|
||||
{
|
||||
callable_noncopyable_no_args() : boost::noncopyable() {}
|
||||
static bool called;
|
||||
|
||||
void operator()() const
|
||||
|
||||
@@ -27,6 +27,7 @@ int main()
|
||||
{
|
||||
typedef boost::chrono::system_clock Clock;
|
||||
typedef Clock::time_point time_point;
|
||||
typedef Clock::duration duration;
|
||||
boost::chrono::milliseconds ms(500);
|
||||
time_point t0 = Clock::now();
|
||||
boost::this_thread::sleep_for(ms);
|
||||
|
||||
Reference in New Issue
Block a user