2
0
mirror of https://github.com/boostorg/thread.git synced 2026-02-03 09:42:16 +00:00

Compare commits

...

66 Commits

Author SHA1 Message Date
Vicente J. Botet Escriba
ec770eeb6a fix forwarding reference_wrapper in make_ready_future. 2015-02-20 16:34:56 +01:00
Vicente J. Botet Escriba
b9ab307912 rollback nullary_function<void()const> specialization. 2015-02-20 16:33:53 +01:00
Vicente J. Botet Escriba
1ae96b3820 Merge branch 'develop' into fix/blocking_future 2015-02-20 14:34:55 +01:00
Vicente J. Botet Escriba
889c178173 fix issues with fallback_to. The route cause was that the original future was locked after destruction. This was more evident when the future was already ready when future::then was called. 2015-02-20 14:34:33 +01:00
Vicente J. Botet Escriba
7ba9591015 first trial towards a work=nullary_function<void() const>. 2015-02-20 10:20:38 +01:00
Vicente J. Botet Escriba
b07f18facf remove include/boost/thread/detail/work.hpp. 2015-02-20 10:18:35 +01:00
Vicente J. Botet Escriba
7b1b1b5daa fix include guard on serial_executor_cont.hpp. 2015-02-19 18:00:29 +01:00
Vicente J. Botet Escriba
63fb28c7d4 Merge branch 'develop' into fix/blocking_future 2015-02-19 10:36:20 +01:00
Vicente J. Botet Escriba
67e18ff039 Merge branch 'feature/serial_executor_continuation' into develop 2015-02-19 10:31:39 +01:00
Vicente J. Botet Escriba
e715d74a95 use a different name for serial_executor continuation as it add more constraints. 2015-02-19 10:30:25 +01:00
Vicente J. Botet Escriba
393d214ac9 Merge branch 'develop' into feature/serial_executor_continuation 2015-02-19 10:16:27 +01:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
0fa6038f6a Revert "Make mandatory that the Win32 API version configured is at least Windows XP or higher."
This reverts commit e0217424f3.
2015-02-18 23:40:46 +00:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
cf1182ee99 Disable physical_concurrency() on Mingw32 alone. 2015-02-18 15:19:48 +00:00
Vicente J. Botet Escriba
a04497af24 make thread-safe serial_executor. There are yet somme synchronization limitations. 2015-02-18 10:45:10 +01:00
Vicente J. Botet Escriba
821a93ca1a first draft for serial_executor based on continuations. 2015-02-17 19:09:56 +01:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
e0217424f3 Make mandatory that the Win32 API version configured is at least Windows XP or higher. 2015-02-17 14:42:39 +00:00
Vicente J. Botet Escriba
cf76bc666c Merge branch 'develop' into fix/blocking_future 2015-02-17 11:44:04 +01:00
Vicente J. Botet Escriba
d00e39acc7 Add traces to sporious fali on fallback_to. 2015-02-17 11:41:21 +01:00
Vicente J. Botet Escriba
90ba3ae7c6 Merge pull request #48 from wmamrak/develop
Fixed documentation bugs.
2015-02-17 11:25:58 +01:00
Vicente J. Botet Escriba
b68702b56d Merge branch 'develop' into fix/blocking_future 2015-02-17 01:50:11 +01:00
Wojciech Mamrak
3b2322db96 Fixed documentation bugs. 2015-02-17 00:52:39 +01:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
6a427ac4b6 Fix physical_concurrency() on win32. 2015-02-16 18:03:46 +00:00
Vicente J. Botet Escriba
ffd856073f Merge branch 'develop' of github.com:boostorg/thread into develop 2015-02-16 14:28:00 +01:00
Vicente J. Botet Escriba
f1fafb117a fix typo. 2015-02-16 14:27:37 +01:00
Vicente J. Botet Escriba
e2cda49b0b cleanup. unlock before submiting to an executor as it can directly call the continuation. 2015-02-16 14:17:57 +01:00
Vicente J. Botet Escriba
d1aa2eec56 Merge pull request #47 from wmamrak/develop
Removed redundant move ctor and ass. operator of Thread class synopsis.
2015-02-15 23:56:24 +01:00
Wojciech Mamrak
1db0ba4639 Removed redundant move ctor and ass. operator of Thread class synopsis. 2015-02-15 20:49:07 +01:00
Vicente J. Botet Escriba
a4e7eba1d4 cleanup. 2015-02-11 07:05:10 +01:00
Vicente J. Botet Escriba
67778b3278 fix shared_future::then, get and get_or. 2015-02-10 00:01:28 +01:00
Vicente J. Botet Escriba
a5e6952a95 merge from develop - coamesced timers. 2015-02-09 13:08:55 +01:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
9cc1357c95 Revert "Try to include some STL headers which Android libc++ claims have not been included."
This reverts commit b571686e5d.
2015-02-06 12:21:55 +00:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
b571686e5d Try to include some STL headers which Android libc++ claims have not been included. 2015-02-06 12:09:52 +00:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
9c67be287e Fix warning on mingw about casting a function pointer through a void *.
Fix warning on MSVC about GetModuleHandle potentially failing.
2015-02-06 12:04:22 +00:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
f599783444 Fixed the MSVC10 breakage caused by coalesced timers support. 2015-02-06 11:51:37 +00:00
Vicente J. Botet Escriba
d628b8d36c Merge branch 'develop' of github.com:boostorg/thread into develop 2015-02-05 08:30:39 +01:00
Vicente J. Botet Escriba
65c519c22c Merge branch 'master' into develop 2015-02-04 22:35:29 +01:00
Vicente J. Botet Escriba
05e492c56c Merge branch 'master' of github.com:boostorg/thread 2015-02-04 22:33:22 +01:00
Vicente J. Botet Escriba
3c2321c37a Merge pull request #45 from Matulis/master
Updated namespace to call no_interruption_point sleep_for
2015-02-04 22:31:11 +01:00
Martin Matulyauskas
6c72a2527f Updated namespace to call no_interruption_point sleep_for 2015-02-04 15:00:51 -06:00
Niall Douglas
1bd09085db Merge pull request #44 from boostorg/win32_coalesced_timers_support
Win32 coalesced timers support
2015-02-04 18:14:40 +00:00
Vicente J. Botet Escriba
d6c3f15947 Merge branch 'develop' 2015-02-04 18:47:40 +01:00
Vicente J. Botet Escriba
5960985355 merge from develop: Reverted parts of c16ec42 because 45510fa was a better fix.: 2015-02-04 18:46:29 +01:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
84e2b7869d Merge branch 'develop' of github.com:boostorg/thread into develop 2015-02-04 13:58:30 +00:00
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
401f69f108 Added coalesced timer support to Windows where that API is available. Tolerable delay is set to the maximum of 5% of interval or 32 ms. 2015-02-04 13:58:11 +00:00
Vicente J. Botet Escriba
4f57e3fb61 Merge pull request #43 from vtnerd/RevertMakeReady
Reverted parts of c16ec42 because 45510fa was a better fix.
2015-02-03 08:34:53 +01:00
Vicente J. Botet Escriba
fdf20f1adc merge Allow to call shared_future::then multiple times. Related to #10972. 2015-02-02 19:40:04 +01:00
Lee Clagett
990474ff47 Reverted parts of c16ec42 because 45510fa was a better fix. 2015-02-02 12:08:38 -05:00
Vicente J. Botet Escriba
786d842ad1 update history. 2015-02-02 17:45:57 +01:00
Vicente J. Botet Escriba
441c89d304 Allow to call shared_future::then multiple times. Related to #10972. 2015-02-02 17:41:57 +01:00
Vicente J. Botet Escriba
63098e84a2 Merge branch 'develop' into fix/blocking_future 2015-02-01 19:39:43 +01:00
Vicente J. Botet Escriba
71997bd9aa Merge branch 'develop' 2015-02-01 19:38:50 +01:00
Vicente J. Botet Escriba
45510facc7 unwrapped future must forward the continuation to the wrapped future. Related to #10964. 2015-02-01 14:56:52 +01:00
Vicente J. Botet Escriba
cf539064d6 Deduce T& when the make_ready_future parameter is reference_wrapper<T>. Relates to #10979. 2015-02-01 13:44:41 +01:00
Vicente J. Botet Escriba
3431736c88 Merge branch 'develop' into fix/blocking_future 2015-01-27 22:22:37 +01:00
Vicente J. Botet Escriba
095b53b2a2 Update changes. 2015-01-27 07:14:17 +01:00
Vicente J. Botet Escriba
7a63c40a01 Merge pull request #39 from jhunold/shadow
Fix gcc/clang shadow warnings.
2015-01-26 19:48:53 +01:00
Jürgen Hunold
c1148a66cc Fix gcc/clang shadow warnings.
The variable names are re-used in the all_futures_lock() functions.
2015-01-26 12:39:27 +01:00
Vicente J. Botet Escriba
5fa0a5d4c5 make shared_future::get() const. Related to #10971. 2015-01-26 08:39:30 +01:00
Vicente J. Botet Escriba
75a8280701 Merge branch 'develop' 2015-01-25 16:00:08 +01:00
Vicente J. Botet Escriba
e74fd82060 Merge from develop. 2015-01-24 18:02:31 +01:00
Vicente J. Botet Escriba
5a141ccf99 Merge branch 'develop' 2015-01-24 09:07:25 +01:00
Vicente J. Botet Escriba
35d7ae0d2e add forgotten wait when shared_future::then deferred. 2015-01-23 08:36:46 +01:00
Vicente J. Botet Escriba
d9c7f95617 fix future async deferred. 2015-01-23 07:10:22 +01:00
Vicente J. Botet Escriba
06b3f6a9d7 disable async deferred on C++98 as not implemented. 2015-01-23 06:02:11 +01:00
Vicente J. Botet Escriba
895b4a0ac5 Try to fix a lot of issues, even if alldoesn't works yet. 2015-01-22 23:10:40 +01:00
Vicente J. Botet Escriba
9cb72849ee Go towards blocking on the last future associated to an async shared state. shared_future don't work yet. 2015-01-18 12:19:17 +01:00
24 changed files with 1255 additions and 451 deletions

