2
0
mirror of https://github.com/boostorg/thread.git synced 2026-02-06 10:32:14 +00:00

Compare commits

..

1 Commits

Author SHA1 Message Date
Marshall Clow
57bd3b0769 Release 1.54.0
[SVN r84923]
2013-07-01 16:53:14 +00:00
78 changed files with 1555 additions and 4790 deletions

View File

@@ -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) ;
}

View File

@@ -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;
}

View File

@@ -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]

View File

@@ -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.

View File

@@ -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.]

View File

@@ -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

View File

@@ -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]

View File

@@ -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]

View File

@@ -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
{

View File

@@ -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

View File

@@ -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]

View File

@@ -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;

View File

@@ -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 :(]

View File

@@ -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]

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;
{

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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));

View File

@@ -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));

View File

@@ -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;
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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

View File

@@ -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

View File

@@ -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.
//

View File

@@ -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.
//

View File

@@ -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

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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);
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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();

View File

@@ -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

View File

@@ -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 :

View File

@@ -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

View File

@@ -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)
{

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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);
}
}
}

View File

@@ -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);
// }
// }
//}
}

View File

@@ -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 ]
;
}

View File

@@ -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");
}
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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());

View File

@@ -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());
}

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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";
}
}

View File

@@ -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!
}
}
}

View File

@@ -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;

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -129,7 +129,7 @@ struct non_copyable_functor:
{
unsigned value;
non_copyable_functor(): boost::noncopyable(),
non_copyable_functor():
value(0)
{}

View File

@@ -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

View File

@@ -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);