diff --git a/doc/async_executors.qbk b/doc/async_executors.qbk index 532260c7..2529446f 100644 --- a/doc/async_executors.qbk +++ b/doc/async_executors.qbk @@ -319,33 +319,23 @@ The reason is that the user can always use a thread_local variable and reset it } ); +[ [heading Default executor] The library authors share some of the concerns of the C++ standard committee (introduction of a new single shared resource, a singleton, could make it difficult to make it portable to all the environments) and that this library doesn't need to provide a default executor for the time been. -The user can always define his default executor himself and use the `at_thread_entry ` member function to set the default constructor. +The user can always define his default executor himself. - thread_local default_executor_state_type default_executor_state; - executor* default_executor() { return default_executor_state.default_executor(); } - - // in main - MyDefaultExecutor myDefaultExecutor( - // at_thread_entry - [](MyDefaultExecutor& ex) { - default_executor_state.set_default_executor(ex); - } - ); - - basic_thread_pool pool( - // at_thread_entry - [&myDefaultExecutor](basic_thread_pool& pool) { - default_executor_state.set_default_executor(myDefaultExecutor); - } - ); + boost::generic_executor_ref default_executor() + { + static boost::basic_thread_pool tp(4); + return generic_executor_ref(tp); + } [endsect] + [/////////////////////] [section:ref Reference] diff --git a/doc/changes.qbk b/doc/changes.qbk index a5ce8496..e158388b 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -14,40 +14,39 @@ * [@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/9311 #9311] ex_lambda_future fails on msvc-11.0 -* [@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/10942 #10942] Boost.Thread fails to build on Cygwin. + +[/ +* [@http://svn.boost.org/trac/boost/ticket/7319 #7319] Take care of c++std-lib-32966 issue * [@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. -Please take a look at [@http://www.boost.org/development/tests/master/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 regression test 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 ( [@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 +* [@http://svn.boost.org/trac/boost/ticket/11048 #11048] Add a serial_executor based on continuations [*Fixed Bugs:] - +* [@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/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. @@ -55,9 +54,13 @@ There are some severe bugs that prevent the use of the library on concrete conte * [@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>::then Has No Implementation * [@http://svn.boost.org/trac/boost/ticket/10964 #10964] future>::unwrap().then() Deadlocks +* [@http://svn.boost.org/trac/boost/ticket/10968 #10968] The futures returned by async() and future::then() are not blocking. * [@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 +* [@http://svn.boost.org/trac/boost/ticket/10996 #10996] Thread physical_concurrency() is failing on Windows +* [@http://svn.boost.org/trac/boost/ticket/11035 #11035] BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE not defined for Android +* [@http://svn.boost.org/trac/boost/ticket/11053 #11053] The attached code results in a R6025 - pure virtual function call in run_thread_exit_callbacks [heading Version 4.4.0 - boost 1.57] @@ -76,6 +79,7 @@ There are some severe bugs that prevent the use of the library on concrete conte * [@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. diff --git a/doc/compliance.qbk b/doc/compliance.qbk index 6846f54c..06e4ca82 100644 --- a/doc/compliance.qbk +++ b/doc/compliance.qbk @@ -1,13 +1,15 @@ [/ - (C) Copyright 2011-2013 Vicente J. Botet Escriba. + (C) Copyright 2011-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). ] [section:compliance Conformance and Extension] +[////////////////////////////////////////////] [section:cpp11 C++11 standard Thread library] +[///////////////////////////////////////////] [note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3376.html C++11 - Standard for Programming Language C++]]] @@ -88,6 +90,7 @@ ] [endsect] [section:cxx14 C++14 standard Thread library - accepted changes] +[//////////////////////////////////////////////////////////////] [note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3797.html Working Draft, Standard for Programming Language C++]] @@ -103,6 +106,7 @@ [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]] @@ -126,8 +130,10 @@ [endsect] [section:cxx1y C++1z TS Concurrency - On going proposals] +[///////////////////////////////////////////////////////] [section:latch C++ Latches and Barriers] +[//////////////////////////////////////] [note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3600.html N3600 C++ Latches and Barriers]] [note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3817.html N3817 C++ Latches and Barriers]] @@ -140,6 +146,7 @@ [endsect] [section:queue C++ Concurrent Queues] +[///////////////////////////////////] [note [@ http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3533.html N3533 C++ Concurrent Queues]] @@ -183,24 +190,25 @@ [[X.3.4] [Managed Indirection] [No] [ - ]] ] [endsect] -[section:executors Asynchronous Executors] +[section:executors Executors and Schedulers] +[//////////////////////////////////////////] [note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3785.pdf N3785 Executors and Schedulers]] -[table Asynchronous Executors +[table Executors and Schedulers [[Section] [Description] [Status] [Comments]] - [[V.1.1] [Class executor] [Yes] [ - ]] - [[V.1.1] [add] [Yes] [ renamed with a function template submit ]] - [[V.1.1] [num_of_pendin_closures] [No] [ ]] + [[V.1.1] [Class `executor`] [Yes] [ - ]] + [[V.1.1] [`add`] [Yes] [ renamed with a function template `submit` ]] + [[V.1.1] [`num_of_pendin_closures`] [No] [ ]] [[V.1.2] [Class sceduled_executor] [No] [ - ]] - [[V.1.2] [add_at] [No] [ renamed with a function template submit_at ]] - [[V.1.2] [add_after] [No] [ renamed with a function template submit_after ]] + [[V.1.2] [`add_at`] [No] [ renamed with a function template `scheduler::submit_at` ]] + [[V.1.2] [`add_after`] [No] [ renamed with a function template `scheduler::submit_after` ]] [[V.2] [Concrete executor classes] [No] [ - ]] - [[V.2.1] [thread_pool] [Yes] [ static version Basic_thread_pool, dynamic one execduler_adaptor ]] - [[V.2.2] [serial_executor] [yes] [ - ]] - [[V.2.3] [loop_executor] [Yes] [ static version loop_scheduler, dynamic one execduler_adaptor ]] - [[V.2.4] [inline_executor] [Yes] [ static version inline_executor, dynamic one execduler_adaptor ]] - [[V.2.5] [thread_executor] [Yes] [ static version thread_executor, dynamic one execduler_adaptor ]] + [[V.2.1] [`thread_pool`] [Yes] [ static version `basic_thread_pool`, dynamic one `execduler_adaptor` ]] + [[V.2.2] [`serial_executor`] [yes] [ - ]] + [[V.2.3] [`loop_executor`] [Yes] [ static version loop_scheduler, dynamic one `execduler_adaptor` ]] + [[V.2.4] [`inline_executor`] [Yes] [ static version `inline_executor`, dynamic one `execduler_adaptor` ]] + [[V.2.5] [`thread_executor`] [Yes] [ static version `thread_executor`, dynamic one `execduler_adaptor` ]] ] [note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3784.pdf N3784-Improvements to `std::future and Related APIs]] @@ -212,8 +220,31 @@ [[30.6.8] [`async`] [Yes] [ - ]] ] +[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4143.pdf N4143-Executors and schedulers, revision 4]] + +[table Executors and Schedulers - revision 4 + [[Section] [Description] [Status] [Comments]] + [[VI.A] [Executor Concept] [Yes] [ `wrapper_type` renamed by `work` and `spawn by `submit` ]] + [[VI.A.1] [`thread_per_task_executor] [Yes] [ renamed `thread_executor`]] + [[VI.A.2] [`thread_pool_executor`] [Yes] [ renamed `basic_thread_pool`]] + [[VI.A.3] [`system_executor`] [No] [ - ]] + [[VI.A.4] [`loop_executor`] [Yes] [ - ]] + [[VI.A.5] [`serial_executor`] [yes] [ - ]] + [[VI.B] [`executor_ref`] [yes] [ - ]] + [[VI.C] [`executor`] [yes] [ renamed `gen_executor_ref` ]] + [[VI.D] [Free Functions and Helper Objects] [partial] [ - ]] + [[VI.D] [`make_package`] [No] [ - ]] + [[VI.D] [`spawn_future`] [No] [ `async(Ex&, ...)` is similar but returns a blocking future. ]] + [[VI.D] [`spawn`] [No] [ - ]] + [[VI.D] [`task_wrapper`] [No] [ renamed `resubmitter` ]] + [[VI.D] [`set_executor`] [No] [ renamed `resubmit` ]] + [[VI.D] [`function_wrapper`] [Partial] [ renamed `work` ]] +] + [endsect] +[////////////////////////////////////////////////////////////// [section:stream_mutex C++ Stream Mutexes - C++ Stream Guards] +[/////////////////////////////////////////////////////////////] While Boost.Thread implementation of stream mutexes differ in the approach, it is worth comparing with the current trend on the standard. @@ -241,7 +272,7 @@ While Boost.Thread implementation of stream mutexes differ in the approach, it i [endsect] - +///////////////////////////////] [endsect] [endsect] diff --git a/doc/external_locking.qbk b/doc/external_locking.qbk index a485f363..9c7b1ee4 100644 --- a/doc/external_locking.qbk +++ b/doc/external_locking.qbk @@ -98,7 +98,7 @@ or inheriting from a class which add these lockable functions. The `basic_lockable_adapter` class helps to define the `BankAccount` class as class BankAccount - : public basic_lockable_adapter + : public basic_lockable_adapter { int balance_; public: @@ -138,7 +138,7 @@ Notice that now acct is being locked by Withdraw after it has already been locke As `boost::mutex` is not recursive, we need to use its recursive version `boost::recursive_mutex`. class BankAccount - : public basic_lockable_adapter + : public basic_lockable_adapter { // ... @@ -147,7 +147,7 @@ As `boost::mutex` is not recursive, we need to use its recursive version `boost: The caller-ensured locking approach is more flexible and the most efficient, but very dangerous. In an implementation using caller-ensured locking, BankAccount still holds a mutex, but its member functions don't manipulate it at all. Deposit and Withdraw are not thread-safe anymore. Instead, the client code is responsible for locking BankAccount properly. class BankAccount - : public basic_lockable_adapter { + : public basic_lockable_adapter { int balance_; public: void Deposit(int amount) { @@ -271,7 +271,7 @@ Now that we have such a strict `strict_lock`, how do we harness its power in def A little code is worth 1,000 words, a (hacked into) saying goes, so here's the new BankAccount class: class BankAccount - : public basic_lockable_adapter + : public basic_lockable_adapter { int balance_; public: @@ -280,7 +280,7 @@ A little code is worth 1,000 words, a (hacked into) saying goes, so here's the n balance_ += amount; } void Deposit(int amount) { - strict_lock guard(*this); // Internally locked + strict_lock guard(*this); // Internally locked Deposit(amount, guard); } void Withdraw(int amount, strict_lock&) { @@ -288,7 +288,7 @@ A little code is worth 1,000 words, a (hacked into) saying goes, so here's the n balance_ -= amount; } void Withdraw(int amount) { - strict_lock guard(*this); // Internally locked + strict_lock guard(*this); // Internally locked Withdraw(amount, guard); } }; @@ -327,7 +327,7 @@ The scheme is useful because the likelihood of a programmer forgetting about any Using `strict_lock` permits compile-time checking of the most common source of errors, and runtime checking of the less frequent problem. Let's see how to enforce that the appropriate BankAccount object is locked. First, we need to add a member function to the `strict_lock` class template. -The `bool strict_lock::owns_lock(Loclable*)` function returns a reference to the locked object. +The `bool strict_lock::owns_lock(Lockable*)` function returns a reference to the locked object. template class strict_lock { ... as before ... @@ -338,7 +338,7 @@ The `bool strict_lock::owns_lock(Loclable*)` function returns a reference to Second, BankAccount needs to use this function compare the locked object against this: class BankAccount { - : public basic_lockable_adapter + : public basic_lockable_adapter int balance_; public: void Deposit(int amount, strict_lock& guard) { @@ -403,7 +403,7 @@ The solution is to use a little bridge template `externally_locked` that control T& get(strict_lock& lock) { #ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED - if (!lock.owns_lock(&lockable_)) throw lock_error(); run time check throw if not locks the same + if (!lock.owns_lock(&lockable_)) throw lock_error(); //run time check throw if not locks the same #endif return obj_; } @@ -421,10 +421,10 @@ The solution is to use a little bridge template `externally_locked` that control Instead of making `checkingAcct_` and `savingsAcct_` of type `BankAccount`, `AccountManager` holds objects of type `externally_locked`: class AccountManager - : public basic_lockable_adapter + : public basic_lockable_adapter { public: - typedef basic_lockable_adapter lockable_base_type; + typedef basic_lockable_adapter lockable_base_type; AccountManager() : checkingAcct_(*this) , savingsAcct_(*this) @@ -498,7 +498,7 @@ Now we need to state that both classes are `strict_lock`s. Well let me show what this `nested_strict_lock` class looks like and the impacts on the `externally_locked` class and the `AccountManager::AMoreComplicatedFunction` function. -First `nested_strict_lock` class will store on a temporary lock the `Locker`, and transfer the lock ownership on the constructor. On destruction it will restore the ownership. Note the use of `lock_traits` and that the `Locker` needs to have a reference to the mutex otherwise and exception is thrown. +First `nested_strict_lock` class will store on a temporary lock the `Locker`, and transfer the lock ownership on the constructor. On destruction it will restore the ownership. Note the use of `lock_traits` and that the `Locker` needs to have a reference to the mutex otherwise an exception is thrown. template class nested_strict_lock @@ -510,7 +510,7 @@ First `nested_strict_lock` class will store on a temporary lock the `Locker`, an nested_strict_lock(Locker& lock) : lock_(lock) // Store reference to locker - , tmp_lock_(lock.move()) // Move ownership to temporaty locker + , tmp_lock_(lock.move()) // Move ownership to temporary locker { #ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED if (tmp_lock_.mutex()==0) { diff --git a/doc/mutex_concepts.qbk b/doc/mutex_concepts.qbk index 78ec5884..825d22c2 100644 --- a/doc/mutex_concepts.qbk +++ b/doc/mutex_concepts.qbk @@ -2664,7 +2664,7 @@ Only the specificities respect to __Lockable are described here. [endsect] [///////////////////////////////] -[section:get2 `get(strict_lock>&)`] +[section:get2 `get(nested_strict_lock&)`] template T& get(nested_strict_lock& lk); @@ -2684,7 +2684,7 @@ Only the specificities respect to __Lockable are described here. [endsect] [///////////////////////////////] -[section:get3 `get(strict_lock>&)`] +[section:get3 `get(Lock&)`] template T& get(Lock& lk); @@ -2826,7 +2826,7 @@ Only the specificities respect to __Lockable are described here. [endsect] [///////////////////////////////] -[section:get2 `get(strict_lock>&)`] +[section:get2 `get(nested_strict_lock&)`] template T& get(nested_strict_lock& lk); @@ -2846,7 +2846,7 @@ Only the specificities respect to __Lockable are described here. [endsect] [///////////////////////////////] -[section:get3 `get(strict_lock>&)`] +[section:get3 `get(Lock&)`] template T& get(Lock& lk); diff --git a/doc/sync_queues_ref.qbk b/doc/sync_queues_ref.qbk index a46f34fc..eba795fc 100644 --- a/doc/sync_queues_ref.qbk +++ b/doc/sync_queues_ref.qbk @@ -181,7 +181,7 @@ where [variablelist -[[Requires:] [Q::value_type is no throw copy movable. This is needed to ensure the exception safety.]] +[[Requires:] [Q::value_type is no throw move constructible. This is needed to ensure the exception safety.]] [[Effects:] [Waits until the queue is not empty and not closed. If the queue is empty and closed throws sync_queue_is_closed. Otherwise pull the element from the queue `q` and moves the pulled element.]] @@ -206,7 +206,7 @@ where [variablelist -[/[Requires:] [Q::value_type is no throw copy movable. This is needed to ensure the exception safety. ]] +[/[Requires:] [Q::value_type is no throw move assignable. This is needed to ensure the exception safety. ]] [[Effects:] [Waits until the queue is not empty and not closed. If the queue is empty and closed throws sync_queue_is_closed. Otherwise pull the element from the queue `q` and moves the pulled element into a shared_ptr.]] @@ -314,7 +314,7 @@ where [variablelist -[[Effects:] [Waits until the queue is not empty and then pull the element from the queue `q` and moves the pulled element into `lve` (this could need an allocation for unbounded queues).]] +[[Effects:] [If the queue is not empty pulls the element from the queue `q` and moves the pulled element into `lve` (this could need an allocation for unbounded queues).]] [[Synchronization:] [Prior pull-like operations on the same object synchronizes with this operation.]] @@ -393,7 +393,7 @@ where [endsect] [/////////////////////////////////////] -[section:nonblocking_push_back_m `s = q.nonblocking_push_back(rve());`] +[section:nonblocking_push_back_m `s = q.nonblocking_push_back(rve);`] [variablelist @@ -427,7 +427,7 @@ where [variablelist -[[Effects:] [Waits until the queue is not empty and then pull the element from the queue `q` and moves the pulled element into `lve` (this could need an allocation for unbounded queues).]] +[[Effects:] [If the queue is not empty pulls the element from the queue `q` and moves the pulled element into `lve` (this could need an allocation for unbounded queues).]] [[Synchronization:] [Prior pull-like operations on the same object synchronizes with this operation.]] @@ -636,12 +636,12 @@ Closed queues add the following valid expressions namespace boost { - template + template class queue_base { public: typedef ValueType value_type; - typedef std::size_t size_type; + typedef SizeType size_type; // Constructors/Assignment/Destructors virtual ~queue_base() {}; @@ -671,7 +671,7 @@ Closed queues add the following valid expressions 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; + virtual queue_op_status wait_pull_front(value_type& elem) = 0; }; } @@ -685,11 +685,11 @@ Closed queues add the following valid expressions namespace boost { template - class queue_adaptor : public queue_base + class queue_adaptor : public queue_base { public: typedef typename Queue::value_type value_type; - typedef std::size_t size_type; + typedef typename Queue::size_type size_type; // Constructors/Assignment/Destructors @@ -1002,13 +1002,13 @@ Closed queues add the following valid expressions namespace boost { - template + template > class sync_queue { public: typedef ValueType value_type; - typedef csbl::deque underlying_queue_type; - typedef std::size_t size_type; + typedef Container underlying_queue_type; + typedef typename Container::size_type size_type; sync_queue(sync_queue const&) = delete; sync_queue& operator=(sync_queue const&) = delete; diff --git a/doc/synchronized_value_ref.qbk b/doc/synchronized_value_ref.qbk index 20b304c8..2826282e 100644 --- a/doc/synchronized_value_ref.qbk +++ b/doc/synchronized_value_ref.qbk @@ -88,9 +88,9 @@ typedef T value_type; typedef Lockable mutex_type; - synchronized_value() noexept(is_nothrow_default_constructible::value); - synchronized_value(T const& other) noexept(is_nothrow_copy_constructible::value); - synchronized_value(T&& other) noexept(is_nothrow_move_constructible::value); + synchronized_value() noexcept(is_nothrow_default_constructible::value); + synchronized_value(T const& other) noexcept(is_nothrow_copy_constructible::value); + synchronized_value(T&& other) noexcept(is_nothrow_move_constructible::value); synchronized_value(synchronized_value const& rhs); synchronized_value(synchronized_value&& other); @@ -129,7 +129,7 @@ [section:constructor `synchronized_value()`] - synchronized_value() noexept(is_nothrow_default_constructible::value); + synchronized_value() noexcept(is_nothrow_default_constructible::value); [variablelist @@ -145,7 +145,7 @@ [section:constructor_vt `synchronized_value(T const&)`] - synchronized_value(T const& other) noexept(is_nothrow_copy_constructible::value); + synchronized_value(T const& other) noexcept(is_nothrow_copy_constructible::value); [variablelist @@ -175,11 +175,11 @@ [section:move_vt `synchronized_value(T&&)`] - synchronized_value(T&& other) noexept(is_nothrow_move_constructible::value); + synchronized_value(T&& other) noexcept(is_nothrow_move_constructible::value); [variablelist -[[Requires:] [`T` is `CopyMovable `.]] +[[Requires:] [`T` is `MoveConstructible `.]] [[Effects:] [Move constructs the cloaked value_type]] [[Throws:] [Any exception thrown by `value_type(value_type&&)`.]] @@ -194,7 +194,7 @@ [variablelist -[[Requires:] [`T` is `CopyMovable `.]] +[[Requires:] [`T` is `MoveConstructible `.]] [[Effects:] [Move constructs the cloaked value_type]] [[Throws:] [Any exception thrown by `value_type(value_type&&)` or `mtx_.lock()`.]] @@ -209,7 +209,7 @@ [variablelist -[[Requires:] [`T` is `Assignale`.]] +[[Requires:] [`T` is `Assignable`.]] [[Effects:] [Copies the underlying value on a scope protected by the two mutexes. The mutex is not copied. The locks are acquired avoiding deadlock. For example, there is no problem if one thread assigns `a = b` and the other assigns `b = a`.]] [[Return:] [`*this`]] @@ -224,7 +224,7 @@ [variablelist -[[Requires:] [`T` is `Assignale`.]] +[[Requires:] [`T` is `Assignable`.]] [[Effects:] [Copies the value on a scope protected by the mutex.]] [[Return:] [`*this`]] @@ -273,7 +273,7 @@ [variablelist -[[Requires:] [`T` is `Assignale`.]] +[[Requires:] [`T` is `Assignable`.]] [[Effects:] [Swaps the data on a scope protected by both mutex. Both mutex are acquired to avoid dead-lock. The mutexes are not swapped.]] [[Throws:] [Any exception thrown by `swap(value_, rhs.value)` or `mtx_.lock()` or `rhs_.mtx_.lock()`.]] diff --git a/doc/thread.qbk b/doc/thread.qbk index efac8747..9605234d 100644 --- a/doc/thread.qbk +++ b/doc/thread.qbk @@ -8,10 +8,10 @@ [library Thread [quickbook 1.5] - [version 4.4.0] + [version 4.5.0] [authors [Williams, Anthony] [Botet Escriba, Vicente J.]] [copyright 2007-11 Anthony Williams] - [copyright 2011-14 Vicente J. Botet Escriba] + [copyright 2011-15 Vicente J. Botet Escriba] [purpose C++ Library for launching threads and synchronizing data between them] [category text] [license diff --git a/example/default_executor.cpp b/example/default_executor.cpp new file mode 100644 index 00000000..ccdb3876 --- /dev/null +++ b/example/default_executor.cpp @@ -0,0 +1,61 @@ +// 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 +#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 +#include +#include +#include +#include + +#include + + +boost::generic_executor_ref default_executor() +{ + static boost::basic_thread_pool tp(4); + return boost::generic_executor_ref(tp); +} + +void p2() +{ + std::cout << BOOST_CONTEXTOF << std::endl; + boost::this_thread::sleep_for(boost::chrono::milliseconds(200)); + std::cout << BOOST_CONTEXTOF << std::endl; +} + + +void p1() +{ + std::cout << BOOST_CONTEXTOF << std::endl; + boost::this_thread::sleep_for(boost::chrono::milliseconds(200)); + default_executor().submit(&p2); + boost::this_thread::sleep_for(boost::chrono::milliseconds(400)); + std::cout << BOOST_CONTEXTOF << std::endl; +} + +int main() +{ + std::cout << BOOST_CONTEXTOF << std::endl; + + default_executor().submit(&p1); + + boost::this_thread::sleep_for(boost::chrono::seconds(5)); + + std::cout << BOOST_CONTEXTOF << std::endl; + + return 1; + +} diff --git a/example/executor.cpp b/example/executor.cpp index 8770d1fb..6cd29eda 100644 --- a/example/executor.cpp +++ b/example/executor.cpp @@ -28,6 +28,10 @@ #include #include +boost::future p(boost::future) { + return boost::make_ready_future(); +} + void p1() { // std::cout << BOOST_CONTEXTOF << std::endl; @@ -191,4 +195,16 @@ int test_executor_adaptor() int main() { return test_executor_adaptor(); + +#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION \ + && defined BOOST_THREAD_PROVIDES_EXECUTORS \ + && ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + + // compiles + boost::make_ready_future().then(&p); + + boost::basic_thread_pool executor; + // doesn't compile + boost::make_ready_future().then(executor, &p); +#endif } diff --git a/example/lambda_future.cpp b/example/lambda_future.cpp index 6df1cee7..fd15d448 100644 --- a/example/lambda_future.cpp +++ b/example/lambda_future.cpp @@ -42,6 +42,14 @@ int main() int result = f2.get(); BOOST_THREAD_LOG << "f2 " << result << BOOST_THREAD_END_LOG; } +#if ! defined BOOST_NO_CXX14_GENERIC_LAMBDAS + { + boost::future f1 = boost::async(boost::launch::async, []() {return 123;}); + boost::future f2 = f1.then([](auto f) {return 2*f.get(); }); + int result = f2.get(); + BOOST_THREAD_LOG << "f2 " << result << BOOST_THREAD_END_LOG; + } +#endif } catch (std::exception& ex) { diff --git a/example/this_executor.cpp b/example/this_executor.cpp new file mode 100644 index 00000000..feeebf85 --- /dev/null +++ b/example/this_executor.cpp @@ -0,0 +1,86 @@ +// 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 +#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_THREAD_ID + +#include +#include +#include +#include +#include +#include +#include + +#include + +struct current_executor_state_type { + boost::shared_ptr current_executor_ptr; + + template + void set_current_executor(Executor& ex) + { + current_executor_ptr = boost::make_shared(ex); + } + boost::generic_executor_ref current_executor() + { + if (current_executor_ptr) + return *current_executor_ptr; + else + throw ""; + } +}; + +thread_local current_executor_state_type current_executor_state; + +boost::generic_executor_ref current_executor() +{ + return current_executor_state.current_executor(); +} + +void p2() +{ + std::cout << BOOST_CONTEXTOF << std::endl; + boost::this_thread::sleep_for(boost::chrono::milliseconds(200)); + std::cout << BOOST_CONTEXTOF << std::endl; +} + + +void p1() +{ + std::cout << BOOST_CONTEXTOF << std::endl; + boost::this_thread::sleep_for(boost::chrono::milliseconds(200)); + current_executor().submit(&p2); + boost::this_thread::sleep_for(boost::chrono::milliseconds(400)); + std::cout << BOOST_CONTEXTOF << std::endl; +} + +int main() +{ + std::cout << BOOST_CONTEXTOF << std::endl; + + boost::basic_thread_pool tp(4, + // at_thread_entry + [](boost::basic_thread_pool& pool) + { + current_executor_state.set_current_executor(pool); + } + ); + + tp.submit(&p1); + + boost::this_thread::sleep_for(boost::chrono::seconds(5)); + + std::cout << BOOST_CONTEXTOF << std::endl; + + return 1; + +} diff --git a/include/boost/thread/concurrent_queues/deque_adaptor.hpp b/include/boost/thread/concurrent_queues/deque_adaptor.hpp index b9f8c950..a8f45f86 100644 --- a/include/boost/thread/concurrent_queues/deque_adaptor.hpp +++ b/include/boost/thread/concurrent_queues/deque_adaptor.hpp @@ -27,12 +27,12 @@ namespace detail template class deque_adaptor_copyable_only : - public boost::deque_base + public boost::deque_base { Queue queue; public: typedef typename Queue::value_type value_type; - typedef std::size_t size_type; + typedef typename Queue::size_type size_type; // Constructors/Assignment/Destructors deque_adaptor_copyable_only() {} @@ -63,12 +63,12 @@ namespace detail }; template class deque_adaptor_movable_only : - public boost::deque_base + public boost::deque_base { Queue queue; public: typedef typename Queue::value_type value_type; - typedef std::size_t size_type; + typedef typename Queue::size_type size_type; // Constructors/Assignment/Destructors @@ -102,12 +102,12 @@ namespace detail template class deque_adaptor_copyable_and_movable : - public boost::deque_base + public boost::deque_base { Queue queue; public: typedef typename Queue::value_type value_type; - typedef std::size_t size_type; + typedef typename Queue::size_type size_type; // Constructors/Assignment/Destructors @@ -195,7 +195,7 @@ namespace detail { public: typedef typename Queue::value_type value_type; - typedef std::size_t size_type; + typedef typename Queue::size_type size_type; // Constructors/Assignment/Destructors virtual ~deque_adaptor() {}; }; diff --git a/include/boost/thread/concurrent_queues/deque_base.hpp b/include/boost/thread/concurrent_queues/deque_base.hpp index 61b256b5..f76e8a76 100644 --- a/include/boost/thread/concurrent_queues/deque_base.hpp +++ b/include/boost/thread/concurrent_queues/deque_base.hpp @@ -27,12 +27,12 @@ namespace concurrent namespace detail { - template + template class deque_base_copyable_only { public: typedef ValueType value_type; - typedef std::size_t size_type; + typedef SizeType size_type; // Constructors/Assignment/Destructors virtual ~deque_base_copyable_only() {}; @@ -58,16 +58,16 @@ namespace detail 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 queue_op_status wait_pull_front(value_type& elem) = 0; }; - template + template class deque_base_movable_only { public: typedef ValueType value_type; - typedef std::size_t size_type; + typedef SizeType size_type; // Constructors/Assignment/Destructors virtual ~deque_base_movable_only() {}; @@ -88,7 +88,7 @@ namespace detail virtual queue_op_status nonblocking_pull_front(value_type&) = 0; - virtual queue_op_status wait_pull_front(ValueType& elem) = 0; + virtual queue_op_status wait_pull_front(value_type& 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; @@ -97,12 +97,12 @@ namespace detail }; - template + template class deque_base_copyable_and_movable { public: typedef ValueType value_type; - typedef std::size_t size_type; + typedef SizeType size_type; // Constructors/Assignment/Destructors virtual ~deque_base_copyable_and_movable() {}; @@ -129,7 +129,7 @@ namespace detail 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 queue_op_status wait_pull_front(value_type& 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; @@ -137,7 +137,7 @@ namespace detail virtual queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0; }; - template struct deque_base; - template - struct deque_base { - typedef deque_base_copyable_and_movable type; + template + struct deque_base { + typedef deque_base_copyable_and_movable type; }; - template - struct deque_base { - typedef deque_base_copyable_only type; + template + struct deque_base { + typedef deque_base_copyable_only type; }; - template - struct deque_base { - typedef deque_base_movable_only type; + template + struct deque_base { + typedef deque_base_movable_only type; }; } - template + template class deque_base : - public detail::deque_base::type + public detail::deque_base::type { public: typedef ValueType value_type; - typedef std::size_t size_type; + typedef SizeType size_type; // Constructors/Assignment/Destructors virtual ~deque_base() {}; }; diff --git a/include/boost/thread/concurrent_queues/detail/sync_deque_base.hpp b/include/boost/thread/concurrent_queues/detail/sync_deque_base.hpp index 0cc8417d..877e1e2e 100644 --- a/include/boost/thread/concurrent_queues/detail/sync_deque_base.hpp +++ b/include/boost/thread/concurrent_queues/detail/sync_deque_base.hpp @@ -37,7 +37,7 @@ namespace detail public: typedef ValueType value_type; typedef Queue underlying_queue_type; - typedef std::size_t size_type; + typedef typename Queue::size_type size_type; typedef queue_op_status op_status; typedef typename chrono::steady_clock clock; diff --git a/include/boost/thread/concurrent_queues/detail/sync_queue_base.hpp b/include/boost/thread/concurrent_queues/detail/sync_queue_base.hpp index 2ca314bf..653e273f 100644 --- a/include/boost/thread/concurrent_queues/detail/sync_queue_base.hpp +++ b/include/boost/thread/concurrent_queues/detail/sync_queue_base.hpp @@ -37,7 +37,7 @@ namespace detail public: typedef ValueType value_type; typedef Queue underlying_queue_type; - typedef std::size_t size_type; + typedef typename Queue::size_type size_type; typedef queue_op_status op_status; typedef typename chrono::steady_clock clock; diff --git a/include/boost/thread/concurrent_queues/queue_adaptor.hpp b/include/boost/thread/concurrent_queues/queue_adaptor.hpp index 8d01bbcd..f04e0354 100644 --- a/include/boost/thread/concurrent_queues/queue_adaptor.hpp +++ b/include/boost/thread/concurrent_queues/queue_adaptor.hpp @@ -27,12 +27,12 @@ namespace detail template class queue_adaptor_copyable_only : - public boost::queue_base + public boost::queue_base { Queue queue; public: typedef typename Queue::value_type value_type; - typedef std::size_t size_type; + typedef typename Queue::size_type size_type; // Constructors/Assignment/Destructors queue_adaptor_copyable_only() {} @@ -63,12 +63,12 @@ namespace detail }; template class queue_adaptor_movable_only : - public boost::queue_base + public boost::queue_base { Queue queue; public: typedef typename Queue::value_type value_type; - typedef std::size_t size_type; + typedef typename Queue::size_type size_type; // Constructors/Assignment/Destructors @@ -102,12 +102,12 @@ namespace detail template class queue_adaptor_copyable_and_movable : - public boost::queue_base + public boost::queue_base { Queue queue; public: typedef typename Queue::value_type value_type; - typedef std::size_t size_type; + typedef typename Queue::size_type size_type; // Constructors/Assignment/Destructors @@ -195,7 +195,7 @@ namespace detail { public: typedef typename Queue::value_type value_type; - typedef std::size_t size_type; + typedef typename Queue::size_type size_type; // Constructors/Assignment/Destructors virtual ~queue_adaptor() {}; }; diff --git a/include/boost/thread/concurrent_queues/queue_base.hpp b/include/boost/thread/concurrent_queues/queue_base.hpp index 3b96c825..0d428391 100755 --- a/include/boost/thread/concurrent_queues/queue_base.hpp +++ b/include/boost/thread/concurrent_queues/queue_base.hpp @@ -27,12 +27,12 @@ namespace concurrent namespace detail { - template + template class queue_base_copyable_only { public: typedef ValueType value_type; - typedef std::size_t size_type; + typedef SizeType size_type; // Constructors/Assignment/Destructors virtual ~queue_base_copyable_only() {}; @@ -62,12 +62,12 @@ namespace detail }; - template + template class queue_base_movable_only { public: typedef ValueType value_type; - typedef std::size_t size_type; + typedef SizeType size_type; // Constructors/Assignment/Destructors virtual ~queue_base_movable_only() {}; @@ -88,7 +88,7 @@ namespace detail virtual queue_op_status nonblocking_pull(value_type&) = 0; - virtual queue_op_status wait_pull(ValueType& elem) = 0; + virtual queue_op_status wait_pull(value_type& elem) = 0; virtual void push(BOOST_THREAD_RV_REF(value_type) x) = 0; virtual queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) = 0; @@ -97,12 +97,12 @@ namespace detail }; - template + template class queue_base_copyable_and_movable { public: typedef ValueType value_type; - typedef std::size_t size_type; + typedef SizeType size_type; // Constructors/Assignment/Destructors virtual ~queue_base_copyable_and_movable() {}; @@ -129,7 +129,7 @@ namespace detail virtual queue_op_status nonblocking_pull(value_type&) = 0; virtual queue_op_status wait_push(const value_type& x) = 0; - virtual queue_op_status wait_pull(ValueType& elem) = 0; + virtual queue_op_status wait_pull(value_type& elem) = 0; virtual void push(BOOST_THREAD_RV_REF(value_type) x) = 0; virtual queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) = 0; @@ -137,7 +137,7 @@ namespace detail virtual queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) = 0; }; - template struct queue_base; - template - struct queue_base { - typedef queue_base_copyable_and_movable type; + template + struct queue_base { + typedef queue_base_copyable_and_movable type; }; - template - struct queue_base { - typedef queue_base_copyable_only type; + template + struct queue_base { + typedef queue_base_copyable_only type; }; - template - struct queue_base { - typedef queue_base_movable_only type; + template + struct queue_base { + typedef queue_base_movable_only type; }; } - template + template class queue_base : - public detail::queue_base::type + public detail::queue_base::type { public: typedef ValueType value_type; - typedef std::size_t size_type; + typedef SizeType size_type; // Constructors/Assignment/Destructors virtual ~queue_base() {}; }; diff --git a/include/boost/thread/concurrent_queues/sync_priority_queue.hpp b/include/boost/thread/concurrent_queues/sync_priority_queue.hpp index b02c6f48..d604faa7 100644 --- a/include/boost/thread/concurrent_queues/sync_priority_queue.hpp +++ b/include/boost/thread/concurrent_queues/sync_priority_queue.hpp @@ -43,12 +43,13 @@ namespace detail { Compare _compare; public: typedef Type value_type; + typedef typename Container::size_type size_type; explicit priority_queue(const Compare& compare = Compare()) : _elements(), _compare(compare) { } - std::size_t size() const + size_type size() const { return _elements.size(); } diff --git a/include/boost/thread/experimental/parallel/v2/task_region.hpp b/include/boost/thread/experimental/parallel/v2/task_region.hpp index 8d1ac085..63aad9b0 100755 --- a/include/boost/thread/experimental/parallel/v2/task_region.hpp +++ b/include/boost/thread/experimental/parallel/v2/task_region.hpp @@ -3,7 +3,7 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Vicente J. Botet Escriba 2014. Distributed under the Boost +// (C) Copyright Vicente J. Botet Escriba 2014-2015. 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) // @@ -50,12 +50,13 @@ BOOST_THREAD_INLINE_NAMESPACE(v2) void handle_task_region_exceptions(exception_list& errors) { try { - boost::rethrow_exception(boost::current_exception()); - //throw boost::current_exception(); + throw; } +#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED catch (task_canceled_exception& ex) { } +#endif catch (exception_list const& el) { for (exception_list::const_iterator it = el.begin(); it != el.end(); ++it) @@ -94,7 +95,7 @@ BOOST_THREAD_INLINE_NAMESPACE(v2) { lock_guard lk(tr.mtx); tr.canceled = true; - handle_task_region_exceptions(tr.exs); + throw; } } }; @@ -123,8 +124,6 @@ BOOST_THREAD_INLINE_NAMESPACE(v2) { wait_for_all(group.begin(), group.end()); - #if ! defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED - for (group_type::iterator it = group.begin(); it != group.end(); ++it) { future& f = *it; @@ -140,11 +139,9 @@ BOOST_THREAD_INLINE_NAMESPACE(v2) } } } - #endif if (exs.size() != 0) { boost::throw_exception(exs); - //throw exs; } } protected: @@ -186,6 +183,7 @@ protected: } #if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED + mutable mutex mtx; bool canceled; #endif #if defined BOOST_THREAD_PROVIDES_EXECUTORS @@ -194,8 +192,6 @@ protected: exception_list exs; typedef csbl::vector > group_type; group_type group; - mutable mutex mtx; - public: BOOST_DELETED_FUNCTION(task_region_handle_gen(const task_region_handle_gen&)) @@ -206,11 +202,12 @@ protected: template void run(BOOST_THREAD_FWD_REF(F) f) { - lock_guard lk(mtx); #if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED - if (canceled) { - boost::throw_exception(task_canceled_exception()); - //throw task_canceled_exception(); + { + lock_guard lk(mtx); + if (canceled) { + boost::throw_exception(task_canceled_exception()); + } } #if defined BOOST_THREAD_PROVIDES_EXECUTORS group.push_back(async(ex, detail::wrapped, F>(*this, forward(f)))); @@ -228,11 +225,12 @@ protected: void wait() { - lock_guard lk(mtx); #if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED - if (canceled) { - boost::throw_exception(task_canceled_exception()); - //throw task_canceled_exception{}; + { + lock_guard lk(mtx); + if (canceled) { + boost::throw_exception(task_canceled_exception()); + } } #endif wait_all(); @@ -276,7 +274,6 @@ protected: } catch (...) { - lock_guard lk(tr.mtx); detail::handle_task_region_exceptions(tr.exs); } tr.wait_all(); @@ -298,7 +295,6 @@ protected: } catch (...) { - lock_guard lk(tr.mtx); detail::handle_task_region_exceptions(tr.exs); } tr.wait_all(); diff --git a/include/boost/thread/future.hpp b/include/boost/thread/future.hpp index efc57b04..28239c4a 100644 --- a/include/boost/thread/future.hpp +++ b/include/boost/thread/future.hpp @@ -1363,6 +1363,28 @@ namespace boost template BOOST_THREAD_FUTURE make_future_deferred_continuation_shared_state(boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); + + template + BOOST_THREAD_FUTURE + make_shared_future_deferred_continuation_shared_state(boost::unique_lock &lock, F f, BOOST_THREAD_FWD_REF(Fp) c); + + template + BOOST_THREAD_FUTURE + make_shared_future_async_continuation_shared_state(boost::unique_lock &lock, F f, BOOST_THREAD_FWD_REF(Fp) c); + + #ifdef BOOST_THREAD_PROVIDES_EXECUTORS + template + BOOST_THREAD_FUTURE + make_future_executor_continuation_shared_state(Ex& ex, boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); + + template + BOOST_THREAD_FUTURE + make_shared_future_executor_continuation_shared_state(Ex& ex, boost::unique_lock &lock, F f, BOOST_THREAD_FWD_REF(Fp) c); + + template + BOOST_THREAD_FUTURE + make_future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f); + #endif #endif #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP template @@ -1372,6 +1394,36 @@ namespace boost make_future_unwrap_shared_state(boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f); #endif } +#if defined(BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY) + template< typename InputIterator> + typename boost::disable_if, + BOOST_THREAD_FUTURE > + >::type + when_all(InputIterator first, InputIterator last); + + inline BOOST_THREAD_FUTURE > when_all(); + + #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template< typename T0, typename ...T> + BOOST_THREAD_FUTURE::type, typename decay::type...> > + when_all(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures); + #endif + + template< typename InputIterator> + typename boost::disable_if, + BOOST_THREAD_FUTURE > + >::type + when_any(InputIterator first, InputIterator last); + + inline BOOST_THREAD_FUTURE > when_any(); + + #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template< typename T0, typename ...T> + BOOST_THREAD_FUTURE::type, typename decay::type...> > + when_any(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures); + #endif +#endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY + template class BOOST_THREAD_FUTURE : public detail::basic_future @@ -1395,6 +1447,28 @@ namespace boost template friend BOOST_THREAD_FUTURE detail::make_future_deferred_continuation_shared_state(boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); + + template + friend BOOST_THREAD_FUTURE + detail::make_shared_future_deferred_continuation_shared_state(boost::unique_lock &lock, F f, BOOST_THREAD_FWD_REF(Fp) c); + + template + friend BOOST_THREAD_FUTURE + detail::make_shared_future_async_continuation_shared_state(boost::unique_lock &lock, F f, BOOST_THREAD_FWD_REF(Fp) c); + + #ifdef BOOST_THREAD_PROVIDES_EXECUTORS + template + friend BOOST_THREAD_FUTURE + detail::make_future_executor_continuation_shared_state(Ex& ex, boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); + + template + friend BOOST_THREAD_FUTURE + detail::make_shared_future_executor_continuation_shared_state(Ex& ex, boost::unique_lock &lock, F f, BOOST_THREAD_FWD_REF(Fp) c); + + template + friend BOOST_THREAD_FUTURE + detail::make_future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f); + #endif #endif #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP template @@ -1403,6 +1477,35 @@ namespace boost friend BOOST_THREAD_FUTURE detail::make_future_unwrap_shared_state(boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f); #endif +#if defined(BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY) + template< typename InputIterator> + friend typename boost::disable_if, + BOOST_THREAD_FUTURE > + >::type + when_all(InputIterator first, InputIterator last); + + //friend inline BOOST_THREAD_FUTURE > when_all(); + + #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template< typename T0, typename ...T> + friend BOOST_THREAD_FUTURE::type, typename decay::type...> > + when_all(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures); + #endif + + template< typename InputIterator> + friend typename boost::disable_if, + BOOST_THREAD_FUTURE > + >::type + when_any(InputIterator first, InputIterator last); + + //friend inline BOOST_THREAD_FUTURE > when_any(); + + #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template< typename T0, typename ...T> + friend BOOST_THREAD_FUTURE::type, typename decay::type...> > + when_any(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures); + #endif +#endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK template friend class packaged_task; // todo check if this works in windows #else @@ -1418,9 +1521,7 @@ namespace boost friend BOOST_THREAD_FUTURE detail::make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f); - typedef typename base_type::move_dest_type move_dest_type; - public: // when_all BOOST_THREAD_FUTURE(future_ptr a_future): base_type(a_future) @@ -1588,7 +1689,7 @@ namespace boost friend class shared_future; friend class promise; - #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION +#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION template friend struct detail::future_async_continuation_shared_state; template @@ -1601,7 +1702,30 @@ namespace boost template friend BOOST_THREAD_FUTURE detail::make_future_deferred_continuation_shared_state(boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); - #endif + + template + friend BOOST_THREAD_FUTURE + detail::make_shared_future_deferred_continuation_shared_state(boost::unique_lock &lock, F f, BOOST_THREAD_FWD_REF(Fp) c); + + template + friend BOOST_THREAD_FUTURE + detail::make_shared_future_async_continuation_shared_state(boost::unique_lock &lock, F f, BOOST_THREAD_FWD_REF(Fp) c); + + #ifdef BOOST_THREAD_PROVIDES_EXECUTORS + template + friend BOOST_THREAD_FUTURE + detail::make_future_executor_continuation_shared_state(Ex& ex, boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); + + template + friend BOOST_THREAD_FUTURE + detail::make_shared_future_executor_continuation_shared_state(Ex& ex, boost::unique_lock &lock, F f, BOOST_THREAD_FWD_REF(Fp) c); + + template + friend BOOST_THREAD_FUTURE + detail::make_future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f); + #endif + +#endif #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP template friend struct detail::future_unwrap_shared_state; @@ -1609,6 +1733,36 @@ namespace boost friend BOOST_THREAD_FUTURE detail::make_future_unwrap_shared_state(boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f); #endif +#if defined(BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY) + template< typename InputIterator> + friend typename boost::disable_if, + BOOST_THREAD_FUTURE > + >::type + when_all(InputIterator first, InputIterator last); + + friend inline BOOST_THREAD_FUTURE > when_all(); + + #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template< typename T0, typename ...T> + friend BOOST_THREAD_FUTURE::type, typename decay::type...> > + when_all(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures); + #endif + + template< typename InputIterator> + friend typename boost::disable_if, + BOOST_THREAD_FUTURE > + >::type + when_any(InputIterator first, InputIterator last); + + friend inline BOOST_THREAD_FUTURE > when_any(); + + #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template< typename T0, typename ...T> + friend BOOST_THREAD_FUTURE::type, typename decay::type...> > + when_any(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures); + #endif +#endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY + #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK template friend class packaged_task; // todo check if this works in windows #else @@ -1630,8 +1784,8 @@ namespace boost base_type(a_future) { } - public: + BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE) typedef future_state::state state; typedef R value_type; // EXTENSION @@ -4892,7 +5046,9 @@ namespace detail make_future_unwrap_shared_state(boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f) { shared_ptr > h(new future_unwrap_shared_state(boost::move(f))); + lock.lock(); h->parent.future_->set_continuation_ptr(h, lock); + lock.unlock(); return BOOST_THREAD_FUTURE(h); } } @@ -4907,6 +5063,7 @@ namespace detail { BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); boost::unique_lock lock(this->future_->mutex); + lock.unlock(); return boost::detail::make_future_unwrap_shared_state >, R2>(lock, boost::move(*this)); } #endif diff --git a/include/boost/thread/pthread/mutex.hpp b/include/boost/thread/pthread/mutex.hpp index c7cf62ac..9ac808b6 100644 --- a/include/boost/thread/pthread/mutex.hpp +++ b/include/boost/thread/pthread/mutex.hpp @@ -1,12 +1,13 @@ #ifndef BOOST_THREAD_PTHREAD_MUTEX_HPP #define BOOST_THREAD_PTHREAD_MUTEX_HPP // (C) Copyright 2007-8 Anthony Williams -// (C) Copyright 2011-2012 Vicente J. Botet Escriba +// (C) Copyright 2011,2012,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 +#include #include #include #include @@ -122,10 +123,12 @@ namespace boost void unlock() { int res = posix::pthread_mutex_unlock(&m); - if (res) - { - boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock")); - } + (void)res; + BOOST_ASSERT(res == 0); +// if (res) +// { +// boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock")); +// } } bool try_lock() @@ -218,10 +221,12 @@ namespace boost void unlock() { int res = posix::pthread_mutex_unlock(&m); - if (res) - { - boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock")); - } + (void)res; + BOOST_ASSERT(res == 0); +// if (res) +// { +// boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock")); +// } } bool try_lock() diff --git a/include/boost/thread/pthread/thread_data.hpp b/include/boost/thread/pthread/thread_data.hpp index 8c22bda5..dc8ba0fb 100644 --- a/include/boost/thread/pthread/thread_data.hpp +++ b/include/boost/thread/pthread/thread_data.hpp @@ -115,8 +115,13 @@ namespace boost boost::detail::thread_exit_callback_node* thread_exit_callbacks; std::map tss_data; +//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + // These data must be at the end so that the access to the other fields doesn't change + // when BOOST_THREAD_PROVIDES_INTERRUPTIONS is defined. + // Another option is to have them always pthread_mutex_t* cond_mutex; pthread_cond_t* current_cond; +//#endif typedef std::vector //, hidden_allocator > > notify_list_t; @@ -136,8 +141,10 @@ namespace boost thread_handle(0), done(false),join_started(false),joined(false), thread_exit_callbacks(0), +//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS cond_mutex(0), current_cond(0), +//#endif notify(), async_states_() //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS diff --git a/include/boost/thread/win32/thread_primitives.hpp b/include/boost/thread/win32/thread_primitives.hpp index d9f63e6c..d0d4f0ae 100644 --- a/include/boost/thread/win32/thread_primitives.hpp +++ b/include/boost/thread/win32/thread_primitives.hpp @@ -35,6 +35,7 @@ namespace boost typedef HANDLE handle; typedef SYSTEM_INFO system_info; typedef unsigned __int64 ticks_type; + typedef FARPROC farproc_t; unsigned const infinite=INFINITE; unsigned const timeout=WAIT_TIMEOUT; handle const invalid_handle_value=INVALID_HANDLE_VALUE; @@ -58,17 +59,20 @@ namespace boost using ::CreateSemaphoreExW; # endif using ::OpenEventW; + using ::GetModuleGandleW; # else using ::CreateMutexA; using ::CreateEventA; using ::OpenEventA; using ::CreateSemaphoreA; + using ::GetModuleHandleA; # endif #if BOOST_PLAT_WINDOWS_RUNTIME using ::GetNativeSystemInfo; using ::GetTickCount64; #else using ::GetSystemInfo; + using ::GetTickCount; #endif using ::CloseHandle; using ::ReleaseMutex; @@ -86,6 +90,7 @@ namespace boost using ::SleepEx; using ::Sleep; using ::QueueUserAPC; + using ::GetProcAddress; #endif } } @@ -135,6 +140,7 @@ namespace boost typedef void* handle; typedef _SYSTEM_INFO system_info; typedef unsigned __int64 ticks_type; + typedef int (__stdcall *farproc_t)(); unsigned const infinite=~0U; unsigned const timeout=258U; handle const invalid_handle_value=(handle)(-1); @@ -160,17 +166,20 @@ namespace boost __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*); + __declspec(dllimport) void* __stdcall GetModuleHandleW(wchar_t const*); # else __declspec(dllimport) void* __stdcall CreateMutexA(_SECURITY_ATTRIBUTES*,int,char const*); __declspec(dllimport) void* __stdcall CreateSemaphoreA(_SECURITY_ATTRIBUTES*,long,long,char const*); __declspec(dllimport) void* __stdcall CreateEventA(_SECURITY_ATTRIBUTES*,int,int,char const*); __declspec(dllimport) void* __stdcall OpenEventA(unsigned long,int,char const*); + __declspec(dllimport) void* __stdcall GetModuleHandleA(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*); + __declspec(dllimport) unsigned long __stdcall GetTickCount(); #endif __declspec(dllimport) int __stdcall CloseHandle(void*); __declspec(dllimport) int __stdcall ReleaseMutex(void*); @@ -183,6 +192,7 @@ namespace boost __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); + __declspec(dllimport) farproc_t __stdcall GetProcAddress(void *, const char *); #endif # ifndef UNDER_CE @@ -216,17 +226,10 @@ namespace boost { namespace win32 { - namespace detail { typedef int (__stdcall *farproc_t)(); typedef ticks_type (__stdcall *gettickcount64_t)(); } + namespace detail { typedef ticks_type (__stdcall *gettickcount64_t)(); } #if !BOOST_PLAT_WINDOWS_RUNTIME extern "C" { - __declspec(dllimport) detail::farproc_t __stdcall GetProcAddress(void *, const char *); -#if !defined(BOOST_NO_ANSI_APIS) - __declspec(dllimport) void * __stdcall GetModuleHandleA(const char *); -#else - __declspec(dllimport) void * __stdcall GetModuleHandleW(const wchar_t *); -#endif - __declspec(dllimport) unsigned long __stdcall GetTickCount(); #ifdef _MSC_VER long _InterlockedCompareExchange(long volatile *, long, long); #pragma intrinsic(_InterlockedCompareExchange) @@ -285,6 +288,7 @@ namespace boost // Oops, we weren't called often enough, we're stuck return 0xFFFFFFFF; } +#else #endif inline detail::gettickcount64_t GetTickCount64_() { @@ -297,7 +301,7 @@ namespace boost #if BOOST_PLAT_WINDOWS_RUNTIME gettickcount64impl = &GetTickCount64; #else - detail::farproc_t addr=GetProcAddress( + farproc_t addr=GetProcAddress( #if !defined(BOOST_NO_ANSI_APIS) GetModuleHandleA("KERNEL32.DLL"), #else diff --git a/src/pthread/thread.cpp b/src/pthread/thread.cpp index 75969f72..bbd25493 100644 --- a/src/pthread/thread.cpp +++ b/src/pthread/thread.cpp @@ -159,7 +159,7 @@ namespace boost static void* thread_proxy(void* param) { boost::detail::thread_data_ptr thread_info = static_cast(param)->self; - thread_info->self.reset(); + //thread_info->self.reset(); detail::set_current_thread_data(thread_info.get()); #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS BOOST_TRY diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 511d61e4..7d3c9bfe 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -953,6 +953,8 @@ rule thread-compile ( sources : reqs * : name ) explicit ts_ ; test-suite ts_ : + [ thread-run2 ../example/this_executor.cpp : ex_this_executor ] + [ thread-run2 ../example/default_executor.cpp : ex_default_executor ] ; } diff --git a/test/experimental/parallel/v2/task_region_pass.cpp b/test/experimental/parallel/v2/task_region_pass.cpp index 3ecb4fbc..814ef28e 100644 --- a/test/experimental/parallel/v2/task_region_pass.cpp +++ b/test/experimental/parallel/v2/task_region_pass.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Vicente J. Botet Escriba +// Copyright (C) 2014-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) @@ -132,7 +132,9 @@ void run_exception_1() { std::cout << "task3" << std::endl; }); +#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED BOOST_TEST(false); +#endif }); BOOST_TEST(false); } diff --git a/test/sync/futures/future/get_or_pass.cpp b/test/sync/futures/future/get_or_pass.cpp index a2bd6522..64409455 100644 --- a/test/sync/futures/future/get_or_pass.cpp +++ b/test/sync/futures/future/get_or_pass.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #if defined BOOST_THREAD_USES_CHRONO @@ -128,49 +129,49 @@ int main() BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; } } -// BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; -// { -// typedef int& T; -// { -// boost::promise p; -// boost::future f = p.get_future(); -//#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) -// boost::thread(func3, boost::move(p)).detach(); -//#else -// int j=5; -// p.set_value(j); -//#endif -// BOOST_TEST(f.valid()); -// int k=4; -// BOOST_TEST(f.get_or(k) == 5); -//#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET -// BOOST_TEST(!f.valid()); -//#endif -// } -// BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; -// { -// boost::promise p; -// boost::future f = p.get_future(); -//#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) -// boost::thread(func4, boost::move(p)).detach(); -//#else -// p.set_exception(boost::make_exception_ptr(3.5)); -//#endif -// try -// { -// BOOST_TEST(f.valid()); -// int j=4; -// BOOST_TEST(f.get_or(j) == 4); -// } -// catch (...) -// { -// BOOST_TEST(false); -// } -//#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET -// BOOST_TEST(!f.valid()); -//#endif -// } -// } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + typedef int& T; + { + boost::promise p; + boost::future f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func3, boost::move(p)).detach(); +#else + int j=5; + p.set_value(j); +#endif + BOOST_TEST(f.valid()); + int k=4; + BOOST_TEST(f.get_or(boost::ref(k)) == 5); +#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + BOOST_TEST(!f.valid()); +#endif + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::promise p; + boost::future f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func4, boost::move(p)).detach(); +#else + p.set_exception(boost::make_exception_ptr(3.5)); +#endif + try + { + BOOST_TEST(f.valid()); + int j=4; + BOOST_TEST(f.get_or(boost::ref(j)) == 4); + } + catch (...) + { + BOOST_TEST(false); + } +#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + BOOST_TEST(!f.valid()); +#endif + } + } BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; diff --git a/test/sync/futures/when_all/iterators_pass.cpp b/test/sync/futures/when_all/iterators_pass.cpp index 2316a8d1..cebf4192 100644 --- a/test/sync/futures/when_all/iterators_pass.cpp +++ b/test/sync/futures/when_all/iterators_pass.cpp @@ -281,7 +281,7 @@ int main() BOOST_TEST(res[1].is_ready()); BOOST_TEST(res[1].get() == 321); } -#if ! defined BOOST_NO_CXX11_DECLTYPE_N3276 +#if defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD // fixme darwin-4.8.0_11 terminate called without an active exception { // deferred future copy-constructible boost::future f1 = boost::async(boost::launch::deferred, &p1); diff --git a/test/sync/futures/when_all/one_pass.cpp b/test/sync/futures/when_all/one_pass.cpp index 437d3ea5..a39e638e 100644 --- a/test/sync/futures/when_all/one_pass.cpp +++ b/test/sync/futures/when_all/one_pass.cpp @@ -152,7 +152,7 @@ int main() 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 +#if defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD // fixme darwin-4.8.0_11 terminate called without an active exception { // deferred future copy-constructible boost::future f1 = boost::async(boost::launch::deferred, &p1); diff --git a/test/sync/futures/when_all/variadic_pass.cpp b/test/sync/futures/when_all/variadic_pass.cpp index 4d34e6f8..1c864c59 100644 --- a/test/sync/futures/when_all/variadic_pass.cpp +++ b/test/sync/futures/when_all/variadic_pass.cpp @@ -236,7 +236,7 @@ int main() 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 +#if defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD // fixme darwin-4.8.0_11 terminate called without an active exception { // deferred future copy-constructible boost::future f1 = boost::async(boost::launch::deferred, &p1); diff --git a/test/sync/futures/when_any/iterators_pass.cpp b/test/sync/futures/when_any/iterators_pass.cpp index 21e2a0ef..75a30cc4 100644 --- a/test/sync/futures/when_any/iterators_pass.cpp +++ b/test/sync/futures/when_any/iterators_pass.cpp @@ -283,7 +283,7 @@ int main() BOOST_TEST(res[1].is_ready()); BOOST_TEST(res[1].get() == 321); } -#if ! defined BOOST_NO_CXX11_DECLTYPE_N3276 +#if defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD // fixme darwin-4.8.0_11 terminate called without an active exception { // deferred future copy-constructible boost::future f1 = boost::async(boost::launch::deferred, &p1); diff --git a/test/sync/futures/when_any/one_pass.cpp b/test/sync/futures/when_any/one_pass.cpp index 50f5dab5..f54d8376 100644 --- a/test/sync/futures/when_any/one_pass.cpp +++ b/test/sync/futures/when_any/one_pass.cpp @@ -125,7 +125,7 @@ int main() 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 +#if defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD // fixme darwin-4.8.0_11 terminate called without an active exception { // deferred future copy-constructible boost::future f1 = boost::async(boost::launch::deferred, &p1); diff --git a/test/sync/futures/when_any/variadic_pass.cpp b/test/sync/futures/when_any/variadic_pass.cpp index e59b3a79..cee81ef1 100644 --- a/test/sync/futures/when_any/variadic_pass.cpp +++ b/test/sync/futures/when_any/variadic_pass.cpp @@ -225,7 +225,7 @@ int main() 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 +#if defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD // fixme darwin-4.8.0_11 terminate called without an active exception { // deferred future copy-constructible boost::future f1 = boost::async(boost::launch::deferred, &p1); diff --git a/test/sync/mutual_exclusion/deque_views/single_thread_pass.cpp b/test/sync/mutual_exclusion/deque_views/single_thread_pass.cpp index 96e8e268..ec310192 100644 --- a/test/sync/mutual_exclusion/deque_views/single_thread_pass.cpp +++ b/test/sync/mutual_exclusion/deque_views/single_thread_pass.cpp @@ -21,9 +21,9 @@ class non_copyable { - BOOST_THREAD_MOVABLE_ONLY(non_copyable) int val; public: + BOOST_THREAD_MOVABLE_ONLY(non_copyable) 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; } diff --git a/test/sync/mutual_exclusion/queue_views/single_thread_pass.cpp b/test/sync/mutual_exclusion/queue_views/single_thread_pass.cpp index 41cf1cf3..d40c1157 100644 --- a/test/sync/mutual_exclusion/queue_views/single_thread_pass.cpp +++ b/test/sync/mutual_exclusion/queue_views/single_thread_pass.cpp @@ -21,9 +21,9 @@ class non_copyable { - BOOST_THREAD_MOVABLE_ONLY(non_copyable) int val; public: + BOOST_THREAD_MOVABLE_ONLY(non_copyable) 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; }