View File

@@ -12,17 +12,20 @@
[*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/6787 #6787] boost::thread::sleep() hangs if system time is rolled back
* [@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
* [@http://svn.boost.org/trac/boost/ticket/9856 #9856] [windows] condition_variable::wait_for returns wrong cv_status on timeout.
* [@http://svn.boost.org/trac/boost/ticket/10651 #10651] boost::thread leaks memory when using the MinGW compiler.
* [@http://svn.boost.org/trac/boost/ticket/10685 #10685] mfc_thread_init.hpp does not compile.
* [@http://svn.boost.org/trac/boost/ticket/10942 #10942] Boost.Thread fails to build on Cygwin.
* [@http://svn.boost.org/trac/boost/ticket/10967 #10967] Timed wait points inconsistently convert relative to absolute waits.
* [@http://svn.boost.org/trac/boost/ticket/10968 #10968] The futures returned by async() and future::then() are not blocking.
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.
@@ -32,16 +35,31 @@ Please take a look at [@http://www.boost.org/development/tests/master/developer/
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,
* on thread specific storage that prevent the library to be used with dynamic libraries ( [@http://svn.boost.org/trac/boost/ticket/3926 #3926], ),
* timed operation on windows are inconsistent ( [@http://svn.boost.org/trac/boost/ticket/9856 #9856], [@http://svn.boost.org/trac/boost/ticket/10967 #10967]).
* The futures returned by async() and future::then() are not blocking ([@http://svn.boost.org/trac/boost/ticket/10968 #10968]).
[*New Experimental Features:]
* [@http://svn.boost.org/trac/boost/ticket/9600 #9600] Async: Add task_region
* [@http://svn.boost.org/trac/boost/ticket/10611 #10611] Add emplace promise::set_value and emplace make_ready_future
* [@http://svn.boost.org/trac/boost/ticket/10826 #10826] Add scheduled executor operations
[*Fixed Bugs:]
* [@http://svn.boost.org/trac/boost/ticket/10734 #10734] Submit method work differently on different executors, some throw exception and some silently ignore error (thread_executor and inline_executor)
* [@http://svn.boost.org/trac/boost/ticket/10736 #10736] Task exceptions silently ignored. I think std::terminate solution from N3785 and std::thread is better choice and more consistent.
* [@http://svn.boost.org/trac/boost/ticket/10737 #10737] In serial_executor we have infinite wait if task throw exception.
* [@http://svn.boost.org/trac/boost/ticket/10822 #10822] Boost.Thread fails to compile on Android
* [@http://svn.boost.org/trac/boost/ticket/10824 #10824] Boost.Thread 1.57 breaks Windows XP compatibility for SP2 and below.
* [@http://svn.boost.org/trac/boost/ticket/10963 #10963] future<future<T>>::then Has No Implementation
* [@http://svn.boost.org/trac/boost/ticket/10964 #10964] future<future<T>>::unwrap().then() Deadlocks
* [@http://svn.boost.org/trac/boost/ticket/10971 #10971] shared_future::get()/get_or() must be const
* [@http://svn.boost.org/trac/boost/ticket/10972 #10972] shared_future::then() can be called multiple times.
* [@http://svn.boost.org/trac/boost/ticket/10979 #10979] Support T& type deduction when the make_ready_future parameter is reference_wrapper<T>
[heading Version 4.4.0 - boost 1.57]
[*Know Bugs:]

View File

@@ -1020,7 +1020,7 @@ There are not too much tests yet, so it is possible that you can find out some t
void swap(shared_future& other);
// retrieving the value
see below get();
see below get() const;
exception_ptr get_exception_ptr(); // EXTENSION
@@ -1066,9 +1066,9 @@ There are not too much tests yet, so it is possible that you can find out some t
[///////////////////////////////////]
[section:get Member function `get()`]
const R& get();
R& get();
void get();
const R& get() const;
R& get() const;
void get() const;
[variablelist
@@ -2362,7 +2362,7 @@ All `R` types must be the same. If any of the `future<R>` or `shared_future<R>`
[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<V> make_ready_future(T&& value); // EXTENSION
future<void> make_ready_future(); // EXTENSION
template <typename T>
future<T> make_ready_future(exception_ptr ex); // DEPRECATED
@@ -2371,11 +2371,15 @@ All `R` types must be the same. If any of the `future<R>` or `shared_future<R>`
[variablelist
[[Remark:][
where `V` is determined as follows: Let `U` be `decay_t<T>`. Then `V` is `X&`
if `U` equals `reference_wrapper<X>`, otherwise `V` is `U`.
]]
[[Effects:] [
- value prototype: The value that is passed into the function is moved to the shared state of the returned function if it is an rvalue.
Otherwise the value is copied to the shared state of the returned function.
- value prototype: The value that is passed into the function is moved to the shared state of the returned future if it is an rvalue.
Otherwise the value is copied to the shared state of the returned future.
- exception: The exception that is passed into the function is copied to the shared state of the returned function.
- exception: The exception that is passed into the function is copied to the shared state of the returned future.
.]]

View File

@@ -93,7 +93,7 @@ the result is ready, it is returned from __unique_future_get__ by rvalue-referen
appropriate for the type.
On the other hand, many instances of __shared_future__ may reference the same result. Instances can be freely copied and assigned,
and __shared_future_get__ returns a non `const` reference so that multiple calls to __shared_future_get__ are safe. You can move an
and __shared_future_get__ returns a `const` reference so that multiple calls to __shared_future_get__ are safe. You can move an
instance of __unique_future__ into an instance of __shared_future__, thus transferring ownership of the associated asynchronous
result, but not vice-versa.

View File

@@ -21,18 +21,18 @@
class scoped_thread;
void swap(scoped_thread& lhs,scoped_thread& rhs) noexcept;
[section:motovation Motivation]
[section:motivation Motivation]
Based on the scoped_thread class defined in C++ Concurrency in Action Boost.Thread defines a thread wrapper class that instead of calling terminate if the thread is joinable on destruction, call a specific action given as template parameter.
While the scoped_thread class defined in C++ Concurrency in Action is closer to strict_scoped_thread class that doesn't allows any change in the wrapped thread, Boost.Thread provides a class scoped_thread that provides the same non-deprecated interface than __thread.
While the scoped_thread class defined in C++ Concurrency in Action is closer to strict_scoped_thread class that doesn't allows any change in the wrapped thread, Boost.Thread provides a class scoped_thread that provides the same non-deprecated interface as __thread.
[endsect]
[section:tutorial Tutorial]
Scoped Threads are wrappers around a thread that allows the user to state what to do at destruction time. One of the common uses is to join the thread at destruction time so this is the default behavior. This is the single difference respect to a thread. While thread call std::terminate() on the destructor is the thread is joinable, strict_scoped_thread<> or scoped_thread<> join the thread if joinable.
Scoped Threads are wrappers around a thread that allows the user to state what to do at destruction time. One of the common uses is to join the thread at destruction time so this is the default behavior. This is the single difference respect to a thread. While thread call std::terminate() on the destructor if the thread is joinable, strict_scoped_thread<> or scoped_thread<> join the thread if joinable.
The difference between strict_scoped_thread and scoped_thread is that the strict_scoped_thread hides completely the owned thread and so the user can do nothing with the owned thread other than the specific action given as parameter, while scoped_thread provide the same interface than __thread and forwards all the operations.
The difference between strict_scoped_thread and scoped_thread is that the strict_scoped_thread hides completely the owned thread and so the user can do nothing with the owned thread other than the specific action given as parameter, while scoped_thread provide the same interface as __thread and forwards all the operations.
boost::strict_scoped_thread<> t1((boost::thread(f)));
//t1.detach(); // compile fails
@@ -114,15 +114,15 @@ The difference between strict_scoped_thread and scoped_thread is that the strict
};
RAI __thread wrapper adding a specific destroyer allowing to master what can be done at destruction time.
RAII __thread wrapper adding a specific destroyer allowing to master what can be done at destruction time.
CallableThread: A callable `void(thread&)`.
The default is a `join_if_joinable`.
`std/boost::thread` destructor terminates the program if the __thread is not joinable.
This wrapper can be used to join the thread before destroying it seems a natural need.
Thread destructor terminates the program if the __thread is joinable.
This wrapper can be used to join the thread before destroying it.
[heading Example]
@@ -233,13 +233,13 @@ This wrapper can be used to join the thread before destroying it seems a natural
void swap(scoped_thread& lhs,scoped_thread& rhs) noexcept;
RAI __thread wrapper adding a specific destroyer allowing to master what can be done at destruction time.
RAII __thread wrapper adding a specific destroyer allowing to master what can be done at destruction time.
CallableThread: A callable void(thread&).
The default is join_if_joinable.
thread std::thread destructor terminates the program if the thread is not joinable.
Having a wrapper that can join the thread before destroying it seems a natural need.
Thread destructor terminates the program if the thread is joinable.
This wrapper can be used to join the thread before destroying it.
Remark: `scoped_thread` is not a __thread as __thread is not designed to be derived from as a polymorphic type.
@@ -312,9 +312,9 @@ any) to `*this`.
[variablelist
[[Effects:] [move the thread to own `t_`.]]
[[Effects:] [Transfers ownership of the thread managed by `other` (if any) to the newly constructed scoped_thread instance.]]
[[Postconditions:] [`*this.t_` refers to the newly created thread of execution and `this->get_id()!=thread::id()`.]]
[[Postconditions:] [other.get_id()==thread::id() and get_id() returns the value of other.get_id() prior to the construction.]]
[[Throws:] [Nothing]]
@@ -329,7 +329,7 @@ any) to `*this`.
[variablelist
[[Effects:] [Construct a internal thread in place.]]
[[Effects:] [Construct an internal thread in place.]]
[[Postconditions:] [`*this.t_` refers to the newly created thread of execution and `this->get_id()!=thread::id()`.]]

View File

@@ -432,12 +432,14 @@ This behavior is incompatible with the current Boost.Thread design, so the use o
class attributes; // EXTENSION
thread() noexcept;
~thread();
thread(const thread&) = delete;
thread& operator=(const thread&) = delete;
// move support
thread(thread&&) noexcept;
thread& operator=(thread&&) noexcept;
~thread();
template <class F>
explicit thread(F f);
@@ -456,10 +458,6 @@ This behavior is incompatible with the current Boost.Thread design, so the use o
template <class F, class ...Args>
explicit thread(attributes& attrs, F&& f, Args&&... args);
// move support
thread(thread && x) noexcept;
thread& operator=(thread && x) noexcept;
void swap(thread& x) noexcept;
class id;

View File

@@ -35,31 +35,83 @@ int p1()
int main()
{
const int number_of_tests = 100;
const int number_of_tests = 200;
BOOST_THREAD_LOG << "<MAIN" << BOOST_THREAD_END_LOG;
{
for (int i=0; i< number_of_tests; i++)
try
{
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
f1.wait();
BOOST_ASSERT(f1.get()==1);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
}
catch (std::exception& ex)
{
std::cout << __FILE__ << "["<< __LINE__<<"] " << "ERRORRRRR "<<ex.what() << "" << std::endl;
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
return 1;
}
catch (...)
{
std::cout << __FILE__ << "["<< __LINE__<<"] " << " ERRORRRRR exception thrown" << std::endl;
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
return 2;
}
}
{
for (int i=0; i< number_of_tests; i++)
try
{
//boost::future<int> f1 = boost::async(boost::launch::async, &p1);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(&p1);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
boost::future<int> f2 = f1.fallback_to(-1);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
f2.wait();
//std::cout << __FILE__ << "["<< __LINE__<<"] " << std::endl;
BOOST_ASSERT(f2.get()==1);
//std::cout << __FILE__ << "["<< __LINE__<<"] " << std::endl;
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
}
catch (std::exception& ex)
{
std::cout << "ERRORRRRR "<<ex.what() << "" << std::endl;
std::cout << __FILE__ << "["<< __LINE__<<"] " << "ERRORRRRR "<<ex.what() << "" << std::endl;
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
return 1;
}
catch (...)
{
std::cout << " ERRORRRRR exception thrown" << std::endl;
std::cout << __FILE__ << "["<< __LINE__<<"] " << " ERRORRRRR exception thrown" << std::endl;
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
return 2;
}
}
{
for (int i=0; i< number_of_tests; i++)
try
{
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
boost::future<int> f1 = boost::async(boost::launch::async, &p1_ex);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
f1.wait();
BOOST_ASSERT(f1.get_or(-1)==-1);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
}
catch (std::exception& ex)
{
std::cout << __FILE__ << "["<< __LINE__<<"] " << "ERRORRRRR "<<ex.what() << "" << std::endl;
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
return 1;
}
catch (...)
{
std::cout << __FILE__ << "["<< __LINE__<<"] " << " ERRORRRRR exception thrown" << std::endl;
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
return 2;
}
@@ -75,18 +127,20 @@ int main()
boost::future<int> f2 = f1.fallback_to(-1);
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
f2.wait();
//std::cout << __FILE__ << "["<< __LINE__<<"] " << std::endl;
BOOST_ASSERT(f2.get()==-1);
//std::cout << __FILE__ << "["<< __LINE__<<"] " << std::endl;
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
}
catch (std::exception& ex)
{
std::cout << "ERRORRRRR "<<ex.what() << "" << std::endl;
std::cout << __FILE__ << "["<< __LINE__<<"] " << "ERRORRRRR "<<ex.what() << "" << std::endl;
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
return 1;
}
catch (...)
{
std::cout << " ERRORRRRR exception thrown" << std::endl;
std::cout << __FILE__ << "["<< __LINE__<<"] " << " ERRORRRRR exception thrown" << std::endl;
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
return 2;
}

View File

@@ -104,6 +104,26 @@ int main()
boost::future<int&> f = compute_ref(0);
std::cout << f.get() << std::endl;
}
#if __cplusplus > 201103L
{
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
int i = 0;
boost::future<int&> f = boost::make_ready_future(std::ref(i));
std::cout << f.get() << std::endl;
}
#endif
{
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
int i = 0;
boost::future<int&> f = boost::make_ready_future(boost::ref(i));
std::cout << f.get() << std::endl;
}
{
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
const int i = 0;
boost::future<int const&> f = boost::make_ready_future(boost::cref(i));
std::cout << f.get() << std::endl;
}
// {
// std::cout << __FILE__ << " "<< __LINE__ << std::endl;
// boost::future<int> f = compute(2);

113
example/serial_executor.cpp Normal file
View File

@@ -0,0 +1,113 @@
// Copyright (C) 2015 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)
#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/serial_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(30));
std::cout << BOOST_CONTEXTOF << std::endl;
}
void p2()
{
std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::milliseconds(10));
std::cout << BOOST_CONTEXTOF << std::endl;
}
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::serial_executor& tp)
{
std::cout << BOOST_CONTEXTOF << std::endl;
for (int i = 0; i < 3; ++i) {
std::cout << BOOST_CONTEXTOF << std::endl;
tp.submit(&p2);
}
for (int i = 0; i < 3; ++i) {
std::cout << BOOST_CONTEXTOF << std::endl;
tp.submit(&p1);
}
std::cout << BOOST_CONTEXTOF << std::endl;
}
void at_th_entry(boost::basic_thread_pool& )
{
}
int test_executor_adaptor()
{
// std::cout << BOOST_CONTEXTOF << std::endl;
{
try
{
#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);
boost::this_thread::sleep_for(boost::chrono::seconds(10));
}
#endif
// std::cout << BOOST_CONTEXTOF << 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_executor_adaptor();
}

View File

@@ -0,0 +1,113 @@
// Copyright (C) 2015 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)
#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/serial_executor_cont.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(30));
std::cout << BOOST_CONTEXTOF << std::endl;
}
void p2()
{
std::cout << BOOST_CONTEXTOF << std::endl;
boost::this_thread::sleep_for(boost::chrono::milliseconds(10));
std::cout << BOOST_CONTEXTOF << std::endl;
}
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::serial_executor_cont& tp)
{
std::cout << BOOST_CONTEXTOF << std::endl;
for (int i = 0; i < 3; ++i) {
std::cout << BOOST_CONTEXTOF << std::endl;
tp.submit(&p2);
}
for (int i = 0; i < 3; ++i) {
std::cout << BOOST_CONTEXTOF << std::endl;
tp.submit(&p1);
}
std::cout << BOOST_CONTEXTOF << std::endl;
}
void at_th_entry(boost::basic_thread_pool& )
{
}
int test_executor_adaptor()
{
// std::cout << BOOST_CONTEXTOF << std::endl;
{
try
{
#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
// std::cout << BOOST_CONTEXTOF << std::endl;
{
boost::basic_thread_pool ea1(4);
boost::serial_executor_cont ea2(ea1);
submit_some(ea2);
boost::this_thread::sleep_for(boost::chrono::seconds(10));
}
#endif
// std::cout << BOOST_CONTEXTOF << 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_executor_adaptor();
}

View File

@@ -1,23 +0,0 @@
// (C) Copyright 2013 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_THREAD_DETAIL_WORK_HPP
#define BOOST_THREAD_DETAIL_WORK_HPP
#include <boost/thread/detail/nullary_function.hpp>
namespace boost
{
namespace thread_detail
{
typedef detail::nullary_function<void()> work;
}
} // namespace boost
#endif // BOOST_THREAD_DETAIL_MEMORY_HPP

View File

@@ -0,0 +1,170 @@
// Copyright (C) 2015 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/11 Vicente J. Botet Escriba
// first implementation of a simple serial scheduler.
#ifndef BOOST_THREAD_SERIAL_EXECUTOR_CONT_HPP
#define BOOST_THREAD_SERIAL_EXECUTOR_CONT_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/concurrent_queues/sync_queue.hpp>
#include <boost/thread/executors/work.hpp>
#include <boost/thread/executors/generic_executor_ref.hpp>
#include <boost/thread/future.hpp>
#include <boost/thread/scoped_thread.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace executors
{
class serial_executor_cont
{
public:
/// type-erasure to store the works to do
typedef executors::work work;
private:
generic_executor_ref ex_;
future<void> fut_; // protected by mtx_
bool closed_; // protected by mtx_
mutex mtx_;
struct continuation {
work task;
template <class X>
struct result {
typedef void type;
};
continuation(BOOST_THREAD_RV_REF(work) tsk)
: task(boost::move(tsk)) {}
void operator()(future<void> f)
{
try {
task();
} catch (...) {
std::terminate();
}
}
};
bool closed(lock_guard<mutex>&) const
{
return closed_;
}
public:
/**
* \par Returns
* The underlying executor wrapped on a generic executor reference.
*/
generic_executor_ref& underlying_executor() BOOST_NOEXCEPT { return ex_; }
/// serial_executor_cont is not copyable.
BOOST_THREAD_NO_COPYABLE(serial_executor_cont)
/**
* \b Effects: creates a serial executor that runs closures in fifo order using one the associated executor.
*
* \b Throws: Whatever exception is thrown while initializing the needed resources.
*
* \b Notes:
* * The lifetime of the associated executor must outlive the serial executor.
* * The current implementation doesn't support submission from synchronous continuation, that is,
* - the executor must execute the continuation asynchronously or
* - the continuation can not submit to this serial executor.
*/
template <class Executor>
serial_executor_cont(Executor& ex)
: ex_(ex), fut_(make_ready_future()), closed_(false)
{
}
/**
* \b Effects: Destroys the thread pool.
*
* \b Synchronization: The completion of all the closures happen before the completion of the \c serial_executor_cont destructor.
*/
~serial_executor_cont()
{
// signal to the worker thread that there will be no more submissions.
close();
}
/**
* \b Effects: close the \c serial_executor_cont for submissions.
* The loop will work until there is no more closures to run.
*/
void close()
{
lock_guard<mutex> lk(mtx_);
closed_ = true;;
}
/**
* \b Returns: whether the pool is closed for submissions.
*/
bool closed()
{
lock_guard<mutex> lk(mtx_);
return closed(lk);
}
/**
* Effects: none.
* Returns: always false.
* Throws: No.
* Remark: A serial executor can not execute one of its pending tasks as the tasks depends on the other tasks.
*/
bool try_executing_one()
{
return false;
}
/**
* \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible.
*
* \b Effects: The specified \c closure will be scheduled for execution after the last submitted closure finish.
* If the invoked closure throws an exception the \c serial_executor_cont will call \c std::terminate, as is the case with threads.
*
* \b Throws: \c sync_queue_is_closed if the executor 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)
{
lock_guard<mutex> lk(mtx_);
if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
fut_ = fut_.then(ex_, continuation(work(closure)));
}
#endif
void submit(void (*closure)())
{
lock_guard<mutex> lk(mtx_);
if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
fut_ = fut_.then(ex_, continuation(work(closure)));
}
template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
{
lock_guard<mutex> lk(mtx_);
if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
fut_ = fut_.then(ex_, continuation(work(boost::forward<Closure>(closure))));
}
};
}
using executors::serial_executor_cont;
}
#include <boost/config/abi_suffix.hpp>
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -81,7 +81,7 @@ namespace boost
};
boost::condition_variable_any cv;
std::vector<registered_waiter> waiters;
std::vector<registered_waiter> waiters_;
count_type future_count;
public:
@@ -98,7 +98,7 @@ namespace boost
registered_waiter waiter(f, f.notify_when_ready(cv), future_count);
try
{
waiters.push_back(waiter);
waiters_.push_back(waiter);
}
catch (...)
{
@@ -120,14 +120,14 @@ namespace boost
count_type wait()
{
all_futures_lock lk(waiters);
all_futures_lock lk(waiters_);
for (;;)
{
for (count_type i = 0; i < waiters.size(); ++i)
for (count_type i = 0; i < waiters_.size(); ++i)
{
if (waiters[i].future_->is_ready(lk.locks[i]))
if (waiters_[i].future_->is_ready(lk.locks[i]))
{
return waiters[i].index;
return waiters_[i].index;
}
}
cv.wait(lk);
@@ -136,9 +136,9 @@ namespace boost
~waiter_for_any_in_seq()
{
for (count_type i = 0; i < waiters.size(); ++i)
for (count_type i = 0; i < waiters_.size(); ++i)
{
waiters[i].future_->unnotify_when_ready(waiters[i].handle);
waiters_[i].future_->unnotify_when_ready(waiters_[i].handle);
}
}
};

View File

@@ -252,7 +252,7 @@ namespace boost
inline
void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns)
{
return boost::this_thread::hiden::sleep_for(boost::detail::to_timespec(ns));
return boost::this_thread::no_interruption_point::hiden::sleep_for(boost::detail::to_timespec(ns));
}
#endif
#endif // BOOST_THREAD_USES_CHRONO

View File

@@ -13,7 +13,7 @@
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/concurrent_queues/sync_queue.hpp>
#include <boost/thread/detail/work.hpp>
#include <boost/thread/executors/work.hpp>
#include <boost/config/abi_prefix.hpp>

View File

@@ -285,7 +285,6 @@ namespace boost
// Oops, we weren't called often enough, we're stuck
return 0xFFFFFFFF;
}
#else
#endif
inline detail::gettickcount64_t GetTickCount64_()
{

View File

@@ -529,11 +529,8 @@ namespace boost
unsigned thread::physical_concurrency() BOOST_NOEXCEPT
{
// a bit too strict: Windows XP with SP3 would be sufficient
#if BOOST_PLAT_WINDOWS_RUNTIME \
|| ( BOOST_USE_WINAPI_VERSION <= BOOST_WINAPI_VERSION_WINXP ) \
|| ( defined(__MINGW32__) && !defined(__MINGW64__) )
return 0;
#if BOOST_PLAT_WINDOWS_RUNTIME || (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
return hardware_concurrency();
#else
unsigned cores = 0;
DWORD size = 0;
@@ -634,7 +631,57 @@ namespace boost
}
}
#ifndef UNDER_CE
#if !BOOST_PLAT_WINDOWS_RUNTIME
namespace detail_
{
typedef struct _REASON_CONTEXT {
ULONG Version;
DWORD Flags;
union {
LPWSTR SimpleReasonString;
struct {
HMODULE LocalizedReasonModule;
ULONG LocalizedReasonId;
ULONG ReasonStringCount;
LPWSTR *ReasonStrings;
} Detailed;
} Reason;
} REASON_CONTEXT, *PREASON_CONTEXT;
static REASON_CONTEXT default_reason_context={0/*POWER_REQUEST_CONTEXT_VERSION*/, 0x00000001/*POWER_REQUEST_CONTEXT_SIMPLE_STRING*/, (LPWSTR)L"generic"};
typedef BOOL (WINAPI *setwaitabletimerex_t)(HANDLE, const LARGE_INTEGER *, LONG, PTIMERAPCROUTINE, LPVOID, PREASON_CONTEXT, ULONG);
static inline BOOL WINAPI SetWaitableTimerEx_emulation(HANDLE hTimer, const LARGE_INTEGER *lpDueTime, LONG lPeriod, PTIMERAPCROUTINE pfnCompletionRoutine, LPVOID lpArgToCompletionRoutine, PREASON_CONTEXT WakeContext, ULONG TolerableDelay)
{
return SetWaitableTimer(hTimer, lpDueTime, lPeriod, pfnCompletionRoutine, lpArgToCompletionRoutine, FALSE);
}
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 6387) // MSVC sanitiser warns that GetModuleHandleA() might fail
#endif
static inline setwaitabletimerex_t SetWaitableTimerEx()
{
static setwaitabletimerex_t setwaitabletimerex_impl;
if(setwaitabletimerex_impl)
return setwaitabletimerex_impl;
void (*addr)()=(void (*)()) GetProcAddress(
#if !defined(BOOST_NO_ANSI_APIS)
GetModuleHandleA("KERNEL32.DLL"),
#else
GetModuleHandleW(L"KERNEL32.DLL"),
#endif
"SetWaitableTimerEx");
if(addr)
setwaitabletimerex_impl=(setwaitabletimerex_t) addr;
else
setwaitabletimerex_impl=&SetWaitableTimerEx_emulation;
return setwaitabletimerex_impl;
}
#ifdef _MSC_VER
#pragma warning(pop)
#endif
}
#endif
#endif
bool interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time)
{
detail::win32::handle handles[4]={0};
@@ -660,32 +707,24 @@ namespace boost
#ifndef UNDER_CE
#if !BOOST_PLAT_WINDOWS_RUNTIME
unsigned const min_timer_wait_period=20;
// Preferentially use coalescing timers for better power consumption and timer accuracy
if(!target_time.is_sentinel())
{
detail::timeout::remaining_time const time_left=target_time.remaining_milliseconds();
if(time_left.milliseconds > min_timer_wait_period)
timer_handle=CreateWaitableTimer(NULL,false,NULL);
if(timer_handle!=0)
{
// for a long-enough timeout, use a waitable timer (which tracks clock changes)
timer_handle=CreateWaitableTimer(NULL,false,NULL);
if(timer_handle!=0)
ULONG tolerable=32; // Empirical testing shows Windows ignores this when <= 26
if(time_left.milliseconds/20>tolerable) // 5%
tolerable=time_left.milliseconds/20;
LARGE_INTEGER due_time=get_due_time(target_time);
bool const set_time_succeeded=detail_::SetWaitableTimerEx()(timer_handle,&due_time,0,0,0,&detail_::default_reason_context,tolerable)!=0;
if(set_time_succeeded)
{
LARGE_INTEGER due_time=get_due_time(target_time);
bool const set_time_succeeded=SetWaitableTimer(timer_handle,&due_time,0,0,0,false)!=0;
if(set_time_succeeded)
{
timeout_index=handle_count;
handles[handle_count++]=timer_handle;
}
timeout_index=handle_count;
handles[handle_count++]=timer_handle;
}
}
else if(!target_time.relative)
{
// convert short absolute-time timeouts into relative ones, so we don't race against clock changes
target_time=detail::timeout(time_left.milliseconds);
}
}
#endif
#endif
@@ -752,32 +791,24 @@ namespace boost
#ifndef UNDER_CE
#if !BOOST_PLAT_WINDOWS_RUNTIME
unsigned const min_timer_wait_period=20;
// Preferentially use coalescing timers for better power consumption and timer accuracy
if(!target_time.is_sentinel())
{
detail::timeout::remaining_time const time_left=target_time.remaining_milliseconds();
if(time_left.milliseconds > min_timer_wait_period)
timer_handle=CreateWaitableTimer(NULL,false,NULL);
if(timer_handle!=0)
{
// for a long-enough timeout, use a waitable timer (which tracks clock changes)
timer_handle=CreateWaitableTimer(NULL,false,NULL);
if(timer_handle!=0)
ULONG tolerable=32; // Empirical testing shows Windows ignores this when <= 26
if(time_left.milliseconds/20>tolerable) // 5%
tolerable=time_left.milliseconds/20;
LARGE_INTEGER due_time=get_due_time(target_time);
bool const set_time_succeeded=detail_::SetWaitableTimerEx()(timer_handle,&due_time,0,0,0,&detail_::default_reason_context,tolerable)!=0;
if(set_time_succeeded)
{
LARGE_INTEGER due_time=get_due_time(target_time);
bool const set_time_succeeded=SetWaitableTimer(timer_handle,&due_time,0,0,0,false)!=0;
if(set_time_succeeded)
{
timeout_index=handle_count;
handles[handle_count++]=timer_handle;
}
timeout_index=handle_count;
handles[handle_count++]=timer_handle;
}
}
else if(!target_time.relative)
{
// convert short absolute-time timeouts into relative ones, so we don't race against clock changes
target_time=detail::timeout(time_left.milliseconds);
}
}
#endif
#endif

View File

@@ -293,7 +293,7 @@ rule thread-compile ( sources : reqs * : name )
[ thread-run test_7328.cpp ]
[ thread-run test_7571.cpp ]
[ thread-run test_9319.cpp ]
#[ thread-run test_9711.cpp ] this test is invalid and should not work :(
#[ thread-run test_9711.cpp ] This is an invalid use of ::then deferred.
[ thread-run test_9856.cpp ]
[ thread-compile test_10963.cpp : : test_10963_c ]
[ thread-run test_10964.cpp ]
@@ -808,6 +808,8 @@ rule thread-compile ( sources : reqs * : name )
[ thread-run2 ../example/user_scheduler.cpp : ex_user_scheduler ]
[ thread-run2 ../example/executor.cpp : ex_executor ]
[ thread-run2 ../example/generic_executor_ref.cpp : ex_generic_executor_ref ]
[ thread-run2 ../example/serial_executor.cpp : ex_serial_executor ]
[ thread-run2 ../example/serial_executor_cont.cpp : ex_serial_executor_cont ]
[ 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 ]

View File

@@ -85,7 +85,7 @@ public:
return *this;
}
int operator()()
int operator()() const
{
boost::this_thread::sleep_for(ms(200));
return 3;
@@ -167,6 +167,48 @@ struct check_timer {
int main()
{
{
try {
boost::async(f0);
} catch (std::exception& ex)
{
std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl;
BOOST_TEST(false && "exception thrown");
}
catch (...)
{
BOOST_TEST(false && "exception thrown");
}
}
{
try {
boost::async(boost::launch::async, f0);
} catch (std::exception& ex)
{
std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl;
BOOST_TEST(false && "exception thrown");
}
catch (...)
{
BOOST_TEST(false && "exception thrown");
}
}
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
{
try {
boost::async(boost::launch::deferred, f0);
} 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

View File

@@ -51,6 +51,29 @@ void p3(boost::future<int> f)
int main()
{
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
{
try
{
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());
}
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);

View File

@@ -72,6 +72,30 @@ int main()
}
}
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
{
boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share();
BOOST_TEST(f1.valid());
boost::future<int> f2 = f1.then(&p2);
boost::future<int> f3 = f1.then(&p2);
BOOST_TEST(f2.valid());
BOOST_TEST(f3.valid());
try
{
BOOST_TEST(f2.get()==2);
BOOST_TEST(f3.get()==2);
}
catch (std::exception& ex)
{
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
BOOST_TEST(false);
}
catch (...)
{
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
BOOST_TEST(false);
}
}
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
{
boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share();
BOOST_TEST(f1.valid());

View File

@@ -29,6 +29,10 @@ struct TestCallback
}
};
void p1()
{
}
int main()
{
#if ! defined BOOST_NO_CXX11_DECLTYPE && ! defined BOOST_NO_CXX11_AUTO_DECLARATIONS
@@ -62,6 +66,11 @@ int main()
TestCallback()).unwrap().then(TestCallback()).get();
}
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
{
boost::future<void> f = boost::async(p1);
f.then(
TestCallback()).unwrap().then(TestCallback()).get();
}
#endif
return 0;
}

View File

@@ -24,18 +24,37 @@ void foo(IntPromise p)
void bar(boost::future<int> fooResult)
{
try {
std::cout << "bar" << std::endl;
int i = fooResult.get(); // Code hangs on this line (Due to future already being locked by the set_value call)
std::cout << "i: " << i << std::endl;
} catch(...) {
std::cout << __FILE__ << ":" << __LINE__ << std::endl;
}
}
int main()
{
std::cout << __FILE__ << ":" << __LINE__ << std::endl;
try {
IntPromise p(new boost::promise<int>());
boost::thread t(boost::bind(foo, p));
boost::future<int> f1 = p->get_future();
//f1.then(launch::deferred, boost::bind(bar, _1));
f1.then(boost::launch::deferred, &bar);
t.join();
} catch(...) {
return 1;
}
std::cout << __FILE__ << ":" << __LINE__ << std::endl;
try {
IntPromise p(new boost::promise<int>());
boost::thread t(boost::bind(foo, p));
boost::future<int> f1 = p->get_future();
f1.then(boost::launch::async, &bar);
t.join();
} catch(...) {
return 2;
}
std::cout << __FILE__ << ":" << __LINE__ << std::endl;
}

View File

@@ -19,6 +19,11 @@ int main() {
}
}
if(failures)
std::cerr << "There were " << failures << " failures out of " << total << " timed waits." << std::endl;
return failures!=0;
std::cout << "There were " << failures << " failures out of " << total << " timed waits." << std::endl;
if((100*failures)/total>10)
{
std::cerr << "This exceeds 10%, so failing the test." << std::endl;
return 1;
}
return 0;
}