mirror of
https://github.com/boostorg/thread.git
synced 2026-02-03 21:52:07 +00:00
Compare commits
135 Commits
boost-1.56
...
boost-1.57
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5fb51a74fe | ||
|
|
02bb6abef4 | ||
|
|
1a4bd71616 | ||
|
|
63dd439992 | ||
|
|
1029fa9c59 | ||
|
|
3e28ea806c | ||
|
|
07dc40a9ff | ||
|
|
6f91af2154 | ||
|
|
c3cff80557 | ||
|
|
729c8b63bb | ||
|
|
6fe7f44ea0 | ||
|
|
8fd4755e79 | ||
|
|
02b007a20e | ||
|
|
c0c78e87fc | ||
|
|
58cde5af05 | ||
|
|
c1f2c8a1f1 | ||
|
|
bacf5b52ec | ||
|
|
3babf7966e | ||
|
|
f3de7bf10f | ||
|
|
90154217cf | ||
|
|
ac0b2f9ba7 | ||
|
|
da739e680a | ||
|
|
b240b097c7 | ||
|
|
debe2fb0d1 | ||
|
|
b264ec8fc0 | ||
|
|
372f8fe10f | ||
|
|
e3c240df0a | ||
|
|
748ea5164e | ||
|
|
b44627f97d | ||
|
|
c8cd7d1d08 | ||
|
|
f0d0c0551b | ||
|
|
bb72eadbd8 | ||
|
|
f52f32afda | ||
|
|
b973e9b32e | ||
|
|
1ffef9ed2d | ||
|
|
f24ea524bd | ||
|
|
4111471ba5 | ||
|
|
5e970b987e | ||
|
|
c7b5729cf3 | ||
|
|
291ebded8e | ||
|
|
0c2c8ed3b8 | ||
|
|
5294dfa149 | ||
|
|
7f5dfb633d | ||
|
|
f381a7d591 | ||
|
|
aceabda609 | ||
|
|
dc4b619b57 | ||
|
|
abb3fc97e0 | ||
|
|
ec6ae7b9b4 | ||
|
|
8c5ba97d39 | ||
|
|
617b979214 | ||
|
|
96667cfcce | ||
|
|
a981650ce9 | ||
|
|
00b25853b2 | ||
|
|
ef04ce8bce | ||
|
|
5091ad705f | ||
|
|
b77f802c47 | ||
|
|
da945436c1 | ||
|
|
27befdf26f | ||
|
|
f73007910a | ||
|
|
8c3cfacf06 | ||
|
|
7d4392e157 | ||
|
|
aff3f424a9 | ||
|
|
546ca909c4 | ||
|
|
7dac51706c | ||
|
|
5ee0e27b5a | ||
|
|
b4fd7fdeb1 | ||
|
|
c75ea7db89 | ||
|
|
19294dc756 | ||
|
|
52a360775e | ||
|
|
c632b75db1 | ||
|
|
11e4c950ac | ||
|
|
8440e9a7d8 | ||
|
|
02bc292c20 | ||
|
|
6d68bac44b | ||
|
|
5d0d128cab | ||
|
|
ec542d3c8b | ||
|
|
6e3216643b | ||
|
|
016f5653cf | ||
|
|
ce46539183 | ||
|
|
e93035ce42 | ||
|
|
53a46593a8 | ||
|
|
c2426b8fad | ||
|
|
7d841f6337 | ||
|
|
556bbde8a7 | ||
|
|
a0c1462a6a | ||
|
|
234df13faf | ||
|
|
24983f0bce | ||
|
|
722997379b | ||
|
|
f36f5d6dbb | ||
|
|
9ee1044f92 | ||
|
|
ebeb36646c | ||
|
|
8ebf0e7f21 | ||
|
|
0dc2f69bc1 | ||
|
|
c3b549d947 | ||
|
|
6552cf64b5 | ||
|
|
d5f335b8a4 | ||
|
|
80591fb64d | ||
|
|
0543b522cb | ||
|
|
3dbc5d0664 | ||
|
|
2d0272345b | ||
|
|
f1a274b51c | ||
|
|
b7f1706ab8 | ||
|
|
f299fb8083 | ||
|
|
074dcbcbf5 | ||
|
|
af6f80a3c7 | ||
|
|
957253401f | ||
|
|
3195253230 | ||
|
|
4336a7bbe3 | ||
|
|
3b75d6dabc | ||
|
|
fc0d7e23b3 | ||
|
|
aeabda8d45 | ||
|
|
3bde7e103c | ||
|
|
ea0889485e | ||
|
|
d4d46c64dd | ||
|
|
f3fa80c866 | ||
|
|
7e21f24991 | ||
|
|
2037a64c51 | ||
|
|
8bfd1cea31 | ||
|
|
a26e7eb8c4 | ||
|
|
e47eba8751 | ||
|
|
8aef8000d9 | ||
|
|
78f1044c68 | ||
|
|
26042ca26a | ||
|
|
74132067ba | ||
|
|
c4d42e6b6c | ||
|
|
59c504d5d8 | ||
|
|
b81a838a43 | ||
|
|
a06dde3794 | ||
|
|
726a3faf19 | ||
|
|
c977c8d420 | ||
|
|
a1faacd7bb | ||
|
|
866b78cbd0 | ||
|
|
0861f81b05 | ||
|
|
6488028a22 | ||
|
|
9ceea9822f |
40
.gitignore
vendored
Normal file
40
.gitignore
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
#mac
|
||||
.DS_Store
|
||||
|
||||
#projects
|
||||
.project
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
bin/*
|
||||
test/bin/*
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
#doc
|
||||
|
||||
doc/html
|
||||
@@ -78,12 +78,12 @@ project boost/thread
|
||||
<toolset>pathscale:<cxxflags>-pedantic
|
||||
|
||||
<toolset>clang:<cxxflags>-Wextra
|
||||
<toolset>clang:<cxxflags>-pedantic
|
||||
#<toolset>clang:<cxxflags>-ansi
|
||||
#<toolset>clang:<cxxflags>-fpermissive
|
||||
<toolset>clang:<cxxflags>-Wno-long-long
|
||||
<toolset>clang:<cxxflags>-Wunused-function
|
||||
<toolset>clang:<cxxflags>-Wno-variadic-macros
|
||||
<toolset>clang:<warnings>on
|
||||
|
||||
#<toolset>gcc-mingw-4.4.0:<cxxflags>-fdiagnostics-show-option
|
||||
#<toolset>gcc-mingw-4.5.0:<cxxflags>-fdiagnostics-show-option
|
||||
|
||||
@@ -122,21 +122,21 @@ An Executor is an object that schedules the closures that have been submitted to
|
||||
|
||||
* The choice of which executor to use is explicit. This is important for reasons described in the Motivation section. In particular, consider the common case of an asynchronous operation that itself spawns asynchronous operations. If both operations ran on the same executor, and if that executor had a bounded number of worker threads, then we could get deadlock. Programs often deal with such issues by splitting different kinds of work between different executors.
|
||||
|
||||
* Even if there could be a strong value in having a default executor, that can be used when detailed control is unnecessary, the authors don't know how to implement it in a portable a robust way.
|
||||
* Even if there could be a strong value in having a default executor, that can be used when detailed control is unnecessary, the authors don't know how to implement it in a portable and robust way.
|
||||
|
||||
* The library provides Executors based on static and dynamic polymorphism. The static polymorphism interface is intended to be used on contexts that need to have the best performances. The dynamic polymorphism interface has the advantage to been able to change the executor a function is suing without making it a template and it possible to pass executors across a binary interface. For some applications, the cost of an additional virtual dispatch could be almost certainly negligible compared to the other operations involved.
|
||||
* The library provides Executors based on static and dynamic polymorphism. The static polymorphism interface is intended to be used on contexts that need to have the best performances. The dynamic polymorphism interface has the advantage to been able to change the executor a function is using without making it a template and is possible to pass executors across a binary interface. For some applications, the cost of an additional virtual dispatch could be almost certainly negligible compared to the other operations involved.
|
||||
|
||||
* Conceptually, an executor puts closures on a queue and at some point executes them. The queue is always unbounded, so adding a closure to an executor never blocks. (Defining “never blocks” formally is challenging, but informally we just mean that submit() is an ordinary function that executes something and returns, rather than waiting for the completion of some potentially long running operation in another thread.)
|
||||
|
||||
[heading Closure]
|
||||
|
||||
One important question is just what a closure is. This library has a very simple answer: a closure is a `Callable` with no parameters and returning `voidv.
|
||||
One important question is just what a closure is. This library has a very simple answer: a closure is a `Callable` with no parameters and returning `void`.
|
||||
|
||||
N3785 choose the more specific `std::function<void()>` as it provides only dynamic polymorphism and states that in practice the implementation of a template based approach or another approach is impractical. The authors of this library think that the template based approach is compatible with a dynamic based approach. They give some arguments:
|
||||
|
||||
The first one is that a virtual function can not be a template. This is true but it is also true that the executor interface can provide the template functions that call to the virtual public functions. Another reason they give is that "a template parameter would complicate the interface without adding any real generality. In the end an executor class is going to need some kind of type erasure to handle all the different kinds of function objects with `void()` signature, and that’s exactly what std::function already does". We think that it is up to the executor to manage with this implementation details, not to the user.
|
||||
|
||||
We share all the argument they give related to the `void()` interface of the work unit. A work unit is a closure that takes no arguments and returns no value. This is indeed a limitation on user code, but combined with `boost::async` taking executors as parameters the user has all what is needs.
|
||||
We share all the argument they give related to the `void()` interface of the work unit. A work unit is a closure that takes no arguments and returns no value. This is indeed a limitation on user code, but combined with `boost::async` taking executors as parameters the user has all what she needs.
|
||||
|
||||
The third one is related to performance. They assert that "any mechanism for storing closures on an executor’s queue will have to use some form of type erasure. There’s no reason to believe that a custom closure mechanism, written just for std::executor and used nowhere else within the standard library, would be better in that respect than `std::function<void()>`". We believe that the implementation can do better that storing the closure on a `std::function<void()>`. e.g. the implementation can use intrusive data to store the closure and the pointers to other nodes needed to store the closures in a given order.
|
||||
|
||||
@@ -166,7 +166,7 @@ Note that when we combine `boost::async` and `Executors`, the exception will be
|
||||
|
||||
It is common idiom to set some thread local variable at the beginning of a thread. As Executors could instantiate threads internally these Executors shall have the ability to call a user specific function at thread entry on the executor constructor.
|
||||
|
||||
For executors that don't instantiate any thread an that would use the current thread this function shall be called only for the thread calling the `at_thread_entry` member function.
|
||||
For executors that don't instantiate any thread and that would use the current thread this function shall be called only for the thread calling the `at_thread_entry` member function.
|
||||
|
||||
[heading Cancelation]
|
||||
|
||||
@@ -287,9 +287,6 @@ The `Executor` concept models the common operations of all the executors.
|
||||
|
||||
A type `E` meets the `Executor` requirements if the following expressions are well-formed and have the specified semantics
|
||||
|
||||
* `E::work`
|
||||
* `e.submit(lw);`
|
||||
* `e.submit(rw);`
|
||||
* `e.submit(lc);`
|
||||
* `e.submit(rc);`
|
||||
* `e.close();`
|
||||
@@ -300,50 +297,10 @@ A type `E` meets the `Executor` requirements if the following expressions are we
|
||||
where
|
||||
|
||||
* `e` denotes a value of type `E`,
|
||||
* `lw` denotes a lvalue referece of type `E::work`,
|
||||
* `rc` denotes a rvalue referece of type `E::work`
|
||||
* `lc` denotes a lvalue referece of type `Closure`,
|
||||
* `rc` denotes a rvalue referece of type `Closure`
|
||||
* `p` denotes a value of type `Predicate`
|
||||
|
||||
[/////////////////////////////////////]
|
||||
[section:submitlw `e.submit(lw);`]
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [The specified closure will be scheduled for execution at some point in the future.
|
||||
If invoked closure throws an exception the executor will call std::terminate, as is the case with threads.]]
|
||||
|
||||
[[Synchronization:] [completion of closure on a particular thread happens before destruction of thread's thread local variables.]]
|
||||
|
||||
[[Return type:] [`void`.]]
|
||||
|
||||
[[Throws:] [sync_queue_is_closed if the thread pool is closed. Whatever exception that can be throw while storing the closure.]]
|
||||
|
||||
[[Exception safety:] [If an exception is thrown then the executor state is unmodified.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:submitrw `e.submit(rw);`]
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [The specified closure will be scheduled for execution at some point in the future.
|
||||
If invoked closure throws an exception the executor will call std::terminate, as is the case with threads.]]
|
||||
|
||||
[[Synchronization:] [completion of closure on a particular thread happens before destruction of thread's thread local variables.]]
|
||||
|
||||
[[Return type:] [`void`.]]
|
||||
|
||||
[[Throws:] [sync_queue_is_closed if the thread pool is closed. Whatever exception that can be throw while storing the closure.]]
|
||||
|
||||
[[Exception safety:] [If an exception is thrown then the executor state is unmodified.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:submitlc `e.submit(lc);`]
|
||||
|
||||
@@ -401,15 +358,16 @@ If invoked closure throws an exception the executor will call std::terminate, as
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:close `b = e.close();`]
|
||||
[section:closed `b = e.closed();`]
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Return type:] [`bool`.]]
|
||||
|
||||
[[Return:] [`void`.]]
|
||||
[[Return:] [whether the pool is closed for submissions.]]
|
||||
|
||||
[[Throws:] [Whatever exception that can be throw while ensuring the thread safety.]]
|
||||
|
||||
[[Throws:] [whether the pool is closed for submissions.]]
|
||||
|
||||
]
|
||||
|
||||
@@ -433,7 +391,7 @@ If invoked closure throws an exception the executor will call std::terminate, as
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:try_executing_one `e.reschedule_until(p);`]
|
||||
[section:reschedule_until `e.reschedule_until(p);`]
|
||||
|
||||
[variablelist
|
||||
|
||||
@@ -491,6 +449,7 @@ Executor abstract base class.
|
||||
virtual bool closed() = 0;
|
||||
|
||||
virtual void submit(work&& closure) = 0;
|
||||
virtual void submit(work& closure) = 0;
|
||||
template <typename Closure>
|
||||
void submit(Closure&& closure);
|
||||
|
||||
@@ -559,6 +518,7 @@ Polymorphic adaptor of a model of Executor to an executor.
|
||||
bool closed();
|
||||
|
||||
void submit(work&& closure);
|
||||
void submit(work& closure);
|
||||
|
||||
bool try_executing_one();
|
||||
|
||||
@@ -584,7 +544,7 @@ Polymorphic adaptor of a model of Executor to an executor.
|
||||
[/////////////////////////////////////]
|
||||
[section:destructor Destructor `~executor_adaptor()`]
|
||||
|
||||
virtual ~ executor_adaptor();
|
||||
virtual ~executor_adaptor();
|
||||
|
||||
[variablelist
|
||||
|
||||
@@ -612,6 +572,39 @@ Polymorphic adaptor of a model of Executor to an executor.
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
||||
|
||||
[/////////////////////////////////]
|
||||
[section:generic_executor_ref Class `generic_executor_ref`]
|
||||
|
||||
Executor abstract base class.
|
||||
|
||||
#include <boost/thread/generic_executor_ref.hpp>
|
||||
namespace boost {
|
||||
class generic_executor_ref
|
||||
{
|
||||
public:
|
||||
generic_executor_ref(generic_executor_ref const&);
|
||||
generic_executor_ref& operator=(generic_executor_ref const&);
|
||||
|
||||
template <class Executor>
|
||||
executor(Executor& ex);
|
||||
generic_executor_ref() {};
|
||||
|
||||
void close() = 0;
|
||||
bool closed() = 0;
|
||||
|
||||
template <typename Closure>
|
||||
void submit(Closure&& closure);
|
||||
|
||||
virtual bool try_executing_one() = 0;
|
||||
template <typename Pred>
|
||||
bool reschedule_until(Pred const& pred);
|
||||
};
|
||||
}
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[/
|
||||
[//////////////////////////////////////////////////////////]
|
||||
[section:scheduled_executor Template Class `scheduled_executor`]
|
||||
@@ -639,6 +632,7 @@ Executor providing time related functions.
|
||||
bool closed();
|
||||
|
||||
void submit(work&& closure);
|
||||
void submit(work& closure);
|
||||
template <typename Closure>
|
||||
void submit(Closure&& closure);
|
||||
|
||||
@@ -707,30 +701,26 @@ Executor providing time related functions.
|
||||
]
|
||||
|
||||
[//////////////////////////////////////////////////////////]
|
||||
[section:scheduled_executor Template Class `serial_executor`]
|
||||
[section:serial_executor Class `serial_executor`]
|
||||
|
||||
A serial executor ensuring that there are no two work units that executes concurrently.
|
||||
|
||||
#include <boost/thread/serial_executor.hpp>
|
||||
namespace boost {
|
||||
template <class Executor>
|
||||
class serial_executor
|
||||
{
|
||||
Executor& ex;
|
||||
public:
|
||||
typedef executors::work work;
|
||||
|
||||
serial_executor(serial_executor const&) = delete;
|
||||
serial_executor& operator=(serial_executor const&) = delete;
|
||||
|
||||
template <class Executor>
|
||||
serial_executor(Executor& ex);
|
||||
|
||||
Executor& underlying_executor();
|
||||
generic_executor_ref underlying_executor();
|
||||
|
||||
void close();
|
||||
bool closed();
|
||||
|
||||
void submit(work&& closure);
|
||||
template <typename Closure>
|
||||
void submit(Closure&& closure);
|
||||
|
||||
@@ -742,8 +732,9 @@ A serial executor ensuring that there are no two work units that executes concur
|
||||
}
|
||||
|
||||
[/////////////////////////////////////]
|
||||
[section:constructor Constructor `serial_executor(Executor&, chrono::duration<Rep, Period>)`]
|
||||
[section:constructor Constructor `serial_executor(Executor&)`]
|
||||
|
||||
template <class Executor>
|
||||
serial_executor(Executor& ex);
|
||||
|
||||
[variablelist
|
||||
@@ -773,7 +764,7 @@ A serial executor ensuring that there are no two work units that executes concur
|
||||
[/////////////////////////////////////]
|
||||
[section:underlying_executor Function member `underlying_executor()`]
|
||||
|
||||
Executor& underlying_executor();
|
||||
generic_executor_ref underlying_executor();
|
||||
|
||||
[variablelist
|
||||
|
||||
@@ -788,6 +779,67 @@ A serial executor ensuring that there are no two work units that executes concur
|
||||
|
||||
[endsect]
|
||||
|
||||
[//////////////////////////////////////////////////////////]
|
||||
[section:inline_executor Class `inline_executor`]
|
||||
|
||||
A serial executor ensuring that there are no two work units that executes concurrently.
|
||||
|
||||
#include <boost/thread/inline_executor.hpp>
|
||||
namespace boost {
|
||||
class inline_executor
|
||||
{
|
||||
public:
|
||||
inline_executor(inline_executor const&) = delete;
|
||||
inline_executor& operator=(inline_executor const&) = delete;
|
||||
|
||||
inline_executor();
|
||||
|
||||
void close();
|
||||
bool closed();
|
||||
|
||||
template <typename Closure>
|
||||
void submit(Closure&& closure);
|
||||
|
||||
bool try_executing_one();
|
||||
template <typename Pred>
|
||||
bool reschedule_until(Pred const& pred);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
[/////////////////////////////////////]
|
||||
[section:constructor Constructor `inline_executor()`]
|
||||
|
||||
inline_executor();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Constructs a inline_executor. ]]
|
||||
|
||||
[[Throws:] [Nothing. ]]
|
||||
|
||||
]
|
||||
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:destructor Destructor `~inline_executor()`]
|
||||
|
||||
~inline_executor();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Destroys the inline_executor.]]
|
||||
|
||||
[[Synchronization:] [The completion of all the closures happen before the completion of the executor destructor.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -801,8 +853,7 @@ A thread pool with up to a fixed number of threads.
|
||||
class basic_thread_pool
|
||||
{
|
||||
public:
|
||||
typedef boost::work work;
|
||||
|
||||
|
||||
basic_thread_pool(basic_thread_pool const&) = delete;
|
||||
basic_thread_pool& operator=(basic_thread_pool const&) = delete;
|
||||
|
||||
@@ -864,8 +915,7 @@ A user scheduled executor.
|
||||
class loop_executor
|
||||
{
|
||||
public:
|
||||
typedef thread_detail::work work;
|
||||
|
||||
|
||||
loop_executor(loop_executor const&) = delete;
|
||||
loop_executor& operator=(loop_executor const&) = delete;
|
||||
|
||||
@@ -909,7 +959,7 @@ A user scheduled executor.
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Destroys the thread pool.]]
|
||||
[[Effects:] [Destroys the executor.]]
|
||||
|
||||
[[Synchronization:] [The completion of all the closures happen before the completion of the executor destructor.]]
|
||||
|
||||
|
||||
@@ -8,6 +8,67 @@
|
||||
|
||||
[section:changes History]
|
||||
|
||||
[heading Version 4.4.0 - boost 1.57]
|
||||
|
||||
[*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/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/9118 #9118] Seg fault on thread join when llvm and libc++ are used
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9309 #9309] test_latch fails often on clang-darwin-tot11
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9310 #9310] test_4648_lib fails on 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/10537 #10537] Application crash on throw exception
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10651 #10651] boost::thread leaks memory when using the MinGW compiler
|
||||
|
||||
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 Know Bugs] to see the current state.
|
||||
|
||||
Please take a look at [@http://www.boost.org/development/tests/master/developer/thread.html thread trunk regression test] to see the last snapshot.
|
||||
|
||||
[*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,
|
||||
|
||||
[*New Experimental Features:]
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/6227 #6227] Synchro: Use of variadic templates on Generic Locking Algorithms on compilers providing them
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10298 #10298] Synchro: Added queue views.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10300 #10300] Async: Added generic_executor_ref.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10552 #10552] Add make_valid_future
|
||||
|
||||
[*Fixed Bugs:]
|
||||
|
||||
* [@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/6787 #6787] boost::thread::sleep() hangs if system time is rolled back
|
||||
* [@http://svn.boost.org/trac/boost/ticket/7665 #7665] this_thread::sleep_for no longer uses steady_clock in thread
|
||||
* [@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/9310 #9310] test_4648_lib fails on clang-darwin-asan11
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9425 #9425] Boost promise & future does not use supplied allocator for value storage
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9558 #9558] future continuations unit test hangs in get()/pthread_cond_wait() on Mac 10.7/32-bit/x86/darwin-4.2.1
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9787 #9787] [windows] Small duration value passed down to basic_timed_mutex::try_lock_until and condition_variable::wait_until can cause infinite or near infinite wait for win32
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9880 #9880] [windows] boost::condition_variable.timed_wait() exception if system time < 1970
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10159 #10159] GCC 4.4 error sorry, unimplemented
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10196 #10196] thread_specific_ptr does not support void*
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10296 #10296] Boost.Thread 1.56 rc1 does not compile on Mingw
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10297 #10297] Boost.Thread 1.56 rc1 hangs when built with clang on armhf
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10340 #10340] No boost::promise<T>::set_value(const T&) overload present in C++03 mode
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10425 #10425] Missing documentation for when_all/when_any.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10426 #10426] Take in account the deferred futures in when_all.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10427 #10427] Take in account the deferred and ready futures in when_any.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10428 #10428] Adapt to new unique_ptr interface in Boost.Move
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10465 #10465] Missing implementation of when_all/when_any when the result is a tuple.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10476 #10476] classes using BOOST_THREAD_MOVABLE_ONLY<T> dont satisfy is_copy_constructible<T>::value == false
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10478 #10478] Data race in boost/thread/future.hpp
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10529 #10529] The pthread/condition_variable_any constructor reports incorrect error code for pthread_cond_init
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10563 #10563] shared_future<R>::then should be const
|
||||
|
||||
|
||||
[heading Version 4.3.0 - boost 1.56]
|
||||
|
||||
[*Know Bugs:]
|
||||
@@ -28,7 +89,7 @@
|
||||
|
||||
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 Know Bugs] to see the current state.
|
||||
|
||||
Please take a look at [@http://www.boost.org/development/tests/release/developer/thread.html thread trunk regression test] to see the last snapshot.
|
||||
Please take a look at [@http://www.boost.org/development/tests/master/developer/thread.html thread trunk regression test] to see the last snapshot.
|
||||
|
||||
|
||||
[*Sever limitations:]
|
||||
@@ -506,12 +567,8 @@ The following features will be included in next releases.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8273 #8273] Synchro: Add externally locked streams.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8514 #8514] Async: Add a thread_pool executor with work stealing.
|
||||
|
||||
# Add some of the extension proposed in [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3428.pdf A Standardized Representation of Asynchronous Operations] or extension to them, in particular
|
||||
|
||||
* [@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/8516 #8516] Async: Add future/shared_future::then taking a scheduler as parameter.
|
||||
# Add extensions related to fork-join as:
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9600 #9600] Async: Add task_region/task_run.
|
||||
|
||||
# And some additional extensions related to futures as:
|
||||
|
||||
|
||||
@@ -101,7 +101,31 @@
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:cxx1y C++1y TS Concurrency - On going proposals]
|
||||
|
||||
[section:cxx1y C++14 TS Extensions for Concurrency V1 ]
|
||||
|
||||
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4107.html N4107-Extensions for Concurrency]]
|
||||
|
||||
|
||||
[table Improvements to std::future<T> and related APIs]
|
||||
[[Section] [Description] [Status] [Comments]]
|
||||
[[2.1] [ - ] [ - ] [ - ]]
|
||||
[[2.2] [Class template future] [Partial] [ - ]]
|
||||
[[2.2] [then] [ Partial ] [ without implicit unwrapping #10550 and blocking #10551 ]]
|
||||
[[2.2] [is_ready] [ Yes ] [ - ]]
|
||||
[[2.3] [Class template shared_future] [Partial] [ - ]]
|
||||
[[2.3] [then] [ Partial ] [ Without implicit unwrapping #10550 and blocking #10551 ]]
|
||||
[[2.3] [is_ready] [ Yes ] [ - ]]
|
||||
[[2.4] [Function template when_all] [Partial] [ interface not complete #10426 and blocking #10551 ]]
|
||||
[[2.5] [Function template when_any] [Partial] [ interface not complete #10427 and blocking #10551 ]]
|
||||
[[2.6] [Function template when_any_back] [No] [ #XXXX ]]
|
||||
[[2.7] [Function template make_ready_future] [Yes] [ - ]]
|
||||
]
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:cxx1y C++1z TS Concurrency - On going proposals]
|
||||
|
||||
[section:latch C++ Latches and Barriers]
|
||||
|
||||
@@ -161,8 +185,6 @@
|
||||
[endsect]
|
||||
[section:executors Asynchronous Executors]
|
||||
|
||||
While Boost.Thread implementation of executors would not use dynamic polymorphism, it is worth comparing with the current trend on the standard.
|
||||
|
||||
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3785.pdf N3785 Executors and Schedulers]]
|
||||
|
||||
[table Asynchronous Executors
|
||||
@@ -181,30 +203,13 @@ While Boost.Thread implementation of executors would not use dynamic polymorphis
|
||||
[[V.2.5] [thread_executor] [Yes] [ static version thread_executor, dynamic one execduler_adaptor<thread_executor> ]]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[section:async Improvements to std::future<T> and Related APIs]
|
||||
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3784.pdf N3784-Improvements to `std::future<T> and Related APIs]]
|
||||
|
||||
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3857.pdf N3857-Improvements to std::future<T> and Related APIs]]
|
||||
|
||||
[note These functions are based on [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3634.pdf [*N3634 - Improvements to std::future<T> and related APIs]] C++1y proposal by N. Gustafsson, A. Laksberg, H. Sutter, S. Mithani.]
|
||||
|
||||
[table Improvements to std::future<T> and related APIs]
|
||||
[table `async, future/shared_future::then`and Executors
|
||||
[[Section] [Description] [Status] [Comments]]
|
||||
[[30.6.6] [Class template future] [Partial] [ - ]]
|
||||
[[30.6.6] [unwrap constructor] [Yes] [ - ]]
|
||||
[[30.6.6] [then] [Yes] [ - ]]
|
||||
[[30.6.6] [unwrap] [Yes] [ - ]]
|
||||
[[30.6.6] [ready] [Partial] [ is_ready ]]
|
||||
[[30.6.7] [Class template shared_future] [Partial] [ - ]]
|
||||
[[30.6.6] [unwrap constructor] [Yes] [ - ]]
|
||||
[[30.6.7] [then] [Yes] [ - ]]
|
||||
[[30.6.7] [unwrap] [No] [ #XXXX ]]
|
||||
[[30.6.7] [ready] [Partial] [ is_ready ]]
|
||||
[[30.6.X] [Function template when_all] [Partial] [ interface not complete #7447 ]]
|
||||
[[30.6.X] [Function template when_any] [Partial] [ interface not complete #7446 ]]
|
||||
[[30.6.X] [Function template when_any_swaped] [No] [ #XXXX ]]
|
||||
[[30.6.X] [Function template make_ready_future] [Yes] [ - ]]
|
||||
[[30.6.8] [Function template async ] [Yes] [ - ]]
|
||||
[[30.6.6] [`future<T>::then`] [Yes] [ ]]
|
||||
[[30.6.7] [`shared_future<T>::then`] [Yes] [ ]]
|
||||
[[30.6.8] [`async`] [Yes] [ - ]]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
@@ -79,47 +79,54 @@
|
||||
struct uses_allocator<packaged_task <S>, Alloc>;
|
||||
|
||||
template <class F>
|
||||
future<typename result_of<typename decay<F>::type()>::type>
|
||||
async(F f);
|
||||
future<typename result_of<typename decay<F>::type()>::type>
|
||||
async(F f);
|
||||
template <class F>
|
||||
future<typename result_of<typename decay<F>::type()>::type>
|
||||
async(launch policy, F f);
|
||||
future<typename result_of<typename decay<F>::type()>::type>
|
||||
async(launch policy, F f);
|
||||
|
||||
template <class F, class... Args>
|
||||
future<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
|
||||
async(F&& f, Args&&... args);
|
||||
future<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
|
||||
async(F&& f, Args&&... args);
|
||||
template <class F, class... Args>
|
||||
future<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
|
||||
async(launch policy, F&& f, Args&&... args);
|
||||
future<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
|
||||
async(launch policy, F&& f, Args&&... args);
|
||||
template <class Executor, class F, class... Args>
|
||||
future<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
|
||||
async(Executor &ex, F&& f, Args&&... args);
|
||||
future<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
|
||||
async(Executor &ex, F&& f, Args&&... args);
|
||||
|
||||
template<typename Iterator>
|
||||
void wait_for_all(Iterator begin,Iterator end); // EXTENSION
|
||||
void wait_for_all(Iterator begin,Iterator end); // EXTENSION
|
||||
template<typename F1,typename... FS>
|
||||
void wait_for_all(F1& f1,Fs&... fs); // EXTENSION
|
||||
void wait_for_all(F1& f1,Fs&... fs); // EXTENSION
|
||||
|
||||
template<typename Iterator>
|
||||
Iterator wait_for_any(Iterator begin,Iterator end); // EXTENSION
|
||||
Iterator wait_for_any(Iterator begin,Iterator end); // EXTENSION
|
||||
template<typename F1,typename... Fs>
|
||||
unsigned wait_for_any(F1& f1,Fs&... fs); // EXTENSION
|
||||
unsigned wait_for_any(F1& f1,Fs&... fs); // EXTENSION
|
||||
|
||||
template <class InputIterator>
|
||||
future<std::vector<typename InputIterator::value_type::value_type>>
|
||||
when_all(InputIterator first, InputIterator last);
|
||||
template <typename... T>
|
||||
future<std::tuple<decay_t<T>...> when_all(T&&... futures);
|
||||
template <class InputIterator>
|
||||
future<std::vector<typename InputIterator::value_type::value_type>>
|
||||
when_any(InputIterator first, InputIterator last); // EXTENSION
|
||||
template <typename... T>
|
||||
future<std::tuple<decay_t<T>...> when_any(T&&... futures);
|
||||
|
||||
template <typename T>
|
||||
future<typename decay<T>::type> make_future(T&& value); // DEPRECATED
|
||||
future<typename decay<T>::type> make_future(T&& value); // DEPRECATED
|
||||
future<void> make_future(); // DEPRECATED
|
||||
|
||||
template <typename T>
|
||||
future<typename decay<T>::type> make_ready_future(T&& value); // EXTENSION
|
||||
future<typename decay<T>::type> make_ready_future(T&& value); // EXTENSION
|
||||
future<void> make_ready_future(); // EXTENSION
|
||||
//template <typename T>
|
||||
//future<T> make_ready_future(exception_ptr ex); // DEPRECATED
|
||||
//template <typename T, typename E>
|
||||
//future<T> make_ready_future(E ex); // DEPRECATED
|
||||
|
||||
exceptional_ptr make_exceptional(exception_ptr ex); // EXTENSION
|
||||
template <typename E>
|
||||
exceptional_ptr make_exceptional(E ex); // EXTENSION
|
||||
exceptional_ptr make_exceptional(E ex); // EXTENSION
|
||||
exceptional_ptr make_exceptional(); // EXTENSION
|
||||
|
||||
|
||||
@@ -333,13 +340,13 @@ The object's `name` virtual function returns a pointer to the string "future".]]
|
||||
shared_future<R> share();
|
||||
|
||||
template<typename F>
|
||||
__unique_future__<typename boost::result_of<F(__unique_future__&)>::type>
|
||||
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
|
||||
then(F&& func); // EXTENSION
|
||||
template<typename S, typename F>
|
||||
__unique_future__<typename boost::result_of<F(__unique_future__&)>::type>
|
||||
then(S& scheduler, F&& func); // EXTENSION NOT_YET_IMPLEMENTED
|
||||
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
|
||||
then(S& scheduler, F&& func); // EXTENSION
|
||||
template<typename F>
|
||||
__unique_future__<typename boost::result_of<F(__unique_future__&)>::type>
|
||||
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
|
||||
then(launch policy, F&& func); // EXTENSION
|
||||
|
||||
see below unwrap(); // EXTENSION
|
||||
@@ -438,6 +445,7 @@ There are not too much tests yet, so it is possible that you can find out some t
|
||||
[variablelist
|
||||
|
||||
[[Requires:] [`other.valid()`.]
|
||||
|
||||
[[Effects:] [Constructs a new __unique_future__, and transfers ownership of the shared state associated with `other` and unwrapping the inner future (see `unwrap()`).]]
|
||||
|
||||
[[Postconditions:] [[unique_future_get_state_link `this->get_state()`] returns the value of `other->get_state()` prior to the
|
||||
@@ -756,6 +764,8 @@ prior to waiting.]]
|
||||
[[Returns:] [`true` if `*this` is associated with a shared state, `false`
|
||||
otherwise.]]
|
||||
|
||||
[[Remarks:] [The result of this function is not stable and that the future could become invalid even if the function returned true or vice-versa.]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
@@ -771,6 +781,8 @@ otherwise.]]
|
||||
[[Returns:] [`true` if `*this` is associated with a shared state and that result is ready for retrieval, `false`
|
||||
otherwise.]]
|
||||
|
||||
[[Remarks:] [The result of this function is not stable and that the future could become not ready even if the function returned true or vice-versa.]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
@@ -786,6 +798,8 @@ otherwise.]]
|
||||
[[Returns:] [`true` if `*this` is associated with a shared state, that result is ready for retrieval, and the result is a
|
||||
stored value, `false` otherwise.]]
|
||||
|
||||
[[Remarks:] [The result of this function is not stable and the future could lost its value even if the function returned true or vice-versa.]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
@@ -801,6 +815,8 @@ stored value, `false` otherwise.]]
|
||||
[[Returns:] [`true` if `*this` is associated with a shared state, that result is ready for retrieval, and the result is a
|
||||
stored exception, `false` otherwise.]]
|
||||
|
||||
[[Remarks:] [The result of this function is not stable and the future could lost its exception even if the function returned true or vice-versa.]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
@@ -818,6 +834,8 @@ entry, and the result has a ['wait callback] set, that callback is invoked prior
|
||||
|
||||
[[Returns:] [a exception_ptr, storring or not an exception.]]
|
||||
|
||||
[[Remarks:] [The result of this function is not stable and the future could lost its exception even if the function returned a valid `exception_ptr` or vice-versa.]]
|
||||
|
||||
[[Throws:] [Whatever `mutex::lock()/mutex::unlock()` can throw.]]
|
||||
|
||||
]
|
||||
@@ -835,6 +853,8 @@ entry, and the result has a ['wait callback] set, that callback is invoked prior
|
||||
[[Returns:] [__uninitialized__ if `*this` is not associated with a shared state. __ready__ if the shared state
|
||||
associated with `*this` is ready for retrieval, __waiting__ otherwise.]]
|
||||
|
||||
[[Remarks:] [The result of this function is not stable.]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
@@ -860,13 +880,13 @@ associated with `*this` is ready for retrieval, __waiting__ otherwise.]]
|
||||
[section:then Member function `then()` - EXTENSION]
|
||||
|
||||
template<typename F>
|
||||
__unique_future__<typename boost::result_of<F(__unique_future__&)>::type>
|
||||
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
|
||||
then(F&& func); // EXTENSION
|
||||
template<typename S, typename F>
|
||||
__unique_future__<typename boost::result_of<F(__unique_future__&)>::type>
|
||||
then(S& scheduler, F&& func); // EXTENSION NOT_YET_IMPLEMENTED
|
||||
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
|
||||
then(S& scheduler, F&& func); // EXTENSION
|
||||
template<typename F>
|
||||
__unique_future__<typename boost::result_of<F(__unique_future__&)>::type>
|
||||
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
|
||||
then(launch policy, F&& func); // EXTENSION
|
||||
|
||||
[warning These functions are experimental and subject to change in future versions.
|
||||
@@ -883,6 +903,8 @@ second parameter.]]
|
||||
|
||||
[[Effects:] [
|
||||
|
||||
All the functions create a shared state that is associated with the returned future object. The further behavior of the functions is as follows.
|
||||
|
||||
- The continuation is called when the object's shared state is ready (has a value or exception stored).
|
||||
|
||||
- The continuation launches according to the specified policy or scheduler.
|
||||
@@ -890,9 +912,11 @@ second parameter.]]
|
||||
- When the scheduler or launch policy is not provided the continuation inherits the
|
||||
parent's launch policy or scheduler.
|
||||
|
||||
- If the parent was created with `promise<<` or with a `packaged_task<>` (has no associated launch policy), the
|
||||
- Any value returned from the continuation is stored as the result in the shared state of the resulting `future`. Any exception propagated from the execution of the continuation is stored as the exceptional result in the shared state of the resulting `future`.
|
||||
|
||||
- If the parent was created with `promise<>` or with a `packaged_task<>` (has no associated launch policy), the
|
||||
continuation behaves the same as the third overload with a policy argument of `launch::async | launch::deferred` and
|
||||
the same argument for func.
|
||||
the same argument for `func`.
|
||||
|
||||
- If the parent has a policy of `launch::deferred` and the continuation does not have a specified launch policy or
|
||||
scheduler, then the parent is filled by immediately calling `.wait()`, and the policy of the antecedent is
|
||||
@@ -902,11 +926,20 @@ scheduler, then the parent is filled by immediately calling `.wait()`, and the p
|
||||
|
||||
[[Returns:] [An object of type `__unique_future__<typename boost::result_of<F(__unique_future__)>` that refers to the shared state created by the continuation.]]
|
||||
|
||||
[[Notes:] [
|
||||
|
||||
- Note that nested futures are not implicitly unwrapped yet. This could be subject to change in future versions.
|
||||
|
||||
- The returned futures behave as the ones returned from boost::async, the destructor of the future object returned from then will block. This could be subject to change in future versions.
|
||||
]]
|
||||
|
||||
[[Postconditions:] [
|
||||
|
||||
- The `__unique_future__` object passed to the parameter of the continuation function is a copy of the original `__unique_future__`.
|
||||
|
||||
- `valid() == false` on original future object immediately after it returns.
|
||||
- `valid() == false` on original future; `valid() == true` on the `future` returned from then.
|
||||
|
||||
[/ In case of implicit unwrapping, the validity of the `future` returned from `then` cannot be established until after the completion of the functor passed into `then`. In such case, the resulting `future` becomes ready with an exception of type `future_error`, with an error code of `future_errc::broken_promise`. ]
|
||||
|
||||
]]
|
||||
|
||||
@@ -928,19 +961,19 @@ There are not too much tests yet, so it is possible that you can find out some t
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Notes:] [Removes the outermost future and returns a future with the associated state been a proxy of inner future.]]
|
||||
[[Notes:] [Removes the outermost future and returns a future with the associated state been a proxy of the outer future.]]
|
||||
|
||||
[[Effects:] [
|
||||
|
||||
- Returns a future that becomes ready when the shared state of the inner future is ready.
|
||||
- Returns a future that becomes ready when the shared state of the outer and inner future is ready. The validity of the future returned from `get()` applied on the outer future cannot be established a priori. If it is not valid, this future is forced to be valid and becomes ready with an exception of type `future_error`, with an error code of `future_errc::broken_promise`.
|
||||
|
||||
]]
|
||||
|
||||
[[Returns:] [An object of type future with the associated state been a proxy of inner future.]]
|
||||
[[Returns:] [An object of type future with the associated state been a proxy of outer future.]]
|
||||
|
||||
[[Postconditions:] [
|
||||
|
||||
- The returned future has `valid() == true` regardless of the validity of the inner future.
|
||||
- The returned future has `valid() == true`.
|
||||
|
||||
]]
|
||||
|
||||
@@ -975,14 +1008,14 @@ There are not too much tests yet, so it is possible that you can find out some t
|
||||
|
||||
// factories
|
||||
template<typename F>
|
||||
__unique_future__<typename boost::result_of<F(shared_future&)>::type>
|
||||
then(F&& func); // EXTENSION
|
||||
__unique_future__<typename boost::result_of<F(shared_future)>::type>
|
||||
then(F&& func) const; // EXTENSION
|
||||
template<typename S, typename F>
|
||||
__unique_future__<typename boost::result_of<F(shared_future&)>::type>
|
||||
then(S& scheduler, F&& func); // EXTENSION NOT_YET_IMPLEMENTED
|
||||
__unique_future__<typename boost::result_of<F(shared_future)>::type>
|
||||
then(S& scheduler, F&& func) const; // EXTENSION
|
||||
template<typename F>
|
||||
__unique_future__<typename boost::result_of<F(shared_future&)>::type>
|
||||
then(launch policy, F&& func); // EXTENSION
|
||||
__unique_future__<typename boost::result_of<F(shared_future)>::type>
|
||||
then(launch policy, F&& func) const; // EXTENSION
|
||||
|
||||
void swap(shared_future& other);
|
||||
|
||||
@@ -1324,14 +1357,14 @@ associated with `*this` is ready for retrieval, __waiting__ otherwise.]]
|
||||
[section:then Member function `then()` EXTENSION]
|
||||
|
||||
template<typename F>
|
||||
__unique_future__<typename boost::result_of<F(shared_future&)>::type>
|
||||
then(F&& func); // EXTENSION
|
||||
__unique_future__<typename boost::result_of<F(shared_future)>::type>
|
||||
then(F&& func) const; // EXTENSION
|
||||
template<typename S, typename F>
|
||||
__unique_future__<typename boost::result_of<F(shared_future&)>::type>
|
||||
then(S& scheduler, F&& func); // EXTENSION NOT_YET_IMPLEMENTED
|
||||
__unique_future__<typename boost::result_of<F(shared_future)>::type>
|
||||
then(S& scheduler, F&& func) const; // EXTENSION
|
||||
template<typename F>
|
||||
__unique_future__<typename boost::result_of<F(shared_future&)>::type>
|
||||
then(launch policy, F&& func); // EXTENSION
|
||||
__unique_future__<typename boost::result_of<F(shared_future)>::type>
|
||||
then(launch policy, F&& func) const; // EXTENSION
|
||||
|
||||
|
||||
[warning These functions are experimental and subject to change in future versions.
|
||||
@@ -1367,11 +1400,22 @@ scheduler, then the parent is filled by immediately calling `.wait()`, and the p
|
||||
|
||||
[[Returns:] [An object of type `__unique_future__<typename boost::result_of<F(shared_future)>` that refers to the shared state created by the continuation.]]
|
||||
|
||||
|
||||
[[Notes:] [
|
||||
|
||||
- Note that nested futures are not implicitly unwrapped yet. This could be subject to change in future versions.
|
||||
|
||||
- The returned futures behave as the ones returned from boost::async, the destructor of the future object returned from then will block. This could be subject to change in future versions.
|
||||
]]
|
||||
|
||||
|
||||
[[Postconditions:] [
|
||||
|
||||
- The future object is moved to the parameter of the continuation function .
|
||||
|
||||
- `valid() == false` on original future object immediately after it returns.
|
||||
- `valid() == true` on original `shared_future`; `valid() == true` on the `future` returned from then.
|
||||
|
||||
[/- In case of implicit unwrapping, the validity of the `future` returned from `then` cannot be established until after the completion of the functor passed into `then`. In such case, the resulting `future` becomes ready with an exception of type `future_error`, with an error code of `future_errc::broken_promise`. ]
|
||||
|
||||
]]
|
||||
|
||||
@@ -1927,19 +1971,17 @@ __packaged_task__.]]
|
||||
The function template async provides a mechanism to launch a function potentially in a new thread and
|
||||
provides the result of the function in a future object with which it shares a shared state.
|
||||
|
||||
[warning `async(launch::deferred, F)` is NOT YET IMPLEMENTED!]
|
||||
|
||||
[heading Non-Variadic variant]
|
||||
|
||||
template <class F>
|
||||
__unique_future__<typename result_of<typename decay<F>::type()>::type>
|
||||
async(F&& f);
|
||||
__unique_future__<typename result_of<typename decay<F>::type()>::type>
|
||||
async(F&& f);
|
||||
template <class F>
|
||||
__unique_future__<typename result_of<typename decay<F>::type()>::type>
|
||||
async(launch policy, F&& f);
|
||||
__unique_future__<typename result_of<typename decay<F>::type()>::type>
|
||||
async(launch policy, F&& f);
|
||||
template <class Executor, class F>
|
||||
__unique_future__<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
|
||||
async(Executor &ex, F&& f, Args&&... args);
|
||||
__unique_future__<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
|
||||
async(Executor &ex, F&& f, Args&&... args);
|
||||
[variablelist
|
||||
|
||||
[[Requires:] [
|
||||
@@ -1955,7 +1997,7 @@ shall be a valid expression.
|
||||
The first function behaves the same as a call to the second function with a policy argument of
|
||||
`launch::async | launch::deferred` and the same arguments for `F`.
|
||||
|
||||
The second function creates a shared state that is associated with the returned future object.
|
||||
The second and third functions create a shared state that is associated with the returned future object.
|
||||
|
||||
The further behavior of the second function depends on the policy argument as follows (if more than one of these conditions applies, the implementation may choose any of the corresponding policies):
|
||||
|
||||
@@ -1963,7 +2005,14 @@ The further behavior of the second function depends on the policy argument as fo
|
||||
|
||||
- if `policy & launch::deferred` is non-zero - Stores `decay_copy(boost::forward<F>(f))` in the shared state. This copy of `f` constitute a deferred function. Invocation of the deferred function evaluates `boost::move(g)()` where `g` is the stored value of `decay_copy(boost::forward<F>(f))`. The shared state is not made ready until the function has completed. The first call to a non-timed waiting function on an asynchronous return object referring to this shared state shall invoke the deferred function in the thread that called the waiting function. Once evaluation of `boost::move(g)()` begins, the function is no longer considered deferred. (Note: If this policy is specified together with other policies, such as when using a policy value of `launch::async | launch::deferred`, implementations should defer invocation or the selection of the policy when no more concurrency can be effectively exploited.)
|
||||
|
||||
- if no valid launch policy is provided the behaviour is undefined.
|
||||
- if no valid launch policy is provided the behavior is undefined.
|
||||
|
||||
|
||||
The further behavior of the third function is as follows:
|
||||
|
||||
- The Executor::submit() function is given a function<void ()> which calls `INVOKE (DECAY_COPY
|
||||
(std::forward<F>(f)), DECAY_COPY (std::forward<Args>(args))...). The implementation of the executor
|
||||
is decided by the programmer.
|
||||
|
||||
]]
|
||||
|
||||
@@ -1991,22 +2040,22 @@ If the implementation chooses the `launch::async` policy,
|
||||
|
||||
]]
|
||||
|
||||
[[Remarks:] [The first signature shall not participate in overload resolution if decay<F>::type is boost::launch.
|
||||
]]
|
||||
[[Remarks::] [The first signature shall not participate in overload resolution if `decay_t<F> is `boost::
|
||||
launch` or `boost::is_executor<F>` is `true_type`.]]
|
||||
|
||||
]
|
||||
|
||||
[heading Variadic variant]
|
||||
|
||||
template <class F, class... Args>
|
||||
__unique_future__<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
|
||||
async(F&& f, Args&&... args);
|
||||
__unique_future__<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
|
||||
async(F&& f, Args&&... args);
|
||||
template <class F, class... Args>
|
||||
__unique_future__<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
|
||||
async(launch policy, F&& f, Args&&... args);
|
||||
__unique_future__<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
|
||||
async(launch policy, F&& f, Args&&... args);
|
||||
template <class Executor, class F, class... Args>
|
||||
__unique_future__<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
|
||||
async(Executor &ex, F&& f, Args&&... args);
|
||||
__unique_future__<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>
|
||||
async(Executor &ex, F&& f, Args&&... args);
|
||||
|
||||
[warning the variadic prototype is provided only on C++11 compilers supporting rvalue references, variadic templates, decltype and a standard library providing <tuple> (waiting for a boost::tuple that is move aware), and BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK is defined.]
|
||||
|
||||
@@ -2087,19 +2136,19 @@ with the return from the last function that releases the shared state, whichever
|
||||
[section:wait_for_any Non-member function `wait_for_any()` - EXTENSION]
|
||||
|
||||
template<typename Iterator>
|
||||
Iterator wait_for_any(Iterator begin,Iterator end); // EXTENSION
|
||||
Iterator wait_for_any(Iterator begin,Iterator end); // EXTENSION
|
||||
|
||||
template<typename F1,typename F2>
|
||||
unsigned wait_for_any(F1& f1,F2& f2); // EXTENSION
|
||||
unsigned wait_for_any(F1& f1,F2& f2); // EXTENSION
|
||||
|
||||
template<typename F1,typename F2,typename F3>
|
||||
unsigned wait_for_any(F1& f1,F2& f2,F3& f3); // EXTENSION
|
||||
unsigned wait_for_any(F1& f1,F2& f2,F3& f3); // EXTENSION
|
||||
|
||||
template<typename F1,typename F2,typename F3,typename F4>
|
||||
unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4); // EXTENSION
|
||||
unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4); // EXTENSION
|
||||
|
||||
template<typename F1,typename F2,typename F3,typename F4,typename F5>
|
||||
unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5); // EXTENSION
|
||||
unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5); // EXTENSION
|
||||
|
||||
[variablelist
|
||||
|
||||
@@ -2127,19 +2176,19 @@ with any of the futures being waited for. `std::bad_alloc` if memory could not
|
||||
[section:wait_for_all Non-member function `wait_for_all()` - EXTENSION]
|
||||
|
||||
template<typename Iterator>
|
||||
void wait_for_all(Iterator begin,Iterator end); // EXTENSION
|
||||
void wait_for_all(Iterator begin,Iterator end); // EXTENSION
|
||||
|
||||
template<typename F1,typename F2>
|
||||
void wait_for_all(F1& f1,F2& f2); // EXTENSION
|
||||
void wait_for_all(F1& f1,F2& f2); // EXTENSION
|
||||
|
||||
template<typename F1,typename F2,typename F3>
|
||||
void wait_for_all(F1& f1,F2& f2,F3& f3); // EXTENSION
|
||||
void wait_for_all(F1& f1,F2& f2,F3& f3); // EXTENSION
|
||||
|
||||
template<typename F1,typename F2,typename F3,typename F4>
|
||||
void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4); // EXTENSION
|
||||
void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4); // EXTENSION
|
||||
|
||||
template<typename F1,typename F2,typename F3,typename F4,typename F5>
|
||||
void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5); // EXTENSION
|
||||
void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5); // EXTENSION
|
||||
|
||||
[variablelist
|
||||
|
||||
@@ -2158,16 +2207,167 @@ __unique_future__ or __shared_future__.]]
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
[/////////////////////////////////////////////////////////////////////]
|
||||
[section:when_all Non-member function `when_all()` - EXTENSION]
|
||||
|
||||
|
||||
template <class InputIterator>
|
||||
future<std::vector<typename InputIterator::value_type::value_type>>
|
||||
when_all(InputIterator first, InputIterator last);
|
||||
|
||||
template <typename... FutTypes>
|
||||
future<std::tuple<decay_t<FutTypes>...> when_all(FutTypes&&... futures);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Requires:] [
|
||||
|
||||
- For the first overload, `InputIterator`'s value type shall be convertible to `future<R>` or `shared_future<R>`.
|
||||
All `R` types must be the same. If any of the `future<R>` or `shared_future<R>` objects are in invalid state (i.e. `valid() == false`), the behavior is undefined.
|
||||
- For the second overload, `FutTypes` is of type `future<R>` or `shared_future<R>`. The effect of calling `when_all` on a `future` or a `shared_future` object for which `valid() == false` is undefined.
|
||||
|
||||
]]
|
||||
|
||||
[[Notes:] [
|
||||
|
||||
- There are two variations of `when_all`. The first version takes a pair of `InputIterators`. The second takes any arbitrary number of `future<R0>` and `shared_future<R1>` objects, where `R0` and `R1` need not be the same type.
|
||||
|
||||
- Calling the first signature of `when_all` where `InputIterator` first equals last, returns a future with an empty `vector` that is immediately ready.
|
||||
|
||||
- Calling the second signature of `when_all` with no arguments returns a future<tuple<>> that is immediately ready.
|
||||
|
||||
]]
|
||||
|
||||
[[Effects:] [
|
||||
|
||||
- If any of the futures supplied to a call to `when_all` refer to deferred tasks that have not started execution, those tasks are executed before the call to `when_all` returns. Once all such tasks have been executed, the call to `when_all` returns immediately.
|
||||
|
||||
- The call to `when_all` does not wait for non-deferred tasks, or deferred tasks that have already started executing elsewhere, to complete before returning.
|
||||
|
||||
- Once all the `future`s/`shared_future`s supplied to the call to `when_all` are ready, the `future`s/`shared_future`s are moved/copied into the associated state of the future returned from the call to `when_all`, preserving the order of the futures supplied to `when_all`.
|
||||
|
||||
- The collection is then stored as the result in a newly created shared state.
|
||||
|
||||
- A new future object that refers to the shared state is created. The exact type of the future is further described below.
|
||||
|
||||
- The `future` returned by `when_all` will not throw an exception when calling `wait()` or `get()`, but the futures held in the output collection may.
|
||||
]]
|
||||
|
||||
[[Returns:] [
|
||||
|
||||
- `future<tuple<>>` if `when_all` is called with zero arguments.
|
||||
|
||||
- `future<vector<future<R>>>` if the input cardinality is unknown at compile and the iterator pair yields `future<R>`. The order of the futures in the output vector will be the same as given by the input iterator.
|
||||
|
||||
- `future<vector<shared_future<R>>>` if the input cardinality is unknown at compile time and the iterator pair yields `shared_future<R>`. The order of the futures in the output vector will be the same as given by the input iterator.
|
||||
|
||||
- `future<tuple<decay_t<FutTypes>...>>` if inputs are fixed in number.
|
||||
|
||||
]]
|
||||
|
||||
[[Postconditions:] [
|
||||
|
||||
- All input futures valid() == false.
|
||||
|
||||
- All input shared future valid() == true.
|
||||
|
||||
- valid() == true.
|
||||
|
||||
]]
|
||||
|
||||
]
|
||||
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////////////////////////////////////]
|
||||
[section:when_any Non-member function `when_any()` - EXTENSION]
|
||||
|
||||
|
||||
template <class InputIterator>
|
||||
future<std::vector<typename InputIterator::value_type::value_type>>
|
||||
when_any(InputIterator first, InputIterator last);
|
||||
|
||||
template <typename... FutTypes>
|
||||
future<std::tuple<decay_t<FutTypes>...>
|
||||
when_any(FutTypes&&... futures);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Requires:] [
|
||||
|
||||
|
||||
|
||||
- For the first overload, `InputIterator`'s value type shall be convertible to `future<R>` or `shared_future<R>`. All `R` types must be the same. If any of the `future<R>` or `shared_future<R>` objects are in invalid state (i.e. `valid() == false`), the behavior is undefined.
|
||||
- For the second overload, `FutTypes` is of type `future<R>` or `shared_future<R>`. The effect of calling `when_any` on a `future` or a `shared_future` object for which `valid() == false is undefined`.
|
||||
|
||||
]]
|
||||
|
||||
[[Notes:] [
|
||||
|
||||
- There are two variations of `when_any `. The first version takes a pair of `InputIterators`. The second takes any arbitrary number of `future<R0>` and `shared_future<R1>` objects, where `R0` and `R1` need not be the same type.
|
||||
|
||||
- Calling the first signature of `when_any ` where `InputIterator` first equals last, returns a future with an empty `vector` that is immediately ready.
|
||||
|
||||
- Calling the second signature of `when_any` with no arguments returns a future<tuple<>> that is immediately ready.
|
||||
|
||||
]]
|
||||
|
||||
[[Effects:] [
|
||||
|
||||
- Each of the futures supplied to `when_any` is checked in the order supplied. If a given future is ready, then no further futures are checked, and the call to `when_any` returns immediately. If a given future refers to a deferred task that has not yet started execution, then no further futures are checked, that task is executed, and the call to `when_any` then returns immediately.
|
||||
|
||||
- The call to `when_any` does not wait for non-deferred tasks, or deferred tasks that have already started executing elsewhere, to complete before returning.
|
||||
|
||||
- Once at least one of the futures supplied to the call to `when_any` are ready, the futures are moved into the associated state of the future returned from the call to `when_any`, preserving the order of the futures supplied to `when_any`. That future is then ready.
|
||||
|
||||
- The collection is then stored as the result in a newly created shared state.
|
||||
|
||||
- A new future object that refers to the shared state is created. The exact type of the future is further described below.
|
||||
|
||||
- The future returned by `when_any` will not throw an exception when calling `wait()` or `get()`, but the futures held in the output collection may.
|
||||
|
||||
]]
|
||||
|
||||
[[Returns:] [
|
||||
|
||||
- `future<tuple<>>` if `when_any ` is called with zero arguments.
|
||||
|
||||
- `future<vector<future<R>>>` if the input cardinality is unknown at compile and the iterator pair yields `future<R>`. The order of the futures in the output vector will be the same as given by the input iterator.
|
||||
|
||||
- `future<vector<shared_future<R>>>` if the input cardinality is unknown at compile time and the iterator pair yields `shared_future<R>`. The order of the futures in the output vector will be the same as given by the input iterator.
|
||||
|
||||
- `future<tuple<decat_t<FutTypes>...>>` if inputs are fixed in number.
|
||||
|
||||
]]
|
||||
|
||||
[[Postconditions:] [
|
||||
|
||||
- All input futures valid() == false.
|
||||
|
||||
- All input shared_futures valid() == true.
|
||||
|
||||
- valid() == true.
|
||||
|
||||
|
||||
]]
|
||||
|
||||
]
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[/////////////////////////////////////////////////////////////////////////////]
|
||||
[section:make_ready_future Non-member function `make_ready_future()` EXTENSION]
|
||||
|
||||
template <typename T>
|
||||
future<typename decay<T>::type> make_ready_future(T&& value); // EXTENSION
|
||||
future<typename decay<T>::type> make_ready_future(T&& value); // EXTENSION
|
||||
future<void> make_ready_future(); // EXTENSION
|
||||
template <typename T>
|
||||
future<T> make_ready_future(exception_ptr ex); // DEPRECATED
|
||||
future<T> make_ready_future(exception_ptr ex); // DEPRECATED
|
||||
template <typename T, typename E>
|
||||
future<T> make_ready_future(E ex); // DEPRECATED
|
||||
future<T> make_ready_future(E ex); // DEPRECATED
|
||||
|
||||
[variablelist
|
||||
|
||||
@@ -2207,7 +2407,7 @@ Otherwise the value is copied to the shared state of the returned function.
|
||||
|
||||
exceptional_ptr make_exceptional(exception_ptr ex); // EXTENSION
|
||||
template <typename E>
|
||||
exceptional_ptr make_exceptional(E ex); // EXTENSION
|
||||
exceptional_ptr make_exceptional(E ex); // EXTENSION
|
||||
exceptional_ptr make_exceptional(); // EXTENSION
|
||||
|
||||
[variablelist
|
||||
@@ -2228,7 +2428,7 @@ An exceptional_ptr instance implicitly convertible to a future<T>
|
||||
[section:make_future Non-member function `make_future()` DEPRECATED]
|
||||
|
||||
template <typename T>
|
||||
future<typename decay<T>::type> make_future(T&& value); // DEPRECATED
|
||||
future<typename decay<T>::type> make_future(T&& value); // DEPRECATED
|
||||
future<void> make_future(); // DEPRECATED
|
||||
|
||||
|
||||
@@ -2264,7 +2464,7 @@ Otherwise the value is copied to the shared state of the returned function.
|
||||
[section:make_shared_future Non-member function `make_shared_future()` DEPRECATED]
|
||||
|
||||
template <typename T>
|
||||
shared_future<typename decay<T>::type> make_shared_future(T&& value); // DEPRECATED
|
||||
shared_future<typename decay<T>::type> make_shared_future(T&& value); // DEPRECATED
|
||||
shared_future<void> make_shared_future(); // DEPRECATED
|
||||
|
||||
[variablelist
|
||||
|
||||
@@ -229,12 +229,12 @@ where
|
||||
[endsect]
|
||||
|
||||
[/////////////////////////////////////]
|
||||
[section:non_waaiting Non-waiting Concurrent Queue Operations]
|
||||
[section:non_waiting Non-waiting Concurrent Queue Operations]
|
||||
|
||||
The ConcurrentQueue concept models a queue with .
|
||||
The ConcurrentQueue concept models a queue with Non-waiting operations.
|
||||
|
||||
|
||||
A type `Q` meets the ConcurrentQueue requirements if the following expressions are well-formed and have the specified semantics
|
||||
A type `Q` meets the ConcurrentQueue requirements if is a model of a BasicConcurrentQueue and the following expressions are well-formed and have the specified semantics
|
||||
|
||||
* `s = q.try_push_back(e);`
|
||||
* `s = q.try_push_back(rve);`
|
||||
@@ -281,7 +281,7 @@ where
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:try_push_back_m `s = q.try_push_back(rve());`]
|
||||
[section:try_push_back_m `s = q.try_push_back(rve);`]
|
||||
|
||||
[variablelist
|
||||
|
||||
@@ -345,7 +345,7 @@ For cases when blocking for mutual exclusion is undesirable, we have non-blockin
|
||||
The interface is the same as the try operations but is allowed to also return queue_op_status::busy
|
||||
in case the operation is unable to complete without blocking.
|
||||
|
||||
Non-blocking operations are provided only for BlockingQueues
|
||||
Non-blocking operations are provided only for lock based queues
|
||||
|
||||
* `s = q.nonblocking_push_back(nb, e);`
|
||||
* `s = q.nonblocking_push_back(nb, rve);`
|
||||
@@ -616,6 +616,226 @@ Closed queues add the following valid expressions
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
||||
|
||||
[/////////////////////////////////////]
|
||||
[section:queue_op_status Queue Operation Status]
|
||||
|
||||
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
enum class queue_op_status { success = 0, empty, full, closed, busy }
|
||||
}
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:queue_base Queue Base]
|
||||
|
||||
#include <boost/thread/concurrent_queues/queue_base.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template <typename ValueType>
|
||||
class queue_base
|
||||
{
|
||||
public:
|
||||
typedef ValueType value_type;
|
||||
typedef std::size_t size_type;
|
||||
|
||||
// Constructors/Assignment/Destructors
|
||||
virtual ~queue_base() {};
|
||||
|
||||
// Observers
|
||||
virtual bool empty() const = 0;
|
||||
virtual bool full() const = 0;
|
||||
virtual size_type size() const = 0;
|
||||
virtual bool closed() const = 0;
|
||||
|
||||
// Modifiers
|
||||
virtual void close() = 0;
|
||||
|
||||
virtual void push_back(const value_type& x) = 0;
|
||||
virtual void push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
||||
|
||||
virtual void pull_front(value_type&) = 0;
|
||||
virtual value_type pull_front() = 0;
|
||||
|
||||
virtual queue_op_status try_push_back(const value_type& x) = 0;
|
||||
virtual queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
||||
virtual queue_op_status try_pull_front(value_type&) = 0;
|
||||
|
||||
virtual queue_op_status nonblocking_push_back(const value_type& x) = 0;
|
||||
virtual queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
||||
virtual queue_op_status nonblocking_pull_front(value_type&) = 0;
|
||||
|
||||
virtual queue_op_status wait_push_back(const value_type& x) = 0;
|
||||
virtual queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
||||
virtual queue_op_status wait_pull_front(ValueType& elem) = 0;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:queue_adaptor Queue Adaptor]
|
||||
|
||||
#include <boost/thread/concurrent_queues/queue_adaptor.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template <typename Queue>
|
||||
class queue_adaptor : public queue_base<typename Queue::value_type>
|
||||
{
|
||||
public:
|
||||
typedef typename Queue::value_type value_type;
|
||||
typedef std::size_t size_type;
|
||||
|
||||
// Constructors/Assignment/Destructors
|
||||
|
||||
queue_adaptor();
|
||||
|
||||
// Observers
|
||||
bool empty() const;
|
||||
bool full() const;
|
||||
size_type size() const { return queue.size(); }
|
||||
bool closed() const;
|
||||
|
||||
// Modifiers
|
||||
void close();
|
||||
|
||||
void push_back(const value_type& x);
|
||||
void push_back(BOOST_THREAD_RV_REF(value_type) x);
|
||||
|
||||
void pull_front(value_type& x);
|
||||
value_type pull_front();
|
||||
|
||||
queue_op_status try_push_back(const value_type& x);
|
||||
queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x);
|
||||
queue_op_status try_pull_front(value_type& x);
|
||||
|
||||
queue_op_status nonblocking_push_back(const value_type& x);
|
||||
queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x);
|
||||
queue_op_status nonblocking_pull_front(value_type& x);
|
||||
|
||||
queue_op_status wait_push_back(const value_type& x);
|
||||
queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x);
|
||||
queue_op_status wait_pull_front(value_type& x);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:queue_views Queue Views]
|
||||
|
||||
#include <boost/thread/concurrent_queues/queue_views.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template <typename Queue>
|
||||
class queue_back_view;
|
||||
template <typename Queue>
|
||||
class queue_front_view
|
||||
|
||||
template <class T>
|
||||
using queue_back = queue_back_view<queue_base<T>>;
|
||||
template <class T>
|
||||
using queue_front = queue_front_view<queue_base<T>>;
|
||||
}
|
||||
|
||||
[/////////////////////////////////////]
|
||||
[section:queue_back_view Class template `queue_back_view<>`]
|
||||
|
||||
template <typename Queue>
|
||||
class queue_back_view
|
||||
{
|
||||
public:
|
||||
typedef typename Queue::value_type value_type;
|
||||
typedef typename Queue::size_type size_type;
|
||||
|
||||
// Constructors/Assignment/Destructors
|
||||
queue_back_view(Queue& q) noexcept;
|
||||
|
||||
// Observers
|
||||
bool empty() const;
|
||||
bool full() const;
|
||||
size_type size() const;
|
||||
bool closed() const;
|
||||
|
||||
// Modifiers
|
||||
void close();
|
||||
|
||||
void push(const value_type& x);
|
||||
void push(BOOST_THREAD_RV_REF(value_type) x);
|
||||
|
||||
void pull(value_type& x);
|
||||
value_type pull();
|
||||
|
||||
queue_op_status try_push(const value_type& x);
|
||||
queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x);
|
||||
|
||||
queue_op_status try_pull(value_type& x);
|
||||
|
||||
queue_op_status nonblocking_push(const value_type& x);
|
||||
queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x);
|
||||
|
||||
queue_op_status nonblocking_pull(value_type& x);
|
||||
|
||||
queue_op_status wait_push(const value_type& x);
|
||||
queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x);
|
||||
queue_op_status wait_pull_front(value_type& x);
|
||||
|
||||
};
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:queue_front_view Class template `queue_front_view<>`]
|
||||
|
||||
|
||||
template <typename Queue>
|
||||
class queue_front_view
|
||||
{
|
||||
public:
|
||||
typedef typename Queue::value_type value_type;
|
||||
typedef typename Queue::size_type size_type;
|
||||
|
||||
// Constructors/Assignment/Destructors
|
||||
queue_front_view(Queue& q) BOOST_NOEXCEPT;
|
||||
|
||||
// Observers
|
||||
bool empty() const;
|
||||
bool full() const;
|
||||
size_type size() const;
|
||||
bool closed() const;
|
||||
|
||||
// Modifiers
|
||||
void close();
|
||||
|
||||
void push(const value_type& x);
|
||||
void push(BOOST_THREAD_RV_REF(value_type) x);
|
||||
|
||||
void pull(value_type& x);
|
||||
value_type pull();
|
||||
|
||||
queue_op_status try_push(const value_type& x);
|
||||
queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x);
|
||||
|
||||
queue_op_status try_pull(value_type& x);
|
||||
|
||||
queue_op_status nonblocking_push(const value_type& x);
|
||||
queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x);
|
||||
|
||||
queue_op_status nonblocking_pull(value_type& x);
|
||||
|
||||
queue_op_status wait_push(const value_type& x);
|
||||
queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x);
|
||||
queue_op_status wait_pull(value_type& x);
|
||||
|
||||
};
|
||||
|
||||
|
||||
[endsect]
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:sync_bounded_queue_ref Synchronized Bounded Queue]
|
||||
@@ -830,7 +1050,7 @@ Closed queues add the following valid expressions
|
||||
|
||||
|
||||
[/////////////////////////////////////]
|
||||
[section:constructor Constructor `sync_bounded_queue(size_type)`]
|
||||
[section:constructor Constructor `sync_queue(size_type)`]
|
||||
|
||||
explicit sync_queue();
|
||||
|
||||
@@ -843,21 +1063,6 @@ Closed queues add the following valid expressions
|
||||
]
|
||||
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:constructort Template Constructor `sync_bounded_queue(size_type, Range)`]
|
||||
|
||||
template <typename Range>
|
||||
sync_bounded_queue(size_type max_elems, Range range);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Constructs an sync_queue with all the elements of the range. ]]
|
||||
|
||||
[[Throws:] [any exception that can be throw because of resources unavailable. ]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:full Member Function `full()`]
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
[library Thread
|
||||
[quickbook 1.5]
|
||||
[version 4.3.0]
|
||||
[version 4.4.0]
|
||||
[authors [Williams, Anthony] [Botet Escriba, Vicente J.]]
|
||||
[copyright 2007-11 Anthony Williams]
|
||||
[copyright 2011-14 Vicente J. Botet Escriba]
|
||||
|
||||
@@ -26,7 +26,13 @@
|
||||
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
|
||||
template <class Rep, class Period>
|
||||
void sleep_for(const chrono::duration<Rep, Period>& rel_time);
|
||||
|
||||
namespace no_interruption_point // EXTENSION
|
||||
{
|
||||
template <class Clock, class Duration>
|
||||
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
|
||||
template <class Rep, class Period>
|
||||
void sleep_for(const chrono::duration<Rep, Period>& rel_time);
|
||||
}
|
||||
template<typename Callable>
|
||||
void at_thread_exit(Callable func); // EXTENSION
|
||||
|
||||
@@ -752,7 +758,7 @@ corresponding successful `join()` return. ]]
|
||||
|
||||
[*resource_deadlock_would_occur]: if deadlock is detected or `this->get_id() == boost::this_thread::get_id()`.
|
||||
|
||||
[*invalid_argument]: if the thread is not joinable and `BOOST_THREAD_TRHOW_IF_PRECONDITION_NOT_SATISFIED` is defined.
|
||||
[*invalid_argument]: if the thread is not joinable and `BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED` is defined.
|
||||
|
||||
|
||||
[/
|
||||
@@ -801,7 +807,7 @@ unchanged.]]
|
||||
|
||||
[*resource_deadlock_would_occur]: if deadlock is detected or this->get_id() == boost::this_thread::get_id().
|
||||
|
||||
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_TRHOW_IF_PRECONDITION_NOT_SATISFIED is defined.
|
||||
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is defined.
|
||||
|
||||
|
||||
[/
|
||||
@@ -841,7 +847,7 @@ unchanged.]]
|
||||
|
||||
[*resource_deadlock_would_occur]: if deadlock is detected or this->get_id() == boost::this_thread::get_id().
|
||||
|
||||
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_TRHOW_IF_PRECONDITION_NOT_SATISFIED is defined.
|
||||
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is defined.
|
||||
|
||||
|
||||
[/
|
||||
@@ -881,7 +887,7 @@ unchanged.]]
|
||||
|
||||
[*resource_deadlock_would_occur]: if deadlock is detected or this->get_id() == boost::this_thread::get_id().
|
||||
|
||||
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_TRHOW_IF_PRECONDITION_NOT_SATISFIED is defined.
|
||||
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is defined.
|
||||
|
||||
|
||||
[/
|
||||
@@ -917,7 +923,7 @@ unchanged.]]
|
||||
|
||||
[*no_such_process]: if the thread is not valid.
|
||||
|
||||
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_TRHOW_IF_PRECONDITION_NOT_SATISFIED is defined.
|
||||
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is defined.
|
||||
|
||||
]]
|
||||
|
||||
@@ -1489,6 +1495,11 @@ specified by `rel_time` has elapsed or the time point specified by
|
||||
{
|
||||
template <class Clock, class Duration>
|
||||
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
|
||||
namespace no_interruption_point
|
||||
{
|
||||
template <class Clock, class Duration>
|
||||
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
|
||||
}
|
||||
}
|
||||
|
||||
[variablelist
|
||||
@@ -1500,6 +1511,7 @@ specified by `rel_time` has elapsed or the time point specified by
|
||||
do not throw exceptions. __thread_interrupted__ if the current thread of execution is interrupted. ]]
|
||||
|
||||
[[Notes:] [`sleep_until()` is one of the predefined __interruption_points__.]]
|
||||
[[Notes:] [`no_interruption_point::sleep_until()` is NOT one of the __interruption_points__.]]
|
||||
|
||||
]
|
||||
|
||||
@@ -1513,6 +1525,11 @@ do not throw exceptions. __thread_interrupted__ if the current thread of executi
|
||||
{
|
||||
template <class Rep, class Period>
|
||||
void sleep_for(const chrono::duration<Rep, Period>& rel_time);
|
||||
namespace no_interruption_point
|
||||
{
|
||||
template <class Rep, class Period>
|
||||
void sleep_for(const chrono::duration<Rep, Period>& rel_time);
|
||||
}
|
||||
}
|
||||
|
||||
[variablelist
|
||||
@@ -1523,6 +1540,7 @@ by `rel_time` has elapsed.]]
|
||||
[[Throws:] [Nothing if operations of chrono::duration<Rep, Period> do not throw exceptions. __thread_interrupted__ if the current thread of execution is interrupted.]]
|
||||
|
||||
[[Notes:] [`sleep_for()` is one of the predefined __interruption_points__.]]
|
||||
[[Notes:] [`no_interruption_point:: sleep_for()` is NOT one of the __interruption_points__.]]
|
||||
|
||||
]
|
||||
|
||||
|
||||
@@ -7,9 +7,6 @@
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
#ifndef BOOST_NO_CXX11_DECLTYPE_N3276
|
||||
#define BOOST_THREAD_NO_CXX11_DECLTYPE_N3276
|
||||
#endif
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
@@ -67,12 +64,13 @@ void submit_some(boost::executor& tp)
|
||||
|
||||
}
|
||||
|
||||
|
||||
void at_th_entry(boost::basic_thread_pool& )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
int test_executor_adaptor()
|
||||
{
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
{
|
||||
@@ -144,3 +142,9 @@ int main()
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
return test_executor_adaptor();
|
||||
}
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifndef BOOST_NO_CXX11_DECLTYPE_N3276
|
||||
#define BOOST_THREAD_NO_CXX11_DECLTYPE_N3276
|
||||
#endif
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
|
||||
@@ -4,11 +4,7 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifndef BOOST_NO_CXX11_DECLTYPE_N3276
|
||||
#define BOOST_THREAD_NO_CXX11_DECLTYPE_N3276
|
||||
#endif
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
//&& ! defined BOOST_NO_CXX11_DECLTYPE_N3276
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
|
||||
@@ -48,6 +44,7 @@ int p2(boost::future<int> f)
|
||||
BOOST_ASSERT(false);
|
||||
}
|
||||
BOOST_THREAD_LOG << "P2>" << BOOST_THREAD_END_LOG;
|
||||
return 0;
|
||||
}
|
||||
int p2s(boost::shared_future<int> f)
|
||||
{
|
||||
@@ -68,6 +65,7 @@ int p2s(boost::shared_future<int> f)
|
||||
BOOST_ASSERT(false);
|
||||
}
|
||||
BOOST_THREAD_LOG << "P2S>" << BOOST_THREAD_END_LOG;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main()
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifndef BOOST_NO_CXX11_DECLTYPE_N3276
|
||||
#define BOOST_THREAD_NO_CXX11_DECLTYPE_N3276
|
||||
#endif
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
|
||||
@@ -5,16 +5,13 @@
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#ifndef BOOST_NO_CXX11_DECLTYPE_N3276
|
||||
#define BOOST_THREAD_NO_CXX11_DECLTYPE_N3276
|
||||
#endif
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_USES_LOG
|
||||
//#define BOOST_THREAD_USES_LOG
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
|
||||
#include <boost/thread/future.hpp>
|
||||
@@ -93,16 +90,80 @@ int main()
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
boost::future<int> f2 = boost::async(boost::launch::async, &p1b);
|
||||
boost::future<std::tuple<> > all0 = boost::when_all();
|
||||
boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2));
|
||||
//(void) all.wait();
|
||||
boost::csbl::vector<boost::future<int> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< res[0].get() <<" " << BOOST_THREAD_END_LOG;
|
||||
BOOST_THREAD_LOG
|
||||
<< res[1].get() <<" " << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<boost::csbl::tuple<> > all0 = boost::when_all();
|
||||
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::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1));
|
||||
boost::csbl::tuple<boost::future<int> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1));
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::csbl::tuple<boost::future<int> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
#endif
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<int> f1 = boost::make_ready_future(1);
|
||||
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1));
|
||||
boost::csbl::tuple<boost::future<int> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
boost::future<int> f2 = boost::async(boost::launch::async, &p1b);
|
||||
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2));
|
||||
//(void) all.wait();
|
||||
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
boost::future<std::string> f2 = boost::make_ready_future(std::string("nnnnnnn"));;
|
||||
boost::future<boost::csbl::tuple<boost::future<int>, boost::future<std::string> > > all = boost::when_all(boost::move(f1), boost::move(f2));
|
||||
//(void) all.wait();
|
||||
boost::csbl::tuple<boost::future<int>, boost::future<std::string> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::csbl::vector<boost::future<int> > v;
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
v.push_back(boost::async(boost::launch::async, &p1));
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
v.push_back(boost::async(boost::launch::async, &p1b));
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(v.begin(), v.end());
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::csbl::vector<boost::future<int> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< res[0].get() <<" " << BOOST_THREAD_END_LOG;
|
||||
BOOST_THREAD_LOG
|
||||
<< res[1].get() <<" " << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
@@ -120,16 +181,113 @@ int main()
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
boost::future<int> f2 = boost::async(boost::launch::async, &p1b);
|
||||
boost::future<std::tuple<> > all0 = boost::when_any();
|
||||
boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
|
||||
//(void) all.wait();
|
||||
boost::csbl::vector<boost::future<int> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< res[0].get() <<" " << BOOST_THREAD_END_LOG;
|
||||
BOOST_THREAD_LOG
|
||||
<< res[1].get() <<" " << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<boost::csbl::tuple<> > all0 = boost::when_any();
|
||||
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::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_any(boost::move(f1));
|
||||
boost::csbl::tuple<boost::future<int> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);
|
||||
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_any(boost::move(f1));
|
||||
boost::csbl::tuple<boost::future<int> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
#endif
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
boost::future<int> f2 = boost::async(boost::launch::async, &p1b);
|
||||
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
|
||||
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<int> f1 = boost::make_ready_future(1);
|
||||
boost::future<int> f2 = boost::async(boost::launch::async, &p1b);
|
||||
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
|
||||
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<std::string> f1 = boost::make_ready_future(std::string("aaaa"));
|
||||
boost::future<int> f2 = boost::async(boost::launch::async, &p1b);
|
||||
boost::future<boost::csbl::tuple<boost::future<std::string>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
|
||||
boost::csbl::tuple<boost::future<std::string>,boost::future<int> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<int> f2 = boost::make_ready_future(1);
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1b);
|
||||
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
|
||||
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);
|
||||
boost::future<int> f2 = boost::async(boost::launch::async, &p1b);
|
||||
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
|
||||
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
boost::future<int> f2 = boost::async(boost::launch::deferred, &p1b);
|
||||
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
|
||||
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
#endif
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::csbl::vector<boost::future<int> > v;
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
v.push_back(boost::async(boost::launch::async, &p1));
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
v.push_back(boost::async(boost::launch::async, &p1b));
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end());
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::csbl::vector<boost::future<int> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< res[0].get() <<" " << BOOST_THREAD_END_LOG;
|
||||
BOOST_THREAD_LOG
|
||||
<< res[1].get() <<" " << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
@@ -155,7 +313,6 @@ using namespace boost;
|
||||
void f( boost::csbl::vector<future<int> > &//vec
|
||||
, BOOST_THREAD_RV_REF(future<int>) //f
|
||||
) {
|
||||
//vec.push_back(boost::forward<future<int> >(f));
|
||||
}
|
||||
int main()
|
||||
{
|
||||
|
||||
153
example/generic_executor_ref.cpp
Normal file
153
example/generic_executor_ref.cpp
Normal file
@@ -0,0 +1,153 @@
|
||||
// Copyright (C) 2014 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 <boost/config.hpp>
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
//#define BOOST_THREAD_USES_LOG
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
|
||||
#include <boost/thread/caller_context.hpp>
|
||||
#include <boost/thread/executors/basic_thread_pool.hpp>
|
||||
#include <boost/thread/executors/loop_executor.hpp>
|
||||
#include <boost/thread/executors/serial_executor.hpp>
|
||||
#include <boost/thread/executors/inline_executor.hpp>
|
||||
#include <boost/thread/executors/thread_executor.hpp>
|
||||
#include <boost/thread/executors/executor.hpp>
|
||||
#include <boost/thread/executors/executor_adaptor.hpp>
|
||||
#include <boost/thread/executor.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
void p1()
|
||||
{
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
//boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
|
||||
}
|
||||
|
||||
void p2()
|
||||
{
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
//boost::this_thread::sleep_for(boost::chrono::seconds(10));
|
||||
}
|
||||
|
||||
int f1()
|
||||
{
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
boost::this_thread::sleep_for(boost::chrono::seconds(1));
|
||||
return 1;
|
||||
}
|
||||
int f2(int i)
|
||||
{
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
boost::this_thread::sleep_for(boost::chrono::seconds(2));
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
void submit_some(boost::generic_executor_ref tp)
|
||||
{
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
tp.submit(&p2);
|
||||
}
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
tp.submit(&p1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void at_th_entry(boost::basic_thread_pool& )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int test_generic_executor_ref()
|
||||
{
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
{
|
||||
try
|
||||
{
|
||||
{
|
||||
boost::basic_thread_pool ea(4);
|
||||
submit_some( ea);
|
||||
{
|
||||
boost::future<int> t1 = boost::async(ea, &f1);
|
||||
boost::future<int> t2 = boost::async(ea, &f1);
|
||||
// std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
|
||||
// std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl;
|
||||
}
|
||||
submit_some(ea);
|
||||
{
|
||||
boost::basic_thread_pool ea3(1);
|
||||
boost::future<int> t1 = boost::async(ea3, &f1);
|
||||
boost::future<int> t2 = boost::async(ea3, &f1);
|
||||
//boost::future<int> t2 = boost::async(ea3, f2, 1); // todo this doesn't compiles yet on C++11
|
||||
//boost::future<int> t2 = boost::async(ea3, boost::bind(f2, 1)); // todo this doesn't compiles yet on C++98
|
||||
// std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
|
||||
// std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl;
|
||||
}
|
||||
submit_some(ea);
|
||||
}
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
{
|
||||
boost::loop_executor ea2;
|
||||
submit_some( ea2);
|
||||
ea2.run_queued_closures();
|
||||
}
|
||||
#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
{
|
||||
boost::basic_thread_pool ea1(4);
|
||||
boost::serial_executor ea2(ea1);
|
||||
submit_some(ea2);
|
||||
}
|
||||
#endif
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
{
|
||||
boost::inline_executor ea1;
|
||||
submit_some(ea1);
|
||||
}
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
{
|
||||
//boost::thread_executor ea1;
|
||||
//submit_some(ea1);
|
||||
}
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
{
|
||||
boost::basic_thread_pool ea(4, at_th_entry);
|
||||
boost::future<int> t1 = boost::async(ea, &f1);
|
||||
// std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
|
||||
}
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
std::cout << "ERROR= " << ex.what() << "" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cout << " ERROR= exception thrown" << std::endl;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
return test_generic_executor_ref();
|
||||
|
||||
|
||||
}
|
||||
@@ -8,9 +8,6 @@
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
#ifndef BOOST_NO_CXX11_DECLTYPE_N3276
|
||||
#define BOOST_THREAD_NO_CXX11_DECLTYPE_N3276
|
||||
#endif
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
//#define BOOST_THREAD_USES_LOG
|
||||
|
||||
@@ -3,12 +3,14 @@
|
||||
// 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 <boost/config.hpp>
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
//#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
|
||||
#include <boost/thread/executors/basic_thread_pool.hpp>
|
||||
|
||||
@@ -3,14 +3,15 @@
|
||||
// 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 <boost/config.hpp>
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
//#ifndef BOOST_NO_CXX11_DECLTYPE_N3276
|
||||
//#define BOOST_THREAD_NO_CXX11_DECLTYPE_N3276
|
||||
//#endif
|
||||
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
|
||||
#include <boost/thread/executors/basic_thread_pool.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
|
||||
@@ -6,9 +6,13 @@
|
||||
|
||||
// adapted from the example given by Howard Hinnant in
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
#include <iostream>
|
||||
#include <boost/thread/scoped_thread.hpp>
|
||||
#ifdef XXXX
|
||||
@@ -87,25 +91,24 @@ void consumer2(the_ostream &mos, boost::sync_queue<int> & sbq)
|
||||
mos << "exception !!!\n";
|
||||
}
|
||||
}
|
||||
//void consumer3(the_ostream &mos, boost::sync_queue<int> & sbq)
|
||||
//{
|
||||
// using namespace boost;
|
||||
// bool closed=false;
|
||||
// try {
|
||||
// for(int i=0; ;++i)
|
||||
// {
|
||||
// int r;
|
||||
// queue_op_status res = sbq.wait_and_pull(r);
|
||||
// if (res==queue_op_status::closed) break;
|
||||
// mos << i << " wait_and_pull(" << r << ")\n";
|
||||
// this_thread::sleep_for(chrono::milliseconds(250));
|
||||
// }
|
||||
// }
|
||||
// catch(...)
|
||||
// {
|
||||
// mos << "exception !!!\n";
|
||||
// }
|
||||
//}
|
||||
void consumer3(the_ostream &mos, boost::sync_queue<int> & sbq)
|
||||
{
|
||||
using namespace boost;
|
||||
try {
|
||||
for(int i=0; ;++i)
|
||||
{
|
||||
int r;
|
||||
queue_op_status res = sbq.wait_pull_front(r);
|
||||
if (res==queue_op_status::closed) break;
|
||||
mos << i << " wait_pull_front(" << r << ")\n";
|
||||
this_thread::sleep_for(chrono::milliseconds(250));
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
mos << "exception !!!\n";
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
150
example/producer_consumer2.cpp
Normal file
150
example/producer_consumer2.cpp
Normal file
@@ -0,0 +1,150 @@
|
||||
// (C) Copyright 2014 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)
|
||||
|
||||
// adapted from the example given by Howard Hinnant in
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
//#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
#include <iostream>
|
||||
#include <boost/thread/scoped_thread.hpp>
|
||||
#ifdef XXXX
|
||||
#include <boost/thread/externally_locked_stream.hpp>
|
||||
typedef boost::externally_locked_stream<std::ostream> the_ostream;
|
||||
#else
|
||||
typedef std::ostream the_ostream;
|
||||
typedef std::istream the_istream;
|
||||
#endif
|
||||
#include <boost/thread/sync_queue.hpp>
|
||||
#include <boost/thread/concurrent_queues/queue_adaptor.hpp>
|
||||
#include <boost/thread/concurrent_queues/queue_views.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
|
||||
void producer(the_ostream &mos, boost::queue_back<int> sbq)
|
||||
{
|
||||
using namespace boost;
|
||||
try {
|
||||
for(int i=0; ;++i)
|
||||
{
|
||||
sbq.push(i);
|
||||
//sbq << i;
|
||||
mos << "push(" << i << ") " << sbq.size() <<"\n";
|
||||
this_thread::sleep_for(chrono::milliseconds(200));
|
||||
}
|
||||
}
|
||||
catch(sync_queue_is_closed&)
|
||||
{
|
||||
mos << "closed !!!\n";
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
mos << "exception !!!\n";
|
||||
}
|
||||
}
|
||||
|
||||
void consumer(
|
||||
the_ostream &mos,
|
||||
boost::queue_front<int> sbq)
|
||||
{
|
||||
using namespace boost;
|
||||
try {
|
||||
for(int i=0; ;++i)
|
||||
{
|
||||
int r;
|
||||
sbq.pull(r);
|
||||
//sbq >> r;
|
||||
mos << i << " pull(" << r << ") " << sbq.size() <<"\n";
|
||||
|
||||
this_thread::sleep_for(chrono::milliseconds(250));
|
||||
}
|
||||
}
|
||||
catch(sync_queue_is_closed&)
|
||||
{
|
||||
mos << "closed !!!\n";
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
mos << "exception !!!\n";
|
||||
}
|
||||
}
|
||||
void consumer2(the_ostream &mos, boost::queue_front<int> sbq)
|
||||
{
|
||||
using namespace boost;
|
||||
try {
|
||||
for(int i=0; ;++i)
|
||||
{
|
||||
int r;
|
||||
queue_op_status st = sbq.try_pull(r);
|
||||
if (queue_op_status::closed == st) break;
|
||||
if (queue_op_status::success == st) {
|
||||
mos << i << " try_pull(" << r << ")\n";
|
||||
}
|
||||
this_thread::sleep_for(chrono::milliseconds(250));
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
mos << "exception !!!\n";
|
||||
}
|
||||
}
|
||||
void consumer3(the_ostream &mos, boost::queue_front<int> sbq)
|
||||
{
|
||||
using namespace boost;
|
||||
try {
|
||||
for(int i=0; ;++i)
|
||||
{
|
||||
int r;
|
||||
queue_op_status res = sbq.wait_pull(r);
|
||||
if (res==queue_op_status::closed) break;
|
||||
mos << i << " wait_pull(" << r << ")\n";
|
||||
this_thread::sleep_for(chrono::milliseconds(250));
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
mos << "exception !!!\n";
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace boost;
|
||||
|
||||
#ifdef XXXX
|
||||
recursive_mutex terminal_mutex;
|
||||
|
||||
externally_locked_stream<std::ostream> mcerr(std::cerr, terminal_mutex);
|
||||
externally_locked_stream<std::ostream> mcout(std::cout, terminal_mutex);
|
||||
externally_locked_stream<std::istream> mcin(std::cin, terminal_mutex);
|
||||
#else
|
||||
the_ostream &mcerr = std::cout;
|
||||
the_ostream &mcout = std::cerr;
|
||||
//the_istream &mcin = std::cin;
|
||||
#endif
|
||||
|
||||
queue_adaptor<sync_queue<int> > sbq;
|
||||
|
||||
{
|
||||
mcout << "begin of main" << std::endl;
|
||||
scoped_thread<> t11(boost::thread(producer, boost::ref(mcerr), concurrent::queue_back<int>(sbq)));
|
||||
scoped_thread<> t12(boost::thread(producer, boost::ref(mcerr), concurrent::queue_back<int>(sbq)));
|
||||
scoped_thread<> t2(boost::thread(consumer, boost::ref(mcout), concurrent::queue_front<int>(sbq)));
|
||||
|
||||
this_thread::sleep_for(chrono::seconds(1));
|
||||
|
||||
mcout << "closed()" << std::endl;
|
||||
sbq.close();
|
||||
mcout << "closed()" << std::endl;
|
||||
|
||||
} // all threads joined here.
|
||||
mcout << "end of main" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -6,8 +6,13 @@
|
||||
|
||||
// adapted from the example given by Howard Hinnant in
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
//#define XXXX
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@@ -3,10 +3,15 @@
|
||||
// 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 <boost/config.hpp>
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_USES_LOG
|
||||
//#define BOOST_THREAD_USES_LOG
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
|
||||
#include <boost/thread/detail/log.hpp>
|
||||
#include <boost/thread/executors/basic_thread_pool.hpp>
|
||||
|
||||
@@ -3,13 +3,18 @@
|
||||
// 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/config.hpp>
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
//#define BOOST_THREAD_USES_LOG
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
#include <boost/thread/detail/log.hpp>
|
||||
#include <boost/thread/executors/loop_executor.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/thread/thread_only.hpp>
|
||||
#include <string>
|
||||
|
||||
void p1()
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace boost
|
||||
{
|
||||
}
|
||||
BOOST_THREAD_MOVABLE(default_barrier_reseter)
|
||||
//BOOST_THREAD_COPYABLE_AND_MOVABLE(default_barrier_reseter)
|
||||
|
||||
default_barrier_reseter(default_barrier_reseter const& other) BOOST_NOEXCEPT :
|
||||
size_(other.size_)
|
||||
@@ -71,6 +72,7 @@ namespace boost
|
||||
{}
|
||||
|
||||
BOOST_THREAD_MOVABLE(void_functor_barrier_reseter)
|
||||
//BOOST_THREAD_COPYABLE_AND_MOVABLE(void_functor_barrier_reseter)
|
||||
|
||||
void_functor_barrier_reseter(void_functor_barrier_reseter const& other) BOOST_NOEXCEPT :
|
||||
size_(other.size_), fct_(other.fct_)
|
||||
@@ -78,6 +80,7 @@ namespace boost
|
||||
}
|
||||
void_functor_barrier_reseter(BOOST_THREAD_RV_REF(void_functor_barrier_reseter) other) BOOST_NOEXCEPT :
|
||||
size_(BOOST_THREAD_RV(other).size_), fct_(BOOST_THREAD_RV(other).fct_)
|
||||
//size_(BOOST_THREAD_RV(other).size_), fct_(boost::move(BOOST_THREAD_RV(other).fct_))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -96,6 +99,7 @@ namespace boost
|
||||
{
|
||||
}
|
||||
BOOST_THREAD_MOVABLE(void_fct_ptr_barrier_reseter)
|
||||
//BOOST_THREAD_COPYABLE_AND_MOVABLE(void_fct_ptr_barrier_reseter)
|
||||
|
||||
void_fct_ptr_barrier_reseter(void_fct_ptr_barrier_reseter const& other) BOOST_NOEXCEPT :
|
||||
size_(other.size_), fct_(other.fct_)
|
||||
@@ -112,6 +116,10 @@ namespace boost
|
||||
}
|
||||
};
|
||||
}
|
||||
//BOOST_THREAD_DCL_MOVABLE(thread_detail::default_barrier_reseter)
|
||||
//BOOST_THREAD_DCL_MOVABLE(thread_detail::void_functor_barrier_reseter)
|
||||
//BOOST_THREAD_DCL_MOVABLE(thread_detail::void_fct_ptr_barrier_reseter)
|
||||
|
||||
class barrier
|
||||
{
|
||||
static inline unsigned int check_counter(unsigned int count)
|
||||
|
||||
209
include/boost/thread/concurrent_queues/queue_adaptor.hpp
Normal file
209
include/boost/thread/concurrent_queues/queue_adaptor.hpp
Normal file
@@ -0,0 +1,209 @@
|
||||
#ifndef BOOST_THREAD_QUEUE_ADAPTOR_HPP
|
||||
#define BOOST_THREAD_QUEUE_ADAPTOR_HPP
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Vicente J. Botet Escriba 2014. 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)
|
||||
//
|
||||
// See http://www.boost.org/libs/thread for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
|
||||
#include <boost/thread/concurrent_queues/queue_base.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace concurrent
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename Queue>
|
||||
class queue_adaptor_copyable_only :
|
||||
public boost::queue_base<typename Queue::value_type>
|
||||
{
|
||||
Queue queue;
|
||||
public:
|
||||
typedef typename Queue::value_type value_type;
|
||||
typedef std::size_t size_type;
|
||||
|
||||
// Constructors/Assignment/Destructors
|
||||
queue_adaptor_copyable_only() {}
|
||||
|
||||
// Observers
|
||||
bool empty() const { return queue.empty(); }
|
||||
bool full() const { return queue.full(); }
|
||||
size_type size() const { return queue.size(); }
|
||||
bool closed() const { return queue.closed(); }
|
||||
|
||||
// Modifiers
|
||||
void close() { queue.close(); }
|
||||
|
||||
void push_back(const value_type& x) { queue.push_back(x); }
|
||||
|
||||
void pull_front(value_type& x) { queue.pull_front(x); };
|
||||
value_type pull_front() { return queue.pull_front(); }
|
||||
|
||||
queue_op_status try_push_back(const value_type& x) { return queue.try_push_back(x); }
|
||||
queue_op_status try_pull_front(value_type& x) { return queue.try_pull_front(x); }
|
||||
|
||||
queue_op_status nonblocking_push_back(const value_type& x) { return queue.nonblocking_push_back(x); }
|
||||
queue_op_status nonblocking_pull_front(value_type& x) { return queue.nonblocking_pull_front(x); }
|
||||
|
||||
queue_op_status wait_push_back(const value_type& x) { return queue.wait_push_back(x); }
|
||||
queue_op_status wait_pull_front(value_type& x) { return queue.wait_pull_front(x); }
|
||||
|
||||
};
|
||||
template <typename Queue>
|
||||
class queue_adaptor_movable_only :
|
||||
public boost::queue_base<typename Queue::value_type>
|
||||
{
|
||||
Queue queue;
|
||||
public:
|
||||
typedef typename Queue::value_type value_type;
|
||||
typedef std::size_t size_type;
|
||||
|
||||
// Constructors/Assignment/Destructors
|
||||
|
||||
queue_adaptor_movable_only() {}
|
||||
|
||||
// Observers
|
||||
bool empty() const { return queue.empty(); }
|
||||
bool full() const { return queue.full(); }
|
||||
size_type size() const { return queue.size(); }
|
||||
bool closed() const { return queue.closed(); }
|
||||
|
||||
// Modifiers
|
||||
void close() { queue.close(); }
|
||||
|
||||
|
||||
void pull_front(value_type& x) { queue.pull_front(x); };
|
||||
// enable_if is_nothrow_copy_movable<value_type>
|
||||
value_type pull_front() { return queue.pull_front(); }
|
||||
|
||||
queue_op_status try_pull_front(value_type& x) { return queue.try_pull_front(x); }
|
||||
|
||||
queue_op_status nonblocking_pull_front(value_type& x) { return queue.nonblocking_pull_front(x); }
|
||||
|
||||
queue_op_status wait_pull_front(value_type& x) { return queue.wait_pull_front(x); }
|
||||
|
||||
void push_back(BOOST_THREAD_RV_REF(value_type) x) { queue.push_back(boost::move(x)); }
|
||||
queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.try_push_back(boost::move(x)); }
|
||||
queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.nonblocking_push_back(boost::move(x)); }
|
||||
queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.wait_push_back(boost::move(x)); }
|
||||
};
|
||||
|
||||
template <typename Queue>
|
||||
class queue_adaptor_copyable_and_movable :
|
||||
public boost::queue_base<typename Queue::value_type>
|
||||
{
|
||||
Queue queue;
|
||||
public:
|
||||
typedef typename Queue::value_type value_type;
|
||||
typedef std::size_t size_type;
|
||||
|
||||
// Constructors/Assignment/Destructors
|
||||
|
||||
queue_adaptor_copyable_and_movable() {}
|
||||
|
||||
// Observers
|
||||
bool empty() const { return queue.empty(); }
|
||||
bool full() const { return queue.full(); }
|
||||
size_type size() const { return queue.size(); }
|
||||
bool closed() const { return queue.closed(); }
|
||||
|
||||
// Modifiers
|
||||
void close() { queue.close(); }
|
||||
|
||||
|
||||
void push_back(const value_type& x) { queue.push_back(x); }
|
||||
|
||||
void pull_front(value_type& x) { queue.pull_front(x); };
|
||||
// enable_if is_nothrow_copy_movable<value_type>
|
||||
value_type pull_front() { return queue.pull_front(); }
|
||||
|
||||
queue_op_status try_push_back(const value_type& x) { return queue.try_push_back(x); }
|
||||
queue_op_status try_pull_front(value_type& x) { return queue.try_pull_front(x); }
|
||||
|
||||
queue_op_status nonblocking_push_back(const value_type& x) { return queue.nonblocking_push_back(x); }
|
||||
queue_op_status nonblocking_pull_front(value_type& x) { return queue.nonblocking_pull_front(x); }
|
||||
|
||||
queue_op_status wait_push_back(const value_type& x) { return queue.wait_push_back(x); }
|
||||
queue_op_status wait_pull_front(value_type& x) { return queue.wait_pull_front(x); }
|
||||
|
||||
void push_back(BOOST_THREAD_RV_REF(value_type) x) { queue.push_back(boost::move(x)); }
|
||||
queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.try_push_back(boost::move(x)); }
|
||||
queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.nonblocking_push_back(boost::move(x)); }
|
||||
queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.wait_push_back(boost::move(x)); }
|
||||
};
|
||||
|
||||
|
||||
template <class Q, class T,
|
||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
#if defined __GNUC__
|
||||
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
bool Copyable = is_copy_constructible<T>::value,
|
||||
bool Movable = true
|
||||
#else
|
||||
bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
|
||||
bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
|
||||
#endif // __GNUC__
|
||||
#elif defined _MSC_VER
|
||||
#if _MSC_VER < 1700
|
||||
bool Copyable = is_copy_constructible<T>::value,
|
||||
bool Movable = true
|
||||
#else
|
||||
bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
|
||||
bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
|
||||
#endif // _MSC_VER
|
||||
#else
|
||||
bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
|
||||
bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
|
||||
#endif
|
||||
#else
|
||||
bool Copyable = is_copy_constructible<T>::value,
|
||||
bool Movable = has_move_emulation_enabled<T>::value
|
||||
#endif
|
||||
>
|
||||
struct queue_adaptor;
|
||||
|
||||
template <class Q, class T>
|
||||
struct queue_adaptor<Q, T, true, true> {
|
||||
typedef queue_adaptor_copyable_and_movable<Q> type;
|
||||
};
|
||||
template <class Q, class T>
|
||||
struct queue_adaptor<Q, T, true, false> {
|
||||
typedef queue_adaptor_copyable_only<Q> type;
|
||||
};
|
||||
template <class Q, class T>
|
||||
struct queue_adaptor<Q, T, false, true> {
|
||||
typedef queue_adaptor_movable_only<Q> type;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <typename Queue>
|
||||
class queue_adaptor :
|
||||
public detail::queue_adaptor<Queue, typename Queue::value_type>::type
|
||||
{
|
||||
public:
|
||||
typedef typename Queue::value_type value_type;
|
||||
typedef std::size_t size_type;
|
||||
// Constructors/Assignment/Destructors
|
||||
virtual ~queue_adaptor() {};
|
||||
};
|
||||
}
|
||||
using concurrent::queue_adaptor;
|
||||
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
202
include/boost/thread/concurrent_queues/queue_base.hpp
Executable file
202
include/boost/thread/concurrent_queues/queue_base.hpp
Executable file
@@ -0,0 +1,202 @@
|
||||
#ifndef BOOST_THREAD_QUEUE_BASE_HPP
|
||||
#define BOOST_THREAD_QUEUE_BASE_HPP
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Vicente J. Botet Escriba 2014. 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)
|
||||
//
|
||||
// See http://www.boost.org/libs/thread for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
|
||||
#include <boost/type_traits/conditional.hpp>
|
||||
#include <boost/type_traits/is_copy_constructible.hpp>
|
||||
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace concurrent
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename ValueType>
|
||||
class queue_base_copyable_only
|
||||
{
|
||||
public:
|
||||
typedef ValueType value_type;
|
||||
typedef std::size_t size_type;
|
||||
|
||||
// Constructors/Assignment/Destructors
|
||||
virtual ~queue_base_copyable_only() {};
|
||||
|
||||
// Observers
|
||||
virtual bool empty() const = 0;
|
||||
virtual bool full() const = 0;
|
||||
virtual size_type size() const = 0;
|
||||
virtual bool closed() const = 0;
|
||||
|
||||
// Modifiers
|
||||
virtual void close() = 0;
|
||||
|
||||
virtual void push_back(const value_type& x) = 0;
|
||||
|
||||
virtual void pull_front(value_type&) = 0;
|
||||
virtual value_type pull_front() = 0;
|
||||
|
||||
virtual queue_op_status try_push_back(const value_type& x) = 0;
|
||||
virtual queue_op_status try_pull_front(value_type&) = 0;
|
||||
|
||||
virtual queue_op_status nonblocking_push_back(const value_type& x) = 0;
|
||||
virtual queue_op_status nonblocking_pull_front(value_type&) = 0;
|
||||
|
||||
virtual queue_op_status wait_push_back(const value_type& x) = 0;
|
||||
virtual queue_op_status wait_pull_front(ValueType& elem) = 0;
|
||||
|
||||
};
|
||||
|
||||
template <typename ValueType>
|
||||
class queue_base_movable_only
|
||||
{
|
||||
public:
|
||||
typedef ValueType value_type;
|
||||
typedef std::size_t size_type;
|
||||
// Constructors/Assignment/Destructors
|
||||
virtual ~queue_base_movable_only() {};
|
||||
|
||||
// Observers
|
||||
virtual bool empty() const = 0;
|
||||
virtual bool full() const = 0;
|
||||
virtual size_type size() const = 0;
|
||||
virtual bool closed() const = 0;
|
||||
|
||||
// Modifiers
|
||||
virtual void close() = 0;
|
||||
|
||||
virtual void pull_front(value_type&) = 0;
|
||||
// enable_if is_nothrow_movable<value_type>
|
||||
virtual value_type pull_front() = 0;
|
||||
|
||||
virtual queue_op_status try_pull_front(value_type&) = 0;
|
||||
|
||||
virtual queue_op_status nonblocking_pull_front(value_type&) = 0;
|
||||
|
||||
virtual queue_op_status wait_pull_front(ValueType& elem) = 0;
|
||||
|
||||
virtual void push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
||||
virtual queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
||||
virtual queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
||||
virtual queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
||||
};
|
||||
|
||||
|
||||
template <typename ValueType>
|
||||
class queue_base_copyable_and_movable
|
||||
{
|
||||
public:
|
||||
typedef ValueType value_type;
|
||||
typedef std::size_t size_type;
|
||||
// Constructors/Assignment/Destructors
|
||||
virtual ~queue_base_copyable_and_movable() {};
|
||||
|
||||
|
||||
// Observers
|
||||
virtual bool empty() const = 0;
|
||||
virtual bool full() const = 0;
|
||||
virtual size_type size() const = 0;
|
||||
virtual bool closed() const = 0;
|
||||
|
||||
// Modifiers
|
||||
virtual void close() = 0;
|
||||
|
||||
virtual void push_back(const value_type& x) = 0;
|
||||
|
||||
virtual void pull_front(value_type&) = 0;
|
||||
// enable_if is_nothrow_copy_movable<value_type>
|
||||
virtual value_type pull_front() = 0;
|
||||
|
||||
virtual queue_op_status try_push_back(const value_type& x) = 0;
|
||||
virtual queue_op_status try_pull_front(value_type&) = 0;
|
||||
|
||||
virtual queue_op_status nonblocking_push_back(const value_type& x) = 0;
|
||||
virtual queue_op_status nonblocking_pull_front(value_type&) = 0;
|
||||
|
||||
virtual queue_op_status wait_push_back(const value_type& x) = 0;
|
||||
virtual queue_op_status wait_pull_front(ValueType& elem) = 0;
|
||||
|
||||
virtual void push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
||||
virtual queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
||||
virtual queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
||||
virtual queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
||||
};
|
||||
|
||||
template <class T,
|
||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
#if defined __GNUC__
|
||||
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
bool Copyable = is_copy_constructible<T>::value,
|
||||
bool Movable = true
|
||||
#else
|
||||
bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
|
||||
bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
|
||||
#endif // __GNUC__
|
||||
#elif defined _MSC_VER
|
||||
#if _MSC_VER < 1700
|
||||
bool Copyable = is_copy_constructible<T>::value,
|
||||
bool Movable = true
|
||||
#else
|
||||
bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
|
||||
bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
|
||||
#endif // _MSC_VER
|
||||
#else
|
||||
bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
|
||||
bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
|
||||
#endif
|
||||
#else
|
||||
bool Copyable = is_copy_constructible<T>::value,
|
||||
bool Movable = has_move_emulation_enabled<T>::value
|
||||
#endif
|
||||
>
|
||||
struct queue_base;
|
||||
|
||||
template <class T>
|
||||
struct queue_base<T, true, true> {
|
||||
typedef queue_base_copyable_and_movable<T> type;
|
||||
};
|
||||
template <class T>
|
||||
struct queue_base<T, true, false> {
|
||||
typedef queue_base_copyable_only<T> type;
|
||||
};
|
||||
template <class T>
|
||||
struct queue_base<T, false, true> {
|
||||
typedef queue_base_movable_only<T> type;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <typename ValueType>
|
||||
class queue_base :
|
||||
public detail::queue_base<ValueType>::type
|
||||
{
|
||||
public:
|
||||
typedef ValueType value_type;
|
||||
typedef std::size_t size_type;
|
||||
// Constructors/Assignment/Destructors
|
||||
virtual ~queue_base() {};
|
||||
};
|
||||
|
||||
}
|
||||
using concurrent::queue_base;
|
||||
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
46
include/boost/thread/concurrent_queues/queue_op_status.hpp
Normal file
46
include/boost/thread/concurrent_queues/queue_op_status.hpp
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef BOOST_THREAD_QUEUE_OP_STATUS_HPP
|
||||
#define BOOST_THREAD_QUEUE_OP_STATUS_HPP
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Vicente J. Botet Escriba 2014. 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)
|
||||
//
|
||||
// See http://www.boost.org/libs/thread for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace concurrent
|
||||
{
|
||||
|
||||
BOOST_SCOPED_ENUM_DECLARE_BEGIN(queue_op_status)
|
||||
{ success = 0, empty, full, closed, busy }
|
||||
BOOST_SCOPED_ENUM_DECLARE_END(queue_op_status)
|
||||
|
||||
struct sync_queue_is_closed : std::exception
|
||||
{
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
struct no_block_tag{};
|
||||
BOOST_CONSTEXPR_OR_CONST no_block_tag no_block = {};
|
||||
#endif
|
||||
|
||||
using concurrent::queue_op_status;
|
||||
using concurrent::sync_queue_is_closed;
|
||||
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
165
include/boost/thread/concurrent_queues/queue_views.hpp
Normal file
165
include/boost/thread/concurrent_queues/queue_views.hpp
Normal file
@@ -0,0 +1,165 @@
|
||||
#ifndef BOOST_THREAD_QUEUE_VIEWS_HPP
|
||||
#define BOOST_THREAD_QUEUE_VIEWS_HPP
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Vicente J. Botet Escriba 2014. 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)
|
||||
//
|
||||
// See http://www.boost.org/libs/thread for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
|
||||
#include <boost/thread/concurrent_queues/queue_base.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace concurrent
|
||||
{
|
||||
|
||||
template <typename Queue>
|
||||
class queue_back_view
|
||||
{
|
||||
Queue* queue;
|
||||
public:
|
||||
typedef typename Queue::value_type value_type;
|
||||
typedef typename Queue::size_type size_type;
|
||||
|
||||
// Constructors/Assignment/Destructors
|
||||
queue_back_view(Queue& q) BOOST_NOEXCEPT : queue(&q) {}
|
||||
|
||||
// Observers
|
||||
bool empty() const { return queue->empty(); }
|
||||
bool full() const { return queue->full(); }
|
||||
size_type size() const { return queue->size(); }
|
||||
bool closed() const { return queue->closed(); }
|
||||
|
||||
// Modifiers
|
||||
void close() { queue->close(); }
|
||||
|
||||
void push(const value_type& x) { queue->push_back(x); }
|
||||
|
||||
void pull(value_type& x) { queue->pull_back(x); }
|
||||
// enable_if is_nothrow_copy_movable<value_type>
|
||||
value_type pull() { return queue->pull_back(); }
|
||||
|
||||
queue_op_status try_push(const value_type& x) { return queue->try_push_back(x); }
|
||||
|
||||
queue_op_status try_pull(value_type& x) { return queue->try_pull_back(x); }
|
||||
|
||||
queue_op_status nonblocking_push(const value_type& x) { return queue->nonblocking_push_back(x); }
|
||||
|
||||
queue_op_status nonblocking_pull(value_type& x) { return queue->nonblocking_pull_back(x); }
|
||||
|
||||
queue_op_status wait_push(const value_type& x) { return queue->wait_push_back(x); }
|
||||
queue_op_status wait_pull(value_type& x) { return queue->wait_pull_back(x); }
|
||||
|
||||
void push(BOOST_THREAD_RV_REF(value_type) x) { queue->push_back(boost::move(x)); }
|
||||
queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->try_push_back(boost::move(x)); }
|
||||
queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->nonblocking_push_back(boost::move(x)); }
|
||||
queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->wait_push_back(boost::move(x)); }
|
||||
};
|
||||
|
||||
template <typename Queue>
|
||||
class queue_front_view
|
||||
{
|
||||
Queue* queue;
|
||||
public:
|
||||
typedef typename Queue::value_type value_type;
|
||||
typedef typename Queue::size_type size_type;
|
||||
|
||||
// Constructors/Assignment/Destructors
|
||||
queue_front_view(Queue& q) BOOST_NOEXCEPT : queue(&q) {}
|
||||
|
||||
// Observers
|
||||
bool empty() const { return queue->empty(); }
|
||||
bool full() const { return queue->full(); }
|
||||
size_type size() const { return queue->size(); }
|
||||
bool closed() const { return queue->closed(); }
|
||||
|
||||
// Modifiers
|
||||
void close() { queue->close(); }
|
||||
|
||||
void push(const value_type& x) { queue->push_front(x); }
|
||||
|
||||
void pull(value_type& x) { queue->pull_front(x); };
|
||||
// enable_if is_nothrow_copy_movable<value_type>
|
||||
value_type pull() { return queue->pull_front(); }
|
||||
|
||||
queue_op_status try_push(const value_type& x) { return queue->try_push_front(x); }
|
||||
|
||||
queue_op_status try_pull(value_type& x) { return queue->try_pull_front(x); }
|
||||
|
||||
queue_op_status nonblocking_push(const value_type& x) { return queue->nonblocking_push_front(x); }
|
||||
|
||||
queue_op_status nonblocking_pull(value_type& x) { return queue->nonblocking_pull_front(x); }
|
||||
|
||||
queue_op_status wait_push(const value_type& x) { return queue->wait_push_front(x); }
|
||||
queue_op_status wait_pull(value_type& x) { return queue->wait_pull_front(x); }
|
||||
void push(BOOST_THREAD_RV_REF(value_type) x) { queue->push_front(forward<value_type>(x)); }
|
||||
queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->try_push_front(forward<value_type>(x)); }
|
||||
queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->nonblocking_push_front(forward<value_type>(x)); }
|
||||
queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->wait_push_front(forward<value_type>(x)); }
|
||||
|
||||
};
|
||||
|
||||
#if ! defined BOOST_NO_CXX11_TEMPLATE_ALIASES
|
||||
|
||||
template <class T>
|
||||
using queue_back = queue_back_view<queue_base<T> > ;
|
||||
template <class T>
|
||||
using queue_front = queue_front_view<queue_base<T> > ;
|
||||
|
||||
#else
|
||||
|
||||
template <class T>
|
||||
struct queue_back : queue_back_view<queue_base<T> >
|
||||
{
|
||||
typedef queue_back_view<queue_base<T> > base_type;
|
||||
queue_back(queue_base<T>& q) BOOST_NOEXCEPT : base_type(q) {}
|
||||
};
|
||||
template <class T>
|
||||
struct queue_front : queue_front_view<queue_base<T> >
|
||||
{
|
||||
typedef queue_front_view<queue_base<T> > base_type;
|
||||
queue_front(queue_base<T>& q) BOOST_NOEXCEPT : base_type(q) {}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// template <class Queue>
|
||||
// queue_back_view<Queue> back(Queue & q) { return queue_back_view<Queue>(q); }
|
||||
// template <class Queue>
|
||||
// queue_front_view<Queue> front(Queue & q) { return queue_front_view<Queue>(q); }
|
||||
//#if 0
|
||||
// template <class T>
|
||||
// queue_back<T> back(queue_base<T> & q) { return queue_back<T>(q); }
|
||||
// template <class T>
|
||||
// queue_front<T> front(queue_base<T> & q) { return queue_front<T>(q); }
|
||||
//#else
|
||||
// template <class T>
|
||||
// typename queue_back<T>::type back(queue_base<T> & q) { return typename queue_back<T>::type(q); }
|
||||
// template <class T>
|
||||
// typename queue_front<T>::type front(queue_base<T> & q) { return typename queue_front<T>::type(q); }
|
||||
//#endif
|
||||
}
|
||||
|
||||
using concurrent::queue_back_view;
|
||||
using concurrent::queue_front_view;
|
||||
using concurrent::queue_back;
|
||||
using concurrent::queue_front;
|
||||
//using concurrent::back;
|
||||
//using concurrent::front;
|
||||
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
@@ -10,8 +10,16 @@
|
||||
#define BOOST_CSBL_DEQUE_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if defined BOOST_THREAD_USES_BOOST_DEQUE || defined BOOST_NO_CXX11_HDR_DEQUE || defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
// MSVC has some trouble instantiating a non_copyable type
|
||||
//C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xmemory0(606) : error C2248: 'non_copyable::non_copyable' : cannot access private member declared in class 'non_copyable'
|
||||
// ..\libs\thread\test\sync\mutual_exclusion\queue_views\single_thread_pass.cpp(24) : see declaration of 'non_copyable::non_copyable'
|
||||
// ..\libs\thread\test\sync\mutual_exclusion\queue_views\single_thread_pass.cpp(23) : see declaration of 'non_copyable'
|
||||
// C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xmemory0(605) : while compiling class template member function 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)'
|
||||
// with
|
||||
// [
|
||||
// _Ty=non_copyable
|
||||
// ]
|
||||
#if defined BOOST_THREAD_USES_BOOST_DEQUE || defined BOOST_NO_CXX11_HDR_DEQUE || defined BOOST_NO_CXX11_RVALUE_REFERENCES || (defined _MSC_VER && _MSC_FULL_VER < 180020827)
|
||||
#ifndef BOOST_THREAD_USES_BOOST_DEQUE
|
||||
#define BOOST_THREAD_USES_BOOST_DEQUE
|
||||
#endif
|
||||
|
||||
@@ -15,97 +15,13 @@
|
||||
// default_delete
|
||||
|
||||
#if defined BOOST_NO_CXX11_SMART_PTR
|
||||
#include <boost/thread/csbl/memory/pointer_traits.hpp>
|
||||
#include <boost/type_traits/remove_cv.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/type_traits/is_scalar.hpp>
|
||||
#include <boost/type_traits/is_pointer.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/move/unique_ptr.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace csbl
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <class _Ptr1, class _Ptr2,
|
||||
bool = is_same<typename remove_cv<typename pointer_traits<_Ptr1>::element_type>::type,
|
||||
typename remove_cv<typename pointer_traits<_Ptr2>::element_type>::type
|
||||
>::value
|
||||
>
|
||||
struct same_or_less_cv_qualified_imp
|
||||
: is_convertible<_Ptr1, _Ptr2>
|
||||
{};
|
||||
|
||||
template <class _Ptr1, class _Ptr2>
|
||||
struct same_or_less_cv_qualified_imp<_Ptr1, _Ptr2, false>
|
||||
: false_type
|
||||
{};
|
||||
|
||||
template <class _Ptr1, class _Ptr2, bool = is_scalar<_Ptr1>::value &&
|
||||
!is_pointer<_Ptr1>::value>
|
||||
struct same_or_less_cv_qualified
|
||||
: same_or_less_cv_qualified_imp<_Ptr1, _Ptr2>
|
||||
{};
|
||||
|
||||
template <class _Ptr1, class _Ptr2>
|
||||
struct same_or_less_cv_qualified<_Ptr1, _Ptr2, true>
|
||||
: false_type
|
||||
{};
|
||||
|
||||
}
|
||||
template <class T>
|
||||
struct BOOST_SYMBOL_VISIBLE default_delete
|
||||
{
|
||||
#ifndef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
BOOST_CONSTEXPR default_delete() = default;
|
||||
#else
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
BOOST_CONSTEXPR default_delete() BOOST_NOEXCEPT
|
||||
{}
|
||||
#endif
|
||||
template <class U>
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
default_delete(const default_delete<U>&,
|
||||
typename enable_if<is_convertible<U*, T*> >::type* = 0) BOOST_NOEXCEPT
|
||||
{}
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
void operator() (T* ptr) const BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_STATIC_ASSERT_MSG(sizeof(T) > 0, "default_delete can not delete incomplete type");
|
||||
delete ptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct BOOST_SYMBOL_VISIBLE default_delete<T[]>
|
||||
{
|
||||
public:
|
||||
#ifndef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
BOOST_CONSTEXPR default_delete() = default;
|
||||
#else
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
BOOST_CONSTEXPR default_delete() BOOST_NOEXCEPT
|
||||
{}
|
||||
#endif
|
||||
template <class U>
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
default_delete(const default_delete<U[]>&,
|
||||
typename enable_if<detail::same_or_less_cv_qualified<U*, T*> >::type* = 0) BOOST_NOEXCEPT
|
||||
{}
|
||||
template <class U>
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
void operator() (U* ptr,
|
||||
typename enable_if<detail::same_or_less_cv_qualified<U*, T*> >::type* = 0) const BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_STATIC_ASSERT_MSG(sizeof(T) > 0, "default_delete can not delete incomplete type");
|
||||
delete [] ptr;
|
||||
}
|
||||
};
|
||||
using ::boost::movelib::default_delete;
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
42
include/boost/thread/csbl/memory/shared_ptr.hpp
Normal file
42
include/boost/thread/csbl/memory/shared_ptr.hpp
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright (C) 2014 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)
|
||||
//
|
||||
// 2014/10 Vicente J. Botet Escriba
|
||||
// Creation.
|
||||
|
||||
#ifndef BOOST_CSBL_MEMORY_SHARED_PTR_HPP
|
||||
#define BOOST_CSBL_MEMORY_SHARED_PTR_HPP
|
||||
|
||||
#include <boost/thread/csbl/memory/config.hpp>
|
||||
|
||||
#if defined BOOST_NO_CXX11_SMART_PTR
|
||||
|
||||
#include <boost/smart_ptr/shared_ptr.hpp>
|
||||
#include <boost/smart_ptr/make_shared.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace csbl
|
||||
{
|
||||
using ::boost::shared_ptr;
|
||||
using ::boost::make_shared;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace csbl
|
||||
{
|
||||
using std::shared_ptr;
|
||||
using std::make_shared;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // header
|
||||
@@ -1,106 +1,28 @@
|
||||
// Copyright (C) 2013 Vicente J. Botet Escriba
|
||||
// Copyright (C) 2013-2014 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)
|
||||
//
|
||||
// 2013/10 Vicente J. Botet Escriba
|
||||
// Creation.
|
||||
// Creation using interprocess::unique_ptr.
|
||||
// 2014/09 Vicente J. Botet Escriba
|
||||
// Adaptation to movelib::unique_ptr
|
||||
|
||||
#ifndef BOOST_CSBL_MEMORY_UNIQUE_PTR_HPP
|
||||
#define BOOST_CSBL_MEMORY_UNIQUE_PTR_HPP
|
||||
|
||||
#include <boost/thread/csbl/memory/config.hpp>
|
||||
|
||||
// 20.8.1 class template unique_ptr:
|
||||
#if defined BOOST_NO_CXX11_SMART_PTR
|
||||
#include <boost/thread/csbl/memory/default_delete.hpp>
|
||||
|
||||
#include <boost/interprocess/smart_ptr/unique_ptr.hpp>
|
||||
#include <boost/move/unique_ptr.hpp>
|
||||
#include <boost/move/make_unique.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace csbl
|
||||
{
|
||||
template <class T, class D = default_delete<T> > class unique_ptr :
|
||||
public ::boost::interprocess::unique_ptr<T,D>
|
||||
{
|
||||
typedef ::boost::interprocess::unique_ptr<T,D> base_type;
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(unique_ptr)
|
||||
protected:
|
||||
//typedef typename base_type::nat nat;
|
||||
//typedef typename base_type::nullptr_t nullptr_t;
|
||||
struct nat {int for_bool;};
|
||||
struct nat2 {int for_nullptr;};
|
||||
typedef int nat2::*nullptr_t;
|
||||
using ::boost::movelib::unique_ptr;
|
||||
using ::boost::movelib::make_unique;
|
||||
|
||||
public:
|
||||
typedef typename base_type::element_type element_type;
|
||||
typedef typename base_type::deleter_type deleter_type;
|
||||
typedef typename base_type::pointer pointer;
|
||||
|
||||
unique_ptr() : base_type()
|
||||
{}
|
||||
explicit unique_ptr(pointer p): base_type(p)
|
||||
{}
|
||||
unique_ptr(pointer p
|
||||
,typename interprocess::ipcdetail::if_<interprocess::ipcdetail::is_reference<D>
|
||||
,D
|
||||
,typename interprocess::ipcdetail::add_reference<const D>::type>::type d)
|
||||
: base_type(p, d)
|
||||
{}
|
||||
unique_ptr(BOOST_RV_REF(unique_ptr) u)
|
||||
: base_type(boost::move(static_cast<base_type&>(u)))
|
||||
{}
|
||||
template <class U, class E>
|
||||
unique_ptr(BOOST_RV_REF_BEG unique_ptr<U, E> BOOST_RV_REF_END u,
|
||||
typename interprocess::ipcdetail::enable_if_c<
|
||||
interprocess::ipcdetail::is_convertible<typename unique_ptr<U, E>::pointer, pointer>::value &&
|
||||
interprocess::ipcdetail::is_convertible<E, D>::value &&
|
||||
(
|
||||
!interprocess::ipcdetail::is_reference<D>::value ||
|
||||
interprocess::ipcdetail::is_same<D, E>::value
|
||||
)
|
||||
,
|
||||
nat
|
||||
>::type = nat())
|
||||
: base_type(boost::move(static_cast< ::boost::interprocess::unique_ptr<U,E>&>(u)))
|
||||
{}
|
||||
unique_ptr& operator=(BOOST_RV_REF(unique_ptr) u)
|
||||
{
|
||||
this->base_type::operator=(boost::move(static_cast<base_type&>(u)));
|
||||
return *this;
|
||||
}
|
||||
template <class U, class E>
|
||||
unique_ptr& operator=(BOOST_RV_REF_BEG unique_ptr<U, E> BOOST_RV_REF_END u)
|
||||
{
|
||||
this->base_type::template operator=<U,E>(boost::move(static_cast< ::boost::interprocess::unique_ptr<U,E>&>(u)));
|
||||
return *this;
|
||||
}
|
||||
unique_ptr& operator=(nullptr_t t)
|
||||
{
|
||||
this->base_type::operator=(t);
|
||||
return *this;
|
||||
}
|
||||
void swap(unique_ptr& u)
|
||||
{
|
||||
this->base_type::swap(u);
|
||||
}
|
||||
};
|
||||
template <class T, class D>
|
||||
class unique_ptr<T[], D> :
|
||||
public ::boost::interprocess::unique_ptr<T[],D>
|
||||
{
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
#else
|
||||
namespace boost
|
||||
{
|
||||
namespace csbl
|
||||
{
|
||||
using ::std::unique_ptr;
|
||||
}
|
||||
}
|
||||
#endif // BOOST_NO_CXX11_SMART_PTR
|
||||
#endif // header
|
||||
|
||||
@@ -28,10 +28,14 @@ namespace boost
|
||||
#if defined BOOST_THREAD_USES_BOOST_TUPLE
|
||||
using ::boost::tuple;
|
||||
using ::boost::get;
|
||||
using ::boost::make_tuple;
|
||||
//using ::boost::tuple_size;
|
||||
#else
|
||||
// 20.4.2, class template tuple:
|
||||
using ::std::tuple;
|
||||
using ::std::get;
|
||||
using ::std::make_tuple;
|
||||
using ::std::tuple_size;
|
||||
// 20.4.2.4, tuple creation functions:
|
||||
// 20.4.2.5, tuple helper classes:
|
||||
// 20.4.2.6, element access:
|
||||
|
||||
@@ -239,7 +239,6 @@
|
||||
! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
|
||||
! defined(BOOST_NO_CXX11_DECLTYPE) && \
|
||||
! defined(BOOST_NO_CXX11_DECLTYPE_N3276) && \
|
||||
! defined(BOOST_THREAD_NO_CXX11_DECLTYPE_N3276) && \
|
||||
! defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) && \
|
||||
! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
|
||||
! defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
@@ -354,6 +353,12 @@
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES || defined BOOST_THREAD_USES_MOVE
|
||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
#define BOOST_THREAD_FUTURE_USES_OPTIONAL
|
||||
#endif
|
||||
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, < 0x600)
|
||||
# pragma warn -8008 // Condition always true/false
|
||||
# pragma warn -8080 // Identifier declared but never used
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
* makes it private.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS
|
||||
#if ! defined BOOST_NO_CXX11_DELETED_FUNCTIONS && ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
#define BOOST_THREAD_DELETE_COPY_CTOR(CLASS) \
|
||||
CLASS(CLASS const&) = delete; \
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace boost
|
||||
|
||||
void call()
|
||||
{
|
||||
f();
|
||||
if (impl) f();
|
||||
}
|
||||
};
|
||||
public:
|
||||
|
||||
@@ -47,7 +47,6 @@ namespace boost
|
||||
#if ! defined(BOOST_NO_SFINAE_EXPR) && \
|
||||
! defined(BOOST_NO_CXX11_DECLTYPE) && \
|
||||
! defined(BOOST_NO_CXX11_DECLTYPE_N3276) && \
|
||||
! defined(BOOST_THREAD_NO_CXX11_DECLTYPE_N3276) && \
|
||||
! defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES)
|
||||
|
||||
#define BOOST_THREAD_PROVIDES_INVOKE
|
||||
@@ -339,7 +338,6 @@ namespace boost
|
||||
! defined BOOST_NO_CXX11_HDR_FUNCTIONAL && \
|
||||
defined BOOST_MSVC
|
||||
|
||||
//#error
|
||||
template <class Ret, class Fp>
|
||||
inline
|
||||
Ret invoke(BOOST_THREAD_RV_REF(Fp) f)
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
// The invoker code is based on the one from libcxx.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef BOOST_THREAD_DETAIL_ASYNC_FUNCT_HPP
|
||||
#define BOOST_THREAD_DETAIL_ASYNC_FUNCT_HPP
|
||||
#ifndef BOOST_THREAD_DETAIL_INVOKER_HPP
|
||||
#define BOOST_THREAD_DETAIL_INVOKER_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace boost
|
||||
csbl::tuple<Fp, Args...> f_;
|
||||
|
||||
public:
|
||||
BOOST_THREAD_MOVABLE_ONLY( invoker)
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE( invoker)
|
||||
//typedef typename invoke_of<_Fp, _Args...>::type Rp;
|
||||
typedef typename result_of<Fp(Args...)>::type result_type;
|
||||
|
||||
@@ -65,6 +65,22 @@ namespace boost
|
||||
invoker(BOOST_THREAD_RV_REF(invoker) f) : f_(boost::move(BOOST_THREAD_RV(f).f_))
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker( const invoker& f) : f_(f.f_)
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker& operator=(BOOST_THREAD_RV_REF(invoker) f)
|
||||
{
|
||||
f_ = boost::move(BOOST_THREAD_RV(f).f_);
|
||||
}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker& operator=( BOOST_THREAD_COPY_ASSIGN_REF(invoker) f)
|
||||
{
|
||||
f_ = f.f_;
|
||||
}
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
typedef typename make_tuple_indices<1+sizeof...(Args), 1>::type Index;
|
||||
@@ -89,7 +105,7 @@ namespace boost
|
||||
csbl::tuple<Fp, Args...> f_;
|
||||
|
||||
public:
|
||||
BOOST_THREAD_MOVABLE_ONLY( invoker_ret)
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE( invoker_ret)
|
||||
typedef R result_type;
|
||||
|
||||
template <class F, class ... As>
|
||||
@@ -147,7 +163,7 @@ namespace boost
|
||||
Fp fp_; \
|
||||
BOOST_PP_REPEAT(n, BOOST_THREAD_DCL, ~) \
|
||||
public: \
|
||||
BOOST_THREAD_MOVABLE_ONLY(invoker) \
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker) \
|
||||
typedef typename result_of<Fp(BOOST_PP_ENUM_PARAMS(n, Arg))>::type result_type; \
|
||||
\
|
||||
template <class F BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class A) > \
|
||||
@@ -160,7 +176,7 @@ namespace boost
|
||||
{} \
|
||||
\
|
||||
BOOST_SYMBOL_VISIBLE \
|
||||
invoker(BOOST_THREAD_FWD_REF(invoker) x) \
|
||||
invoker(BOOST_THREAD_RV_REF(invoker) x) \
|
||||
: fp_(boost::move(x.fp_)) \
|
||||
BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_RHS_PARAM, ~) \
|
||||
{} \
|
||||
@@ -179,7 +195,7 @@ namespace boost
|
||||
Fp fp_; \
|
||||
BOOST_PP_REPEAT(n, BOOST_THREAD_DCL, ~) \
|
||||
public: \
|
||||
BOOST_THREAD_MOVABLE_ONLY(invoker) \
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker) \
|
||||
typedef typename result_of<Fp(BOOST_PP_ENUM_PARAMS(n, Arg))>::type result_type; \
|
||||
\
|
||||
template <class R2 BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class A) > \
|
||||
@@ -192,7 +208,7 @@ namespace boost
|
||||
{} \
|
||||
\
|
||||
BOOST_SYMBOL_VISIBLE \
|
||||
invoker(BOOST_THREAD_FWD_REF(invoker) x) \
|
||||
invoker(BOOST_THREAD_RV_REF(invoker) x) \
|
||||
: fp_(x.fp_) \
|
||||
BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_RHS_PARAM, ~) \
|
||||
{} \
|
||||
@@ -248,7 +264,7 @@ namespace boost
|
||||
//::boost::tuple<Fp, T0, T1, T2, T3, T4, T5, T6, T7, T8> f_;
|
||||
|
||||
public:
|
||||
BOOST_THREAD_MOVABLE_ONLY(invoker)
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
|
||||
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5, T6, T7, T8)>::type result_type;
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
@@ -276,7 +292,7 @@ namespace boost
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker(BOOST_THREAD_FWD_REF(invoker) f)
|
||||
invoker(BOOST_THREAD_RV_REF(invoker) f)
|
||||
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
|
||||
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
|
||||
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
|
||||
@@ -317,7 +333,7 @@ namespace boost
|
||||
T6 v6_;
|
||||
T7 v7_;
|
||||
public:
|
||||
BOOST_THREAD_MOVABLE_ONLY(invoker)
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
|
||||
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5, T6, T7)>::type result_type;
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
@@ -343,7 +359,7 @@ namespace boost
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker(BOOST_THREAD_FWD_REF(invoker) f)
|
||||
invoker(BOOST_THREAD_RV_REF(invoker) f)
|
||||
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
|
||||
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
|
||||
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
|
||||
@@ -381,7 +397,7 @@ namespace boost
|
||||
T5 v5_;
|
||||
T6 v6_;
|
||||
public:
|
||||
BOOST_THREAD_MOVABLE_ONLY(invoker)
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
|
||||
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5, T6)>::type result_type;
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
@@ -405,7 +421,7 @@ namespace boost
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker(BOOST_THREAD_FWD_REF(invoker) f)
|
||||
invoker(BOOST_THREAD_RV_REF(invoker) f)
|
||||
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
|
||||
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
|
||||
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
|
||||
@@ -440,7 +456,7 @@ namespace boost
|
||||
T4 v4_;
|
||||
T5 v5_;
|
||||
public:
|
||||
BOOST_THREAD_MOVABLE_ONLY(invoker)
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
|
||||
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5)>::type result_type;
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
@@ -462,7 +478,7 @@ namespace boost
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker(BOOST_THREAD_FWD_REF(invoker) f)
|
||||
invoker(BOOST_THREAD_RV_REF(invoker) f)
|
||||
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
|
||||
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
|
||||
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
|
||||
@@ -494,7 +510,7 @@ namespace boost
|
||||
T3 v3_;
|
||||
T4 v4_;
|
||||
public:
|
||||
BOOST_THREAD_MOVABLE_ONLY(invoker)
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
|
||||
typedef typename result_of<Fp(T0, T1, T2, T3, T4)>::type result_type;
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
@@ -514,7 +530,7 @@ namespace boost
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker(BOOST_THREAD_FWD_REF(invoker) f)
|
||||
invoker(BOOST_THREAD_RV_REF(invoker) f)
|
||||
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
|
||||
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
|
||||
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
|
||||
@@ -543,7 +559,7 @@ namespace boost
|
||||
T2 v2_;
|
||||
T3 v3_;
|
||||
public:
|
||||
BOOST_THREAD_MOVABLE_ONLY(invoker)
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
|
||||
typedef typename result_of<Fp(T0, T1, T2, T3)>::type result_type;
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
@@ -561,7 +577,7 @@ namespace boost
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker(BOOST_THREAD_FWD_REF(invoker) f)
|
||||
invoker(BOOST_THREAD_RV_REF(invoker) f)
|
||||
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
|
||||
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
|
||||
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
|
||||
@@ -587,7 +603,7 @@ namespace boost
|
||||
T1 v1_;
|
||||
T2 v2_;
|
||||
public:
|
||||
BOOST_THREAD_MOVABLE_ONLY(invoker)
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
|
||||
typedef typename result_of<Fp(T0, T1, T2)>::type result_type;
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
@@ -603,7 +619,7 @@ namespace boost
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker(BOOST_THREAD_FWD_REF(invoker) f)
|
||||
invoker(BOOST_THREAD_RV_REF(invoker) f)
|
||||
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
|
||||
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
|
||||
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
|
||||
@@ -626,7 +642,7 @@ namespace boost
|
||||
T0 v0_;
|
||||
T1 v1_;
|
||||
public:
|
||||
BOOST_THREAD_MOVABLE_ONLY(invoker)
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
|
||||
typedef typename result_of<Fp(T0, T1)>::type result_type;
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
@@ -640,7 +656,7 @@ namespace boost
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker(BOOST_THREAD_FWD_REF(invoker) f)
|
||||
invoker(BOOST_THREAD_RV_REF(invoker) f)
|
||||
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
|
||||
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
|
||||
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
|
||||
@@ -660,7 +676,7 @@ namespace boost
|
||||
Fp fp_;
|
||||
T0 v0_;
|
||||
public:
|
||||
BOOST_THREAD_MOVABLE_ONLY(invoker)
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
|
||||
typedef typename result_of<Fp(T0)>::type result_type;
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
@@ -672,7 +688,7 @@ namespace boost
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker(BOOST_THREAD_FWD_REF(invoker) f)
|
||||
invoker(BOOST_THREAD_RV_REF(invoker) f)
|
||||
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
|
||||
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
|
||||
{}
|
||||
@@ -697,7 +713,7 @@ namespace boost
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker(BOOST_THREAD_FWD_REF(invoker) f)
|
||||
invoker(BOOST_THREAD_RV_REF(invoker) f)
|
||||
: fp_(boost::move(f.fp_))
|
||||
{}
|
||||
result_type operator()()
|
||||
@@ -719,7 +735,7 @@ namespace boost
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker(BOOST_THREAD_FWD_REF(invoker) f)
|
||||
invoker(BOOST_THREAD_RV_REF(invoker) f)
|
||||
: fp_(f.fp_)
|
||||
{}
|
||||
result_type operator()()
|
||||
|
||||
@@ -80,6 +80,7 @@ namespace boost
|
||||
|
||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
|
||||
#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) BOOST_COPY_ASSIGN_REF(TYPE)
|
||||
#define BOOST_THREAD_RV_REF(TYPE) BOOST_RV_REF(TYPE)
|
||||
#define BOOST_THREAD_RV_REF_2_TEMPL_ARGS(TYPE) BOOST_RV_REF_2_TEMPL_ARGS(TYPE)
|
||||
#define BOOST_THREAD_RV_REF_BEG BOOST_RV_REF_BEG
|
||||
@@ -100,6 +101,7 @@ namespace boost
|
||||
|
||||
#elif ! defined BOOST_NO_CXX11_RVALUE_REFERENCES && defined BOOST_MSVC
|
||||
|
||||
#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) BOOST_COPY_ASSIGN_REF(TYPE)
|
||||
#define BOOST_THREAD_RV_REF(TYPE) BOOST_RV_REF(TYPE)
|
||||
#define BOOST_THREAD_RV_REF_2_TEMPL_ARGS(TYPE) BOOST_RV_REF_2_TEMPL_ARGS(TYPE)
|
||||
#define BOOST_THREAD_RV_REF_BEG BOOST_RV_REF_BEG
|
||||
@@ -121,6 +123,7 @@ namespace boost
|
||||
#else
|
||||
|
||||
#if defined BOOST_THREAD_USES_MOVE
|
||||
#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) BOOST_COPY_ASSIGN_REF(TYPE)
|
||||
#define BOOST_THREAD_RV_REF(TYPE) BOOST_RV_REF(TYPE)
|
||||
#define BOOST_THREAD_RV_REF_2_TEMPL_ARGS(TYPE) BOOST_RV_REF_2_TEMPL_ARGS(TYPE)
|
||||
#define BOOST_THREAD_RV_REF_BEG BOOST_RV_REF_BEG
|
||||
@@ -140,6 +143,7 @@ namespace boost
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) const TYPE&
|
||||
#define BOOST_THREAD_RV_REF(TYPE) boost::detail::thread_move_t< TYPE >
|
||||
#define BOOST_THREAD_RV_REF_BEG boost::detail::thread_move_t<
|
||||
#define BOOST_THREAD_RV_REF_END >
|
||||
@@ -198,6 +202,8 @@ namespace detail
|
||||
|
||||
#define BOOST_THREAD_MOVABLE(TYPE)
|
||||
|
||||
#define BOOST_THREAD_COPYABLE(TYPE)
|
||||
|
||||
#else
|
||||
|
||||
#if defined BOOST_THREAD_USES_MOVE
|
||||
@@ -220,6 +226,11 @@ namespace detail
|
||||
return *static_cast<const ::boost::rv<TYPE>* >(this); \
|
||||
}\
|
||||
|
||||
#define BOOST_THREAD_COPYABLE(TYPE) \
|
||||
TYPE& operator=(TYPE &t)\
|
||||
{ this->operator=(static_cast<const ::boost::rv<TYPE> &>(const_cast<const TYPE &>(t))); return *this;}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_THREAD_MOVABLE(TYPE) \
|
||||
@@ -233,15 +244,20 @@ namespace detail
|
||||
return x; \
|
||||
} \
|
||||
|
||||
#define BOOST_THREAD_COPYABLE(TYPE)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define BOOST_THREAD_MOVABLE_ONLY(TYPE) \
|
||||
BOOST_THREAD_NO_COPYABLE(TYPE) \
|
||||
BOOST_THREAD_MOVABLE(TYPE) \
|
||||
typedef int boost_move_no_copy_constructor_or_assign; \
|
||||
|
||||
|
||||
#define BOOST_THREAD_COPYABLE_AND_MOVABLE(TYPE) \
|
||||
BOOST_THREAD_MOVABLE(TYPE) \
|
||||
BOOST_THREAD_COPYABLE(TYPE) \
|
||||
BOOST_THREAD_MOVABLE(TYPE) \
|
||||
|
||||
|
||||
|
||||
@@ -249,6 +265,31 @@ namespace boost
|
||||
{
|
||||
namespace thread_detail
|
||||
{
|
||||
|
||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
#elif defined BOOST_THREAD_USES_MOVE
|
||||
template <class T>
|
||||
struct is_rv
|
||||
: ::boost::move_detail::is_rv<T>
|
||||
{};
|
||||
|
||||
#else
|
||||
template <class T>
|
||||
struct is_rv
|
||||
: ::boost::integral_constant<bool, false>
|
||||
{};
|
||||
|
||||
template <class T>
|
||||
struct is_rv< ::boost::detail::thread_move_t<T> >
|
||||
: ::boost::integral_constant<bool, true>
|
||||
{};
|
||||
|
||||
template <class T>
|
||||
struct is_rv< const ::boost::detail::thread_move_t<T> >
|
||||
: ::boost::integral_constant<bool, true>
|
||||
{};
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
template <class Tp>
|
||||
struct remove_reference : boost::remove_reference<Tp> {};
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/thread/detail/memory.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/smart_ptr/shared_ptr.hpp>
|
||||
#include <boost/thread/csbl/memory/shared_ptr.hpp>
|
||||
#include <boost/type_traits/decay.hpp>
|
||||
|
||||
namespace boost
|
||||
@@ -33,7 +33,7 @@ namespace boost
|
||||
{
|
||||
}
|
||||
};
|
||||
shared_ptr<impl_base> impl;
|
||||
csbl::shared_ptr<impl_base> impl;
|
||||
template <typename F>
|
||||
struct impl_type: impl_base
|
||||
{
|
||||
@@ -64,7 +64,7 @@ namespace boost
|
||||
}
|
||||
};
|
||||
public:
|
||||
BOOST_THREAD_MOVABLE(nullary_function)
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE(nullary_function)
|
||||
|
||||
explicit nullary_function(void (*f)()):
|
||||
impl(new impl_type_ptr(f))
|
||||
@@ -90,29 +90,39 @@ namespace boost
|
||||
{
|
||||
}
|
||||
nullary_function(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT :
|
||||
#if defined BOOST_NO_CXX11_SMART_PTR
|
||||
impl(BOOST_THREAD_RV(other).impl)
|
||||
{
|
||||
BOOST_THREAD_RV(other).impl.reset();
|
||||
}
|
||||
#else
|
||||
impl(boost::move(other.impl))
|
||||
{
|
||||
}
|
||||
#endif
|
||||
~nullary_function()
|
||||
{
|
||||
}
|
||||
|
||||
nullary_function& operator=(nullary_function const& other) BOOST_NOEXCEPT
|
||||
nullary_function& operator=(BOOST_THREAD_COPY_ASSIGN_REF(nullary_function) other) BOOST_NOEXCEPT
|
||||
{
|
||||
impl=other.impl;
|
||||
return *this;
|
||||
}
|
||||
nullary_function& operator=(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT
|
||||
{
|
||||
#if defined BOOST_NO_CXX11_SMART_PTR
|
||||
impl=BOOST_THREAD_RV(other).impl;
|
||||
BOOST_THREAD_RV(other).impl.reset();
|
||||
#else
|
||||
impl = boost::move(other.impl);
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void operator()()
|
||||
{ impl->call();}
|
||||
{ if (impl) impl->call();}
|
||||
|
||||
};
|
||||
|
||||
@@ -126,7 +136,7 @@ namespace boost
|
||||
{
|
||||
}
|
||||
};
|
||||
shared_ptr<impl_base> impl;
|
||||
csbl::shared_ptr<impl_base> impl;
|
||||
template <typename F>
|
||||
struct impl_type: impl_base
|
||||
{
|
||||
@@ -158,7 +168,7 @@ namespace boost
|
||||
}
|
||||
};
|
||||
public:
|
||||
BOOST_THREAD_MOVABLE(nullary_function)
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE(nullary_function)
|
||||
|
||||
nullary_function(R (*f)()):
|
||||
impl(new impl_type_ptr(f))
|
||||
@@ -179,10 +189,16 @@ namespace boost
|
||||
{
|
||||
}
|
||||
nullary_function(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT :
|
||||
#if defined BOOST_NO_CXX11_SMART_PTR
|
||||
impl(BOOST_THREAD_RV(other).impl)
|
||||
{
|
||||
BOOST_THREAD_RV(other).impl.reset();
|
||||
}
|
||||
#else
|
||||
impl(boost::move(other.impl))
|
||||
{
|
||||
}
|
||||
#endif
|
||||
nullary_function()
|
||||
: impl()
|
||||
{
|
||||
@@ -191,23 +207,28 @@ namespace boost
|
||||
{
|
||||
}
|
||||
|
||||
nullary_function& operator=(nullary_function const& other) BOOST_NOEXCEPT
|
||||
nullary_function& operator=(BOOST_THREAD_COPY_ASSIGN_REF(nullary_function) other) BOOST_NOEXCEPT
|
||||
{
|
||||
impl=other.impl;
|
||||
return *this;
|
||||
}
|
||||
nullary_function& operator=(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT
|
||||
{
|
||||
#if defined BOOST_NO_CXX11_SMART_PTR
|
||||
impl=BOOST_THREAD_RV(other).impl;
|
||||
BOOST_THREAD_RV(other).impl.reset();
|
||||
#else
|
||||
impl = boost::move(other.impl);
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
R operator()()
|
||||
{ return impl->call();}
|
||||
{ if (impl) return impl->call(); else return R();}
|
||||
|
||||
};
|
||||
}
|
||||
//BOOST_THREAD_DCL_MOVABLE_BEG(F) detail::nullary_function<F> BOOST_THREAD_DCL_MOVABLE_END
|
||||
}
|
||||
|
||||
#endif // header
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/predef/platform.h>
|
||||
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#ifndef BOOST_NO_IOSTREAM
|
||||
@@ -291,7 +292,8 @@ namespace boost
|
||||
template <class F>
|
||||
explicit thread(F f
|
||||
, typename disable_if_c<
|
||||
boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F)>::value
|
||||
boost::thread_detail::is_rv<F>::value // todo ass a thread_detail::is_rv
|
||||
//boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F)>::value
|
||||
//|| is_same<typename decay<F>::type, thread>::value
|
||||
, dummy* >::type=0
|
||||
):
|
||||
@@ -301,7 +303,8 @@ namespace boost
|
||||
}
|
||||
template <class F>
|
||||
thread(attributes const& attrs, F f
|
||||
, typename disable_if<boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F) >, dummy* >::type=0
|
||||
, typename disable_if<boost::thread_detail::is_rv<F>, dummy* >::type=0
|
||||
//, typename disable_if<boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F) >, dummy* >::type=0
|
||||
):
|
||||
thread_info(make_thread_info(f))
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2013 Vicente J. Botet Escriba
|
||||
// Copyright (C) 2013-2014 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)
|
||||
@@ -85,12 +85,23 @@ namespace executors
|
||||
*/
|
||||
void worker_thread()
|
||||
{
|
||||
while (!closed())
|
||||
try
|
||||
{
|
||||
schedule_one_or_yield();
|
||||
for(;;)
|
||||
{
|
||||
work task;
|
||||
queue_op_status st = work_queue.wait_pull_front(task);
|
||||
if (st == queue_op_status::closed) return;
|
||||
task();
|
||||
}
|
||||
}
|
||||
while (try_executing_one())
|
||||
catch (std::exception& )
|
||||
{
|
||||
return;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
@@ -98,37 +109,19 @@ namespace executors
|
||||
void worker_thread1(AtThreadEntry& at_thread_entry)
|
||||
{
|
||||
at_thread_entry(*this);
|
||||
while (!closed())
|
||||
{
|
||||
schedule_one_or_yield();
|
||||
}
|
||||
while (try_executing_one())
|
||||
{
|
||||
}
|
||||
worker_thread();
|
||||
}
|
||||
#endif
|
||||
void worker_thread2(void(*at_thread_entry)(basic_thread_pool&))
|
||||
{
|
||||
at_thread_entry(*this);
|
||||
while (!closed())
|
||||
{
|
||||
schedule_one_or_yield();
|
||||
}
|
||||
while (try_executing_one())
|
||||
{
|
||||
}
|
||||
worker_thread();
|
||||
}
|
||||
template <class AtThreadEntry>
|
||||
void worker_thread3(BOOST_THREAD_FWD_REF(AtThreadEntry) at_thread_entry)
|
||||
{
|
||||
at_thread_entry(*this);
|
||||
while (!closed())
|
||||
{
|
||||
schedule_one_or_yield();
|
||||
}
|
||||
while (try_executing_one())
|
||||
{
|
||||
}
|
||||
worker_thread();
|
||||
}
|
||||
static void do_nothing_at_thread_entry(basic_thread_pool&) {}
|
||||
|
||||
@@ -238,6 +231,17 @@ namespace executors
|
||||
// joins all the threads as the threads were scoped_threads
|
||||
}
|
||||
|
||||
/**
|
||||
* \b Effects: join all the threads.
|
||||
*/
|
||||
void join()
|
||||
{
|
||||
for (unsigned i = 0; i < threads.size(); ++i)
|
||||
{
|
||||
threads[i].join();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \b Effects: close the \c basic_thread_pool for submissions.
|
||||
* The worker threads will work until there is no more closures to run.
|
||||
@@ -271,33 +275,20 @@ namespace executors
|
||||
template <typename Closure>
|
||||
void submit(Closure & closure)
|
||||
{
|
||||
//work w ((closure));
|
||||
//work_queue.push_back(boost::move(w));
|
||||
work_queue.push_back(work(closure)); // todo check why this doesn't work
|
||||
work_queue.push_back(work(closure));
|
||||
}
|
||||
#endif
|
||||
void submit(void (*closure)())
|
||||
{
|
||||
//work w ((closure));
|
||||
//work_queue.push_back(boost::move(w));
|
||||
work_queue.push_back(work(closure)); // todo check why this doesn't work
|
||||
work_queue.push_back(work(closure));
|
||||
}
|
||||
|
||||
#if 0
|
||||
template <typename Closure>
|
||||
void submit(BOOST_THREAD_RV_REF(Closure) closure)
|
||||
{
|
||||
work w = boost::move(closure);
|
||||
work_queue.push_back(boost::move(w));
|
||||
//work_queue.push_back(work(boost::move(closure))); // todo check why this doesn't work
|
||||
}
|
||||
#else
|
||||
template <typename Closure>
|
||||
void submit(BOOST_THREAD_FWD_REF(Closure) closure)
|
||||
{
|
||||
work_queue.push_back(work(boost::forward<Closure>(closure)));
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \b Requires: This must be called from an scheduled task.
|
||||
*
|
||||
|
||||
@@ -32,43 +32,55 @@ namespace boost
|
||||
executor() {}
|
||||
|
||||
/**
|
||||
* \b Effects: Destroys the executor.
|
||||
* \par Effects
|
||||
* Destroys the executor.
|
||||
*
|
||||
* \b Synchronization: The completion of all the closures happen before the completion of the executor destructor.
|
||||
* \par Synchronization
|
||||
* The completion of all the closures happen before the completion of the executor destructor.
|
||||
*/
|
||||
virtual ~executor() {};
|
||||
|
||||
/**
|
||||
* \b Effects: close the \c executor for submissions.
|
||||
* \par Effects
|
||||
* Close the \c executor for submissions.
|
||||
* The worker threads will work until there is no more closures to run.
|
||||
*/
|
||||
virtual void close() = 0;
|
||||
|
||||
/**
|
||||
* \b Returns: whether the pool is closed for submissions.
|
||||
* \par Returns
|
||||
* Whether the pool is closed for submissions.
|
||||
*/
|
||||
virtual bool closed() = 0;
|
||||
|
||||
/**
|
||||
* \b Effects: The specified closure will be scheduled for execution at some point in the future.
|
||||
* \par Effects
|
||||
* The specified closure will be scheduled for execution at some point in the future.
|
||||
* If invoked closure throws an exception the executor will call std::terminate, as is the case with threads.
|
||||
*
|
||||
* \b Synchronization: completion of closure on a particular thread happens before destruction of thread's thread local variables.
|
||||
* \par Synchronization
|
||||
* Ccompletion of closure on a particular thread happens before destruction of thread's thread local variables.
|
||||
*
|
||||
* \b Throws: \c sync_queue_is_closed if the thread pool is closed.
|
||||
* \par Throws
|
||||
* \c sync_queue_is_closed if the thread pool is closed.
|
||||
* Whatever exception that can be throw while storing the closure.
|
||||
*/
|
||||
virtual void submit(BOOST_THREAD_RV_REF(work) closure) = 0;
|
||||
// virtual void submit(work& closure) = 0;
|
||||
|
||||
/**
|
||||
* \b Requires: \c Closure is a model of Callable(void()) and a model of CopyConstructible/MoveConstructible.
|
||||
* \par Requires
|
||||
* \c Closure is a model of Callable(void()) and a model of CopyConstructible/MoveConstructible.
|
||||
*
|
||||
* \b Effects: The specified closure will be scheduled for execution at some point in the future.
|
||||
* \par Effects
|
||||
* The specified closure will be scheduled for execution at some point in the future.
|
||||
* If invoked closure throws an exception the thread pool will call std::terminate, as is the case with threads.
|
||||
*
|
||||
* \b Synchronization: completion of closure on a particular thread happens before destruction of thread's thread local variables.
|
||||
* \par Synchronization
|
||||
* Completion of closure on a particular thread happens before destruction of thread's thread local variables.
|
||||
*
|
||||
* \b Throws: \c sync_queue_is_closed if the thread pool is closed.
|
||||
* \par Throws
|
||||
* \c sync_queue_is_closed if the thread pool is closed.
|
||||
* Whatever exception that can be throw while storing the closure.
|
||||
*/
|
||||
|
||||
@@ -94,16 +106,23 @@ namespace boost
|
||||
}
|
||||
|
||||
/**
|
||||
* Effects: try to execute one task.
|
||||
* Returns: whether a task has been executed.
|
||||
* Throws: whatever the current task constructor throws or the task() throws.
|
||||
* \par Effects
|
||||
* Try to execute one task.
|
||||
*
|
||||
* \par Returns
|
||||
* Whether a task has been executed.
|
||||
*
|
||||
* \par Throws
|
||||
* Whatever the current task constructor throws or the task() throws.
|
||||
*/
|
||||
virtual bool try_executing_one() = 0;
|
||||
|
||||
/**
|
||||
* \b Requires: This must be called from an scheduled task.
|
||||
* \par Requires
|
||||
* This must be called from an scheduled task.
|
||||
*
|
||||
* \b Effects: reschedule functions until pred()
|
||||
* \par Effects
|
||||
* Reschedule functions until pred()
|
||||
*/
|
||||
template <typename Pred>
|
||||
bool reschedule_until(Pred const& pred)
|
||||
@@ -119,7 +138,6 @@ namespace boost
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
using executors::executor;
|
||||
}
|
||||
|
||||
@@ -97,39 +97,28 @@ namespace executors
|
||||
*/
|
||||
void submit(BOOST_THREAD_RV_REF(work) closure) {
|
||||
return ex.submit(boost::move(closure));
|
||||
//return ex.submit(boost::forward<work>(closure));
|
||||
}
|
||||
// void submit(work & closure) {
|
||||
// return ex.submit(closure);
|
||||
// }
|
||||
|
||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
template <typename Closure>
|
||||
void submit(Closure & closure)
|
||||
{
|
||||
work w ((closure));
|
||||
submit(boost::move(w));
|
||||
//submit(work(closure));
|
||||
submit(work(closure));
|
||||
}
|
||||
#endif
|
||||
void submit(void (*closure)())
|
||||
{
|
||||
work w ((closure));
|
||||
submit(boost::move(w));
|
||||
//submit(work(closure));
|
||||
submit(work(closure));
|
||||
}
|
||||
|
||||
#if 0
|
||||
template <typename Closure>
|
||||
void submit(BOOST_THREAD_RV_REF(Closure) closure)
|
||||
{
|
||||
work w =boost::move(closure);
|
||||
submit(boost::move(w));
|
||||
}
|
||||
#else
|
||||
template <typename Closure>
|
||||
void submit(BOOST_THREAD_FWD_REF(Closure) closure)
|
||||
{
|
||||
submit(work(boost::forward<Closure>(closure)));
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Effects: try to execute one task.
|
||||
|
||||
211
include/boost/thread/executors/generic_executor_ref.hpp
Normal file
211
include/boost/thread/executors/generic_executor_ref.hpp
Normal file
@@ -0,0 +1,211 @@
|
||||
// Copyright (C) 2014 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)
|
||||
//
|
||||
|
||||
#ifndef BOOST_THREAD_EXECUTORS_GENERIC_EXECUTOR_REF_HPP
|
||||
#define BOOST_THREAD_EXECUTORS_GENERIC_EXECUTOR_REF_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/thread/detail/delete.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/executors/executor.hpp>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace executors
|
||||
{
|
||||
|
||||
template <class Executor>
|
||||
class executor_ref : public executor
|
||||
{
|
||||
Executor& ex;
|
||||
public:
|
||||
/// type-erasure to store the works to do
|
||||
typedef executors::work work;
|
||||
|
||||
/// executor is not copyable.
|
||||
BOOST_THREAD_NO_COPYABLE(executor_ref)
|
||||
executor_ref(Executor& ex) : ex(ex) {}
|
||||
|
||||
/**
|
||||
* \par Effects
|
||||
* Destroys the executor.
|
||||
*
|
||||
* \par Synchronization
|
||||
* The completion of all the closures happen before the completion of the executor destructor.
|
||||
*/
|
||||
~executor_ref() {};
|
||||
|
||||
/**
|
||||
* \par Effects
|
||||
* Close the \c executor for submissions.
|
||||
* The worker threads will work until there is no more closures to run.
|
||||
*/
|
||||
void close() { ex.close(); }
|
||||
|
||||
/**
|
||||
* \par Returns
|
||||
* Whether the pool is closed for submissions.
|
||||
*/
|
||||
bool closed() { return ex.closed(); }
|
||||
|
||||
/**
|
||||
* \par Effects
|
||||
* The specified closure will be scheduled for execution at some point in the future.
|
||||
* If invoked closure throws an exception the executor will call std::terminate, as is the case with threads.
|
||||
*
|
||||
* \par Synchronization
|
||||
* Ccompletion of closure on a particular thread happens before destruction of thread's thread local variables.
|
||||
*
|
||||
* \par Throws
|
||||
* \c sync_queue_is_closed if the thread pool is closed.
|
||||
* Whatever exception that can be throw while storing the closure.
|
||||
*/
|
||||
void submit(BOOST_THREAD_RV_REF(work) closure) {
|
||||
ex.submit(boost::move(closure));
|
||||
}
|
||||
// void submit(work& closure) {
|
||||
// ex.submit(closure);
|
||||
// }
|
||||
|
||||
|
||||
/**
|
||||
* \par Effects
|
||||
* Try to execute one task.
|
||||
*
|
||||
* \par Returns
|
||||
* Whether a task has been executed.
|
||||
*
|
||||
* \par Throws
|
||||
* Whatever the current task constructor throws or the task() throws.
|
||||
*/
|
||||
bool try_executing_one() { return ex.try_executing_one(); }
|
||||
|
||||
};
|
||||
|
||||
class generic_executor_ref
|
||||
{
|
||||
shared_ptr<executor> ex;
|
||||
public:
|
||||
/// type-erasure to store the works to do
|
||||
typedef executors::work work;
|
||||
|
||||
template<typename Executor>
|
||||
generic_executor_ref(Executor& ex)
|
||||
//: ex(make_shared<executor_ref<Executor> >(ex)) // todo check why this doesn't works with C++03
|
||||
: ex( new executor_ref<Executor>(ex) )
|
||||
{
|
||||
}
|
||||
|
||||
//generic_executor_ref(generic_executor_ref const& other) noexcept {}
|
||||
//generic_executor_ref& operator=(generic_executor_ref const& other) noexcept {}
|
||||
|
||||
|
||||
/**
|
||||
* \par Effects
|
||||
* Close the \c executor for submissions.
|
||||
* The worker threads will work until there is no more closures to run.
|
||||
*/
|
||||
void close() { ex->close(); }
|
||||
|
||||
/**
|
||||
* \par Returns
|
||||
* Whether the pool is closed for submissions.
|
||||
*/
|
||||
bool closed() { return ex->closed(); }
|
||||
|
||||
void submit(BOOST_THREAD_RV_REF(work) closure)
|
||||
{
|
||||
ex->submit(boost::forward<work>(closure));
|
||||
}
|
||||
|
||||
/**
|
||||
* \par Requires
|
||||
* \c Closure is a model of Callable(void()) and a model of CopyConstructible/MoveConstructible.
|
||||
*
|
||||
* \par Effects
|
||||
* The specified closure will be scheduled for execution at some point in the future.
|
||||
* If invoked closure throws an exception the thread pool will call std::terminate, as is the case with threads.
|
||||
*
|
||||
* \par Synchronization
|
||||
* Completion of closure on a particular thread happens before destruction of thread's thread local variables.
|
||||
*
|
||||
* \par Throws
|
||||
* \c sync_queue_is_closed if the thread pool is closed.
|
||||
* Whatever exception that can be throw while storing the closure.
|
||||
*/
|
||||
|
||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
template <typename Closure>
|
||||
void submit(Closure & closure)
|
||||
{
|
||||
work w ((closure));
|
||||
submit(boost::move(w));
|
||||
}
|
||||
#endif
|
||||
void submit(void (*closure)())
|
||||
{
|
||||
work w ((closure));
|
||||
submit(boost::move(w));
|
||||
}
|
||||
|
||||
template <typename Closure>
|
||||
void submit(BOOST_THREAD_RV_REF(Closure) closure)
|
||||
{
|
||||
work w = boost::move(closure);
|
||||
submit(boost::move(w));
|
||||
}
|
||||
|
||||
// size_t num_pending_closures() const
|
||||
// {
|
||||
// return ex->num_pending_closures();
|
||||
// }
|
||||
|
||||
/**
|
||||
* \par Effects
|
||||
* Try to execute one task.
|
||||
*
|
||||
* \par Returns
|
||||
* Whether a task has been executed.
|
||||
*
|
||||
* \par Throws
|
||||
* Whatever the current task constructor throws or the task() throws.
|
||||
*/
|
||||
bool try_executing_one() { return ex->try_executing_one(); }
|
||||
|
||||
/**
|
||||
* \par Requires
|
||||
* This must be called from an scheduled task.
|
||||
*
|
||||
* \par Effects
|
||||
* reschedule functions until pred()
|
||||
*/
|
||||
template <typename Pred>
|
||||
bool reschedule_until(Pred const& pred)
|
||||
{
|
||||
do {
|
||||
//schedule_one_or_yield();
|
||||
if ( ! try_executing_one())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} while (! pred());
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
using executors::executor_ref;
|
||||
using executors::generic_executor_ref;
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
@@ -148,24 +148,18 @@ namespace executors
|
||||
template <typename Closure>
|
||||
void submit(Closure & closure)
|
||||
{
|
||||
work w ((closure));
|
||||
work_queue.push_back(boost::move(w));
|
||||
//work_queue.push(work(closure)); // todo check why this doesn't work
|
||||
work_queue.push_back(work(closure));
|
||||
}
|
||||
#endif
|
||||
void submit(void (*closure)())
|
||||
{
|
||||
work w ((closure));
|
||||
work_queue.push_back(boost::move(w));
|
||||
//work_queue.push_back(work(closure)); // todo check why this doesn't work
|
||||
work_queue.push_back(work(closure));
|
||||
}
|
||||
|
||||
template <typename Closure>
|
||||
void submit(BOOST_THREAD_RV_REF(Closure) closure)
|
||||
{
|
||||
work w =boost::move(closure);
|
||||
work_queue.push_back(boost::move(w));
|
||||
//work_queue.push_back(work(boost::move(closure))); // todo check why this doesn't work
|
||||
work_queue.push_back(work(boost::forward<Closure>(closure)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -184,17 +178,18 @@ namespace executors
|
||||
} while (! pred());
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* run queued closures
|
||||
*/
|
||||
void run_queued_closures()
|
||||
{
|
||||
sync_queue<work>::underlying_queue_type q = work_queue.underlying_queue();
|
||||
while (q.empty())
|
||||
while (! q.empty())
|
||||
{
|
||||
work task = q.front();
|
||||
q.pop_front();
|
||||
work& task = q.front();
|
||||
task();
|
||||
q.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/sync_queue.hpp>
|
||||
#include <boost/thread/executors/work.hpp>
|
||||
#include <boost/thread/executors/executor.hpp>
|
||||
#include <boost/thread/executors/generic_executor_ref.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/thread/scoped_thread.hpp>
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace executors
|
||||
|
||||
/// the thread safe work queue
|
||||
sync_queue<work > work_queue;
|
||||
executor& ex;
|
||||
generic_executor_ref ex;
|
||||
thread_t thr;
|
||||
|
||||
struct try_executing_one_task {
|
||||
@@ -48,6 +48,12 @@ namespace executors
|
||||
}
|
||||
};
|
||||
public:
|
||||
/**
|
||||
* \par Returns
|
||||
* The underlying executor wrapped on a generic executor reference.
|
||||
*/
|
||||
generic_executor_ref underlying_executor() BOOST_NOEXCEPT { return ex; }
|
||||
|
||||
/**
|
||||
* Effects: try to execute one task.
|
||||
* Returns: whether a task has been executed.
|
||||
@@ -118,7 +124,8 @@ namespace executors
|
||||
*
|
||||
* \b Throws: Whatever exception is thrown while initializing the needed resources.
|
||||
*/
|
||||
serial_executor(executor& ex)
|
||||
template <class Executor>
|
||||
serial_executor(Executor& ex)
|
||||
: ex(ex), thr(&serial_executor::worker_thread, this)
|
||||
{
|
||||
}
|
||||
@@ -166,24 +173,18 @@ namespace executors
|
||||
template <typename Closure>
|
||||
void submit(Closure & closure)
|
||||
{
|
||||
work w ((closure));
|
||||
work_queue.push_back(boost::move(w));
|
||||
//work_queue.push(work(closure)); // todo check why this doesn't work
|
||||
work_queue.push_back(work(closure));
|
||||
}
|
||||
#endif
|
||||
void submit(void (*closure)())
|
||||
{
|
||||
work w ((closure));
|
||||
work_queue.push_back(boost::move(w));
|
||||
//work_queue.push_back(work(closure)); // todo check why this doesn't work
|
||||
work_queue.push_back(work(closure));
|
||||
}
|
||||
|
||||
template <typename Closure>
|
||||
void submit(BOOST_THREAD_RV_REF(Closure) closure)
|
||||
{
|
||||
work w =boost::move(closure);
|
||||
work_queue.push_back(boost::move(w));
|
||||
//work_queue.push_back(work(boost::move(closure))); // todo check why this doesn't work
|
||||
work_queue.push_back(work(boost::forward<Closure>(closure)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,6 +7,15 @@
|
||||
#ifndef BOOST_THREAD_EXECUTORS_WORK_HPP
|
||||
#define BOOST_THREAD_EXECUTORS_WORK_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#if ! defined BOOST_THREAD_EXECUTORS_WORK_ACCEPTS_MOVABLE \
|
||||
&& ! defined BOOST_THREAD_EXECUTORS_WORK_DONT_ACCEPT_MOVABLE
|
||||
#define BOOST_THREAD_EXECUTORS_WORK_ACCEPTS_MOVABLE
|
||||
//#define BOOST_THREAD_EXECUTORS_WORK_DONT_ACCEPT_MOVABLE
|
||||
#endif
|
||||
|
||||
#if defined BOOST_THREAD_EXECUTORS_WORK_ACCEPTS_MOVABLE
|
||||
|
||||
#include <boost/thread/detail/nullary_function.hpp>
|
||||
|
||||
@@ -18,4 +27,17 @@ namespace boost
|
||||
}
|
||||
} // namespace boost
|
||||
|
||||
#else
|
||||
#include <boost/thread/csbl/functional.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace executors
|
||||
{
|
||||
typedef csbl::function<void()> work;
|
||||
}
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
||||
#endif // BOOST_THREAD_EXECUTORS_WORK_HPP
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -34,7 +34,7 @@ namespace boost
|
||||
if (--count_ == 0)
|
||||
{
|
||||
++generation_;
|
||||
lk.unlock();
|
||||
//lk.unlock();
|
||||
cond_.notify_all();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ namespace boost
|
||||
if(res2)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
|
||||
boost::throw_exception(thread_resource_error(res, "boost::condition_variable_any::condition_variable_any() failed in pthread_cond_init"));
|
||||
boost::throw_exception(thread_resource_error(res2, "boost::condition_variable_any::condition_variable_any() failed in pthread_cond_init"));
|
||||
}
|
||||
}
|
||||
~condition_variable_any()
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Vicente J. Botet Escriba 2013. Distributed under the Boost
|
||||
// (C) Copyright Vicente J. Botet Escriba 2013-2014. 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)
|
||||
//
|
||||
@@ -16,6 +16,8 @@
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
|
||||
|
||||
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
#include <boost/smart_ptr/shared_ptr.hpp>
|
||||
#include <boost/smart_ptr/make_shared.hpp>
|
||||
@@ -25,19 +27,6 @@
|
||||
namespace boost
|
||||
{
|
||||
|
||||
BOOST_SCOPED_ENUM_DECLARE_BEGIN(queue_op_status)
|
||||
{ success = 0, empty, full, closed, busy }
|
||||
BOOST_SCOPED_ENUM_DECLARE_END(queue_op_status)
|
||||
|
||||
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
struct no_block_tag{};
|
||||
BOOST_CONSTEXPR_OR_CONST no_block_tag no_block = {};
|
||||
#endif
|
||||
|
||||
struct sync_queue_is_closed : std::exception
|
||||
{
|
||||
};
|
||||
|
||||
template <typename ValueType>
|
||||
class sync_bounded_queue
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Vicente J. Botet Escriba 2013. Distributed under the Boost
|
||||
// (C) Copyright Vicente J. Botet Escriba 2013-2014. 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)
|
||||
//
|
||||
@@ -15,11 +15,12 @@
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
|
||||
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/smart_ptr/shared_ptr.hpp>
|
||||
#include <boost/smart_ptr/make_shared.hpp>
|
||||
|
||||
#include <boost/thread/sync_bounded_queue.hpp>
|
||||
#include <boost/thread/csbl/deque.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
@@ -93,6 +94,7 @@ namespace boost
|
||||
|
||||
inline underlying_queue_type underlying_queue() {
|
||||
lock_guard<mutex> lk(mtx_);
|
||||
waiting_empty_ = 0;
|
||||
return boost::move(data_);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,10 +19,10 @@ namespace boost
|
||||
{
|
||||
virtual ~tss_cleanup_function()
|
||||
{}
|
||||
|
||||
|
||||
virtual void operator()(void* data)=0;
|
||||
};
|
||||
|
||||
|
||||
BOOST_THREAD_DECL void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing);
|
||||
BOOST_THREAD_DECL void* get_tss_data(void const* key);
|
||||
}
|
||||
@@ -42,16 +42,16 @@ namespace boost
|
||||
delete static_cast<T*>(data);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct run_custom_cleanup_function:
|
||||
detail::tss_cleanup_function
|
||||
{
|
||||
void (*cleanup_function)(T*);
|
||||
|
||||
|
||||
explicit run_custom_cleanup_function(void (*cleanup_function_)(T*)):
|
||||
cleanup_function(cleanup_function_)
|
||||
{}
|
||||
|
||||
|
||||
void operator()(void* data)
|
||||
{
|
||||
cleanup_function(static_cast<T*>(data));
|
||||
@@ -60,10 +60,10 @@ namespace boost
|
||||
|
||||
|
||||
boost::shared_ptr<detail::tss_cleanup_function> cleanup;
|
||||
|
||||
|
||||
public:
|
||||
typedef T element_type;
|
||||
|
||||
|
||||
thread_specific_ptr():
|
||||
cleanup(detail::heap_new<delete_data>(),detail::do_heap_delete<delete_data>())
|
||||
{}
|
||||
@@ -87,7 +87,7 @@ namespace boost
|
||||
{
|
||||
return get();
|
||||
}
|
||||
T& operator*() const
|
||||
typename boost::detail::sp_dereference< T >::type operator*() const
|
||||
{
|
||||
return *get();
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace boost
|
||||
|
||||
do
|
||||
{
|
||||
unsigned const retval(win32::WaitForSingleObject(sem, ::boost::detail::win32::infinite));
|
||||
unsigned const retval(win32::WaitForSingleObjectEx(sem, ::boost::detail::win32::infinite,0));
|
||||
BOOST_VERIFY(0 == retval || ::boost::detail::win32::wait_abandoned == retval);
|
||||
// BOOST_VERIFY(win32::WaitForSingleObject(
|
||||
// sem,::boost::detail::win32::infinite)==0);
|
||||
@@ -142,7 +142,7 @@ namespace boost
|
||||
|
||||
do
|
||||
{
|
||||
if(win32::WaitForSingleObject(sem,::boost::detail::get_milliseconds_until(wait_until))!=0)
|
||||
if(win32::WaitForSingleObjectEx(sem,::boost::detail::get_milliseconds_until(wait_until),0)!=0)
|
||||
{
|
||||
BOOST_INTERLOCKED_DECREMENT(&active_count);
|
||||
return false;
|
||||
@@ -203,9 +203,14 @@ namespace boost
|
||||
|
||||
do
|
||||
{
|
||||
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now());
|
||||
chrono::time_point<chrono::system_clock, chrono::system_clock::duration> now = chrono::system_clock::now();
|
||||
if (tp<=now) {
|
||||
BOOST_INTERLOCKED_DECREMENT(&active_count);
|
||||
return false;
|
||||
}
|
||||
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-now);
|
||||
|
||||
if(win32::WaitForSingleObject(sem,static_cast<unsigned long>(rel_time.count()))!=0)
|
||||
if(win32::WaitForSingleObjectEx(sem,static_cast<unsigned long>(rel_time.count()),0)!=0)
|
||||
{
|
||||
BOOST_INTERLOCKED_DECREMENT(&active_count);
|
||||
return false;
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace boost
|
||||
|
||||
bool woken()
|
||||
{
|
||||
unsigned long const woken_result=detail::win32::WaitForSingleObject(wake_sem,0);
|
||||
unsigned long const woken_result=detail::win32::WaitForSingleObjectEx(wake_sem,0,0);
|
||||
BOOST_ASSERT((woken_result==detail::win32::timeout) || (woken_result==0));
|
||||
return woken_result==0;
|
||||
}
|
||||
|
||||
@@ -17,34 +17,29 @@
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
|
||||
extern "C" void _ReadWriteBarrier(void);
|
||||
#pragma intrinsic(_ReadWriteBarrier)
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
// Since VS2005 volatile reads always acquire
|
||||
inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
|
||||
{
|
||||
long const res=*x;
|
||||
_ReadWriteBarrier();
|
||||
return res;
|
||||
}
|
||||
inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
|
||||
{
|
||||
void* const res=*x;
|
||||
_ReadWriteBarrier();
|
||||
return res;
|
||||
}
|
||||
|
||||
// Since VS2005 volatile writes always release
|
||||
inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
|
||||
{
|
||||
_ReadWriteBarrier();
|
||||
*x=value;
|
||||
}
|
||||
inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
|
||||
{
|
||||
_ReadWriteBarrier();
|
||||
*x=value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,14 +152,11 @@ namespace boost
|
||||
{
|
||||
name_once_mutex(mutex_name,flag_address);
|
||||
}
|
||||
#ifdef BOOST_NO_ANSI_APIS
|
||||
return ::boost::detail::win32::CreateEventW(
|
||||
#else
|
||||
return ::boost::detail::win32::CreateEventA(
|
||||
#endif
|
||||
0,::boost::detail::win32::manual_reset_event,
|
||||
::boost::detail::win32::event_initially_reset,
|
||||
mutex_name);
|
||||
|
||||
return ::boost::detail::win32::create_event(
|
||||
mutex_name,
|
||||
::boost::detail::win32::manual_reset_event,
|
||||
::boost::detail::win32::event_initially_reset);
|
||||
}
|
||||
|
||||
struct once_context {
|
||||
@@ -267,8 +264,8 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
|
||||
ctx.event_handle,::boost::detail::win32::infinite));
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite, 0));
|
||||
}
|
||||
}
|
||||
//#endif
|
||||
@@ -311,8 +308,8 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
|
||||
ctx.event_handle,::boost::detail::win32::infinite));
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
template<typename Function, class A, class ...ArgTypes>
|
||||
@@ -358,8 +355,8 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
|
||||
ctx.event_handle,::boost::detail::win32::infinite));
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
#else
|
||||
@@ -403,8 +400,8 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
|
||||
ctx.event_handle,::boost::detail::win32::infinite));
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
template<typename Function, typename T1>
|
||||
@@ -446,8 +443,8 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
|
||||
ctx.event_handle,::boost::detail::win32::infinite));
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
template<typename Function, typename T1, typename T2>
|
||||
@@ -489,8 +486,8 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
|
||||
ctx.event_handle,::boost::detail::win32::infinite));
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
template<typename Function, typename T1, typename T2, typename T3>
|
||||
@@ -532,8 +529,8 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
|
||||
ctx.event_handle,::boost::detail::win32::infinite));
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
#elif defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
@@ -577,8 +574,8 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
|
||||
ctx.event_handle,::boost::detail::win32::infinite));
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
template<typename Function, typename T1>
|
||||
@@ -620,8 +617,8 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
|
||||
ctx.event_handle,::boost::detail::win32::infinite));
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
template<typename Function, typename T1, typename T2>
|
||||
@@ -663,8 +660,8 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
|
||||
ctx.event_handle,::boost::detail::win32::infinite));
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
template<typename Function, typename T1, typename T2, typename T3>
|
||||
@@ -706,8 +703,8 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
|
||||
ctx.event_handle,::boost::detail::win32::infinite));
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -751,8 +748,8 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
|
||||
ctx.event_handle,::boost::detail::win32::infinite));
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
template<typename T1>
|
||||
@@ -796,8 +793,8 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
|
||||
ctx.event_handle,::boost::detail::win32::infinite));
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
template<typename Function, typename T1, typename T2>
|
||||
@@ -842,8 +839,8 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
|
||||
ctx.event_handle,::boost::detail::win32::infinite));
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
template<typename Function, typename T1, typename T2, typename T3>
|
||||
@@ -889,8 +886,8 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
|
||||
ctx.event_handle,::boost::detail::win32::infinite));
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -933,8 +930,8 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
|
||||
ctx.event_handle,::boost::detail::win32::infinite));
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -980,8 +977,8 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
|
||||
ctx.event_handle,::boost::detail::win32::infinite));
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
template<typename Function, typename T1, typename T2>
|
||||
@@ -1027,8 +1024,8 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
|
||||
ctx.event_handle,::boost::detail::win32::infinite));
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
template<typename Function, typename T1, typename T2, typename T3>
|
||||
@@ -1076,8 +1073,8 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
|
||||
ctx.event_handle,::boost::detail::win32::infinite));
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +75,13 @@ namespace boost
|
||||
BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
|
||||
}
|
||||
}
|
||||
|
||||
void release_shared_waiters(state_data old_state)
|
||||
{
|
||||
if(old_state.shared_waiting || old_state.exclusive_waiting)
|
||||
{
|
||||
BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
BOOST_THREAD_NO_COPYABLE(shared_mutex)
|
||||
@@ -184,7 +190,7 @@ namespace boost
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned long const res=detail::win32::WaitForSingleObject(semaphores[unlock_sem],::boost::detail::get_milliseconds_until(wait_until));
|
||||
unsigned long const res=detail::win32::WaitForSingleObjectEx(semaphores[unlock_sem],::boost::detail::get_milliseconds_until(wait_until), 0);
|
||||
if(res==detail::win32::timeout)
|
||||
{
|
||||
for(;;)
|
||||
@@ -289,8 +295,8 @@ namespace boost
|
||||
unsigned long res;
|
||||
if (tp>n) {
|
||||
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-n);
|
||||
res=detail::win32::WaitForSingleObject(semaphores[unlock_sem],
|
||||
static_cast<unsigned long>(rel_time.count()));
|
||||
res=detail::win32::WaitForSingleObjectEx(semaphores[unlock_sem],
|
||||
static_cast<unsigned long>(rel_time.count()), 0);
|
||||
} else {
|
||||
res=detail::win32::timeout;
|
||||
}
|
||||
@@ -466,7 +472,7 @@ namespace boost
|
||||
#else
|
||||
const bool wait_all = false;
|
||||
#endif
|
||||
unsigned long const wait_res=detail::win32::WaitForMultipleObjects(2,semaphores,wait_all,::boost::detail::get_milliseconds_until(wait_until));
|
||||
unsigned long const wait_res=detail::win32::WaitForMultipleObjectsEx(2,semaphores,wait_all,::boost::detail::get_milliseconds_until(wait_until), 0);
|
||||
if(wait_res==detail::win32::timeout)
|
||||
{
|
||||
for(;;)
|
||||
@@ -578,8 +584,8 @@ namespace boost
|
||||
unsigned long wait_res;
|
||||
if (tp>n) {
|
||||
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now());
|
||||
wait_res=detail::win32::WaitForMultipleObjects(2,semaphores,wait_all,
|
||||
static_cast<unsigned long>(rel_time.count()));
|
||||
wait_res=detail::win32::WaitForMultipleObjectsEx(2,semaphores,wait_all,
|
||||
static_cast<unsigned long>(rel_time.count()), 0);
|
||||
} else {
|
||||
wait_res=detail::win32::timeout;
|
||||
}
|
||||
@@ -690,7 +696,7 @@ namespace boost
|
||||
return;
|
||||
}
|
||||
|
||||
BOOST_VERIFY(!detail::win32::WaitForSingleObject(semaphores[unlock_sem],detail::win32::infinite));
|
||||
BOOST_VERIFY(!detail::win32::WaitForSingleObjectEx(semaphores[unlock_sem],detail::win32::infinite, 0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -750,6 +756,9 @@ namespace boost
|
||||
{
|
||||
release_waiters(old_state);
|
||||
}
|
||||
else {
|
||||
release_shared_waiters(old_state);
|
||||
}
|
||||
// #7720
|
||||
//else {
|
||||
// release_waiters(old_state);
|
||||
@@ -779,7 +788,7 @@ namespace boost
|
||||
{
|
||||
if(!last_reader)
|
||||
{
|
||||
BOOST_VERIFY(!detail::win32::WaitForSingleObject(upgrade_sem,detail::win32::infinite));
|
||||
BOOST_VERIFY(!detail::win32::WaitForSingleObjectEx(upgrade_sem,detail::win32::infinite, 0));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#include <boost/thread/win32/thread_primitives.hpp>
|
||||
#include <boost/thread/win32/thread_heap_alloc.hpp>
|
||||
|
||||
#include <boost/predef/platform.h>
|
||||
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
#include <boost/chrono/system_clocks.hpp>
|
||||
@@ -93,10 +95,18 @@ namespace boost
|
||||
struct BOOST_THREAD_DECL thread_data_base
|
||||
{
|
||||
long count;
|
||||
|
||||
// Win32 threading APIs are not available in store apps so
|
||||
// use abstraction on top of Windows::System::Threading.
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
detail::win32::scoped_winrt_thread thread_handle;
|
||||
#else
|
||||
detail::win32::handle_manager thread_handle;
|
||||
#endif
|
||||
|
||||
boost::detail::thread_exit_callback_node* thread_exit_callbacks;
|
||||
std::map<void const*,boost::detail::tss_data_node> tss_data;
|
||||
unsigned id;
|
||||
std::map<void const*,boost::detail::tss_data_node> tss_data;
|
||||
typedef std::vector<std::pair<condition_variable*, mutex*>
|
||||
//, hidden_allocator<std::pair<condition_variable*, mutex*> >
|
||||
> notify_list_t;
|
||||
@@ -113,9 +123,11 @@ namespace boost
|
||||
//#endif
|
||||
|
||||
thread_data_base():
|
||||
count(0),thread_handle(detail::win32::invalid_handle_value),
|
||||
thread_exit_callbacks(0),tss_data(),
|
||||
count(0),
|
||||
thread_handle(),
|
||||
thread_exit_callbacks(0),
|
||||
id(0),
|
||||
tss_data(),
|
||||
notify(),
|
||||
async_states_()
|
||||
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
@@ -173,14 +185,15 @@ namespace boost
|
||||
static unsigned long const max_non_infinite_wait=0xfffffffe;
|
||||
|
||||
timeout(uintmax_t milliseconds_):
|
||||
start(win32::GetTickCount64()()),
|
||||
start(win32::GetTickCount64_()()),
|
||||
milliseconds(milliseconds_),
|
||||
relative(true),
|
||||
abs_time(boost::get_system_time())
|
||||
relative(true)
|
||||
//,
|
||||
// abs_time(boost::get_system_time())
|
||||
{}
|
||||
|
||||
timeout(boost::system_time const& abs_time_):
|
||||
start(win32::GetTickCount64()()),
|
||||
start(win32::GetTickCount64_()()),
|
||||
milliseconds(0),
|
||||
relative(false),
|
||||
abs_time(abs_time_)
|
||||
@@ -205,7 +218,7 @@ namespace boost
|
||||
}
|
||||
else if(relative)
|
||||
{
|
||||
win32::ticks_type const now=win32::GetTickCount64()();
|
||||
win32::ticks_type const now=win32::GetTickCount64_()();
|
||||
win32::ticks_type const elapsed=now-start;
|
||||
return remaining_time((elapsed<milliseconds)?(milliseconds-elapsed):0);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/predef/platform.h>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
@@ -18,6 +19,10 @@
|
||||
//#include <boost/detail/winapi/synchronization.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
#include <thread>
|
||||
#endif
|
||||
|
||||
#if defined( BOOST_USE_WINDOWS_H )
|
||||
# include <windows.h>
|
||||
|
||||
@@ -28,40 +33,60 @@ namespace boost
|
||||
namespace win32
|
||||
{
|
||||
typedef HANDLE handle;
|
||||
typedef SYSTEM_INFO system_info;
|
||||
typedef unsigned __int64 ticks_type;
|
||||
unsigned const infinite=INFINITE;
|
||||
unsigned const timeout=WAIT_TIMEOUT;
|
||||
handle const invalid_handle_value=INVALID_HANDLE_VALUE;
|
||||
unsigned const event_modify_state=EVENT_MODIFY_STATE;
|
||||
unsigned const synchronize=SYNCHRONIZE;
|
||||
unsigned const wait_abandoned=WAIT_ABANDONED;
|
||||
|
||||
unsigned const create_event_initial_set = 0x00000002;
|
||||
unsigned const create_event_manual_reset = 0x00000001;
|
||||
unsigned const event_all_access = EVENT_ALL_ACCESS;
|
||||
unsigned const semaphore_all_access = SEMAPHORE_ALL_ACCESS;
|
||||
|
||||
|
||||
# ifdef BOOST_NO_ANSI_APIS
|
||||
# if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA
|
||||
using ::CreateMutexW;
|
||||
using ::CreateEventW;
|
||||
using ::OpenEventW;
|
||||
using ::CreateSemaphoreW;
|
||||
# else
|
||||
using ::CreateMutexExW;
|
||||
using ::CreateEventExW;
|
||||
using ::CreateSemaphoreExW;
|
||||
# endif
|
||||
using ::OpenEventW;
|
||||
# else
|
||||
using ::CreateMutexA;
|
||||
using ::CreateEventA;
|
||||
using ::OpenEventA;
|
||||
using ::CreateSemaphoreA;
|
||||
# endif
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
using ::GetNativeSystemInfo;
|
||||
using ::GetTickCount64;
|
||||
#else
|
||||
using ::GetSystemInfo;
|
||||
#endif
|
||||
using ::CloseHandle;
|
||||
using ::ReleaseMutex;
|
||||
using ::ReleaseSemaphore;
|
||||
using ::SetEvent;
|
||||
using ::ResetEvent;
|
||||
using ::WaitForMultipleObjects;
|
||||
using ::WaitForSingleObject;
|
||||
using ::WaitForMultipleObjectsEx;
|
||||
using ::WaitForSingleObjectEx;
|
||||
using ::GetCurrentProcessId;
|
||||
using ::GetCurrentThreadId;
|
||||
using ::GetCurrentThread;
|
||||
using ::GetCurrentProcess;
|
||||
using ::DuplicateHandle;
|
||||
#if !BOOST_PLAT_WINDOWS_RUNTIME
|
||||
using ::SleepEx;
|
||||
using ::Sleep;
|
||||
using ::QueueUserAPC;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,13 +107,19 @@ extern "C" {
|
||||
typedef int BOOL;
|
||||
typedef unsigned long DWORD;
|
||||
typedef void* HANDLE;
|
||||
|
||||
# include <kfuncs.h>
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
struct _SYSTEM_INFO;
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
@@ -102,20 +133,32 @@ namespace boost
|
||||
typedef unsigned long ulong_ptr;
|
||||
# endif
|
||||
typedef void* handle;
|
||||
typedef _SYSTEM_INFO system_info;
|
||||
typedef unsigned __int64 ticks_type;
|
||||
unsigned const infinite=~0U;
|
||||
unsigned const timeout=258U;
|
||||
handle const invalid_handle_value=(handle)(-1);
|
||||
unsigned const event_modify_state=2;
|
||||
unsigned const synchronize=0x100000u;
|
||||
unsigned const wait_abandoned=0x00000080u;
|
||||
unsigned const create_event_initial_set = 0x00000002;
|
||||
unsigned const create_event_manual_reset = 0x00000001;
|
||||
unsigned const event_all_access = 0x1F0003;
|
||||
unsigned const semaphore_all_access = 0x1F0003;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
struct _SECURITY_ATTRIBUTES;
|
||||
# ifdef BOOST_NO_ANSI_APIS
|
||||
# if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA
|
||||
__declspec(dllimport) void* __stdcall CreateMutexW(_SECURITY_ATTRIBUTES*,int,wchar_t const*);
|
||||
__declspec(dllimport) void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*);
|
||||
__declspec(dllimport) void* __stdcall CreateEventW(_SECURITY_ATTRIBUTES*,int,int,wchar_t const*);
|
||||
# else
|
||||
__declspec(dllimport) void* __stdcall CreateMutexExW(_SECURITY_ATTRIBUTES*,wchar_t const*,unsigned long,unsigned long);
|
||||
__declspec(dllimport) void* __stdcall CreateEventExW(_SECURITY_ATTRIBUTES*,wchar_t const*,unsigned long,unsigned long);
|
||||
__declspec(dllimport) void* __stdcall CreateSemaphoreExW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*,unsigned long,unsigned long);
|
||||
# endif
|
||||
__declspec(dllimport) void* __stdcall OpenEventW(unsigned long,int,wchar_t const*);
|
||||
# else
|
||||
__declspec(dllimport) void* __stdcall CreateMutexA(_SECURITY_ATTRIBUTES*,int,char const*);
|
||||
@@ -123,16 +166,24 @@ namespace boost
|
||||
__declspec(dllimport) void* __stdcall CreateEventA(_SECURITY_ATTRIBUTES*,int,int,char const*);
|
||||
__declspec(dllimport) void* __stdcall OpenEventA(unsigned long,int,char const*);
|
||||
# endif
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
__declspec(dllimport) void __stdcall GetNativeSystemInfo(_SYSTEM_INFO*);
|
||||
__declspec(dllimport) ticks_type __stdcall GetTickCount64();
|
||||
#else
|
||||
__declspec(dllimport) void __stdcall GetSystemInfo(_SYSTEM_INFO*);
|
||||
#endif
|
||||
__declspec(dllimport) int __stdcall CloseHandle(void*);
|
||||
__declspec(dllimport) int __stdcall ReleaseMutex(void*);
|
||||
__declspec(dllimport) unsigned long __stdcall WaitForSingleObject(void*,unsigned long);
|
||||
__declspec(dllimport) unsigned long __stdcall WaitForMultipleObjects(unsigned long nCount,void* const * lpHandles,int bWaitAll,unsigned long dwMilliseconds);
|
||||
__declspec(dllimport) unsigned long __stdcall WaitForSingleObjectEx(void*,unsigned long,int);
|
||||
__declspec(dllimport) unsigned long __stdcall WaitForMultipleObjectsEx(unsigned long nCount,void* const * lpHandles,int bWaitAll,unsigned long dwMilliseconds,int bAlertable);
|
||||
__declspec(dllimport) int __stdcall ReleaseSemaphore(void*,long,long*);
|
||||
__declspec(dllimport) int __stdcall DuplicateHandle(void*,void*,void*,void**,unsigned long,int,unsigned long);
|
||||
#if !BOOST_PLAT_WINDOWS_RUNTIME
|
||||
__declspec(dllimport) unsigned long __stdcall SleepEx(unsigned long,int);
|
||||
__declspec(dllimport) void __stdcall Sleep(unsigned long);
|
||||
typedef void (__stdcall *queue_user_apc_callback_function)(ulong_ptr);
|
||||
__declspec(dllimport) unsigned long __stdcall QueueUserAPC(queue_user_apc_callback_function,void*,ulong_ptr);
|
||||
#endif
|
||||
|
||||
# ifndef UNDER_CE
|
||||
__declspec(dllimport) unsigned long __stdcall GetCurrentProcessId();
|
||||
@@ -165,19 +216,26 @@ namespace boost
|
||||
{
|
||||
namespace win32
|
||||
{
|
||||
typedef unsigned __int64 ticks_type;
|
||||
namespace detail { typedef int (__stdcall *farproc_t)(); typedef ticks_type (__stdcall *gettickcount64_t)(); }
|
||||
#if !BOOST_PLAT_WINDOWS_RUNTIME
|
||||
extern "C"
|
||||
{
|
||||
__declspec(dllimport) detail::farproc_t __stdcall GetProcAddress(void *, const char *);
|
||||
__declspec(dllimport) detail::farproc_t __stdcall GetProcAddress(void *, const char *);
|
||||
#if !defined(BOOST_NO_ANSI_APIS)
|
||||
__declspec(dllimport) void * __stdcall GetModuleHandleA(const char *);
|
||||
__declspec(dllimport) void * __stdcall GetModuleHandleA(const char *);
|
||||
#else
|
||||
__declspec(dllimport) void * __stdcall GetModuleHandleW(const wchar_t *);
|
||||
__declspec(dllimport) void * __stdcall GetModuleHandleW(const wchar_t *);
|
||||
#endif
|
||||
int __stdcall GetTickCount();
|
||||
__declspec(dllimport) unsigned long __stdcall GetTickCount();
|
||||
#ifdef _MSC_VER
|
||||
long _InterlockedCompareExchange(long volatile *, long, long);
|
||||
#pragma intrinsic(_InterlockedCompareExchange)
|
||||
#elif defined(__MINGW64_VERSION_MAJOR)
|
||||
long _InterlockedCompareExchange(long volatile *, long, long);
|
||||
#else
|
||||
// Mingw doesn't provide intrinsics
|
||||
#define _InterlockedCompareExchange InterlockedCompareExchange
|
||||
#endif
|
||||
}
|
||||
// Borrowed from https://stackoverflow.com/questions/8211820/userland-interrupt-timer-access-such-as-via-kequeryinterrupttime-or-similar
|
||||
inline ticks_type __stdcall GetTickCount64emulation()
|
||||
@@ -227,11 +285,19 @@ namespace boost
|
||||
// Oops, we weren't called often enough, we're stuck
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
inline detail::gettickcount64_t GetTickCount64()
|
||||
#else
|
||||
#endif
|
||||
inline detail::gettickcount64_t GetTickCount64_()
|
||||
{
|
||||
static detail::gettickcount64_t gettickcount64impl;
|
||||
if(gettickcount64impl)
|
||||
return gettickcount64impl;
|
||||
|
||||
// GetTickCount and GetModuleHandle are not allowed in the Windows Runtime,
|
||||
// and kernel32 isn't used in Windows Phone.
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
gettickcount64impl = &GetTickCount64;
|
||||
#else
|
||||
detail::farproc_t addr=GetProcAddress(
|
||||
#if !defined(BOOST_NO_ANSI_APIS)
|
||||
GetModuleHandleA("KERNEL32.DLL"),
|
||||
@@ -243,10 +309,11 @@ namespace boost
|
||||
gettickcount64impl=(detail::gettickcount64_t) addr;
|
||||
else
|
||||
gettickcount64impl=&GetTickCount64emulation;
|
||||
#endif
|
||||
return gettickcount64impl;
|
||||
}
|
||||
|
||||
enum event_type
|
||||
enum event_type
|
||||
{
|
||||
auto_reset_event=false,
|
||||
manual_reset_event=true
|
||||
@@ -258,13 +325,32 @@ namespace boost
|
||||
event_initially_set=true
|
||||
};
|
||||
|
||||
inline handle create_anonymous_event(event_type type,initial_event_state state)
|
||||
inline handle create_event(
|
||||
#if !defined(BOOST_NO_ANSI_APIS)
|
||||
const char *mutex_name,
|
||||
#else
|
||||
const wchar_t *mutex_name,
|
||||
#endif
|
||||
event_type type,
|
||||
initial_event_state state)
|
||||
{
|
||||
#if !defined(BOOST_NO_ANSI_APIS)
|
||||
handle const res=win32::CreateEventA(0,type,state,0);
|
||||
handle const res = win32::CreateEventA(0, type, state, mutex_name);
|
||||
#elif BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA
|
||||
handle const res = win32::CreateEventW(0, type, state, mutex_name);
|
||||
#else
|
||||
handle const res=win32::CreateEventW(0,type,state,0);
|
||||
handle const res = win32::CreateEventExW(
|
||||
0,
|
||||
mutex_name,
|
||||
type ? create_event_manual_reset : 0 | state ? create_event_initial_set : 0,
|
||||
event_all_access);
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
inline handle create_anonymous_event(event_type type,initial_event_state state)
|
||||
{
|
||||
handle const res = create_event(0, type, state);
|
||||
if(!res)
|
||||
{
|
||||
boost::throw_exception(thread_resource_error());
|
||||
@@ -272,28 +358,29 @@ namespace boost
|
||||
return res;
|
||||
}
|
||||
|
||||
inline handle create_anonymous_semaphore(long initial_count,long max_count)
|
||||
inline handle create_anonymous_semaphore_nothrow(long initial_count,long max_count)
|
||||
{
|
||||
#if !defined(BOOST_NO_ANSI_APIS)
|
||||
handle const res=CreateSemaphoreA(0,initial_count,max_count,0);
|
||||
handle const res=win32::CreateSemaphoreA(0,initial_count,max_count,0);
|
||||
#else
|
||||
handle const res=CreateSemaphoreW(0,initial_count,max_count,0);
|
||||
#if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA
|
||||
handle const res=win32::CreateSemaphoreEx(0,initial_count,max_count,0,0);
|
||||
#else
|
||||
handle const res=win32::CreateSemaphoreExW(0,initial_count,max_count,0,0,semaphore_all_access);
|
||||
#endif
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
inline handle create_anonymous_semaphore(long initial_count,long max_count)
|
||||
{
|
||||
handle const res=create_anonymous_semaphore_nothrow(initial_count,max_count);
|
||||
if(!res)
|
||||
{
|
||||
boost::throw_exception(thread_resource_error());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
inline handle create_anonymous_semaphore_nothrow(long initial_count,long max_count)
|
||||
{
|
||||
#if !defined(BOOST_NO_ANSI_APIS)
|
||||
handle const res=CreateSemaphoreA(0,initial_count,max_count,0);
|
||||
#else
|
||||
handle const res=CreateSemaphoreW(0,initial_count,max_count,0);
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
inline handle duplicate_handle(handle source)
|
||||
{
|
||||
@@ -312,7 +399,64 @@ namespace boost
|
||||
{
|
||||
BOOST_VERIFY(ReleaseSemaphore(semaphore,count,0)!=0);
|
||||
}
|
||||
|
||||
inline void get_system_info(system_info *info)
|
||||
{
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
win32::GetNativeSystemInfo(info);
|
||||
#else
|
||||
win32::GetSystemInfo(info);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void sleep(unsigned long milliseconds)
|
||||
{
|
||||
if(milliseconds == 0)
|
||||
{
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
std::this_thread::yield();
|
||||
#else
|
||||
::boost::detail::win32::Sleep(0);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
::boost::detail::win32::WaitForSingleObjectEx(::boost::detail::win32::GetCurrentThread(), milliseconds, 0);
|
||||
#else
|
||||
::boost::detail::win32::Sleep(milliseconds);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
class BOOST_THREAD_DECL scoped_winrt_thread
|
||||
{
|
||||
public:
|
||||
scoped_winrt_thread() : m_completionHandle(invalid_handle_value)
|
||||
{}
|
||||
|
||||
~scoped_winrt_thread()
|
||||
{
|
||||
if (m_completionHandle != ::boost::detail::win32::invalid_handle_value)
|
||||
{
|
||||
CloseHandle(m_completionHandle);
|
||||
}
|
||||
}
|
||||
|
||||
typedef unsigned(__stdcall * thread_func)(void *);
|
||||
bool start(thread_func address, void *parameter, unsigned int *thrdId);
|
||||
|
||||
handle waitable_handle() const
|
||||
{
|
||||
BOOST_ASSERT(m_completionHandle != ::boost::detail::win32::invalid_handle_value);
|
||||
return m_completionHandle;
|
||||
}
|
||||
|
||||
private:
|
||||
handle m_completionHandle;
|
||||
};
|
||||
#endif
|
||||
class BOOST_THREAD_DECL handle_manager
|
||||
{
|
||||
private:
|
||||
@@ -375,7 +519,6 @@ namespace boost
|
||||
cleanup();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,11 +46,12 @@ namespace boost {
|
||||
* );
|
||||
*/
|
||||
template <class Lockable, class Function, class... Args>
|
||||
auto with_lock_guard(
|
||||
typename boost::result_of<Function(Args...)>::type with_lock_guard(
|
||||
Lockable& m,
|
||||
BOOST_FWD_REF(Function) func,
|
||||
BOOST_FWD_REF(Args)... args
|
||||
) -> decltype(func(boost::forward<Args>(args)...)) {
|
||||
) //-> decltype(func(boost::forward<Args>(args)...))
|
||||
{
|
||||
boost::lock_guard<Lockable> lock(m);
|
||||
return func(boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
#include <boost/thread/detail/tss_hooks.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
@@ -33,6 +32,19 @@
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
#include <boost/predef/platform.h>
|
||||
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
#include <mutex>
|
||||
#include <atomic>
|
||||
#include <Activation.h>
|
||||
#include <wrl\client.h>
|
||||
#include <wrl\event.h>
|
||||
#include <wrl\wrappers\corewrappers.h>
|
||||
#include <wrl\ftm.h>
|
||||
#include <windows.system.threading.h>
|
||||
#pragma comment(lib, "runtimeobject.lib")
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
@@ -65,50 +77,67 @@ namespace boost
|
||||
// Windows CE does not define the TLS_OUT_OF_INDEXES constant.
|
||||
#define TLS_OUT_OF_INDEXES 0xFFFFFFFF
|
||||
#endif
|
||||
#if !BOOST_PLAT_WINDOWS_RUNTIME
|
||||
DWORD current_thread_tls_key=TLS_OUT_OF_INDEXES;
|
||||
#else
|
||||
__declspec(thread) boost::detail::thread_data_base* current_thread_data_base;
|
||||
#endif
|
||||
|
||||
void create_current_thread_tls_key()
|
||||
{
|
||||
tss_cleanup_implemented(); // if anyone uses TSS, we need the cleanup linked in
|
||||
#if !BOOST_PLAT_WINDOWS_RUNTIME
|
||||
current_thread_tls_key=TlsAlloc();
|
||||
BOOST_ASSERT(current_thread_tls_key!=TLS_OUT_OF_INDEXES);
|
||||
#endif
|
||||
}
|
||||
|
||||
void cleanup_tls_key()
|
||||
{
|
||||
#if !BOOST_PLAT_WINDOWS_RUNTIME
|
||||
if(current_thread_tls_key!=TLS_OUT_OF_INDEXES)
|
||||
{
|
||||
TlsFree(current_thread_tls_key);
|
||||
current_thread_tls_key=TLS_OUT_OF_INDEXES;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void set_current_thread_data(detail::thread_data_base* new_data)
|
||||
{
|
||||
boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key);
|
||||
if (current_thread_tls_key!=TLS_OUT_OF_INDEXES)
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
current_thread_data_base = new_data;
|
||||
#else
|
||||
if (current_thread_tls_key != TLS_OUT_OF_INDEXES)
|
||||
{
|
||||
BOOST_VERIFY(TlsSetValue(current_thread_tls_key,new_data));
|
||||
BOOST_VERIFY(TlsSetValue(current_thread_tls_key, new_data));
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_VERIFY(false);
|
||||
//boost::throw_exception(thread_resource_error());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
thread_data_base* get_current_thread_data()
|
||||
{
|
||||
if(current_thread_tls_key==TLS_OUT_OF_INDEXES)
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
return current_thread_data_base;
|
||||
#else
|
||||
if (current_thread_tls_key == TLS_OUT_OF_INDEXES)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return (detail::thread_data_base*)TlsGetValue(current_thread_tls_key);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
#ifndef BOOST_HAS_THREADEX
|
||||
@@ -165,6 +194,66 @@ namespace boost
|
||||
|
||||
}
|
||||
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
namespace detail
|
||||
{
|
||||
std::atomic_uint threadCount;
|
||||
|
||||
bool win32::scoped_winrt_thread::start(thread_func address, void *parameter, unsigned int *thrdId)
|
||||
{
|
||||
Microsoft::WRL::ComPtr<ABI::Windows::System::Threading::IThreadPoolStatics> threadPoolFactory;
|
||||
HRESULT hr = ::Windows::Foundation::GetActivationFactory(
|
||||
Microsoft::WRL::Wrappers::HStringReference(RuntimeClass_Windows_System_Threading_ThreadPool).Get(),
|
||||
&threadPoolFactory);
|
||||
if (hr != S_OK)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create event for tracking work item completion.
|
||||
*thrdId = ++threadCount;
|
||||
handle completionHandle = CreateEventExW(NULL, NULL, 0, EVENT_ALL_ACCESS);
|
||||
if (!completionHandle)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_completionHandle = completionHandle;
|
||||
|
||||
// Create new work item.
|
||||
Microsoft::WRL::ComPtr<ABI::Windows::System::Threading::IWorkItemHandler> workItem =
|
||||
Microsoft::WRL::Callback<Microsoft::WRL::Implements<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, ABI::Windows::System::Threading::IWorkItemHandler, Microsoft::WRL::FtmBase>>
|
||||
([address, parameter, completionHandle](ABI::Windows::Foundation::IAsyncAction *)
|
||||
{
|
||||
// Add a reference since we need to access the completionHandle after the thread_start_function.
|
||||
// This is to handle cases where detach() was called and run_thread_exit_callbacks() would end
|
||||
// up closing the handle.
|
||||
::boost::detail::thread_data_base* const thread_info(reinterpret_cast<::boost::detail::thread_data_base*>(parameter));
|
||||
intrusive_ptr_add_ref(thread_info);
|
||||
|
||||
__try
|
||||
{
|
||||
address(parameter);
|
||||
}
|
||||
__finally
|
||||
{
|
||||
SetEvent(completionHandle);
|
||||
intrusive_ptr_release(thread_info);
|
||||
}
|
||||
return S_OK;
|
||||
});
|
||||
|
||||
// Schedule work item on the threadpool.
|
||||
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncAction> asyncAction;
|
||||
hr = threadPoolFactory->RunWithPriorityAndOptionsAsync(
|
||||
workItem.Get(),
|
||||
ABI::Windows::System::Threading::WorkItemPriority_Normal,
|
||||
ABI::Windows::System::Threading::WorkItemOptions_TimeSliced,
|
||||
&asyncAction);
|
||||
return hr == S_OK;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
void run_thread_exit_callbacks()
|
||||
@@ -199,7 +288,6 @@ namespace boost
|
||||
current_thread_data->tss_data.erase(current);
|
||||
}
|
||||
}
|
||||
|
||||
set_current_thread_data(0);
|
||||
}
|
||||
}
|
||||
@@ -236,6 +324,16 @@ namespace boost
|
||||
|
||||
bool thread::start_thread_noexcept()
|
||||
{
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
intrusive_ptr_add_ref(thread_info.get());
|
||||
if (!thread_info->thread_handle.start(&thread_start_function, thread_info.get(), &thread_info->id))
|
||||
{
|
||||
intrusive_ptr_release(thread_info.get());
|
||||
// boost::throw_exception(thread_resource_error());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
uintptr_t const new_thread=_beginthreadex(0,0,&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id);
|
||||
if(!new_thread)
|
||||
{
|
||||
@@ -246,10 +344,16 @@ namespace boost
|
||||
thread_info->thread_handle=(detail::win32::handle)(new_thread);
|
||||
ResumeThread(thread_info->thread_handle);
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool thread::start_thread_noexcept(const attributes& attr)
|
||||
{
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
// Stack size isn't supported with Windows Runtime.
|
||||
attr;
|
||||
return start_thread_noexcept();
|
||||
#else
|
||||
//uintptr_t const new_thread=_beginthreadex(attr.get_security(),attr.get_stack_size(),&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id);
|
||||
uintptr_t const new_thread=_beginthreadex(0,static_cast<unsigned int>(attr.get_stack_size()),&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id);
|
||||
if(!new_thread)
|
||||
@@ -261,8 +365,9 @@ namespace boost
|
||||
thread_info->thread_handle=(detail::win32::handle)(new_thread);
|
||||
ResumeThread(thread_info->thread_handle);
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
thread::thread(detail::thread_data_ptr data):
|
||||
thread_info(data)
|
||||
{}
|
||||
@@ -321,31 +426,37 @@ namespace boost
|
||||
}
|
||||
return current_thread_data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
thread::id thread::get_id() const BOOST_NOEXCEPT
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
|
||||
detail::thread_data_ptr local_thread_info=(get_thread_info)();
|
||||
return local_thread_info?local_thread_info->id:0;
|
||||
//return const_cast<thread*>(this)->native_handle();
|
||||
#else
|
||||
#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
|
||||
detail::thread_data_ptr local_thread_info=(get_thread_info)();
|
||||
if(!local_thread_info)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return local_thread_info->id;
|
||||
#else
|
||||
return thread::id((get_thread_info)());
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
bool thread::joinable() const BOOST_NOEXCEPT
|
||||
{
|
||||
return (get_thread_info)() ? true : false;
|
||||
detail::thread_data_ptr local_thread_info = (get_thread_info)();
|
||||
if(!local_thread_info)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool thread::join_noexcept()
|
||||
{
|
||||
|
||||
detail::thread_data_ptr local_thread_info=(get_thread_info)();
|
||||
if(local_thread_info)
|
||||
{
|
||||
this_thread::interruptible_wait(local_thread_info->thread_handle,detail::timeout::sentinel());
|
||||
this_thread::interruptible_wait(this->native_handle(),detail::timeout::sentinel());
|
||||
release_handle();
|
||||
return true;
|
||||
}
|
||||
@@ -366,7 +477,7 @@ namespace boost
|
||||
detail::thread_data_ptr local_thread_info=(get_thread_info)();
|
||||
if(local_thread_info)
|
||||
{
|
||||
if(!this_thread::interruptible_wait(local_thread_info->thread_handle,milli))
|
||||
if(!this_thread::interruptible_wait(this->native_handle(),milli))
|
||||
{
|
||||
res=false;
|
||||
return true;
|
||||
@@ -404,21 +515,23 @@ namespace boost
|
||||
bool thread::interruption_requested() const BOOST_NOEXCEPT
|
||||
{
|
||||
detail::thread_data_ptr local_thread_info=(get_thread_info)();
|
||||
return local_thread_info.get() && (detail::win32::WaitForSingleObject(local_thread_info->interruption_handle,0)==0);
|
||||
return local_thread_info.get() && (detail::win32::WaitForSingleObjectEx(local_thread_info->interruption_handle,0,0)==0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
unsigned thread::hardware_concurrency() BOOST_NOEXCEPT
|
||||
{
|
||||
//SYSTEM_INFO info={{0}};
|
||||
SYSTEM_INFO info;
|
||||
GetSystemInfo(&info);
|
||||
detail::win32::system_info info;
|
||||
detail::win32::get_system_info(&info);
|
||||
return info.dwNumberOfProcessors;
|
||||
}
|
||||
|
||||
unsigned thread::physical_concurrency() BOOST_NOEXCEPT
|
||||
{
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
return hardware_concurrency();
|
||||
#else
|
||||
unsigned cores = 0;
|
||||
#if !(defined(__MINGW32__) || defined (__MINGW64__))
|
||||
DWORD size = 0;
|
||||
@@ -439,12 +552,22 @@ namespace boost
|
||||
}
|
||||
#endif
|
||||
return cores;
|
||||
#endif
|
||||
}
|
||||
|
||||
thread::native_handle_type thread::native_handle()
|
||||
{
|
||||
detail::thread_data_ptr local_thread_info=(get_thread_info)();
|
||||
return local_thread_info?(detail::win32::handle)local_thread_info->thread_handle:detail::win32::invalid_handle_value;
|
||||
if(!local_thread_info)
|
||||
{
|
||||
return detail::win32::invalid_handle_value;
|
||||
}
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
// There is no 'real' Win32 handle so we return a handle that at least can be waited on.
|
||||
return local_thread_info->thread_handle.waitable_handle();
|
||||
#else
|
||||
return (detail::win32::handle)local_thread_info->thread_handle;
|
||||
#endif
|
||||
}
|
||||
|
||||
detail::thread_data_ptr thread::get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const
|
||||
@@ -461,7 +584,7 @@ namespace boost
|
||||
LARGE_INTEGER due_time={{0,0}};
|
||||
if(target_time.relative)
|
||||
{
|
||||
detail::win32::ticks_type const elapsed_milliseconds=detail::win32::GetTickCount64()()-target_time.start;
|
||||
detail::win32::ticks_type const elapsed_milliseconds=detail::win32::GetTickCount64_()()-target_time.start;
|
||||
LONGLONG const remaining_milliseconds=(target_time.milliseconds-elapsed_milliseconds);
|
||||
LONGLONG const hundred_nanoseconds_in_one_millisecond=10000;
|
||||
|
||||
@@ -535,6 +658,7 @@ namespace boost
|
||||
detail::win32::handle_manager timer_handle;
|
||||
|
||||
#ifndef UNDER_CE
|
||||
#if !BOOST_PLAT_WINDOWS_RUNTIME
|
||||
unsigned const min_timer_wait_period=20;
|
||||
|
||||
if(!target_time.is_sentinel())
|
||||
@@ -562,6 +686,7 @@ namespace boost
|
||||
target_time=detail::timeout(time_left.milliseconds);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
bool const using_timer=timeout_index!=~0u;
|
||||
@@ -576,7 +701,7 @@ namespace boost
|
||||
|
||||
if(handle_count)
|
||||
{
|
||||
unsigned long const notified_index=detail::win32::WaitForMultipleObjects(handle_count,handles,false,using_timer?INFINITE:time_left.milliseconds);
|
||||
unsigned long const notified_index=detail::win32::WaitForMultipleObjectsEx(handle_count,handles,false,using_timer?INFINITE:time_left.milliseconds, 0);
|
||||
if(notified_index<handle_count)
|
||||
{
|
||||
if(notified_index==wait_handle_index)
|
||||
@@ -598,7 +723,7 @@ namespace boost
|
||||
}
|
||||
else
|
||||
{
|
||||
detail::win32::Sleep(time_left.milliseconds);
|
||||
detail::win32::sleep(time_left.milliseconds);
|
||||
}
|
||||
if(target_time.relative)
|
||||
{
|
||||
@@ -625,6 +750,7 @@ namespace boost
|
||||
detail::win32::handle_manager timer_handle;
|
||||
|
||||
#ifndef UNDER_CE
|
||||
#if !BOOST_PLAT_WINDOWS_RUNTIME
|
||||
unsigned const min_timer_wait_period=20;
|
||||
|
||||
if(!target_time.is_sentinel())
|
||||
@@ -652,6 +778,7 @@ namespace boost
|
||||
target_time=detail::timeout(time_left.milliseconds);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
bool const using_timer=timeout_index!=~0u;
|
||||
@@ -666,7 +793,7 @@ namespace boost
|
||||
|
||||
if(handle_count)
|
||||
{
|
||||
unsigned long const notified_index=detail::win32::WaitForMultipleObjects(handle_count,handles,false,using_timer?INFINITE:time_left.milliseconds);
|
||||
unsigned long const notified_index=detail::win32::WaitForMultipleObjectsEx(handle_count,handles,false,using_timer?INFINITE:time_left.milliseconds, 0);
|
||||
if(notified_index<handle_count)
|
||||
{
|
||||
if(notified_index==wait_handle_index)
|
||||
@@ -681,7 +808,7 @@ namespace boost
|
||||
}
|
||||
else
|
||||
{
|
||||
detail::win32::Sleep(time_left.milliseconds);
|
||||
detail::win32::sleep(time_left.milliseconds);
|
||||
}
|
||||
if(target_time.relative)
|
||||
{
|
||||
@@ -695,11 +822,18 @@ namespace boost
|
||||
|
||||
thread::id get_id() BOOST_NOEXCEPT
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
|
||||
return detail::win32::GetCurrentThreadId();
|
||||
#else
|
||||
#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
detail::thread_data_base* current_thread_data(detail::get_current_thread_data());
|
||||
if (current_thread_data)
|
||||
{
|
||||
return current_thread_data->id;
|
||||
}
|
||||
#endif
|
||||
return detail::win32::GetCurrentThreadId();
|
||||
#else
|
||||
return thread::id(get_or_make_current_thread_data());
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
@@ -719,13 +853,13 @@ namespace boost
|
||||
|
||||
bool interruption_requested() BOOST_NOEXCEPT
|
||||
{
|
||||
return detail::get_current_thread_data() && (detail::win32::WaitForSingleObject(detail::get_current_thread_data()->interruption_handle,0)==0);
|
||||
return detail::get_current_thread_data() && (detail::win32::WaitForSingleObjectEx(detail::get_current_thread_data()->interruption_handle,0,0)==0);
|
||||
}
|
||||
#endif
|
||||
|
||||
void yield() BOOST_NOEXCEPT
|
||||
{
|
||||
detail::win32::Sleep(0);
|
||||
detail::win32::sleep(0);
|
||||
}
|
||||
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
@@ -839,6 +973,7 @@ namespace boost
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_THREAD_DECL void __cdecl on_process_enter()
|
||||
{}
|
||||
|
||||
|
||||
111
test/Jamfile.v2
111
test/Jamfile.v2
@@ -49,7 +49,8 @@ project
|
||||
<toolset>pathscale:<cxxflags>-pedantic
|
||||
|
||||
<toolset>clang:<cxxflags>-Wextra
|
||||
<toolset>clang:<cxxflags>-pedantic
|
||||
#<toolset>clang:<cxxflags>-pedantic
|
||||
<toolset>clang:<warnings>on
|
||||
<toolset>clang:<cxxflags>-Wno-long-long
|
||||
#<toolset>clang:<cxxflags>-ansi
|
||||
#<toolset>clang:<cxxflags>-fpermissive # doesn't work
|
||||
@@ -95,13 +96,12 @@ project
|
||||
<toolset>intel:<cxxflags>-wd193,304,383,444
|
||||
<toolset>intel:<cxxflags>-wd593,981
|
||||
<toolset>intel:<cxxflags>-wd1418
|
||||
<toolset>intel:<cxxflags>-wd2415
|
||||
|
||||
|
||||
<toolset>intel:<cxxflags>-wd2415
|
||||
;
|
||||
|
||||
rule thread-run ( sources )
|
||||
{
|
||||
sources = $(sources) winrt_init.cpp ;
|
||||
return
|
||||
[ run $(sources) ../build//boost_thread ]
|
||||
[ run $(sources) ../src/tss_null.cpp ../build//boost_thread/<link>static
|
||||
@@ -112,6 +112,7 @@ rule thread-run ( sources )
|
||||
|
||||
rule thread-test ( sources )
|
||||
{
|
||||
sources = $(sources) winrt_init.cpp ;
|
||||
return
|
||||
[ run $(sources) ../build//boost_thread : : :
|
||||
<library>/boost/test//boost_unit_test_framework/<link>static
|
||||
@@ -126,6 +127,7 @@ rule thread-test ( sources )
|
||||
|
||||
rule thread-run2 ( sources : name )
|
||||
{
|
||||
sources = $(sources) winrt_init.cpp ;
|
||||
return
|
||||
[ run $(sources) ../build//boost_thread : : :
|
||||
: $(name) ]
|
||||
@@ -137,6 +139,7 @@ rule thread-run2 ( sources : name )
|
||||
|
||||
rule thread-run2-noit ( sources : name )
|
||||
{
|
||||
sources = $(sources) winrt_init.cpp ;
|
||||
return
|
||||
[ run $(sources) ../build//boost_thread : : :
|
||||
: $(name) ]
|
||||
@@ -151,6 +154,7 @@ rule thread-run2-noit ( sources : name )
|
||||
|
||||
rule thread-run2-noit-pthread ( sources : name )
|
||||
{
|
||||
sources = $(sources) winrt_init.cpp ;
|
||||
return
|
||||
[ run $(sources) ../build//boost_thread : : : <threadapi>win32:<build>no
|
||||
: $(name) ]
|
||||
@@ -165,6 +169,7 @@ rule thread-run2-noit-pthread ( sources : name )
|
||||
|
||||
rule thread-run2-h ( sources : name )
|
||||
{
|
||||
sources = $(sources) winrt_init.cpp ;
|
||||
return
|
||||
[ run $(sources) : : :
|
||||
<library>/boost/system//boost_system
|
||||
@@ -177,6 +182,7 @@ rule thread-run2-h ( sources : name )
|
||||
|
||||
rule thread-run-lib2 ( sources : name )
|
||||
{
|
||||
sources = $(sources) winrt_init.cpp ;
|
||||
return
|
||||
[ run $(sources) ../src/tss_null.cpp ../build//boost_thread/<link>static
|
||||
: : :
|
||||
@@ -367,6 +373,9 @@ rule thread-compile ( sources : reqs * : name )
|
||||
[ thread-run2-noit ./sync/futures/future/wait_for_pass.cpp : future__wait_for_p ]
|
||||
[ thread-run2-noit ./sync/futures/future/wait_until_pass.cpp : future__wait_until_p ]
|
||||
[ thread-run2-noit ./sync/futures/future/then_pass.cpp : future__then_p ]
|
||||
[ thread-run2-noit ./sync/futures/future/then_executor_pass.cpp : future__then_executor_p ]
|
||||
[ thread-run2-noit ./sync/futures/future/async_deferred_then_pass.cpp : future__async_def_then_p ]
|
||||
[ thread-run2-noit ./sync/futures/future/then_deferred_pass.cpp : future__then_def_p ]
|
||||
;
|
||||
|
||||
#explicit ts_shared_future ;
|
||||
@@ -383,6 +392,7 @@ rule thread-compile ( sources : reqs * : name )
|
||||
[ 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 ]
|
||||
[ thread-run2-noit ./sync/futures/shared_future/then_executor_pass.cpp : shared_future__then_executor_p ]
|
||||
;
|
||||
|
||||
#explicit ts_packaged_task ;
|
||||
@@ -407,6 +417,24 @@ rule thread-compile ( sources : reqs * : name )
|
||||
;
|
||||
|
||||
|
||||
#explicit ts_when_all ;
|
||||
test-suite ts_when_all
|
||||
:
|
||||
[ thread-run2-noit ./sync/futures/when_all/none_pass.cpp : when_all__none_p ]
|
||||
[ thread-run2-noit ./sync/futures/when_all/one_pass.cpp : when_all__one_p ]
|
||||
[ thread-run2-noit ./sync/futures/when_all/iterators_pass.cpp : when_all__iterators_p ]
|
||||
[ thread-run2-noit ./sync/futures/when_all/variadic_pass.cpp : when_all__variadic_p ]
|
||||
;
|
||||
|
||||
#explicit ts_when_any ;
|
||||
test-suite ts_when_any
|
||||
:
|
||||
[ thread-run2-noit ./sync/futures/when_any/none_pass.cpp : when_any__none_p ]
|
||||
[ thread-run2-noit ./sync/futures/when_any/one_pass.cpp : when_any__one_p ]
|
||||
[ thread-run2-noit ./sync/futures/when_any/iterators_pass.cpp : when_any__iterators_p ]
|
||||
[ thread-run2-noit ./sync/futures/when_any/variadic_pass.cpp : when_any__variadic_p ]
|
||||
;
|
||||
|
||||
#explicit ts_lock_guard ;
|
||||
test-suite ts_lock_guard
|
||||
:
|
||||
@@ -430,10 +458,10 @@ rule thread-compile ( sources : reqs * : name )
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/duration_pass.cpp : unique_lock__cons__duration_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_assign_pass.cpp : unique_lock__cons__move_assign_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_pass.cpp : unique_lock__cons__move_ctor_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_pass.cpp : unique_lock__cons__move_ctor_upgrade_lock_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_try_pass.cpp : unique_lock__cons__move_ctor_upgrade_lock_try_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_for_pass.cpp : unique_lock__cons__move_ctor_upgrade_lock_for_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_until_pass.cpp : unique_lock__cons__move_ctor_upgrade_lock_until_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_pass.cpp : uq_lk_cons_mv_c_upg_lk_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_try_pass.cpp : uq_lk_cons_mv_c_upg_lk_t_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_for_pass.cpp : uq_lk_cons_mv_c_upg_lk_f_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_until_pass.cpp : uq_lk_cons_mv_c_upg_lk_u_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/mutex_pass.cpp : unique_lock__cons__mutex_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/time_point_pass.cpp : unique_lock__cons__time_point_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/try_to_lock_pass.cpp : unique_lock__cons__try_to_lock_p ]
|
||||
@@ -477,8 +505,8 @@ rule thread-compile ( sources : reqs * : name )
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/duration_pass.cpp : shared_lock__cons__duration_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/move_assign_pass.cpp : shared_lock__cons__move_assign_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_pass.cpp : shared_lock__cons__move_ctor_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_unique_lock_pass.cpp : shared_lock__cons__move_ctor_unique_lock_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_upgrade_lock_pass.cpp : shared_lock__cons__move_ctor_upgrade_lock_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_unique_lock_pass.cpp : sh_lock_cons_move_ctor_unq_lock_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_upgrade_lock_pass.cpp : sh_lock_cons_move_ctor_upg_lock_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/mutex_pass.cpp : shared_lock__cons__mutex_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/time_point_pass.cpp : shared_lock__cons__time_point_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/try_to_lock_pass.cpp : shared_lock__cons__try_to_lock_p ]
|
||||
@@ -511,7 +539,7 @@ rule thread-compile ( sources : reqs * : name )
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/duration_pass.cpp : upgrade_lock__cons__duration_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_assign_pass.cpp : upgrade_lock__cons__move_assign_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_pass.cpp : upgrade_lock__cons__move_ctor_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_unique_lock_pass.cpp : upgrade_lock__cons__move_ctor_unique_lock_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_unique_lock_pass.cpp : upg_lock_cons_mv_ctor_uq_lock_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/mutex_pass.cpp : upgrade_lock__cons__mutex_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/time_point_pass.cpp : upgrade_lock__cons__time_point_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/try_to_lock_pass.cpp : upgrade_lock__cons__try_to_lock_p ]
|
||||
@@ -543,8 +571,8 @@ rule thread-compile ( sources : reqs * : name )
|
||||
#explicit ts_nested_strict_lock ;
|
||||
test-suite ts_nested_strict_lock
|
||||
:
|
||||
[ thread-compile-fail ./sync/mutual_exclusion/locks/nested_strict_lock/copy_assign_fail.cpp : : nested_strict_lock__cons__copy_assign_f ]
|
||||
[ thread-compile-fail ./sync/mutual_exclusion/locks/nested_strict_lock/copy_ctor_fail.cpp : : nested_strict_lock__cons__copy_ctor_f ]
|
||||
[ thread-compile-fail ./sync/mutual_exclusion/locks/nested_strict_lock/copy_assign_fail.cpp : : nested_strict_lock_cons_copy_assign_f ]
|
||||
[ thread-compile-fail ./sync/mutual_exclusion/locks/nested_strict_lock/copy_ctor_fail.cpp : : nested_strict_lock_cons_copy_ctor_f ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/nested_strict_lock/default_pass.cpp : nested_strict_lock__cons__default_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/nested_strict_lock/owns_lock_pass.cpp : nested_strict_lock__owns_lock_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/nested_strict_lock/types_pass.cpp : nested_strict_lock__types_p ]
|
||||
@@ -590,10 +618,10 @@ rule thread-compile ( sources : reqs * : name )
|
||||
[ thread-compile-fail ./sync/mutual_exclusion/recursive_timed_mutex/copy_fail.cpp : : recursive_timed_mutex__copy_f ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/recursive_timed_mutex/default_pass.cpp : recursive_timed_mutex__default_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/recursive_timed_mutex/lock_pass.cpp : recursive_timed_mutex__lock_p ]
|
||||
[ thread-run2-noit-pthread ./sync/mutual_exclusion/recursive_timed_mutex/native_handle_pass.cpp : recursive_timed_mutex__native_handle_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/recursive_timed_mutex/try_lock_for_pass.cpp : recursive_timed_mutex__try_lock_for_p ]
|
||||
[ thread-run2-noit-pthread ./sync/mutual_exclusion/recursive_timed_mutex/native_handle_pass.cpp : rec_timed_mutex_native_handle_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/recursive_timed_mutex/try_lock_for_pass.cpp : rec_timed_mutex_try_lock_for_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/recursive_timed_mutex/try_lock_pass.cpp : recursive_timed_mutex__try_lock_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/recursive_timed_mutex/try_lock_until_pass.cpp : recursive_timed_mutex__try_lock_until_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/recursive_timed_mutex/try_lock_until_pass.cpp : rec_timed_mutex_try_lock_until_p ]
|
||||
;
|
||||
|
||||
#explicit ts_timed_mutex ;
|
||||
@@ -643,8 +671,14 @@ rule thread-compile ( sources : reqs * : name )
|
||||
|
||||
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 ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/sync_bounded_queue/single_thread_pass.cpp : sync_bounded_q_single_thread_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/sync_bounded_queue/multi_thread_pass.cpp : sync_bounded_q_multi_thread_p ]
|
||||
;
|
||||
|
||||
test-suite ts_queue_views
|
||||
:
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/queue_views/single_thread_pass.cpp : queue_views__single_thread_p ]
|
||||
#[ thread-run2-noit ./sync/mutual_exclusion/queue_views/multi_thread_pass.cpp : queue_views__multi_thread_p ]
|
||||
;
|
||||
|
||||
#explicit ts_this_thread ;
|
||||
@@ -719,13 +753,15 @@ rule thread-compile ( sources : reqs * : name )
|
||||
[ thread-run2-noit ../example/ba_externallly_locked.cpp : ex_ba_externallly_locked ]
|
||||
[ thread-run2 ../example/producer_consumer_bounded.cpp : ex_producer_consumer_bounded ]
|
||||
[ thread-run2 ../example/producer_consumer.cpp : ex_producer_consumer ]
|
||||
[ thread-run2 ../example/producer_consumer2.cpp : ex_producer_consumer2 ]
|
||||
[ thread-run2 ../example/not_interleaved.cpp : ex_not_interleaved ]
|
||||
[ thread-run2 ../example/lambda_future.cpp : ex_lambda_future ]
|
||||
[ thread-run2 ../example/not_interleaved2.cpp : ex_not_interleaved2 ]
|
||||
[ thread-run2 ../example/thread_pool.cpp : ex_thread_pool ]
|
||||
[ thread-run2 ../example/user_scheduler.cpp : ex_user_scheduler ]
|
||||
[ thread-run2 ../example/executor.cpp : ex_executor ]
|
||||
[ thread-run2 ../example/future_when_all.cpp : future_when_all ]
|
||||
[ thread-run2 ../example/generic_executor_ref.cpp : ex_generic_executor_ref ]
|
||||
[ thread-run2 ../example/future_when_all.cpp : ex_future_when_all ]
|
||||
[ thread-run2 ../example/parallel_accumulate.cpp : ex_parallel_accumulate ]
|
||||
[ thread-run2 ../example/parallel_quick_sort.cpp : ex_parallel_quick_sort ]
|
||||
[ thread-run2 ../example/with_lock_guard.cpp : ex_with_lock_guard ]
|
||||
@@ -735,13 +771,13 @@ rule thread-compile ( sources : reqs * : name )
|
||||
#explicit ts_shared_upwards ;
|
||||
test-suite ts_shared_upwards
|
||||
:
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_try_pass.cpp : unique_lock__cons__move_ctor_shared_lock_try_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_for_pass.cpp : unique_lock__cons__move_ctor_shared_lock_for_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_until_pass.cpp : unique_lock__cons__move_ctor_shared_lock_until_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_try_pass.cpp : uq_lock_cons_mv_ctor_sh_lock_try_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_for_pass.cpp : uq_lock_cons_mv_ctor_sh_lock_for_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_until_pass.cpp : uq_lock_cons_mv_ctor_sh_lock_until_p ]
|
||||
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_try_pass.cpp : upgrade_lock__cons__move_ctor_shared_lock_try_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_for_pass.cpp : upgrade_lock__cons__move_ctor_shared_lock_for_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_until_pass.cpp : upgrade_lock__cons__move_ctor_shared_lock_until_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_try_pass.cpp : upg_lock_cons_move_ctor_sh_lock_try_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_for_pass.cpp : upg_lock_cons_move_ctor_sh_lock_for_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_until_pass.cpp : upg_lock_cons_move_ctor_sh_lock_untl_p ]
|
||||
;
|
||||
|
||||
|
||||
@@ -810,6 +846,8 @@ rule thread-compile ( sources : reqs * : name )
|
||||
[ thread-run2-noit ./functional/invoker/invoker_rvalue_pass.cpp : invoker_rvalue_p ]
|
||||
;
|
||||
|
||||
|
||||
|
||||
explicit ts_more ;
|
||||
test-suite ts_more
|
||||
:
|
||||
@@ -825,6 +863,11 @@ rule thread-compile ( sources : reqs * : name )
|
||||
[ thread-run test_9079_a.cpp ]
|
||||
[ thread-run test_9079_b.cpp ]
|
||||
[ thread-run test_9192.cpp ]
|
||||
#[ thread-run test_9303.cpp ]
|
||||
#[ thread-run test_9720.cpp ]
|
||||
#[ thread-run test_10125.cpp ]
|
||||
#[ thread-run test_10128.cpp ]
|
||||
#[ thread-run test_10340.cpp ]
|
||||
;
|
||||
|
||||
explicit ts_more_cpp11 ;
|
||||
@@ -833,21 +876,17 @@ rule thread-compile ( sources : reqs * : name )
|
||||
[ thread-run test_8596.cpp ]
|
||||
[ thread-run test_8600.cpp ]
|
||||
;
|
||||
|
||||
explicit perf ;
|
||||
test-suite perf
|
||||
:
|
||||
#[ thread-run ../example/perf_condition_variable.cpp ]
|
||||
#[ thread-run ../example/perf_shared_mutex.cpp ]
|
||||
;
|
||||
|
||||
explicit ts_ ;
|
||||
test-suite ts_
|
||||
:
|
||||
#[ thread-run ../example/test_so.cpp ]
|
||||
#[ thread-run ../example/test_so2.cpp ]
|
||||
#[ thread-run ../example/perf_condition_variable.cpp ]
|
||||
#[ thread-run ../example/perf_shared_mutex.cpp ]
|
||||
#[ thread-run ../example/std_async_test.cpp ]
|
||||
#[ compile virtual_noexcept.cpp ]
|
||||
#[ thread-run clang_main.cpp ]
|
||||
#[ thread-run test_9303.cpp ]
|
||||
#[ thread-run test_9720.cpp ]
|
||||
#[ thread-run test_10125.cpp ]
|
||||
#[ thread-run test_10128.cpp ]
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
@@ -70,38 +70,38 @@ public:
|
||||
|
||||
int value;
|
||||
|
||||
BOOST_THREAD_MOVABLE_ONLY(MoveOnly)
|
||||
BOOST_THREAD_MOVABLE_ONLY(MoveOnly)
|
||||
MoveOnly()
|
||||
{
|
||||
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)
|
||||
{
|
||||
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()
|
||||
{
|
||||
@@ -263,6 +263,32 @@ 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<long> f = boost::async(boost::launch::deferred, A(3));
|
||||
//boost::this_thread::sleep_for(ms(300));
|
||||
int res;
|
||||
{
|
||||
check_timer timer(ms(500));
|
||||
res = f.get();
|
||||
}
|
||||
BOOST_TEST(res == 3);
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl;
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
{
|
||||
@@ -289,6 +315,31 @@ int main()
|
||||
}
|
||||
|
||||
}
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
{
|
||||
try
|
||||
{
|
||||
A a(3);
|
||||
boost::future<long> f = boost::async(boost::launch::deferred, &A::doit, &a);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
int res;
|
||||
{
|
||||
check_timer timer(ms(500));
|
||||
res = f.get();
|
||||
}
|
||||
BOOST_TEST(res == 3);
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl;
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
{
|
||||
@@ -313,6 +364,31 @@ int main()
|
||||
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, BOOST_THREAD_MAKE_RV_REF(MoveOnly()));
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
int res;
|
||||
{
|
||||
check_timer timer(ms(500));
|
||||
res = f.get();
|
||||
}
|
||||
BOOST_TEST(res == 3);
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl;
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
{
|
||||
try
|
||||
@@ -342,7 +418,7 @@ int main()
|
||||
try
|
||||
{
|
||||
boost::future<int> f = boost::async(boost::launch::deferred, f0);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
//boost::this_thread::sleep_for(ms(300));
|
||||
int res;
|
||||
{
|
||||
check_timer timer(ms(500));
|
||||
@@ -436,7 +512,7 @@ int main()
|
||||
try
|
||||
{
|
||||
boost::future<int&> f = boost::async(boost::launch::deferred, f1);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
//boost::this_thread::sleep_for(ms(300));
|
||||
int* res;
|
||||
{
|
||||
check_timer timer(ms(500));
|
||||
@@ -524,7 +600,7 @@ int main()
|
||||
try
|
||||
{
|
||||
boost::future<void> f = boost::async(boost::launch::deferred, f2);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
//boost::this_thread::sleep_for(ms(300));
|
||||
{
|
||||
check_timer timer(ms(500));
|
||||
f.get();
|
||||
@@ -565,6 +641,31 @@ int main()
|
||||
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<MoveOnly> f = boost::async(boost::launch::deferred, &f3_1);
|
||||
//boost::this_thread::sleep_for(ms(300));
|
||||
MoveOnly res;
|
||||
{
|
||||
check_timer timer(ms(500));
|
||||
res = f.get();
|
||||
}
|
||||
BOOST_TEST_EQ(res.value, 2);
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl;
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
{
|
||||
try
|
||||
@@ -638,6 +739,29 @@ int main()
|
||||
}
|
||||
}
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl;
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::future<boost::csbl::unique_ptr<int> > f = boost::async(boost::launch::deferred, &f3, 3);
|
||||
//boost::this_thread::sleep_for(ms(300));
|
||||
boost::csbl::unique_ptr<int> res;
|
||||
{
|
||||
check_timer timer(ms(500));
|
||||
res = f.get();
|
||||
}
|
||||
BOOST_TEST(*res == 3);
|
||||
}
|
||||
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
|
||||
{
|
||||
@@ -687,6 +811,29 @@ int main()
|
||||
}
|
||||
}
|
||||
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl;
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::future<boost::csbl::unique_ptr<int> > f = boost::async(boost::launch::deferred, &f4, boost::csbl::unique_ptr<int>(new int(3)));
|
||||
//boost::this_thread::sleep_for(ms(300));
|
||||
boost::csbl::unique_ptr<int> res;
|
||||
{
|
||||
check_timer timer(ms(500));
|
||||
res = f.get();
|
||||
}
|
||||
BOOST_TEST(*res == 3);
|
||||
}
|
||||
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
|
||||
{
|
||||
|
||||
130
test/sync/futures/future/async_deferred_then_pass.cpp
Normal file
130
test/sync/futures/future/async_deferred_then_pass.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
// 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 && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
|
||||
|
||||
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::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::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::future<int> f1 = boost::async(boost::launch::deferred, &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);
|
||||
}
|
||||
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> f1 = boost::async(boost::launch::deferred, &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(boost::launch::deferred, p1).then(&p2);
|
||||
BOOST_TEST(f2.get()==2);
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
boost::future<int> f1 = boost::async(boost::launch::deferred, p1);
|
||||
boost::future<int> f21 = f1.then(&p2);
|
||||
boost::future<int> f2= f21.then(&p2);
|
||||
BOOST_TEST(f2.get()==4);
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
boost::future<int> f1 = boost::async(boost::launch::deferred, p1);
|
||||
boost::future<int> f2= f1.then(&p2).then(&p2);
|
||||
BOOST_TEST(f2.get()==4);
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
boost::future<int> f2 = boost::async(boost::launch::deferred, p1).then(&p2).then(&p2);
|
||||
BOOST_TEST(f2.get()==4);
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -11,7 +11,7 @@
|
||||
// R& future<R&>::get_or(R&);
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_USES_LOG
|
||||
//#define BOOST_THREAD_USES_LOG
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
#include <boost/thread/detail/log.hpp>
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
//#define BOOST_THREAD_VERSION 3
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_USES_LOG
|
||||
//#define BOOST_THREAD_USES_LOG
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
#include <boost/thread/detail/log.hpp>
|
||||
|
||||
|
||||
130
test/sync/futures/future/then_deferred_pass.cpp
Normal file
130
test/sync/futures/future/then_deferred_pass.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
// 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::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::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::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<int> f2 = f1.then(boost::launch::deferred, &p2);
|
||||
BOOST_TEST(f2.valid());
|
||||
BOOST_TEST(! f1.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::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<void> f2 = f1.then(boost::launch::deferred, &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(boost::launch::deferred, &p2);
|
||||
BOOST_TEST(f2.get()==2);
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
boost::future<int> f1 = boost::async(p1);
|
||||
boost::future<int> f21 = f1.then(boost::launch::deferred, &p2);
|
||||
boost::future<int> f2= f21.then(boost::launch::deferred, &p2);
|
||||
BOOST_TEST(f2.get()==4);
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
boost::future<int> f1 = boost::async(p1);
|
||||
boost::future<int> f2= f1.then(boost::launch::deferred, &p2).then(boost::launch::deferred, &p2);
|
||||
BOOST_TEST(f2.get()==4);
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
boost::future<int> f2 = boost::async(p1).then(boost::launch::deferred, &p2).then(boost::launch::deferred, &p2);
|
||||
BOOST_TEST(f2.get()==4);
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
139
test/sync/futures/future/then_executor_pass.cpp
Normal file
139
test/sync/futures/future/then_executor_pass.cpp
Normal file
@@ -0,0 +1,139 @@
|
||||
// Copyright (C) 2014 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_PROVIDES_EXECUTORS
|
||||
//#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/executors/basic_thread_pool.hpp>
|
||||
#include <boost/thread/executor.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::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::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::basic_thread_pool ex(1);
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<int> f2 = f1.then(ex, &p2);
|
||||
BOOST_TEST(f2.valid());
|
||||
BOOST_TEST(! f1.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::basic_thread_pool ex(1);
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<void> f2 = f1.then(ex, &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::basic_thread_pool ex(1);
|
||||
boost::future<int> f2 = boost::async(p1).then(ex, &p2);
|
||||
BOOST_TEST(f2.get()==2);
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
boost::basic_thread_pool ex(1);
|
||||
boost::future<int> f1 = boost::async(p1);
|
||||
boost::future<int> f21 = f1.then(ex, &p2);
|
||||
boost::future<int> f2= f21.then(ex, &p2);
|
||||
BOOST_TEST(f2.get()==4);
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
boost::basic_thread_pool ex(1);
|
||||
boost::future<int> f1 = boost::async(p1);
|
||||
boost::future<int> f2= f1.then(&p2).then(ex, &p2);
|
||||
BOOST_TEST(f2.get()==4);
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
boost::basic_thread_pool ex(1);
|
||||
boost::future<int> f2 = boost::async(p1).then(ex, &p2).then(ex, &p2);
|
||||
BOOST_TEST(f2.get()==4);
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -11,7 +11,7 @@
|
||||
// auto then(F&& func) -> future<decltype(func(*this))>;
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_USES_LOG
|
||||
//#define BOOST_THREAD_USES_LOG
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
#include <boost/thread/detail/log.hpp>
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
// wait_for(const chrono::duration<Rep, Period>& rel_time) const;
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_USES_LOG
|
||||
//#define BOOST_THREAD_USES_LOG
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
#include <boost/thread/detail/log.hpp>
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
//#define BOOST_THREAD_VERSION 3
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_USES_LOG
|
||||
//#define BOOST_THREAD_USES_LOG
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
#include <boost/thread/detail/log.hpp>
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
//#define BOOST_THREAD_VERSION 3
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_USES_LOG
|
||||
//#define BOOST_THREAD_USES_LOG
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
#include <boost/thread/detail/log.hpp>
|
||||
|
||||
|
||||
@@ -64,11 +64,24 @@ public:
|
||||
++n_instances;
|
||||
++n_moves; BOOST_THREAD_RV(a).data_ = -1;
|
||||
}
|
||||
A& operator=(BOOST_THREAD_RV_REF(A) a)
|
||||
{
|
||||
data_ = BOOST_THREAD_RV(a).data_;
|
||||
BOOST_THREAD_RV(a).data_ = -1;
|
||||
++n_moves;
|
||||
return *this;
|
||||
}
|
||||
A(const A& a) : data_(a.data_)
|
||||
{
|
||||
++n_instances;
|
||||
++n_copies;
|
||||
}
|
||||
A& operator=(BOOST_THREAD_COPY_ASSIGN_REF(A) a)
|
||||
{
|
||||
data_ = a.data_;
|
||||
++n_copies;
|
||||
return *this;
|
||||
}
|
||||
~A()
|
||||
{
|
||||
--n_instances;
|
||||
|
||||
@@ -94,7 +94,7 @@ public:
|
||||
{
|
||||
++n_copies;
|
||||
}
|
||||
A& operator=(A const& a)
|
||||
A& operator=(BOOST_THREAD_COPY_ASSIGN_REF(A) a)
|
||||
{
|
||||
data_ = a.data_;
|
||||
++n_copies;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Copyright (C) 2011 Vicente J. Botet Escriba
|
||||
// Copyright (C) 2011,2014 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)
|
||||
@@ -16,33 +16,39 @@
|
||||
|
||||
// class promise<R>
|
||||
|
||||
// void promise::set_exception_at_thread_exit(exception_ptr p);
|
||||
// void promise::set_value_at_thread_exit(R&& p);
|
||||
|
||||
#define BOOST_THREAD_VERSION 3
|
||||
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <boost/thread/detail/memory.hpp>
|
||||
//#include <boost/interprocess/smart_ptr/unique_ptr.hpp>
|
||||
#include <boost/thread/csbl/memory/unique_ptr.hpp>
|
||||
|
||||
//void func(boost::promise<boost::csbl::unique_ptr<int> > p)
|
||||
boost::promise<boost::csbl::unique_ptr<int> > p;
|
||||
boost::promise<boost::csbl::unique_ptr<int> > p2;
|
||||
void func()
|
||||
{
|
||||
boost::csbl::unique_ptr<int> uptr(new int(5));
|
||||
p.set_value_at_thread_exit(boost::move(uptr));
|
||||
}
|
||||
void func2()
|
||||
{
|
||||
p2.set_value_at_thread_exit(boost::csbl::make_unique<int>(5));
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
//boost::promise<boost::csbl::unique_ptr<int> > > p;
|
||||
boost::future<boost::csbl::unique_ptr<int> > f = p.get_future();
|
||||
//boost::thread(func, boost::move(p)).detach();
|
||||
boost::thread(func).detach();
|
||||
BOOST_TEST(*f.get() == 5);
|
||||
}
|
||||
{
|
||||
boost::future<boost::csbl::unique_ptr<int> > f = p2.get_future();
|
||||
boost::thread(func2).detach();
|
||||
BOOST_TEST(*f.get() == 5);
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Copyright (C) 2011 Vicente J. Botet Escriba
|
||||
// Copyright (C) 2011,2014 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)
|
||||
@@ -24,8 +24,6 @@
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
|
||||
struct A
|
||||
{
|
||||
A() :
|
||||
@@ -36,8 +34,9 @@ struct A
|
||||
value(i)
|
||||
{
|
||||
}
|
||||
BOOST_THREAD_DELETE_COPY_CTOR(A)
|
||||
A(A&& rhs)
|
||||
BOOST_THREAD_MOVABLE_ONLY(A)
|
||||
|
||||
A(BOOST_THREAD_RV_REF(A) rhs)
|
||||
{
|
||||
if(rhs.value==0)
|
||||
throw 9;
|
||||
@@ -47,14 +46,58 @@ struct A
|
||||
rhs.value=0;
|
||||
}
|
||||
}
|
||||
A& operator=(BOOST_THREAD_RV_REF(A) rhs)
|
||||
{
|
||||
if(rhs.value==0)
|
||||
throw 9;
|
||||
else
|
||||
{
|
||||
value=rhs.value;
|
||||
rhs.value=0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
int value;
|
||||
};
|
||||
|
||||
#endif // BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
A make(int i) {
|
||||
return A(i);
|
||||
}
|
||||
|
||||
struct movable2
|
||||
{
|
||||
int value_;
|
||||
BOOST_THREAD_MOVABLE_ONLY(movable2)
|
||||
movable2() : value_(1){}
|
||||
movable2(int i) : value_(i){}
|
||||
|
||||
//Move constructor and assignment
|
||||
movable2(BOOST_RV_REF(movable2) m)
|
||||
{ value_ = m.value_; m.value_ = 0; }
|
||||
|
||||
movable2 & operator=(BOOST_THREAD_RV_REF(movable2) m)
|
||||
{ value_ = m.value_; m.value_ = 0; return *this; }
|
||||
|
||||
bool moved() const //Observer
|
||||
{ return !value_; }
|
||||
|
||||
int value() const //Observer
|
||||
{ return value_; }
|
||||
};
|
||||
|
||||
|
||||
movable2 move_return_function2(int i) {
|
||||
return movable2(i);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
#if defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
BOOST_STATIC_ASSERT((boost::is_copy_constructible<movable2>::value == false));
|
||||
BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<movable2>::value == true));
|
||||
BOOST_STATIC_ASSERT((boost::is_copy_constructible<A>::value == false));
|
||||
BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<A>::value == true));
|
||||
#endif
|
||||
|
||||
{
|
||||
typedef A T;
|
||||
@@ -75,6 +118,25 @@ int main()
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
{
|
||||
typedef A T;
|
||||
T i;
|
||||
boost::promise<T> p;
|
||||
boost::future<T> f = p.get_future();
|
||||
try
|
||||
{
|
||||
p.set_value((T()));
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
catch (int j)
|
||||
{
|
||||
BOOST_TEST(j == 9);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
{
|
||||
typedef A T;
|
||||
T i(3);
|
||||
@@ -97,6 +159,49 @@ int main()
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
|
||||
}
|
||||
{
|
||||
movable2 i(3);
|
||||
boost::promise<movable2> p;
|
||||
boost::future<movable2> f = p.get_future();
|
||||
p.set_value(move_return_function2(3));
|
||||
BOOST_TEST(f.get().value_ == 3);
|
||||
try
|
||||
{
|
||||
movable2 j(3);
|
||||
p.set_value(boost::move(j));
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
catch (const boost::future_error& e)
|
||||
{
|
||||
BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
|
||||
}
|
||||
{
|
||||
boost::promise<A> p;
|
||||
boost::future<A> f = p.get_future();
|
||||
p.set_value(make(3));
|
||||
BOOST_TEST(f.get().value == 3);
|
||||
try
|
||||
{
|
||||
A j(3);
|
||||
p.set_value(boost::move(j));
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
catch (const boost::future_error& e)
|
||||
{
|
||||
BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
|
||||
}
|
||||
{
|
||||
typedef A T;
|
||||
@@ -146,7 +251,6 @@ int main()
|
||||
BOOST_TEST(f2.get().get() == 3);
|
||||
}
|
||||
|
||||
#endif // BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
|
||||
137
test/sync/futures/shared_future/then_executor_pass.cpp
Normal file
137
test/sync/futures/shared_future/then_executor_pass.cpp
Normal file
@@ -0,0 +1,137 @@
|
||||
// Copyright (C) 2014 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_PROVIDES_EXECUTORS
|
||||
//#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/executors/basic_thread_pool.hpp>
|
||||
#include <boost/thread/executor.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::basic_thread_pool ex(1);
|
||||
boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share();
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<int> f2 = f1.then(ex, &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::basic_thread_pool ex(1);
|
||||
boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share();
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<void> f2 = f1.then(ex, &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::basic_thread_pool ex(1);
|
||||
boost::future<int> f2 = boost::async(p1).share().then(ex, &p2);
|
||||
BOOST_TEST(f2.get()==2);
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
boost::basic_thread_pool ex(1);
|
||||
boost::shared_future<int> f1 = boost::async(p1).share();
|
||||
boost::shared_future<int> f21 = f1.then(ex, &p2).share();
|
||||
boost::future<int> f2= f21.then(&p2);
|
||||
BOOST_TEST(f2.get()==4);
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
boost::basic_thread_pool ex(1);
|
||||
boost::shared_future<int> f1 = boost::async(p1).share();
|
||||
boost::future<int> f2= f1.then(ex, &p2).share().then(ex, &p2);
|
||||
BOOST_TEST(f2.get()==4);
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
boost::basic_thread_pool ex(1);
|
||||
boost::future<int> f2 = boost::async(p1).share().then(ex, &p2).share().then(ex, &p2);
|
||||
BOOST_TEST(f2.get()==4);
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -11,7 +11,7 @@
|
||||
// auto then(F&& func) -> future<decltype(func(*this))>;
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_USES_LOG
|
||||
//#define BOOST_THREAD_USES_LOG
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
#include <boost/thread/detail/log.hpp>
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
// wait_for(const chrono::duration<Rep, Period>& rel_time) const;
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_USES_LOG
|
||||
//#define BOOST_THREAD_USES_LOG
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
#include <boost/thread/detail/log.hpp>
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
//#define BOOST_THREAD_VERSION 3
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_USES_LOG
|
||||
//#define BOOST_THREAD_USES_LOG
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
#include <boost/thread/detail/log.hpp>
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
//#define BOOST_THREAD_VERSION 3
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_USES_LOG
|
||||
//#define BOOST_THREAD_USES_LOG
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
#include <boost/thread/detail/log.hpp>
|
||||
|
||||
|
||||
358
test/sync/futures/when_all/iterators_pass.cpp
Normal file
358
test/sync/futures/when_all/iterators_pass.cpp
Normal file
@@ -0,0 +1,358 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Copyright (C) 2014 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>
|
||||
|
||||
// template< typename InputIterator>
|
||||
// future<vector<typename InputIterator::value_type> >
|
||||
// when_all(InputIterator first, InputIterator last)
|
||||
|
||||
#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/future.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
int p1()
|
||||
{
|
||||
return 123;
|
||||
}
|
||||
|
||||
int thr()
|
||||
{
|
||||
throw std::logic_error("123");
|
||||
}
|
||||
int p2()
|
||||
{
|
||||
return 321;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
|
||||
if (0) // todo not yet implemented
|
||||
{ // invalid future copy-constructible
|
||||
boost::csbl::vector<boost::future<int> > v;
|
||||
boost::future<int> f1;
|
||||
v.push_back(boost::move(f1));
|
||||
v.push_back(boost::make_ready_future(321));
|
||||
BOOST_TEST(! v[0].valid());
|
||||
BOOST_TEST(v[1].valid());
|
||||
|
||||
boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(v.begin(), v.end());
|
||||
BOOST_TEST(! v[0].valid());
|
||||
BOOST_TEST(! v[1].valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::vector<boost::future<int> > res = all.get();
|
||||
BOOST_TEST(res.size() == 2);
|
||||
BOOST_TEST(res[1].valid());
|
||||
BOOST_TEST(res[1].is_ready());
|
||||
// has exception
|
||||
//BOOST_TEST(res[0].get() == 123);
|
||||
BOOST_TEST(res[1].valid());
|
||||
BOOST_TEST(res[1].is_ready());
|
||||
BOOST_TEST(res[1].get() == 321);
|
||||
}
|
||||
{ // is_ready future copy-constructible
|
||||
boost::future<int> f1 = boost::make_ready_future(123);
|
||||
boost::future<int> f2 = boost::make_ready_future(321);
|
||||
boost::csbl::vector<boost::future<int> > v;
|
||||
v.push_back(boost::move(f1));
|
||||
v.push_back(boost::move(f2));
|
||||
BOOST_TEST(v[0].valid());
|
||||
BOOST_TEST(v[0].is_ready());
|
||||
BOOST_TEST(v[1].valid());
|
||||
BOOST_TEST(v[1].is_ready());
|
||||
boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(v.begin(), v.end());
|
||||
BOOST_TEST(! v[0].valid());
|
||||
BOOST_TEST(! v[1].valid());
|
||||
BOOST_TEST(all.valid());
|
||||
if (0) // todo FAILS not yet implemented
|
||||
BOOST_TEST(all.is_ready());
|
||||
boost::csbl::vector<boost::future<int> > res = all.get();
|
||||
BOOST_TEST(res[0].valid());
|
||||
BOOST_TEST(res[0].is_ready());
|
||||
BOOST_TEST(res[0].get() == 123);
|
||||
BOOST_TEST(res[1].valid());
|
||||
BOOST_TEST(res[1].is_ready());
|
||||
BOOST_TEST(res[1].get() == 321);
|
||||
}
|
||||
{ // is_ready shared_future copy-constructible
|
||||
boost::shared_future<int> f1 = boost::make_ready_future(123).share();
|
||||
boost::shared_future<int> f2 = boost::make_ready_future(321).share();
|
||||
boost::csbl::vector<boost::shared_future<int> > v;
|
||||
v.push_back(f1);
|
||||
v.push_back(f2);
|
||||
BOOST_TEST(v[0].valid());
|
||||
BOOST_TEST(v[0].is_ready());
|
||||
BOOST_TEST(v[1].valid());
|
||||
BOOST_TEST(v[1].is_ready());
|
||||
boost::future<boost::csbl::vector<boost::shared_future<int> > > all = boost::when_all(v.begin(), v.end());
|
||||
if (0) // fixme
|
||||
BOOST_TEST(v[0].valid());
|
||||
if (0) // fixme
|
||||
BOOST_TEST(v[1].valid());
|
||||
BOOST_TEST(all.valid());
|
||||
if (0) // todo FAILS not yet implemented
|
||||
BOOST_TEST(all.is_ready());
|
||||
boost::csbl::vector<boost::shared_future<int> > res = all.get();
|
||||
BOOST_TEST(res[0].valid());
|
||||
BOOST_TEST(res[0].is_ready());
|
||||
BOOST_TEST(res[0].get() == 123);
|
||||
BOOST_TEST(res[1].valid());
|
||||
BOOST_TEST(res[1].is_ready());
|
||||
BOOST_TEST(res[1].get() == 321);
|
||||
}
|
||||
{ // packaged_task future copy-constructible
|
||||
boost::packaged_task<int()> pt1(&p1);
|
||||
boost::future<int> f1 = pt1.get_future();
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::packaged_task<int()> pt2(&p2);
|
||||
boost::future<int> f2 = pt2.get_future();
|
||||
BOOST_TEST(f2.valid());
|
||||
boost::csbl::vector<boost::future<int> > v;
|
||||
v.push_back(boost::move(f1));
|
||||
v.push_back(boost::move(f2));
|
||||
BOOST_TEST(v[0].valid());
|
||||
BOOST_TEST(v[1].valid());
|
||||
boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(v.begin(), v.end());
|
||||
BOOST_TEST(! v[0].valid());
|
||||
BOOST_TEST(! v[1].valid());
|
||||
BOOST_TEST(all.valid());
|
||||
pt1();
|
||||
pt2();
|
||||
boost::csbl::vector<boost::future<int> > res = all.get();
|
||||
BOOST_TEST(res[0].valid());
|
||||
BOOST_TEST(res[0].is_ready());
|
||||
BOOST_TEST(res[0].get() == 123);
|
||||
BOOST_TEST(res[1].valid());
|
||||
BOOST_TEST(res[1].is_ready());
|
||||
BOOST_TEST(res[1].get() == 321);
|
||||
}
|
||||
{ // packaged_task future copy-constructible
|
||||
boost::packaged_task<int()> pt1(&thr);
|
||||
boost::future<int> f1 = pt1.get_future();
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::packaged_task<int()> pt2(&p2);
|
||||
boost::future<int> f2 = pt2.get_future();
|
||||
BOOST_TEST(f2.valid());
|
||||
boost::csbl::vector<boost::future<int> > v;
|
||||
v.push_back(boost::move(f1));
|
||||
v.push_back(boost::move(f2));
|
||||
BOOST_TEST(v[0].valid());
|
||||
BOOST_TEST(v[1].valid());
|
||||
boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(v.begin(), v.end());
|
||||
BOOST_TEST(! v[0].valid());
|
||||
BOOST_TEST(! v[1].valid());
|
||||
BOOST_TEST(all.valid());
|
||||
pt1();
|
||||
pt2();
|
||||
boost::csbl::vector<boost::future<int> > res = all.get();
|
||||
BOOST_TEST(res[0].valid());
|
||||
BOOST_TEST(res[0].is_ready());
|
||||
try {
|
||||
res[0].get();
|
||||
BOOST_TEST(false);
|
||||
} catch (std::logic_error& ex) {
|
||||
BOOST_TEST(ex.what() == std::string("123"));
|
||||
} catch (...) {
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
BOOST_TEST(res[1].valid());
|
||||
BOOST_TEST(res[1].is_ready());
|
||||
BOOST_TEST(res[1].get() == 321);
|
||||
}
|
||||
{ // packaged_task shared_future copy-constructible
|
||||
boost::packaged_task<int()> pt1(&p1);
|
||||
boost::shared_future<int> f1 = pt1.get_future().share();
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::packaged_task<int()> pt2(&p2);
|
||||
boost::shared_future<int> f2 = pt2.get_future().share();
|
||||
BOOST_TEST(f2.valid());
|
||||
boost::csbl::vector<boost::shared_future<int> > v;
|
||||
v.push_back(f1);
|
||||
v.push_back(f2);
|
||||
BOOST_TEST(v[0].valid());
|
||||
BOOST_TEST(v[1].valid());
|
||||
boost::future<boost::csbl::vector<boost::shared_future<int> > > all = boost::when_all(v.begin(), v.end());
|
||||
if (0) // fixme
|
||||
BOOST_TEST(v[0].valid());
|
||||
if (0) // fixme
|
||||
BOOST_TEST(v[1].valid());
|
||||
BOOST_TEST(all.valid());
|
||||
BOOST_TEST(! all.is_ready());
|
||||
pt1();
|
||||
BOOST_TEST(! all.is_ready());
|
||||
pt2();
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(300));
|
||||
BOOST_TEST(all.is_ready());
|
||||
boost::csbl::vector<boost::shared_future<int> > res = all.get();
|
||||
BOOST_TEST(res[0].valid());
|
||||
BOOST_TEST(res[0].is_ready());
|
||||
BOOST_TEST(res[0].get() == 123);
|
||||
BOOST_TEST(res[1].valid());
|
||||
BOOST_TEST(res[1].is_ready());
|
||||
BOOST_TEST(res[1].get() == 321);
|
||||
}
|
||||
{ // async future copy-constructible
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<int> f2 = boost::async(boost::launch::async, &p2);
|
||||
BOOST_TEST(f2.valid());
|
||||
boost::csbl::vector<boost::future<int> > v;
|
||||
v.push_back(boost::move(f1));
|
||||
v.push_back(boost::move(f2));
|
||||
BOOST_TEST(v[0].valid());
|
||||
BOOST_TEST(v[1].valid());
|
||||
boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(v.begin(), v.end());
|
||||
BOOST_TEST(! v[0].valid());
|
||||
BOOST_TEST(! v[1].valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::vector<boost::future<int> > res = all.get();
|
||||
BOOST_TEST(res[0].valid());
|
||||
BOOST_TEST(res[0].is_ready());
|
||||
BOOST_TEST(res[0].get() == 123);
|
||||
BOOST_TEST(res[1].valid());
|
||||
BOOST_TEST(res[1].is_ready());
|
||||
BOOST_TEST(res[1].get() == 321);
|
||||
}
|
||||
{ // async shared_future copy-constructible
|
||||
boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share();
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::shared_future<int> f2 = boost::async(boost::launch::async, &p2).share();
|
||||
BOOST_TEST(f2.valid());
|
||||
boost::csbl::vector<boost::shared_future<int> > v;
|
||||
v.push_back(f1);
|
||||
v.push_back(f2);
|
||||
BOOST_TEST(v[0].valid());
|
||||
BOOST_TEST(v[1].valid());
|
||||
boost::future<boost::csbl::vector<boost::shared_future<int> > > all = boost::when_all(v.begin(), v.end());
|
||||
if (0) // fixme
|
||||
BOOST_TEST(v[0].valid());
|
||||
if (0) // fixme
|
||||
BOOST_TEST(v[1].valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::vector<boost::shared_future<int> > res = all.get();
|
||||
BOOST_TEST(res[0].valid());
|
||||
BOOST_TEST(res[0].is_ready());
|
||||
BOOST_TEST(res[0].get() == 123);
|
||||
BOOST_TEST(res[1].valid());
|
||||
BOOST_TEST(res[1].is_ready());
|
||||
BOOST_TEST(res[1].get() == 321);
|
||||
}
|
||||
{ // async future copy-constructible
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<int> f2 = boost::make_ready_future(321);
|
||||
BOOST_TEST(f2.valid());
|
||||
BOOST_TEST(f2.is_ready());
|
||||
boost::csbl::vector<boost::future<int> > v;
|
||||
v.push_back(boost::move(f1));
|
||||
v.push_back(boost::move(f2));
|
||||
BOOST_TEST(v[0].valid());
|
||||
BOOST_TEST(v[1].valid());
|
||||
boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(v.begin(), v.end());
|
||||
BOOST_TEST(! v[0].valid());
|
||||
BOOST_TEST(! v[1].valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::vector<boost::future<int> > res = all.get();
|
||||
BOOST_TEST(res[0].valid());
|
||||
BOOST_TEST(res[0].is_ready());
|
||||
BOOST_TEST(res[0].get() == 123);
|
||||
BOOST_TEST(res[1].valid());
|
||||
BOOST_TEST(res[1].is_ready());
|
||||
BOOST_TEST(res[1].get() == 321);
|
||||
}
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE_N3276
|
||||
// fixme darwin-4.8.0_11 terminate called without an active exception
|
||||
{ // deferred future copy-constructible
|
||||
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);
|
||||
boost::future<int> f2 = boost::async(boost::launch::deferred, &p2);
|
||||
boost::csbl::vector<boost::future<int> > v;
|
||||
v.push_back(boost::move(f1));
|
||||
v.push_back(boost::move(f2));
|
||||
BOOST_TEST(v[0].valid());
|
||||
BOOST_TEST(v[1].valid());
|
||||
boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(v.begin(), v.end());
|
||||
BOOST_TEST(! v[0].valid());
|
||||
BOOST_TEST(! v[1].valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::vector<boost::future<int> > res = all.get();
|
||||
BOOST_TEST(res[0].valid());
|
||||
BOOST_TEST(res[0].is_ready());
|
||||
BOOST_TEST(res[0].get() == 123);
|
||||
BOOST_TEST(res[1].valid());
|
||||
BOOST_TEST(res[1].is_ready());
|
||||
BOOST_TEST(res[1].get() == 321);
|
||||
}
|
||||
// fixme darwin-4.8.0_11 terminate called without an active exception
|
||||
{ // deferred shared_future copy-constructible
|
||||
boost::shared_future<int> f1 = boost::async(boost::launch::deferred, &p1).share();
|
||||
boost::shared_future<int> f2 = boost::async(boost::launch::deferred, &p2).share();
|
||||
boost::csbl::vector<boost::shared_future<int> > v;
|
||||
v.push_back(f1);
|
||||
v.push_back(f2);
|
||||
BOOST_TEST(v[0].valid());
|
||||
BOOST_TEST(v[1].valid());
|
||||
boost::future<boost::csbl::vector<boost::shared_future<int> > > all = boost::when_all(v.begin(), v.end());
|
||||
if (0) // fixme
|
||||
BOOST_TEST(v[0].valid());
|
||||
if (0) // fixme
|
||||
BOOST_TEST(v[1].valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::vector<boost::shared_future<int> > res = all.get();
|
||||
BOOST_TEST(res[0].valid());
|
||||
BOOST_TEST(res[0].is_ready());
|
||||
BOOST_TEST(res[0].get() == 123);
|
||||
BOOST_TEST(res[1].valid());
|
||||
BOOST_TEST(res[1].is_ready());
|
||||
BOOST_TEST(res[1].get() == 321);
|
||||
}
|
||||
#endif
|
||||
#if ! defined BOOST_NO_CXX11_LAMBDAS
|
||||
{ // async futures copy-constructible then()
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<int> f2 = boost::async(boost::launch::async, &p2);
|
||||
BOOST_TEST(f2.valid());
|
||||
boost::csbl::vector<boost::future<int> > v;
|
||||
v.push_back(boost::move(f1));
|
||||
v.push_back(boost::move(f2));
|
||||
BOOST_TEST(v[0].valid());
|
||||
BOOST_TEST(v[1].valid());
|
||||
boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(v.begin(), v.end());
|
||||
BOOST_TEST(! v[0].valid());
|
||||
BOOST_TEST(! v[1].valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::future<int> sum = all.then([](boost::future<boost::csbl::vector<boost::future<int> > > f)
|
||||
{
|
||||
boost::csbl::vector<boost::future<int> > v = f.get();
|
||||
return v[0].get() + v[1].get();
|
||||
});
|
||||
BOOST_TEST(sum.valid());
|
||||
BOOST_TEST(sum.get() == 444);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
44
test/sync/futures/when_all/none_pass.cpp
Executable file
44
test/sync/futures/when_all/none_pass.cpp
Executable file
@@ -0,0 +1,44 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Copyright (C) 2014 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>
|
||||
|
||||
// future<tuple<>> when_all();
|
||||
|
||||
#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/future.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
|
||||
|
||||
{
|
||||
boost::future<boost::csbl::tuple<> > all = boost::when_all();
|
||||
BOOST_TEST(all.valid());
|
||||
BOOST_TEST(all.is_ready());
|
||||
}
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
182
test/sync/futures/when_all/one_pass.cpp
Normal file
182
test/sync/futures/when_all/one_pass.cpp
Normal file
@@ -0,0 +1,182 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Copyright (C) 2014 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>
|
||||
|
||||
// template <class T, class Ts>
|
||||
// future<tuple<T>> when_all(T&&);
|
||||
|
||||
#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/future.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
int p1()
|
||||
{
|
||||
return 123;
|
||||
}
|
||||
|
||||
int thr()
|
||||
{
|
||||
throw std::logic_error("123");
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
|
||||
if (0) // todo not yet implemented
|
||||
{ // invalid future copy-constructible
|
||||
boost::future<int> f1;
|
||||
BOOST_TEST(! f1.valid());
|
||||
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1));
|
||||
BOOST_TEST(! f1.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::tuple<boost::future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
// has exception
|
||||
//BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
}
|
||||
{ // is_ready future copy-constructible
|
||||
boost::future<int> f1 = boost::make_ready_future(123);
|
||||
BOOST_TEST(f1.valid());
|
||||
BOOST_TEST(f1.is_ready());
|
||||
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1));
|
||||
BOOST_TEST(! f1.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
if (0) // todo FAILS not yet implemented
|
||||
BOOST_TEST(all.is_ready());
|
||||
boost::csbl::tuple<boost::future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
}
|
||||
{ // is_ready shared_future copy-constructible
|
||||
boost::shared_future<int> f1 = boost::make_ready_future(123).share();
|
||||
BOOST_TEST(f1.valid());
|
||||
BOOST_TEST(f1.is_ready());
|
||||
boost::future<boost::csbl::tuple<boost::shared_future<int> > > all = boost::when_all(f1);
|
||||
BOOST_TEST(f1.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
if (0) // todo FAILS not yet implemented
|
||||
BOOST_TEST(all.is_ready());
|
||||
boost::csbl::tuple<boost::shared_future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
}
|
||||
{ // packaged_task future copy-constructible
|
||||
boost::packaged_task<int()> pt1(&p1);
|
||||
boost::future<int> f1 = pt1.get_future();
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1));
|
||||
BOOST_TEST(! f1.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
pt1();
|
||||
boost::csbl::tuple<boost::future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
}
|
||||
{ // packaged_task shared_future copy-constructible
|
||||
boost::packaged_task<int()> pt1(&p1);
|
||||
boost::shared_future<int> f1 = pt1.get_future().share();
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<boost::csbl::tuple<boost::shared_future<int> > > all = boost::when_all(f1);
|
||||
BOOST_TEST(f1.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
pt1();
|
||||
boost::csbl::tuple<boost::shared_future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
}
|
||||
{ // packaged_task future copy-constructible
|
||||
boost::packaged_task<int()> pt1(&thr);
|
||||
boost::future<int> f1 = pt1.get_future();
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1));
|
||||
BOOST_TEST(! f1.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
pt1();
|
||||
boost::csbl::tuple<boost::future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
try {
|
||||
boost::csbl::get<0>(res).get();
|
||||
BOOST_TEST(false);
|
||||
} catch (std::logic_error& ex) {
|
||||
BOOST_TEST(ex.what() == std::string("123"));
|
||||
} catch (...) {
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
{ // async future copy-constructible
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1));
|
||||
BOOST_TEST(! f1.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::tuple<boost::future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
}
|
||||
{ // async shared_future copy-constructible
|
||||
boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share();
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<boost::csbl::tuple<boost::shared_future<int> > > all = boost::when_all(f1);
|
||||
BOOST_TEST(f1.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::tuple<boost::shared_future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
}
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE_N3276
|
||||
// fixme darwin-4.8.0_11 terminate called without an active exception
|
||||
{ // deferred future copy-constructible
|
||||
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);
|
||||
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1));
|
||||
BOOST_TEST(! f1.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::tuple<boost::future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
}
|
||||
// fixme darwin-4.8.0_11 terminate called without an active exception
|
||||
{ // deferred shared_future copy-constructible
|
||||
boost::shared_future<int> f1 = boost::async(boost::launch::deferred, &p1).share();
|
||||
boost::future<boost::csbl::tuple<boost::shared_future<int> > > all = boost::when_all(f1);
|
||||
BOOST_TEST(f1.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::tuple<boost::shared_future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
296
test/sync/futures/when_all/variadic_pass.cpp
Normal file
296
test/sync/futures/when_all/variadic_pass.cpp
Normal file
@@ -0,0 +1,296 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Copyright (C) 2014 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>
|
||||
|
||||
// template <class T, class Ts>
|
||||
// future<tuple<T, Ts...>> when_all(T&&, Ts&& ...);
|
||||
|
||||
#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/future.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
int p1()
|
||||
{
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
|
||||
return 123;
|
||||
}
|
||||
|
||||
int thr()
|
||||
{
|
||||
throw std::logic_error("123");
|
||||
}
|
||||
int p2()
|
||||
{
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
|
||||
return 321;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
|
||||
if (0) // todo not yet implemented
|
||||
{ // invalid future copy-constructible
|
||||
boost::future<int> f1;
|
||||
boost::future<int> f2 = boost::make_ready_future(321);
|
||||
BOOST_TEST(! f1.valid());
|
||||
BOOST_TEST(f2.valid());
|
||||
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2));
|
||||
BOOST_TEST(! f1.valid());
|
||||
BOOST_TEST(! f2.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
// has exception
|
||||
//BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
BOOST_TEST(boost::csbl::get<1>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
|
||||
}
|
||||
{ // is_ready future copy-constructible
|
||||
boost::future<int> f1 = boost::make_ready_future(123);
|
||||
boost::future<int> f2 = boost::make_ready_future(321);
|
||||
BOOST_TEST(f1.valid());
|
||||
BOOST_TEST(f1.is_ready());
|
||||
BOOST_TEST(f2.valid());
|
||||
BOOST_TEST(f2.is_ready());
|
||||
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2));
|
||||
BOOST_TEST(! f1.valid());
|
||||
BOOST_TEST(! f2.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
if (0) // todo FAILS not yet implemented
|
||||
BOOST_TEST(all.is_ready());
|
||||
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
BOOST_TEST(boost::csbl::get<1>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
|
||||
}
|
||||
{ // is_ready shared_future copy-constructible
|
||||
boost::shared_future<int> f1 = boost::make_ready_future(123).share();
|
||||
boost::shared_future<int> f2 = boost::make_ready_future(321).share();
|
||||
BOOST_TEST(f1.valid());
|
||||
BOOST_TEST(f1.is_ready());
|
||||
BOOST_TEST(f2.valid());
|
||||
BOOST_TEST(f2.is_ready());
|
||||
boost::future<boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > > all = boost::when_all(f1, f2);
|
||||
BOOST_TEST(f1.valid());
|
||||
BOOST_TEST(f2.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
if (0) // todo FAILS not yet implemented
|
||||
BOOST_TEST(all.is_ready());
|
||||
boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
BOOST_TEST(boost::csbl::get<1>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
|
||||
}
|
||||
{ // packaged_task future copy-constructible
|
||||
boost::packaged_task<int()> pt1(&p1);
|
||||
boost::future<int> f1 = pt1.get_future();
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::packaged_task<int()> pt2(&p2);
|
||||
boost::future<int> f2 = pt2.get_future();
|
||||
BOOST_TEST(f2.valid());
|
||||
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2));
|
||||
BOOST_TEST(! f1.valid());
|
||||
BOOST_TEST(! f2.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
pt1();
|
||||
pt2();
|
||||
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
BOOST_TEST(boost::csbl::get<1>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
|
||||
}
|
||||
{ // packaged_task future copy-constructible
|
||||
boost::packaged_task<int()> pt1(&thr);
|
||||
boost::future<int> f1 = pt1.get_future();
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::packaged_task<int()> pt2(&p2);
|
||||
boost::future<int> f2 = pt2.get_future();
|
||||
BOOST_TEST(f2.valid());
|
||||
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2));
|
||||
BOOST_TEST(! f1.valid());
|
||||
BOOST_TEST(! f2.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
pt1();
|
||||
pt2();
|
||||
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
try {
|
||||
boost::csbl::get<0>(res).get();
|
||||
BOOST_TEST(false);
|
||||
} catch (std::logic_error& ex) {
|
||||
BOOST_TEST(ex.what() == std::string("123"));
|
||||
} catch (...) {
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
BOOST_TEST(boost::csbl::get<1>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
|
||||
}
|
||||
{ // packaged_task shared_future copy-constructible
|
||||
boost::packaged_task<int()> pt1(&p1);
|
||||
boost::shared_future<int> f1 = pt1.get_future().share();
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::packaged_task<int()> pt2(&p2);
|
||||
boost::shared_future<int> f2 = pt2.get_future().share();
|
||||
BOOST_TEST(f2.valid());
|
||||
boost::future<boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > > all = boost::when_all(f1, f2);
|
||||
BOOST_TEST(f1.valid());
|
||||
BOOST_TEST(f2.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
BOOST_TEST(! all.is_ready());
|
||||
pt1();
|
||||
BOOST_TEST(! all.is_ready());
|
||||
pt2();
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(300));
|
||||
BOOST_TEST(all.is_ready());
|
||||
boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
BOOST_TEST(boost::csbl::get<1>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
|
||||
}
|
||||
{ // async future copy-constructible
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<int> f2 = boost::async(boost::launch::async, &p2);
|
||||
BOOST_TEST(f2.valid());
|
||||
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2));
|
||||
BOOST_TEST(! f1.valid());
|
||||
BOOST_TEST(! f2.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
BOOST_TEST(boost::csbl::get<1>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
|
||||
}
|
||||
{ // async shared_future copy-constructible
|
||||
boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share();
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::shared_future<int> f2 = boost::async(boost::launch::async, &p2).share();
|
||||
BOOST_TEST(f2.valid());
|
||||
boost::future<boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > > all = boost::when_all(f1, f2);
|
||||
BOOST_TEST(f1.valid());
|
||||
BOOST_TEST(f2.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
BOOST_TEST(boost::csbl::get<1>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
|
||||
}
|
||||
{ // async future copy-constructible
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<int> f2 = boost::make_ready_future(321);
|
||||
BOOST_TEST(f2.valid());
|
||||
BOOST_TEST(f2.is_ready());
|
||||
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2));
|
||||
BOOST_TEST(! f1.valid());
|
||||
BOOST_TEST(! f2.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
BOOST_TEST(boost::csbl::get<1>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
|
||||
}
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE_N3276
|
||||
// fixme darwin-4.8.0_11 terminate called without an active exception
|
||||
{ // deferred future copy-constructible
|
||||
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);
|
||||
boost::future<int> f2 = boost::async(boost::launch::deferred, &p2);
|
||||
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2));
|
||||
BOOST_TEST(! f1.valid());
|
||||
BOOST_TEST(! f2.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
|
||||
}
|
||||
// fixme darwin-4.8.0_11 terminate called without an active exception
|
||||
{ // deferred shared_future copy-constructible
|
||||
boost::shared_future<int> f1 = boost::async(boost::launch::deferred, &p1).share();
|
||||
boost::shared_future<int> f2 = boost::async(boost::launch::deferred, &p2).share();
|
||||
boost::future<boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > > all = boost::when_all(f1, f2);
|
||||
BOOST_TEST(f1.valid());
|
||||
BOOST_TEST(f2.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
|
||||
}
|
||||
#endif
|
||||
#if ! defined BOOST_NO_CXX11_LAMBDAS
|
||||
{ // async futures copy-constructible then()
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<int> f2 = boost::async(boost::launch::async, &p2);
|
||||
BOOST_TEST(f2.valid());
|
||||
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2));
|
||||
BOOST_TEST(! f1.valid());
|
||||
BOOST_TEST(! f2.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::future<int> sum = all.then([](boost::future<boost::csbl::tuple<boost::future<int>, boost::future<int> > > f)
|
||||
{
|
||||
boost::csbl::tuple<boost::future<int>,boost::future<int> > v = f.get();
|
||||
return boost::csbl::get<0>(v).get()+boost::csbl::get<1>(v).get();
|
||||
});
|
||||
BOOST_TEST(sum.valid());
|
||||
BOOST_TEST(sum.get() == 444);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
360
test/sync/futures/when_any/iterators_pass.cpp
Normal file
360
test/sync/futures/when_any/iterators_pass.cpp
Normal file
@@ -0,0 +1,360 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Copyright (C) 2014 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>
|
||||
|
||||
// template< typename InputIterator>
|
||||
// future<vector<typename InputIterator::value_type> >
|
||||
// when_any(InputIterator first, InputIterator last)
|
||||
|
||||
#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/future.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
int p1()
|
||||
{
|
||||
return 123;
|
||||
}
|
||||
|
||||
int thr()
|
||||
{
|
||||
throw std::logic_error("123");
|
||||
}
|
||||
int p2()
|
||||
{
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
|
||||
return 321;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
|
||||
if (0) // todo not yet implemented
|
||||
{ // invalid future copy-constructible
|
||||
boost::csbl::vector<boost::future<int> > v;
|
||||
boost::future<int> f1;
|
||||
v.push_back(boost::move(f1));
|
||||
v.push_back(boost::make_ready_future(321));
|
||||
BOOST_TEST(! v[0].valid());
|
||||
BOOST_TEST(v[1].valid());
|
||||
|
||||
boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end());
|
||||
BOOST_TEST(! v[0].valid());
|
||||
BOOST_TEST(! v[1].valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::vector<boost::future<int> > res = all.get();
|
||||
BOOST_TEST(res.size() == 2);
|
||||
BOOST_TEST(res[1].valid());
|
||||
BOOST_TEST(res[1].is_ready());
|
||||
// has exception
|
||||
//BOOST_TEST(res[0].get() == 123);
|
||||
BOOST_TEST(res[1].valid());
|
||||
BOOST_TEST(res[1].is_ready());
|
||||
BOOST_TEST(res[1].get() == 321);
|
||||
}
|
||||
{ // is_ready future copy-constructible
|
||||
boost::future<int> f1 = boost::make_ready_future(123);
|
||||
boost::future<int> f2 = boost::make_ready_future(321);
|
||||
boost::csbl::vector<boost::future<int> > v;
|
||||
v.push_back(boost::move(f1));
|
||||
v.push_back(boost::move(f2));
|
||||
BOOST_TEST(v[0].valid());
|
||||
BOOST_TEST(v[0].is_ready());
|
||||
BOOST_TEST(v[1].valid());
|
||||
BOOST_TEST(v[1].is_ready());
|
||||
boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end());
|
||||
BOOST_TEST(! v[0].valid());
|
||||
BOOST_TEST(! v[1].valid());
|
||||
BOOST_TEST(all.valid());
|
||||
if (0) // todo FAILS not yet implemented
|
||||
BOOST_TEST(all.is_ready());
|
||||
boost::csbl::vector<boost::future<int> > res = all.get();
|
||||
BOOST_TEST(res[0].valid());
|
||||
BOOST_TEST(res[0].is_ready());
|
||||
BOOST_TEST(res[0].get() == 123);
|
||||
BOOST_TEST(res[1].valid());
|
||||
BOOST_TEST(res[1].is_ready());
|
||||
BOOST_TEST(res[1].get() == 321);
|
||||
}
|
||||
{ // is_ready shared_future copy-constructible
|
||||
boost::shared_future<int> f1 = boost::make_ready_future(123).share();
|
||||
boost::shared_future<int> f2 = boost::make_ready_future(321).share();
|
||||
boost::csbl::vector<boost::shared_future<int> > v;
|
||||
v.push_back(f1);
|
||||
v.push_back(f2);
|
||||
BOOST_TEST(v[0].valid());
|
||||
BOOST_TEST(v[0].is_ready());
|
||||
BOOST_TEST(v[1].valid());
|
||||
BOOST_TEST(v[1].is_ready());
|
||||
boost::future<boost::csbl::vector<boost::shared_future<int> > > all = boost::when_any(v.begin(), v.end());
|
||||
if (0) // fixme
|
||||
BOOST_TEST(v[0].valid());
|
||||
if (0) // fixme
|
||||
BOOST_TEST(v[1].valid());
|
||||
BOOST_TEST(all.valid());
|
||||
if (0) // todo FAILS not yet implemented
|
||||
BOOST_TEST(all.is_ready());
|
||||
boost::csbl::vector<boost::shared_future<int> > res = all.get();
|
||||
BOOST_TEST(res[0].valid());
|
||||
BOOST_TEST(res[0].is_ready());
|
||||
BOOST_TEST(res[0].get() == 123);
|
||||
BOOST_TEST(res[1].valid());
|
||||
BOOST_TEST(res[1].is_ready());
|
||||
BOOST_TEST(res[1].get() == 321);
|
||||
}
|
||||
{ // packaged_task future copy-constructible
|
||||
boost::packaged_task<int()> pt1(&p1);
|
||||
boost::future<int> f1 = pt1.get_future();
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::packaged_task<int()> pt2(&p2);
|
||||
boost::future<int> f2 = pt2.get_future();
|
||||
BOOST_TEST(f2.valid());
|
||||
boost::csbl::vector<boost::future<int> > v;
|
||||
v.push_back(boost::move(f1));
|
||||
v.push_back(boost::move(f2));
|
||||
BOOST_TEST(v[0].valid());
|
||||
BOOST_TEST(v[1].valid());
|
||||
boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end());
|
||||
BOOST_TEST(! v[0].valid());
|
||||
BOOST_TEST(! v[1].valid());
|
||||
BOOST_TEST(all.valid());
|
||||
pt1();
|
||||
pt2();
|
||||
boost::csbl::vector<boost::future<int> > res = all.get();
|
||||
BOOST_TEST(res[0].valid());
|
||||
BOOST_TEST(res[0].is_ready());
|
||||
BOOST_TEST(res[0].get() == 123);
|
||||
BOOST_TEST(res[1].valid());
|
||||
BOOST_TEST(res[1].is_ready());
|
||||
BOOST_TEST(res[1].get() == 321);
|
||||
}
|
||||
{ // packaged_task future copy-constructible
|
||||
boost::packaged_task<int()> pt1(&thr);
|
||||
boost::future<int> f1 = pt1.get_future();
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::packaged_task<int()> pt2(&p2);
|
||||
boost::future<int> f2 = pt2.get_future();
|
||||
BOOST_TEST(f2.valid());
|
||||
boost::csbl::vector<boost::future<int> > v;
|
||||
v.push_back(boost::move(f1));
|
||||
v.push_back(boost::move(f2));
|
||||
BOOST_TEST(v[0].valid());
|
||||
BOOST_TEST(v[1].valid());
|
||||
boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end());
|
||||
BOOST_TEST(! v[0].valid());
|
||||
BOOST_TEST(! v[1].valid());
|
||||
BOOST_TEST(all.valid());
|
||||
pt1();
|
||||
pt2();
|
||||
boost::csbl::vector<boost::future<int> > res = all.get();
|
||||
BOOST_TEST(res[0].valid());
|
||||
BOOST_TEST(res[0].is_ready());
|
||||
try {
|
||||
res[0].get();
|
||||
BOOST_TEST(false);
|
||||
} catch (std::logic_error& ex) {
|
||||
BOOST_TEST(ex.what() == std::string("123"));
|
||||
} catch (...) {
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
BOOST_TEST(res[1].valid());
|
||||
BOOST_TEST(res[1].is_ready());
|
||||
BOOST_TEST(res[1].get() == 321);
|
||||
}
|
||||
{ // packaged_task shared_future copy-constructible
|
||||
boost::packaged_task<int()> pt1(&p1);
|
||||
boost::shared_future<int> f1 = pt1.get_future().share();
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::packaged_task<int()> pt2(&p2);
|
||||
boost::shared_future<int> f2 = pt2.get_future().share();
|
||||
BOOST_TEST(f2.valid());
|
||||
boost::csbl::vector<boost::shared_future<int> > v;
|
||||
v.push_back(f1);
|
||||
v.push_back(f2);
|
||||
BOOST_TEST(v[0].valid());
|
||||
BOOST_TEST(v[1].valid());
|
||||
boost::future<boost::csbl::vector<boost::shared_future<int> > > all = boost::when_any(v.begin(), v.end());
|
||||
if (0) // fixme
|
||||
BOOST_TEST(v[0].valid());
|
||||
if (0) // fixme
|
||||
BOOST_TEST(v[1].valid());
|
||||
BOOST_TEST(all.valid());
|
||||
BOOST_TEST(! all.is_ready());
|
||||
pt1();
|
||||
BOOST_TEST(! all.is_ready());
|
||||
pt2();
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(300));
|
||||
BOOST_TEST(all.is_ready());
|
||||
boost::csbl::vector<boost::shared_future<int> > res = all.get();
|
||||
BOOST_TEST(res[0].valid());
|
||||
BOOST_TEST(res[0].is_ready());
|
||||
BOOST_TEST(res[0].get() == 123);
|
||||
BOOST_TEST(res[1].valid());
|
||||
BOOST_TEST(res[1].is_ready());
|
||||
BOOST_TEST(res[1].get() == 321);
|
||||
}
|
||||
{ // async future copy-constructible
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<int> f2 = boost::async(boost::launch::async, &p2);
|
||||
BOOST_TEST(f2.valid());
|
||||
boost::csbl::vector<boost::future<int> > v;
|
||||
v.push_back(boost::move(f1));
|
||||
v.push_back(boost::move(f2));
|
||||
BOOST_TEST(v[0].valid());
|
||||
BOOST_TEST(v[1].valid());
|
||||
boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end());
|
||||
BOOST_TEST(! v[0].valid());
|
||||
BOOST_TEST(! v[1].valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::vector<boost::future<int> > res = all.get();
|
||||
BOOST_TEST(res[0].valid());
|
||||
BOOST_TEST(res[0].is_ready());
|
||||
BOOST_TEST(res[0].get() == 123);
|
||||
BOOST_TEST(res[1].valid());
|
||||
BOOST_TEST(! res[1].is_ready());
|
||||
BOOST_TEST(res[1].get() == 321);
|
||||
}
|
||||
{ // async shared_future copy-constructible
|
||||
boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share();
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::shared_future<int> f2 = boost::async(boost::launch::async, &p2).share();
|
||||
BOOST_TEST(f2.valid());
|
||||
boost::csbl::vector<boost::shared_future<int> > v;
|
||||
v.push_back(f1);
|
||||
v.push_back(f2);
|
||||
BOOST_TEST(v[0].valid());
|
||||
BOOST_TEST(v[1].valid());
|
||||
boost::future<boost::csbl::vector<boost::shared_future<int> > > all = boost::when_any(v.begin(), v.end());
|
||||
if (0) // fixme
|
||||
BOOST_TEST(v[0].valid());
|
||||
if (0) // fixme
|
||||
BOOST_TEST(v[1].valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::vector<boost::shared_future<int> > res = all.get();
|
||||
BOOST_TEST(res[0].valid());
|
||||
BOOST_TEST(res[0].is_ready());
|
||||
BOOST_TEST(res[0].get() == 123);
|
||||
BOOST_TEST(res[1].valid());
|
||||
BOOST_TEST(! res[1].is_ready());
|
||||
BOOST_TEST(res[1].get() == 321);
|
||||
}
|
||||
{ // async future copy-constructible
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<int> f2 = boost::make_ready_future(321);
|
||||
BOOST_TEST(f2.valid());
|
||||
BOOST_TEST(f2.is_ready());
|
||||
boost::csbl::vector<boost::future<int> > v;
|
||||
v.push_back(boost::move(f1));
|
||||
v.push_back(boost::move(f2));
|
||||
BOOST_TEST(v[0].valid());
|
||||
BOOST_TEST(v[1].valid());
|
||||
boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end());
|
||||
BOOST_TEST(! v[0].valid());
|
||||
BOOST_TEST(! v[1].valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::vector<boost::future<int> > res = all.get();
|
||||
BOOST_TEST(res[0].valid());
|
||||
if (0) // fixme
|
||||
BOOST_TEST(! res[0].is_ready());
|
||||
BOOST_TEST(res[0].get() == 123);
|
||||
BOOST_TEST(res[1].valid());
|
||||
BOOST_TEST(res[1].is_ready());
|
||||
BOOST_TEST(res[1].get() == 321);
|
||||
}
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE_N3276
|
||||
// fixme darwin-4.8.0_11 terminate called without an active exception
|
||||
{ // deferred future copy-constructible
|
||||
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);
|
||||
boost::future<int> f2 = boost::async(boost::launch::deferred, &p2);
|
||||
boost::csbl::vector<boost::future<int> > v;
|
||||
v.push_back(boost::move(f1));
|
||||
v.push_back(boost::move(f2));
|
||||
BOOST_TEST(v[0].valid());
|
||||
BOOST_TEST(v[1].valid());
|
||||
boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end());
|
||||
BOOST_TEST(! v[0].valid());
|
||||
BOOST_TEST(! v[1].valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::vector<boost::future<int> > res = all.get();
|
||||
BOOST_TEST(res[0].valid());
|
||||
BOOST_TEST(res[0].is_ready());
|
||||
BOOST_TEST(res[0].get() == 123);
|
||||
BOOST_TEST(res[1].valid());
|
||||
BOOST_TEST(! res[1].is_ready());
|
||||
BOOST_TEST(res[1].get() == 321);
|
||||
}
|
||||
// fixme darwin-4.8.0_11 terminate called without an active exception
|
||||
{ // deferred shared_future copy-constructible
|
||||
boost::shared_future<int> f1 = boost::async(boost::launch::deferred, &p1).share();
|
||||
boost::shared_future<int> f2 = boost::async(boost::launch::deferred, &p2).share();
|
||||
boost::csbl::vector<boost::shared_future<int> > v;
|
||||
v.push_back(f1);
|
||||
v.push_back(f2);
|
||||
BOOST_TEST(v[0].valid());
|
||||
BOOST_TEST(v[1].valid());
|
||||
boost::future<boost::csbl::vector<boost::shared_future<int> > > all = boost::when_any(v.begin(), v.end());
|
||||
if (0) // fixme
|
||||
BOOST_TEST(v[0].valid());
|
||||
if (0) // fixme
|
||||
BOOST_TEST(v[1].valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::vector<boost::shared_future<int> > res = all.get();
|
||||
BOOST_TEST(res[0].valid());
|
||||
BOOST_TEST(res[0].is_ready());
|
||||
BOOST_TEST(res[0].get() == 123);
|
||||
BOOST_TEST(res[1].valid());
|
||||
BOOST_TEST(! res[1].is_ready());
|
||||
BOOST_TEST(res[1].get() == 321);
|
||||
}
|
||||
#endif
|
||||
#if ! defined BOOST_NO_CXX11_LAMBDAS
|
||||
{ // async futures copy-constructible then()
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<int> f2 = boost::async(boost::launch::async, &p2);
|
||||
BOOST_TEST(f2.valid());
|
||||
boost::csbl::vector<boost::future<int> > v;
|
||||
v.push_back(boost::move(f1));
|
||||
v.push_back(boost::move(f2));
|
||||
BOOST_TEST(v[0].valid());
|
||||
BOOST_TEST(v[1].valid());
|
||||
boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end());
|
||||
BOOST_TEST(! v[0].valid());
|
||||
BOOST_TEST(! v[1].valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::future<int> sum = all.then([](boost::future<boost::csbl::vector<boost::future<int> > > f)
|
||||
{
|
||||
boost::csbl::vector<boost::future<int> > v = f.get();
|
||||
return v[0].get() + v[1].get();
|
||||
});
|
||||
BOOST_TEST(sum.valid());
|
||||
BOOST_TEST(sum.get() == 444);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
44
test/sync/futures/when_any/none_pass.cpp
Executable file
44
test/sync/futures/when_any/none_pass.cpp
Executable file
@@ -0,0 +1,44 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Copyright (C) 2014 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>
|
||||
|
||||
// future<tuple<>> when_any();
|
||||
|
||||
#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/future.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
|
||||
|
||||
{
|
||||
boost::future<boost::csbl::tuple<> > all = boost::when_any();
|
||||
BOOST_TEST(all.valid());
|
||||
BOOST_TEST(all.is_ready());
|
||||
}
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
155
test/sync/futures/when_any/one_pass.cpp
Normal file
155
test/sync/futures/when_any/one_pass.cpp
Normal file
@@ -0,0 +1,155 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Copyright (C) 2014 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>
|
||||
|
||||
// future<tuple<T>> when_any(T&&);
|
||||
|
||||
#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/future.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
int p1()
|
||||
{
|
||||
return 123;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
|
||||
if (0) // todo not yet implemented
|
||||
{ // invalid future copy-constructible
|
||||
boost::future<int> f1;
|
||||
BOOST_TEST(! f1.valid());
|
||||
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_any(boost::move(f1));
|
||||
BOOST_TEST(! f1.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::tuple<boost::future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
// has exception
|
||||
//BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
}
|
||||
{ // is_ready future copy-constructible
|
||||
boost::future<int> f1 = boost::make_ready_future(123);
|
||||
BOOST_TEST(f1.valid());
|
||||
BOOST_TEST(f1.is_ready());
|
||||
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_any(boost::move(f1));
|
||||
BOOST_TEST(! f1.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
if (0) // todo FAILS not yet implemented
|
||||
BOOST_TEST(all.is_ready());
|
||||
boost::csbl::tuple<boost::future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
}
|
||||
{ // is_ready shared_future copy-constructible
|
||||
boost::shared_future<int> f1 = boost::make_ready_future(123).share();
|
||||
BOOST_TEST(f1.valid());
|
||||
BOOST_TEST(f1.is_ready());
|
||||
boost::future<boost::csbl::tuple<boost::shared_future<int> > > all = boost::when_any(f1);
|
||||
BOOST_TEST(f1.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
if (0) // todo FAILS not yet implemented
|
||||
BOOST_TEST(all.is_ready());
|
||||
boost::csbl::tuple<boost::shared_future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
}
|
||||
{ // packaged_task future copy-constructible
|
||||
boost::packaged_task<int()> pt1(&p1);
|
||||
boost::future<int> f1 = pt1.get_future();
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_any(boost::move(f1));
|
||||
BOOST_TEST(! f1.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
pt1();
|
||||
boost::csbl::tuple<boost::future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
}
|
||||
{ // packaged_task shared_future copy-constructible
|
||||
boost::packaged_task<int()> pt1(&p1);
|
||||
boost::shared_future<int> f1 = pt1.get_future().share();
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<boost::csbl::tuple<boost::shared_future<int> > > all = boost::when_any(f1);
|
||||
BOOST_TEST(f1.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
pt1();
|
||||
boost::csbl::tuple<boost::shared_future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
}
|
||||
{ // async future copy-constructible
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_any(boost::move(f1));
|
||||
BOOST_TEST(! f1.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::tuple<boost::future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
}
|
||||
{ // async shared_future copy-constructible
|
||||
boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share();
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<boost::csbl::tuple<boost::shared_future<int> > > all = boost::when_any(f1);
|
||||
BOOST_TEST(f1.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::tuple<boost::shared_future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
}
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE_N3276
|
||||
// fixme darwin-4.8.0_11 terminate called without an active exception
|
||||
{ // deferred future copy-constructible
|
||||
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);
|
||||
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_any(boost::move(f1));
|
||||
BOOST_TEST(! f1.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::tuple<boost::future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
}
|
||||
// fixme darwin-4.8.0_11 terminate called without an active exception
|
||||
{ // deferred shared_future copy-constructible
|
||||
boost::shared_future<int> f1 = boost::async(boost::launch::deferred, &p1).share();
|
||||
boost::future<boost::csbl::tuple<boost::shared_future<int> > > all = boost::when_any(f1);
|
||||
BOOST_TEST(f1.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::tuple<boost::shared_future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
320
test/sync/futures/when_any/variadic_pass.cpp
Normal file
320
test/sync/futures/when_any/variadic_pass.cpp
Normal file
@@ -0,0 +1,320 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Copyright (C) 2014 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>
|
||||
|
||||
// template <class T, class Ts>
|
||||
// future<tuple<T, Ts...>> when_any(T&&, Ts&& ...);
|
||||
|
||||
#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/future.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
int p1()
|
||||
{
|
||||
return 123;
|
||||
}
|
||||
|
||||
int thr()
|
||||
{
|
||||
throw std::logic_error("123");
|
||||
}
|
||||
int p2()
|
||||
{
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
|
||||
return 321;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
|
||||
if (0) // todo not yet implemented
|
||||
{ // invalid future copy-constructible
|
||||
boost::future<int> f1;
|
||||
boost::future<int> f2 = boost::make_ready_future(321);
|
||||
BOOST_TEST(! f1.valid());
|
||||
BOOST_TEST(f2.valid());
|
||||
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
|
||||
BOOST_TEST(! f1.valid());
|
||||
BOOST_TEST(! f2.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready() || boost::csbl::get<1>(res).is_ready());
|
||||
// has exception
|
||||
//BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
|
||||
}
|
||||
{ // is_ready future copy-constructible
|
||||
boost::future<int> f1 = boost::make_ready_future(123);
|
||||
boost::future<int> f2 = boost::make_ready_future(321);
|
||||
BOOST_TEST(f1.valid());
|
||||
BOOST_TEST(f1.is_ready());
|
||||
BOOST_TEST(f2.valid());
|
||||
BOOST_TEST(f2.is_ready());
|
||||
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
|
||||
BOOST_TEST(! f1.valid());
|
||||
BOOST_TEST(! f2.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
if (0) // todo FAILS not yet implemented
|
||||
BOOST_TEST(all.is_ready());
|
||||
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready() || boost::csbl::get<1>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
|
||||
}
|
||||
{ // is_ready shared_future copy-constructible
|
||||
boost::shared_future<int> f1 = boost::make_ready_future(123).share();
|
||||
boost::shared_future<int> f2 = boost::make_ready_future(321).share();
|
||||
BOOST_TEST(f1.valid());
|
||||
BOOST_TEST(f1.is_ready());
|
||||
BOOST_TEST(f2.valid());
|
||||
BOOST_TEST(f2.is_ready());
|
||||
boost::future<boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > > all = boost::when_any(f1, f2);
|
||||
BOOST_TEST(f1.valid());
|
||||
BOOST_TEST(f2.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
if (0) // todo FAILS not yet implemented
|
||||
BOOST_TEST(all.is_ready());
|
||||
boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready() || boost::csbl::get<1>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
|
||||
}
|
||||
{ // packaged_task future copy-constructible
|
||||
boost::packaged_task<int()> pt1(&p1);
|
||||
boost::future<int> f1 = pt1.get_future();
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::packaged_task<int()> pt2(&p2);
|
||||
boost::future<int> f2 = pt2.get_future();
|
||||
BOOST_TEST(f2.valid());
|
||||
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
|
||||
BOOST_TEST(! f1.valid());
|
||||
BOOST_TEST(! f2.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
pt1();
|
||||
pt2();
|
||||
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready() || boost::csbl::get<1>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
|
||||
}
|
||||
{ // packaged_task future copy-constructible
|
||||
boost::packaged_task<int()> pt1(&thr);
|
||||
boost::future<int> f1 = pt1.get_future();
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::packaged_task<int()> pt2(&p2);
|
||||
boost::future<int> f2 = pt2.get_future();
|
||||
BOOST_TEST(f2.valid());
|
||||
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
|
||||
BOOST_TEST(! f1.valid());
|
||||
BOOST_TEST(! f2.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
pt1();
|
||||
pt2();
|
||||
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready() || boost::csbl::get<1>(res).is_ready());
|
||||
try {
|
||||
boost::csbl::get<0>(res).get();
|
||||
BOOST_TEST(false);
|
||||
} catch (std::logic_error& ex) {
|
||||
BOOST_TEST(ex.what() == std::string("123"));
|
||||
} catch (...) {
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
|
||||
}
|
||||
{ // packaged_task shared_future copy-constructible
|
||||
boost::packaged_task<int()> pt1(&p1);
|
||||
boost::shared_future<int> f1 = pt1.get_future().share();
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::packaged_task<int()> pt2(&p2);
|
||||
boost::shared_future<int> f2 = pt2.get_future().share();
|
||||
BOOST_TEST(f2.valid());
|
||||
boost::future<boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > > all = boost::when_any(f1, f2);
|
||||
BOOST_TEST(f1.valid());
|
||||
BOOST_TEST(f2.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
BOOST_TEST(! all.is_ready());
|
||||
pt1();
|
||||
BOOST_TEST(! all.is_ready());
|
||||
pt2();
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(300));
|
||||
BOOST_TEST(all.is_ready());
|
||||
boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready() || boost::csbl::get<1>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
|
||||
}
|
||||
{ // async future copy-constructible
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<int> f2 = boost::async(boost::launch::async, &p2);
|
||||
BOOST_TEST(f2.valid());
|
||||
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
|
||||
BOOST_TEST(! f1.valid());
|
||||
BOOST_TEST(! f2.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready() || boost::csbl::get<1>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
|
||||
}
|
||||
{ // async shared_future copy-constructible
|
||||
boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share();
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::shared_future<int> f2 = boost::async(boost::launch::async, &p2).share();
|
||||
BOOST_TEST(f2.valid());
|
||||
boost::future<boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > > all = boost::when_any(f1, f2);
|
||||
BOOST_TEST(f1.valid());
|
||||
BOOST_TEST(f2.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready() || boost::csbl::get<1>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
|
||||
}
|
||||
{ // async future copy-constructible
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<int> f2 = boost::make_ready_future(321);
|
||||
BOOST_TEST(f2.valid());
|
||||
BOOST_TEST(f2.is_ready());
|
||||
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
|
||||
BOOST_TEST(! f1.valid());
|
||||
BOOST_TEST(! f2.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
//BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
|
||||
}
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE_N3276
|
||||
// fixme darwin-4.8.0_11 terminate called without an active exception
|
||||
{ // deferred future copy-constructible
|
||||
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);
|
||||
boost::future<int> f2 = boost::async(boost::launch::deferred, &p2);
|
||||
std::cout << __FILE__ << " " << __LINE__ << std::endl;
|
||||
|
||||
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
|
||||
std::cout << __FILE__ << " " << __LINE__ << std::endl;
|
||||
BOOST_TEST(! f1.valid());
|
||||
BOOST_TEST(! f2.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
std::cout << __FILE__ << " " << __LINE__ << std::endl;
|
||||
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
|
||||
std::cout << __FILE__ << " " << __LINE__ << std::endl;
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready() || boost::csbl::get<1>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
|
||||
}
|
||||
// fixme darwin-4.8.0_11 terminate called without an active exception
|
||||
{ // deferred future copy-constructible
|
||||
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);
|
||||
boost::future<int> f2 = boost::async(boost::launch::async, &p2);
|
||||
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
|
||||
BOOST_TEST(! f1.valid());
|
||||
BOOST_TEST(! f2.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
BOOST_TEST(boost::csbl::get<1>(res).valid());
|
||||
//BOOST_TEST(! boost::csbl::get<1>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
|
||||
}
|
||||
// fixme darwin-4.8.0_11 terminate called without an active exception
|
||||
{ // deferred future copy-constructible
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
boost::future<int> f2 = boost::async(boost::launch::deferred, &p2);
|
||||
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
|
||||
BOOST_TEST(! f1.valid());
|
||||
BOOST_TEST(! f2.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
//BOOST_TEST(boost::csbl::get<0>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
|
||||
}
|
||||
// fixme darwin-4.8.0_11 terminate called without an active exception
|
||||
{ // deferred shared_future copy-constructible
|
||||
boost::shared_future<int> f1 = boost::async(boost::launch::deferred, &p1).share();
|
||||
boost::shared_future<int> f2 = boost::async(boost::launch::deferred, &p2).share();
|
||||
boost::future<boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > > all = boost::when_any(f1, f2);
|
||||
BOOST_TEST(f1.valid());
|
||||
BOOST_TEST(f2.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > res = all.get();
|
||||
BOOST_TEST(boost::csbl::get<0>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<1>(res).valid());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).is_ready() || boost::csbl::get<1>(res).is_ready());
|
||||
BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
|
||||
BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
|
||||
}
|
||||
#endif
|
||||
#if ! defined BOOST_NO_CXX11_LAMBDAS
|
||||
{ // async futures copy-constructible then()
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<int> f2 = boost::async(boost::launch::async, &p2);
|
||||
BOOST_TEST(f2.valid());
|
||||
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
|
||||
BOOST_TEST(! f1.valid());
|
||||
BOOST_TEST(! f2.valid());
|
||||
BOOST_TEST(all.valid());
|
||||
boost::future<int> sum = all.then([](boost::future<boost::csbl::tuple<boost::future<int>, boost::future<int> > > f)
|
||||
{
|
||||
boost::csbl::tuple<boost::future<int>,boost::future<int> > v = f.get();
|
||||
return boost::csbl::get<0>(v).get()+boost::csbl::get<1>(v).get();
|
||||
});
|
||||
BOOST_TEST(sum.valid());
|
||||
BOOST_TEST(sum.get() == 444);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
455
test/sync/mutual_exclusion/queue_views/single_thread_pass.cpp
Normal file
455
test/sync/mutual_exclusion/queue_views/single_thread_pass.cpp
Normal file
@@ -0,0 +1,455 @@
|
||||
// Copyright (C) 2014 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
|
||||
//#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
|
||||
#include <boost/thread/sync_queue.hpp>
|
||||
#include <boost/thread/concurrent_queues/queue_adaptor.hpp>
|
||||
#include <boost/thread/concurrent_queues/queue_views.hpp>
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
class non_copyable
|
||||
{
|
||||
BOOST_THREAD_MOVABLE_ONLY(non_copyable)
|
||||
int val;
|
||||
public:
|
||||
non_copyable(int v) : val(v){}
|
||||
non_copyable(BOOST_RV_REF(non_copyable) x): val(x.val) {}
|
||||
non_copyable& operator=(BOOST_RV_REF(non_copyable) x) { val=x.val; return *this; }
|
||||
bool operator==(non_copyable const& x) const {return val==x.val;}
|
||||
template <typename OSTREAM>
|
||||
friend OSTREAM& operator <<(OSTREAM& os, non_copyable const&x )
|
||||
{
|
||||
os << x.val;
|
||||
return os;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#if defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
BOOST_STATIC_ASSERT( ! boost::is_copy_constructible<non_copyable>::value );
|
||||
BOOST_STATIC_ASSERT( boost::has_move_emulation_enabled<non_copyable>::value );
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
{
|
||||
// default queue invariants
|
||||
boost::queue_adaptor<boost::sync_queue<int> > sq;
|
||||
boost::queue_back<int> q(sq);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// default queue invariants
|
||||
boost::queue_adaptor<boost::sync_queue<int> > sq;
|
||||
boost::queue_front<int> q(sq);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
// empty queue try_pull fails
|
||||
boost::queue_adaptor<boost::sync_queue<int> > sq;
|
||||
boost::queue_front<int> q(sq);
|
||||
int i;
|
||||
BOOST_TEST( boost::queue_op_status::empty == q.try_pull(i));
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue push rvalue/copyable succeeds
|
||||
boost::queue_adaptor<boost::sync_queue<int> > sq;
|
||||
boost::queue_back<int> q(sq);
|
||||
q.push(1);
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue push lvalue/copyable succeeds
|
||||
boost::queue_adaptor<boost::sync_queue<int> > sq;
|
||||
boost::queue_back<int> q(sq);
|
||||
int i;
|
||||
q.push(i);
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
{
|
||||
// empty queue push rvalue/non_copyable succeeds
|
||||
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
|
||||
boost::queue_back<non_copyable> q(sq);
|
||||
q.push(non_copyable(1));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
#endif
|
||||
{
|
||||
// empty queue push rvalue/non_copyable succeeds
|
||||
boost::queue_adaptor<boost::sync_queue<non_copyable> > q;
|
||||
//boost::sync_queue<non_copyable> q;
|
||||
//boost::queue_back<non_copyable> q(sq);
|
||||
non_copyable nc(1);
|
||||
q.push_back(boost::move(nc));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
|
||||
{
|
||||
// empty queue push rvalue succeeds
|
||||
boost::queue_adaptor<boost::sync_queue<int> > sq;
|
||||
boost::queue_back<int> q(sq);
|
||||
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 lvalue succeeds
|
||||
boost::queue_adaptor<boost::sync_queue<int> > sq;
|
||||
boost::queue_back<int> q(sq);
|
||||
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/copyable succeeds
|
||||
boost::queue_adaptor<boost::sync_queue<int> > sq;
|
||||
boost::queue_back<int> q(sq);
|
||||
BOOST_TEST(boost::queue_op_status::success == 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 rvalue/copyable succeeds
|
||||
boost::queue_adaptor<boost::sync_queue<int> > sq;
|
||||
boost::queue_back<int> q(sq);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.try_push(1));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
|
||||
#if 0
|
||||
{
|
||||
// empty queue try_push rvalue/non-copyable succeeds
|
||||
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
|
||||
boost::queue_back<non_copyable> q(sq);
|
||||
non_copyable nc(1);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.try_push(boost::move(nc)));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
// empty queue try_push lvalue succeeds
|
||||
boost::queue_adaptor<boost::sync_queue<int> > sq;
|
||||
boost::queue_back<int> q(sq);
|
||||
int i;
|
||||
BOOST_TEST(boost::queue_op_status::success == 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::queue_adaptor<boost::sync_queue<int> > sq;
|
||||
boost::queue_back<int> q(sq);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(1));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
{
|
||||
// empty queue nonblocking_push_back rvalue/non-copyable succeeds
|
||||
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
|
||||
boost::queue_back<non_copyable> q(sq);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(non_copyable(1)));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
#endif
|
||||
{
|
||||
// empty queue nonblocking_push_back rvalue/non-copyable succeeds
|
||||
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
|
||||
boost::queue_back<non_copyable> q(sq);
|
||||
non_copyable nc(1);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(boost::move(nc)));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue pull_front succeed
|
||||
boost::queue_adaptor<boost::sync_queue<int> > sq;
|
||||
boost::queue_front<int> q(sq);
|
||||
sq.push_back(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_front succeed
|
||||
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
|
||||
boost::queue_front<non_copyable> q(sq);
|
||||
non_copyable nc1(1);
|
||||
sq.push_back(boost::move(nc1));
|
||||
non_copyable nc2(2);
|
||||
q.pull(nc2);
|
||||
BOOST_TEST_EQ(nc1, nc2);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue pull_front succeed
|
||||
boost::queue_adaptor<boost::sync_queue<int> > sq;
|
||||
boost::queue_front<int> q(sq);
|
||||
sq.push_back(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 pull_front succeed
|
||||
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
|
||||
boost::queue_front<non_copyable> q(sq);
|
||||
non_copyable nc1(1);
|
||||
sq.push_back(boost::move(nc1));
|
||||
non_copyable nc = q.pull();
|
||||
BOOST_TEST_EQ(nc, nc1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue try_pull_front succeed
|
||||
boost::queue_adaptor<boost::sync_queue<int> > sq;
|
||||
boost::queue_front<int> q(sq);
|
||||
sq.push_back(1);
|
||||
int i;
|
||||
BOOST_TEST(boost::queue_op_status::success == 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_front succeed
|
||||
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
|
||||
boost::queue_front<non_copyable> q(sq);
|
||||
non_copyable nc1(1);
|
||||
sq.push_back(boost::move(nc1));
|
||||
non_copyable nc(2);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.try_pull(nc));
|
||||
BOOST_TEST_EQ(nc, nc1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue nonblocking_pull_front succeed
|
||||
boost::queue_adaptor<boost::sync_queue<int> > sq;
|
||||
boost::queue_front<int> q(sq);
|
||||
sq.push_back(1);
|
||||
int i;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_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 nonblocking_pull_front succeed
|
||||
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
|
||||
boost::queue_front<non_copyable> q(sq);
|
||||
non_copyable nc1(1);
|
||||
sq.push_back(boost::move(nc1));
|
||||
non_copyable nc(2);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(nc));
|
||||
BOOST_TEST_EQ(nc, nc1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue wait_pull_front succeed
|
||||
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
|
||||
boost::queue_front<non_copyable> q(sq);
|
||||
non_copyable nc1(1);
|
||||
sq.push_back(boost::move(nc1));
|
||||
non_copyable nc(2);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc));
|
||||
BOOST_TEST_EQ(nc, nc1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue wait_pull_front succeed
|
||||
boost::queue_adaptor<boost::sync_queue<int> > sq;
|
||||
boost::queue_front<int> q(sq);
|
||||
sq.push_back(1);
|
||||
int i;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.wait_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 wait_pull_front succeed
|
||||
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
|
||||
boost::queue_front<non_copyable> q(sq);
|
||||
non_copyable nc1(1);
|
||||
sq.push_back(boost::move(nc1));
|
||||
non_copyable nc(2);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc));
|
||||
BOOST_TEST_EQ(nc, nc1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
|
||||
{
|
||||
// closed invariants
|
||||
boost::queue_adaptor<boost::sync_queue<int> > sq;
|
||||
boost::queue_back<int> q(sq);
|
||||
q.close();
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(q.closed());
|
||||
}
|
||||
{
|
||||
// closed invariants
|
||||
boost::queue_adaptor<boost::sync_queue<int> > sq;
|
||||
boost::queue_front<int> q(sq);
|
||||
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::queue_adaptor<boost::sync_queue<int> > sq;
|
||||
boost::queue_back<int> q(sq);
|
||||
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::queue_adaptor<boost::sync_queue<int> > sq;
|
||||
boost::queue_front<int> q(sq);
|
||||
sq.push_back(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());
|
||||
}
|
||||
{
|
||||
// 1-element closed queue wait_pull_front succeed
|
||||
boost::queue_adaptor<boost::sync_queue<int> > sq;
|
||||
boost::queue_front<int> q(sq);
|
||||
sq.push_back(1);
|
||||
q.close();
|
||||
int i;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.wait_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());
|
||||
}
|
||||
{
|
||||
// closed empty queue wait_pull_front fails
|
||||
boost::queue_adaptor<boost::sync_queue<int> > sq;
|
||||
boost::queue_front<int> q(sq);
|
||||
q.close();
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(q.closed());
|
||||
int i;
|
||||
BOOST_TEST(boost::queue_op_status::closed == q.wait_pull(i));
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(q.closed());
|
||||
}
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ int main()
|
||||
{
|
||||
// empty queue try_push value succeeds
|
||||
boost::sync_bounded_queue<int> q(2);
|
||||
int i;
|
||||
int i=1;
|
||||
BOOST_TEST(q.try_push(i));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
@@ -357,7 +357,7 @@ int main()
|
||||
{
|
||||
// empty queue try_push value succeeds
|
||||
boost::sync_bounded_queue<int> q(2);
|
||||
int i;
|
||||
int i=1;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.try_push_back(i));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
|
||||
@@ -334,9 +334,23 @@ void test_concurrent_push_back_on_empty_queue()
|
||||
push_done[i]=boost::async(boost::launch::async,
|
||||
call_push_back<int>(&q,&go));
|
||||
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
try
|
||||
{
|
||||
for (unsigned int i = 0; i < n; ++i)
|
||||
push_done[i].get();
|
||||
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
try
|
||||
{
|
||||
BOOST_TEST(!q.empty());
|
||||
for (unsigned int i =0; i< n; ++i)
|
||||
BOOST_TEST_EQ(q.pull_front(), 42);
|
||||
@@ -364,7 +378,16 @@ void test_concurrent_pull_front_on_queue()
|
||||
|
||||
for (unsigned int i =0; i< n; ++i)
|
||||
pull_done[i]=boost::async(boost::launch::async,
|
||||
call_pull_front<int>(&q,&go));
|
||||
#if ! defined BOOST_NO_CXX11_LAMBDAS
|
||||
[&q,&go]() -> int
|
||||
{
|
||||
go.wait();
|
||||
return q.pull_front();
|
||||
}
|
||||
#else
|
||||
call_pull_front<int>(&q,&go)
|
||||
#endif
|
||||
);
|
||||
|
||||
for (unsigned int i = 0; i < n; ++i)
|
||||
BOOST_TEST_EQ(pull_done[i].get(), 42);
|
||||
|
||||
@@ -266,7 +266,7 @@ int main()
|
||||
{
|
||||
// empty queue try_push lvalue succeeds
|
||||
boost::sync_queue<int> q;
|
||||
int i;
|
||||
int i=1;
|
||||
BOOST_TEST(q.try_push(i));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
@@ -308,7 +308,7 @@ int main()
|
||||
{
|
||||
// empty queue try_push lvalue succeeds
|
||||
boost::sync_queue<int> q;
|
||||
int i;
|
||||
int i=1;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.try_push_back(i));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
|
||||
@@ -128,7 +128,7 @@ void test_variadic_templates() {
|
||||
);
|
||||
BOOST_TEST(a3 == 200);
|
||||
BOOST_TEST(a4 == true);
|
||||
BOOST_TEST(res6 == 888);
|
||||
BOOST_TEST_EQ(res6_move, 888);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
23
test/test_10340.cpp
Normal file
23
test/test_10340.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
|
||||
#include <boost/thread/future.hpp>
|
||||
|
||||
struct foo
|
||||
{
|
||||
foo(int i_): i(i_) {}
|
||||
int i;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
boost::promise<foo> p;
|
||||
const foo f(42);
|
||||
p.set_value(f);
|
||||
|
||||
// Clearly a const future ref isn't much use, but I needed to
|
||||
// prove the problem wasn't me trying to copy a unique_future
|
||||
|
||||
const boost::future<foo>& fut = boost::make_ready_future( foo(42) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// Copyright (C) 2008 Vicente J. Botet Escriba
|
||||
//
|
||||
// Copyright (C) 2008 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)
|
||||
|
||||
@@ -60,6 +59,7 @@ void test_stack_size()
|
||||
BOOST_CHECK(attrs.get_stack_size() >= 0x4000);
|
||||
|
||||
}
|
||||
|
||||
void do_test_creation_with_attrs()
|
||||
{
|
||||
test_value = 0;
|
||||
@@ -85,5 +85,3 @@ boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
|
||||
|
||||
return test;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -50,9 +50,10 @@ void test_barrier()
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
g.interrupt_all();
|
||||
g.join_all();
|
||||
throw;
|
||||
//throw;
|
||||
}
|
||||
|
||||
BOOST_TEST(global_parameter==5);
|
||||
|
||||
@@ -50,9 +50,10 @@ void test_barrier()
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
g.interrupt_all();
|
||||
g.join_all();
|
||||
throw;
|
||||
//throw;
|
||||
}
|
||||
|
||||
BOOST_TEST(global_parameter==5);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user