2
0
mirror of https://github.com/boostorg/thread.git synced 2026-02-07 23:02:13 +00:00

Compare commits

..

33 Commits

Author SHA1 Message Date
Vicente J. Botet Escriba
0f6a3ebbe5 Merge branch 'develop' 2015-03-21 15:44:02 +01:00
Vicente J. Botet Escriba
a5c34e7be2 update version and copyright. 2015-03-21 15:43:04 +01:00
Vicente J. Botet Escriba
287100119a Merge branch 'develop' 2015-03-17 03:16:35 +01:00
Vicente J. Botet Escriba
ba2f814342 Don't lock while storing the exception_ptr list as only the task_region thread can do it. 2015-03-16 08:41:04 +01:00
Vicente J. Botet Escriba
5169a5414b mutex::unlock must not throw. 2015-03-14 16:26:35 +01:00
Vicente J. Botet Escriba
82b9a4e28c Use coherently size_type. 2015-03-12 04:09:34 +01:00
Vicente J. Botet Escriba
e989d2f626 Add comments. 2015-03-12 04:08:42 +01:00
Vicente J. Botet Escriba
331f0b9325 Added test for future<T&>::get_or. 2015-03-10 07:54:09 +01:00
Vicente J. Botet Escriba
ec6a1fcf80 try to get rid of data race. 2015-03-10 00:48:12 +01:00
Vicente J. Botet Escriba
dcebe26a11 try to get rid of possible deadlock. 2015-03-10 00:47:38 +01:00
Vicente J. Botet Escriba
d7721940f3 update history. 2015-03-09 23:17:35 +01:00
Vicente J. Botet Escriba
b678edb0d8 update history. 2015-03-08 23:31:37 +01:00
Vicente J. Botet Escriba
1371728e02 Merge pull request #50 from wmamrak/develop
Fixed some documentation bugs.
2015-03-06 00:11:52 +01:00
Wojciech Mamrak
17d802db81 Fixed documentation bugs. 2015-03-05 13:22:04 +01:00
Wojciech Mamrak
9fc06a8741 Fixed documentation bugs. 2015-03-05 12:37:10 +01:00
Wojciech Mamrak
946fac633e Fixed documentation bugs. 2015-03-04 12:22:33 +01:00
Wojciech Mamrak
af1c7d0c26 Fixed documentation bugs. 2015-03-03 19:03:18 +01:00
Vicente J. Botet Escriba
d9594e7fc8 Merge branch 'develop' 2015-03-01 18:54:42 +01:00
Vicente J. Botet Escriba
0653efff3d Added this_executor and default_executor examples. 2015-03-01 18:53:11 +01:00
Vicente J. Botet Escriba
566199e49b Added this_executor and default_executor examples. 2015-03-01 18:37:16 +01:00
Vicente J. Botet Escriba
c7bb6fa318 Allow timed and recursive mutex on ANDROID. Related to #11035. 2015-03-01 01:37:45 +01:00
Vicente J. Botet Escriba
c678b3794b Crash issue while calling run_thread_exit_callbacks. Related to #11053. 2015-03-01 01:37:35 +01:00
Vicente J. Botet Escriba
e0ce8af1d9 cleanup work.hpp 2015-02-28 12:39:03 +01:00
Vicente J. Botet Escriba
c54dbe30a2 move the work parameter. 2015-02-28 12:37:27 +01:00
Vicente J. Botet Escriba
b8763b05ad Add missing push(movable&&) and Run some failing tests that work when BOOST_NO_CXX11_RVALUE_REFERENCES is not defined. 2015-02-28 12:35:42 +01:00
Vicente J. Botet Escriba
3755af2063 Run some failing tests that work when BOOST_NO_CXX11_RVALUE_REFERENCES is not defined. 2015-02-28 12:35:23 +01:00
Vicente J. Botet Escriba
41172e4814 fix missing include in caller_context.hpp and let the possibility to dump function at compile time. 2015-02-28 12:33:46 +01:00
Vicente J. Botet Escriba
25310eaf7c make use of nullary_function<void()> as work for timed schedulers (priority_queue) on C++11. 2015-02-22 23:44:34 +01:00
Vicente J. Botet Escriba
55f9563f60 Merge branch 'fix/blocking_future' into develop 2015-02-20 16:36:18 +01:00
Vicente J. Botet Escriba
83ced837fa rollback nullary_function specialization as is the cause of compile failures. 2015-02-20 15:33:26 +01:00
Vicente J. Botet Escriba
ce2b2801d6 Merge branch 'fix/blocking_future' into develop 2015-02-20 14:37:10 +01:00
Vicente J. Botet Escriba
855e56076b Merge branch 'develop' 2015-02-19 08:59:18 +01:00
Vicente J. Botet Escriba
3c6a183aa3 Merge branch 'develop' 2015-02-08 18:19:07 +01:00
36 changed files with 544 additions and 301 deletions

View File

@@ -319,33 +319,23 @@ The reason is that the user can always use a thread_local variable and reset it
} }
); );
[
[heading Default executor] [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 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; boost::generic_executor_ref default_executor()
executor* default_executor() { return default_executor_state.default_executor(); } {
static boost::basic_thread_pool tp(4);
// in main return generic_executor_ref(tp);
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);
}
);
[endsect] [endsect]
[/////////////////////] [/////////////////////]
[section:ref Reference] [section:ref Reference]

View File

@@ -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/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/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/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/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/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/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/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/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/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 [@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:] [*Sever limitations:]
There are some severe bugs that prevent the use of the library on concrete contexts, in particular: 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], ), * 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:] [*New Experimental Features:]
* [@http://svn.boost.org/trac/boost/ticket/9600 #9600] Async: Add task_region * [@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/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/10826 #10826] Add scheduled executor operations
* [@http://svn.boost.org/trac/boost/ticket/11048 #11048] Add a serial_executor based on continuations
[*Fixed Bugs:] [*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/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/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/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/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/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/10964 #10964] future<future<T>>::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/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/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> * [@http://svn.boost.org/trac/boost/ticket/10979 #10979] Support T& type deduction when the make_ready_future parameter is reference_wrapper<T>
* [@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] [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/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/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 [@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 snapshot.

View File

@@ -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 The `basic_lockable_adapter` class helps to define the `BankAccount` class as
class BankAccount class BankAccount
: public basic_lockable_adapter<thread_mutex> : public basic_lockable_adapter<boost::mutex>
{ {
int balance_; int balance_;
public: 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`. As `boost::mutex` is not recursive, we need to use its recursive version `boost::recursive_mutex`.
class BankAccount class BankAccount
: public basic_lockable_adapter<recursive_mutex> : public basic_lockable_adapter<boost::recursive_mutex>
{ {
// ... // ...
@@ -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. 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 class BankAccount
: public basic_lockable_adapter<boost:mutex> { : public basic_lockable_adapter<boost::mutex> {
int balance_; int balance_;
public: public:
void Deposit(int amount) { 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: A little code is worth 1,000 words, a (hacked into) saying goes, so here's the new BankAccount class:
class BankAccount class BankAccount
: public basic_lockable_adapter<boost:recursive_mutex> : public basic_lockable_adapter<boost::mutex>
{ {
int balance_; int balance_;
public: 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; balance_ += amount;
} }
void Deposit(int amount) { void Deposit(int amount) {
strict_lock<boost:mutex> guard(*this); // Internally locked strict_lock<BankAccount> guard(*this); // Internally locked
Deposit(amount, guard); Deposit(amount, guard);
} }
void Withdraw(int amount, strict_lock<BankAccount>&) { void Withdraw(int amount, strict_lock<BankAccount>&) {
@@ -288,7 +288,7 @@ A little code is worth 1,000 words, a (hacked into) saying goes, so here's the n
balance_ -= amount; balance_ -= amount;
} }
void Withdraw(int amount) { void Withdraw(int amount) {
strict_lock<boost:mutex> guard(*this); // Internally locked strict_lock<BankAccount> guard(*this); // Internally locked
Withdraw(amount, guard); 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. 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. 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<T>::owns_lock(Loclable*)` function returns a reference to the locked object. The `bool strict_lock<T>::owns_lock(Lockable*)` function returns a reference to the locked object.
template <class Lockable> class strict_lock { template <class Lockable> class strict_lock {
... as before ... ... as before ...
@@ -338,7 +338,7 @@ The `bool strict_lock<T>::owns_lock(Loclable*)` function returns a reference to
Second, BankAccount needs to use this function compare the locked object against this: Second, BankAccount needs to use this function compare the locked object against this:
class BankAccount { class BankAccount {
: public basic_lockable_adapter<boost::recursive_mutex> : public basic_lockable_adapter<boost::mutex>
int balance_; int balance_;
public: public:
void Deposit(int amount, strict_lock<BankAccount>& guard) { void Deposit(int amount, strict_lock<BankAccount>& guard) {
@@ -403,7 +403,7 @@ The solution is to use a little bridge template `externally_locked` that control
T& get(strict_lock<Lockable>& lock) { T& get(strict_lock<Lockable>& lock) {
#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED #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 #endif
return obj_; 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<BankAccount, AccountManager>`: Instead of making `checkingAcct_` and `savingsAcct_` of type `BankAccount`, `AccountManager` holds objects of type `externally_locked<BankAccount, AccountManager>`:
class AccountManager class AccountManager
: public basic_lockable_adapter<thread_mutex> : public basic_lockable_adapter<boost::mutex>
{ {
public: public:
typedef basic_lockable_adapter<thread_mutex> lockable_base_type; typedef basic_lockable_adapter<boost::mutex> lockable_base_type;
AccountManager() AccountManager()
: checkingAcct_(*this) : checkingAcct_(*this)
, savingsAcct_(*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. 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 <typename Locker > template <typename Locker >
class nested_strict_lock 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) nested_strict_lock(Locker& lock)
: lock_(lock) // Store reference to locker : 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 #ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
if (tmp_lock_.mutex()==0) { if (tmp_lock_.mutex()==0) {

View File

@@ -2664,7 +2664,7 @@ Only the specificities respect to __Lockable are described here.
[endsect] [endsect]
[///////////////////////////////] [///////////////////////////////]
[section:get2 `get(strict_lock<nested_strict_lock<Lock>>&)`] [section:get2 `get(nested_strict_lock<Lock>&)`]
template <class Lock> template <class Lock>
T& get(nested_strict_lock<Lock>& lk); T& get(nested_strict_lock<Lock>& lk);
@@ -2684,7 +2684,7 @@ Only the specificities respect to __Lockable are described here.
[endsect] [endsect]
[///////////////////////////////] [///////////////////////////////]
[section:get3 `get(strict_lock<nested_strict_lock<Lock>>&)`] [section:get3 `get(Lock&)`]
template <class Lock> template <class Lock>
T& get(Lock& lk); T& get(Lock& lk);
@@ -2826,7 +2826,7 @@ Only the specificities respect to __Lockable are described here.
[endsect] [endsect]
[///////////////////////////////] [///////////////////////////////]
[section:get2 `get(strict_lock<nested_strict_lock<Lock>>&)`] [section:get2 `get(nested_strict_lock<Lock>&)`]
template <class Lock> template <class Lock>
T& get(nested_strict_lock<Lock>& lk); T& get(nested_strict_lock<Lock>& lk);
@@ -2846,7 +2846,7 @@ Only the specificities respect to __Lockable are described here.
[endsect] [endsect]
[///////////////////////////////] [///////////////////////////////]
[section:get3 `get(strict_lock<nested_strict_lock<Lock>>&)`] [section:get3 `get(Lock&)`]
template <class Lock> template <class Lock>
T& get(Lock& lk); T& get(Lock& lk);

View File

@@ -181,7 +181,7 @@ where
[variablelist [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.]] [[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 [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.]] [[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 [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.]] [[Synchronization:] [Prior pull-like operations on the same object synchronizes with this operation.]]
@@ -393,7 +393,7 @@ where
[endsect] [endsect]
[/////////////////////////////////////] [/////////////////////////////////////]
[section:nonblocking_push_back_m `s = q.nonblocking_push_back(rve());`] [section:nonblocking_push_back_m `s = q.nonblocking_push_back(rve);`]
[variablelist [variablelist
@@ -427,7 +427,7 @@ where
[variablelist [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.]] [[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 namespace boost
{ {
template <typename ValueType> template <typename ValueType, class SizeType=std::size_t>
class queue_base class queue_base
{ {
public: public:
typedef ValueType value_type; typedef ValueType value_type;
typedef std::size_t size_type; typedef SizeType size_type;
// Constructors/Assignment/Destructors // Constructors/Assignment/Destructors
virtual ~queue_base() {}; 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(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_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 namespace boost
{ {
template <typename Queue> template <typename Queue>
class queue_adaptor : public queue_base<typename Queue::value_type> class queue_adaptor : public queue_base<typename Queue::value_type, typename Queue::size_type>
{ {
public: public:
typedef typename Queue::value_type value_type; typedef typename Queue::value_type value_type;
typedef std::size_t size_type; typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors // Constructors/Assignment/Destructors
@@ -1002,13 +1002,13 @@ Closed queues add the following valid expressions
namespace boost namespace boost
{ {
template <typename ValueType> template <typename ValueType, class Container = csbl::devector<ValueType>>
class sync_queue class sync_queue
{ {
public: public:
typedef ValueType value_type; typedef ValueType value_type;
typedef csbl::deque<ValueType> underlying_queue_type; typedef Container underlying_queue_type;
typedef std::size_t size_type; typedef typename Container::size_type size_type;
sync_queue(sync_queue const&) = delete; sync_queue(sync_queue const&) = delete;
sync_queue& operator=(sync_queue const&) = delete; sync_queue& operator=(sync_queue const&) = delete;

View File

@@ -88,9 +88,9 @@
typedef T value_type; typedef T value_type;
typedef Lockable mutex_type; typedef Lockable mutex_type;
synchronized_value() noexept(is_nothrow_default_constructible<T>::value); synchronized_value() noexcept(is_nothrow_default_constructible<T>::value);
synchronized_value(T const& other) noexept(is_nothrow_copy_constructible<T>::value); synchronized_value(T const& other) noexcept(is_nothrow_copy_constructible<T>::value);
synchronized_value(T&& other) noexept(is_nothrow_move_constructible<T>::value); synchronized_value(T&& other) noexcept(is_nothrow_move_constructible<T>::value);
synchronized_value(synchronized_value const& rhs); synchronized_value(synchronized_value const& rhs);
synchronized_value(synchronized_value&& other); synchronized_value(synchronized_value&& other);
@@ -129,7 +129,7 @@
[section:constructor `synchronized_value()`] [section:constructor `synchronized_value()`]
synchronized_value() noexept(is_nothrow_default_constructible<T>::value); synchronized_value() noexcept(is_nothrow_default_constructible<T>::value);
[variablelist [variablelist
@@ -145,7 +145,7 @@
[section:constructor_vt `synchronized_value(T const&)`] [section:constructor_vt `synchronized_value(T const&)`]
synchronized_value(T const& other) noexept(is_nothrow_copy_constructible<T>::value); synchronized_value(T const& other) noexcept(is_nothrow_copy_constructible<T>::value);
[variablelist [variablelist
@@ -175,11 +175,11 @@
[section:move_vt `synchronized_value(T&&)`] [section:move_vt `synchronized_value(T&&)`]
synchronized_value(T&& other) noexept(is_nothrow_move_constructible<T>::value); synchronized_value(T&& other) noexcept(is_nothrow_move_constructible<T>::value);
[variablelist [variablelist
[[Requires:] [`T` is `CopyMovable `.]] [[Requires:] [`T` is `MoveConstructible `.]]
[[Effects:] [Move constructs the cloaked value_type]] [[Effects:] [Move constructs the cloaked value_type]]
[[Throws:] [Any exception thrown by `value_type(value_type&&)`.]] [[Throws:] [Any exception thrown by `value_type(value_type&&)`.]]
@@ -194,7 +194,7 @@
[variablelist [variablelist
[[Requires:] [`T` is `CopyMovable `.]] [[Requires:] [`T` is `MoveConstructible `.]]
[[Effects:] [Move constructs the cloaked value_type]] [[Effects:] [Move constructs the cloaked value_type]]
[[Throws:] [Any exception thrown by `value_type(value_type&&)` or `mtx_.lock()`.]] [[Throws:] [Any exception thrown by `value_type(value_type&&)` or `mtx_.lock()`.]]
@@ -209,7 +209,7 @@
[variablelist [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`.]] [[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`]] [[Return:] [`*this`]]
@@ -224,7 +224,7 @@
[variablelist [variablelist
[[Requires:] [`T` is `Assignale`.]] [[Requires:] [`T` is `Assignable`.]]
[[Effects:] [Copies the value on a scope protected by the mutex.]] [[Effects:] [Copies the value on a scope protected by the mutex.]]
[[Return:] [`*this`]] [[Return:] [`*this`]]
@@ -273,7 +273,7 @@
[variablelist [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.]] [[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()`.]] [[Throws:] [Any exception thrown by `swap(value_, rhs.value)` or `mtx_.lock()` or `rhs_.mtx_.lock()`.]]

View File

@@ -8,10 +8,10 @@
[library Thread [library Thread
[quickbook 1.5] [quickbook 1.5]
[version 4.4.0] [version 4.5.0]
[authors [Williams, Anthony] [Botet Escriba, Vicente J.]] [authors [Williams, Anthony] [Botet Escriba, Vicente J.]]
[copyright 2007-11 Anthony Williams] [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] [purpose C++ Library for launching threads and synchronizing data between them]
[category text] [category text]
[license [license

View File

@@ -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 <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/generic_executor_ref.hpp>
#include <string>
#include <iostream>
#include <boost/thread/caller_context.hpp>
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;
}

86
example/this_executor.cpp Normal file
View File

@@ -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 <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_THREAD_ID
#include <boost/thread/caller_context.hpp>
#include <boost/thread/executors/basic_thread_pool.hpp>
#include <boost/thread/executors/generic_executor_ref.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared.hpp>
#include <string>
#include <iostream>
#include <boost/thread/caller_context.hpp>
struct current_executor_state_type {
boost::shared_ptr<boost::generic_executor_ref> current_executor_ptr;
template <class Executor>
void set_current_executor(Executor& ex)
{
current_executor_ptr = boost::make_shared<boost::generic_executor_ref>(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;
}

View File

@@ -1,4 +1,4 @@
// (C) Copyright 2013 Vicente J. Botet Escriba // (C) Copyright 2013,2015 Vicente J. Botet Escriba
// Distributed under the Boost Software License, Version 1.0. (See // Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at // accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
@@ -12,6 +12,7 @@
#include <boost/thread/thread.hpp> #include <boost/thread/thread.hpp>
#endif #endif
#include <boost/current_function.hpp> #include <boost/current_function.hpp>
#include <boost/io/ios_state.hpp>
#include <iomanip> #include <iomanip>
#include <boost/config/abi_prefix.hpp> #include <boost/config/abi_prefix.hpp>
@@ -43,9 +44,11 @@ namespace boost
#endif #endif
{ {
io::ios_flags_saver ifs(os); io::ios_flags_saver ifs(os);
os << ctx.filename << "[" os << std::setw(50) << ctx.filename << "["
<< std::setw(4) << std::right << std::dec<< ctx.lineno << "] "; << std::setw(4) << std::right << std::dec<< ctx.lineno << "] ";
#if defined BOOST_THREAD_USES_LOG_CURRENT_FUNCTION
os << ctx.func << " " ; os << ctx.func << " " ;
#endif
} }
return os; return os;
} }

View File

@@ -27,12 +27,12 @@ namespace detail
template <typename Queue> template <typename Queue>
class deque_adaptor_copyable_only : class deque_adaptor_copyable_only :
public boost::deque_base<typename Queue::value_type> public boost::deque_base<typename Queue::value_type, typename Queue::size_type>
{ {
Queue queue; Queue queue;
public: public:
typedef typename Queue::value_type value_type; typedef typename Queue::value_type value_type;
typedef std::size_t size_type; typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors // Constructors/Assignment/Destructors
deque_adaptor_copyable_only() {} deque_adaptor_copyable_only() {}
@@ -63,12 +63,12 @@ namespace detail
}; };
template <typename Queue> template <typename Queue>
class deque_adaptor_movable_only : class deque_adaptor_movable_only :
public boost::deque_base<typename Queue::value_type> public boost::deque_base<typename Queue::value_type, typename Queue::size_type>
{ {
Queue queue; Queue queue;
public: public:
typedef typename Queue::value_type value_type; typedef typename Queue::value_type value_type;
typedef std::size_t size_type; typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors // Constructors/Assignment/Destructors
@@ -102,12 +102,12 @@ namespace detail
template <typename Queue> template <typename Queue>
class deque_adaptor_copyable_and_movable : class deque_adaptor_copyable_and_movable :
public boost::deque_base<typename Queue::value_type> public boost::deque_base<typename Queue::value_type, typename Queue::size_type>
{ {
Queue queue; Queue queue;
public: public:
typedef typename Queue::value_type value_type; typedef typename Queue::value_type value_type;
typedef std::size_t size_type; typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors // Constructors/Assignment/Destructors
@@ -195,7 +195,7 @@ namespace detail
{ {
public: public:
typedef typename Queue::value_type value_type; typedef typename Queue::value_type value_type;
typedef std::size_t size_type; typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors // Constructors/Assignment/Destructors
virtual ~deque_adaptor() {}; virtual ~deque_adaptor() {};
}; };

View File

@@ -27,12 +27,12 @@ namespace concurrent
namespace detail namespace detail
{ {
template <typename ValueType> template <typename ValueType, class SizeType>
class deque_base_copyable_only class deque_base_copyable_only
{ {
public: public:
typedef ValueType value_type; typedef ValueType value_type;
typedef std::size_t size_type; typedef SizeType size_type;
// Constructors/Assignment/Destructors // Constructors/Assignment/Destructors
virtual ~deque_base_copyable_only() {}; 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 nonblocking_pull_front(value_type&) = 0;
virtual queue_op_status wait_push_back(const value_type& x) = 0; virtual queue_op_status wait_push_back(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 <typename ValueType> template <typename ValueType, class SizeType>
class deque_base_movable_only class deque_base_movable_only
{ {
public: public:
typedef ValueType value_type; typedef ValueType value_type;
typedef std::size_t size_type; typedef SizeType size_type;
// Constructors/Assignment/Destructors // Constructors/Assignment/Destructors
virtual ~deque_base_movable_only() {}; 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 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 void push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0; virtual queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
@@ -97,12 +97,12 @@ namespace detail
}; };
template <typename ValueType> template <typename ValueType, class SizeType>
class deque_base_copyable_and_movable class deque_base_copyable_and_movable
{ {
public: public:
typedef ValueType value_type; typedef ValueType value_type;
typedef std::size_t size_type; typedef SizeType size_type;
// Constructors/Assignment/Destructors // Constructors/Assignment/Destructors
virtual ~deque_base_copyable_and_movable() {}; 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 nonblocking_pull_front(value_type&) = 0;
virtual queue_op_status wait_push_back(const value_type& x) = 0; virtual queue_op_status wait_push_back(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 void push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0; virtual queue_op_status 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; virtual queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
}; };
template <class T, template <class T, class ST,
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#if defined __GNUC__ && ! defined __clang__ #if defined __GNUC__ && ! defined __clang__
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__) #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
@@ -166,28 +166,28 @@ namespace detail
> >
struct deque_base; struct deque_base;
template <class T> template <class T, class ST>
struct deque_base<T, true, true> { struct deque_base<T, ST, true, true> {
typedef deque_base_copyable_and_movable<T> type; typedef deque_base_copyable_and_movable<T, ST> type;
}; };
template <class T> template <class T, class ST>
struct deque_base<T, true, false> { struct deque_base<T, ST, true, false> {
typedef deque_base_copyable_only<T> type; typedef deque_base_copyable_only<T, ST> type;
}; };
template <class T> template <class T, class ST>
struct deque_base<T, false, true> { struct deque_base<T, ST, false, true> {
typedef deque_base_movable_only<T> type; typedef deque_base_movable_only<T, ST> type;
}; };
} }
template <typename ValueType> template <class ValueType, class SizeType=std::size_t>
class deque_base : class deque_base :
public detail::deque_base<ValueType>::type public detail::deque_base<ValueType, SizeType>::type
{ {
public: public:
typedef ValueType value_type; typedef ValueType value_type;
typedef std::size_t size_type; typedef SizeType size_type;
// Constructors/Assignment/Destructors // Constructors/Assignment/Destructors
virtual ~deque_base() {}; virtual ~deque_base() {};
}; };

View File

@@ -37,7 +37,7 @@ namespace detail
public: public:
typedef ValueType value_type; typedef ValueType value_type;
typedef Queue underlying_queue_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 queue_op_status op_status;
typedef typename chrono::steady_clock clock; typedef typename chrono::steady_clock clock;

View File

@@ -37,7 +37,7 @@ namespace detail
public: public:
typedef ValueType value_type; typedef ValueType value_type;
typedef Queue underlying_queue_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 queue_op_status op_status;
typedef typename chrono::steady_clock clock; typedef typename chrono::steady_clock clock;

View File

@@ -27,12 +27,12 @@ namespace detail
template <typename Queue> template <typename Queue>
class queue_adaptor_copyable_only : class queue_adaptor_copyable_only :
public boost::queue_base<typename Queue::value_type> public boost::queue_base<typename Queue::value_type, typename Queue::size_type>
{ {
Queue queue; Queue queue;
public: public:
typedef typename Queue::value_type value_type; typedef typename Queue::value_type value_type;
typedef std::size_t size_type; typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors // Constructors/Assignment/Destructors
queue_adaptor_copyable_only() {} queue_adaptor_copyable_only() {}
@@ -63,12 +63,12 @@ namespace detail
}; };
template <typename Queue> template <typename Queue>
class queue_adaptor_movable_only : class queue_adaptor_movable_only :
public boost::queue_base<typename Queue::value_type> public boost::queue_base<typename Queue::value_type, typename Queue::size_type>
{ {
Queue queue; Queue queue;
public: public:
typedef typename Queue::value_type value_type; typedef typename Queue::value_type value_type;
typedef std::size_t size_type; typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors // Constructors/Assignment/Destructors
@@ -102,12 +102,12 @@ namespace detail
template <typename Queue> template <typename Queue>
class queue_adaptor_copyable_and_movable : class queue_adaptor_copyable_and_movable :
public boost::queue_base<typename Queue::value_type> public boost::queue_base<typename Queue::value_type, typename Queue::size_type>
{ {
Queue queue; Queue queue;
public: public:
typedef typename Queue::value_type value_type; typedef typename Queue::value_type value_type;
typedef std::size_t size_type; typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors // Constructors/Assignment/Destructors
@@ -195,7 +195,7 @@ namespace detail
{ {
public: public:
typedef typename Queue::value_type value_type; typedef typename Queue::value_type value_type;
typedef std::size_t size_type; typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors // Constructors/Assignment/Destructors
virtual ~queue_adaptor() {}; virtual ~queue_adaptor() {};
}; };

View File

@@ -27,12 +27,12 @@ namespace concurrent
namespace detail namespace detail
{ {
template <typename ValueType> template <typename ValueType, class SizeType>
class queue_base_copyable_only class queue_base_copyable_only
{ {
public: public:
typedef ValueType value_type; typedef ValueType value_type;
typedef std::size_t size_type; typedef SizeType size_type;
// Constructors/Assignment/Destructors // Constructors/Assignment/Destructors
virtual ~queue_base_copyable_only() {}; virtual ~queue_base_copyable_only() {};
@@ -62,12 +62,12 @@ namespace detail
}; };
template <typename ValueType> template <typename ValueType, class SizeType>
class queue_base_movable_only class queue_base_movable_only
{ {
public: public:
typedef ValueType value_type; typedef ValueType value_type;
typedef std::size_t size_type; typedef SizeType size_type;
// Constructors/Assignment/Destructors // Constructors/Assignment/Destructors
virtual ~queue_base_movable_only() {}; virtual ~queue_base_movable_only() {};
@@ -88,7 +88,7 @@ namespace detail
virtual queue_op_status nonblocking_pull(value_type&) = 0; 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 void push(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status try_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 <typename ValueType> template <typename ValueType, class SizeType>
class queue_base_copyable_and_movable class queue_base_copyable_and_movable
{ {
public: public:
typedef ValueType value_type; typedef ValueType value_type;
typedef std::size_t size_type; typedef SizeType size_type;
// Constructors/Assignment/Destructors // Constructors/Assignment/Destructors
virtual ~queue_base_copyable_and_movable() {}; 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 nonblocking_pull(value_type&) = 0;
virtual queue_op_status wait_push(const value_type& x) = 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 void push(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status try_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; virtual queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) = 0;
}; };
template <class T, template <class T, class ST,
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#if defined __GNUC__ && ! defined __clang__ #if defined __GNUC__ && ! defined __clang__
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__) #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
@@ -166,28 +166,28 @@ namespace detail
> >
struct queue_base; struct queue_base;
template <class T> template <class T, class ST>
struct queue_base<T, true, true> { struct queue_base<T, ST, true, true> {
typedef queue_base_copyable_and_movable<T> type; typedef queue_base_copyable_and_movable<T, ST> type;
}; };
template <class T> template <class T, class ST>
struct queue_base<T, true, false> { struct queue_base<T, ST, true, false> {
typedef queue_base_copyable_only<T> type; typedef queue_base_copyable_only<T, ST> type;
}; };
template <class T> template <class T, class ST>
struct queue_base<T, false, true> { struct queue_base<T, ST, false, true> {
typedef queue_base_movable_only<T> type; typedef queue_base_movable_only<T, ST> type;
}; };
} }
template <typename ValueType> template <typename ValueType, class SizeType=std::size_t>
class queue_base : class queue_base :
public detail::queue_base<ValueType>::type public detail::queue_base<ValueType, SizeType>::type
{ {
public: public:
typedef ValueType value_type; typedef ValueType value_type;
typedef std::size_t size_type; typedef SizeType size_type;
// Constructors/Assignment/Destructors // Constructors/Assignment/Destructors
virtual ~queue_base() {}; virtual ~queue_base() {};
}; };

View File

@@ -43,12 +43,13 @@ namespace detail {
Compare _compare; Compare _compare;
public: public:
typedef Type value_type; typedef Type value_type;
typedef typename Container::size_type size_type;
explicit priority_queue(const Compare& compare = Compare()) explicit priority_queue(const Compare& compare = Compare())
: _elements(), _compare(compare) : _elements(), _compare(compare)
{ } { }
std::size_t size() const size_type size() const
{ {
return _elements.size(); return _elements.size();
} }

View File

@@ -106,6 +106,11 @@ namespace detail
template <class Rep, class Period> template <class Rep, class Period>
void push(const T& elem, chrono::duration<Rep,Period> const& dura); void push(const T& elem, chrono::duration<Rep,Period> const& dura);
template <class Duration>
void push(BOOST_THREAD_RV_REF(T) elem, chrono::time_point<clock,Duration> const& tp);
template <class Rep, class Period>
void push(BOOST_THREAD_RV_REF(T) elem, chrono::duration<Rep,Period> const& dura);
template <class Duration> template <class Duration>
queue_op_status try_push(const T& elem, chrono::time_point<clock,Duration> const& tp); queue_op_status try_push(const T& elem, chrono::time_point<clock,Duration> const& tp);
template <class Rep, class Period> template <class Rep, class Period>
@@ -158,6 +163,22 @@ namespace detail
push(elem, clock::now() + dura); push(elem, clock::now() + dura);
} }
template <class T, class Clock>
template <class Duration>
void sync_timed_queue<T, Clock>::push(BOOST_THREAD_RV_REF(T) elem, chrono::time_point<clock,Duration> const& tp)
{
super::push(stype(boost::move(elem),tp));
}
template <class T, class Clock>
template <class Rep, class Period>
void sync_timed_queue<T, Clock>::push(BOOST_THREAD_RV_REF(T) elem, chrono::duration<Rep,Period> const& dura)
{
push(boost::move(elem), clock::now() + dura);
}
template <class T, class Clock> template <class T, class Clock>
template <class Duration> template <class Duration>
queue_op_status sync_timed_queue<T, Clock>::try_push(const T& elem, chrono::time_point<clock,Duration> const& tp) queue_op_status sync_timed_queue<T, Clock>::try_push(const T& elem, chrono::time_point<clock,Duration> const& tp)

View File

@@ -24,8 +24,8 @@ namespace detail
class priority_executor_base class priority_executor_base
{ {
public: public:
typedef boost::function<void()> work; //typedef boost::function<void()> work;
//typedef executors::work work; typedef executors::work_pq work;
protected: protected:
typedef Queue queue_type; typedef Queue queue_type;
queue_type _workq; queue_type _workq;

View File

@@ -1,5 +1,5 @@
// Copyright (C) 2014 Ian Forbed // Copyright (C) 2014 Ian Forbed
// 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 // 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) // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -16,6 +16,8 @@
#include <boost/atomic.hpp> #include <boost/atomic.hpp>
#include <boost/function.hpp> #include <boost/function.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost namespace boost
{ {
namespace executors namespace executors
@@ -23,11 +25,10 @@ namespace executors
namespace detail namespace detail
{ {
template <class Clock=chrono::steady_clock> template <class Clock=chrono::steady_clock>
class scheduled_executor_base : public priority_executor_base<concurrent::sync_timed_queue<boost::function<void()>, Clock > > class scheduled_executor_base : public priority_executor_base<concurrent::sync_timed_queue<executors::work_pq, Clock > >
{ {
public: public:
typedef boost::function<void()> work; typedef executors::work_pq work;
//typedef executors::work work;
typedef Clock clock; typedef Clock clock;
typedef typename clock::duration duration; typedef typename clock::duration duration;
typedef typename clock::time_point time_point; typedef typename clock::time_point time_point;
@@ -46,12 +47,12 @@ namespace detail
void submit_at(work w, const time_point& tp) void submit_at(work w, const time_point& tp)
{ {
this->_workq.push(w, tp); this->_workq.push(boost::move(w), tp);
} }
void submit_after(work w, const duration& dura) void submit_after(work w, const duration& dura)
{ {
this->_workq.push(w, dura+clock::now()); this->_workq.push(boost::move(w), dura+clock::now());
} }
}; //end class }; //end class
@@ -59,4 +60,7 @@ namespace detail
} //end detail namespace } //end detail namespace
} //end executors namespace } //end executors namespace
} //end boost namespace } //end boost namespace
#include <boost/config/abi_suffix.hpp>
#endif #endif

View File

@@ -8,36 +8,23 @@
#define BOOST_THREAD_EXECUTORS_WORK_HPP #define BOOST_THREAD_EXECUTORS_WORK_HPP
#include <boost/thread/detail/config.hpp> #include <boost/thread/detail/config.hpp>
#if ! defined BOOST_THREAD_EXECUTORS_WORK_ACCEPTS_MOVABLE \
&& ! defined BOOST_THREAD_EXECUTORS_WORK_DONT_ACCEPT_MOVABLE
#define BOOST_THREAD_EXECUTORS_WORK_ACCEPTS_MOVABLE
//#define BOOST_THREAD_EXECUTORS_WORK_DONT_ACCEPT_MOVABLE
#endif
#if defined BOOST_THREAD_EXECUTORS_WORK_ACCEPTS_MOVABLE
#include <boost/thread/detail/nullary_function.hpp> #include <boost/thread/detail/nullary_function.hpp>
namespace boost
{
namespace executors
{
typedef detail::nullary_function<void()> work;
}
} // namespace boost
#else
#include <boost/thread/csbl/functional.hpp> #include <boost/thread/csbl/functional.hpp>
namespace boost namespace boost
{ {
namespace executors namespace executors
{ {
typedef csbl::function<void()> work; typedef detail::nullary_function<void()> work;
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
typedef detail::nullary_function<void()> work_pq;
//typedef csbl::function<void()> work_pq;
#else
typedef csbl::function<void()> work_pq;
#endif
} }
} // namespace boost } // namespace boost
#endif
#endif // BOOST_THREAD_EXECUTORS_WORK_HPP #endif // BOOST_THREAD_EXECUTORS_WORK_HPP

View File

@@ -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 // Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // 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) void handle_task_region_exceptions(exception_list& errors)
{ {
try { try {
boost::rethrow_exception(boost::current_exception()); throw;
//throw boost::current_exception();
} }
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
catch (task_canceled_exception& ex) catch (task_canceled_exception& ex)
{ {
} }
#endif
catch (exception_list const& el) catch (exception_list const& el)
{ {
for (exception_list::const_iterator it = el.begin(); it != el.end(); ++it) for (exception_list::const_iterator it = el.begin(); it != el.end(); ++it)
@@ -94,7 +95,7 @@ BOOST_THREAD_INLINE_NAMESPACE(v2)
{ {
lock_guard<mutex> lk(tr.mtx); lock_guard<mutex> lk(tr.mtx);
tr.canceled = true; 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()); 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) for (group_type::iterator it = group.begin(); it != group.end(); ++it)
{ {
future<void>& f = *it; future<void>& f = *it;
@@ -140,11 +139,9 @@ BOOST_THREAD_INLINE_NAMESPACE(v2)
} }
} }
} }
#endif
if (exs.size() != 0) if (exs.size() != 0)
{ {
boost::throw_exception(exs); boost::throw_exception(exs);
//throw exs;
} }
} }
protected: protected:
@@ -187,6 +184,7 @@ protected:
} }
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED #if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
mutable mutex mtx;
bool canceled; bool canceled;
#endif #endif
#if defined BOOST_THREAD_PROVIDES_EXECUTORS #if defined BOOST_THREAD_PROVIDES_EXECUTORS
@@ -195,8 +193,6 @@ protected:
exception_list exs; exception_list exs;
typedef csbl::vector<future<void> > group_type; typedef csbl::vector<future<void> > group_type;
group_type group; group_type group;
mutable mutex mtx;
public: public:
BOOST_DELETED_FUNCTION(task_region_handle_gen(const task_region_handle_gen&)) BOOST_DELETED_FUNCTION(task_region_handle_gen(const task_region_handle_gen&))
@@ -207,11 +203,12 @@ protected:
template<typename F> template<typename F>
void run(BOOST_THREAD_FWD_REF(F) f) void run(BOOST_THREAD_FWD_REF(F) f)
{ {
lock_guard<mutex> lk(mtx);
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED #if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
if (canceled) { {
boost::throw_exception(task_canceled_exception()); lock_guard<mutex> lk(mtx);
//throw task_canceled_exception(); if (canceled) {
boost::throw_exception(task_canceled_exception());
}
} }
#if defined BOOST_THREAD_PROVIDES_EXECUTORS #if defined BOOST_THREAD_PROVIDES_EXECUTORS
group.push_back(async(*ex, detail::wrapped<task_region_handle_gen<Executor>, F>(*this, forward<F>(f)))); group.push_back(async(*ex, detail::wrapped<task_region_handle_gen<Executor>, F>(*this, forward<F>(f))));
@@ -229,11 +226,12 @@ protected:
void wait() void wait()
{ {
lock_guard<mutex> lk(mtx);
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED #if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
if (canceled) { {
boost::throw_exception(task_canceled_exception()); lock_guard<mutex> lk(mtx);
//throw task_canceled_exception{}; if (canceled) {
boost::throw_exception(task_canceled_exception());
}
} }
#endif #endif
wait_all(); wait_all();
@@ -276,7 +274,6 @@ protected:
} }
catch (...) catch (...)
{ {
lock_guard<mutex> lk(tr.mtx);
detail::handle_task_region_exceptions(tr.exs); detail::handle_task_region_exceptions(tr.exs);
} }
tr.wait_all(); tr.wait_all();
@@ -298,7 +295,6 @@ protected:
} }
catch (...) catch (...)
{ {
lock_guard<mutex> lk(tr.mtx);
detail::handle_task_region_exceptions(tr.exs); detail::handle_task_region_exceptions(tr.exs);
} }
tr.wait_all(); tr.wait_all();

View File

@@ -4892,7 +4892,9 @@ namespace detail
make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f) { make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f) {
shared_ptr<future_unwrap_shared_state<F, Rp> > shared_ptr<future_unwrap_shared_state<F, Rp> >
h(new future_unwrap_shared_state<F, Rp>(boost::move(f))); h(new future_unwrap_shared_state<F, Rp>(boost::move(f)));
lock.lock();
h->parent.future_->set_continuation_ptr(h, lock); h->parent.future_->set_continuation_ptr(h, lock);
lock.unlock();
return BOOST_THREAD_FUTURE<Rp>(h); return BOOST_THREAD_FUTURE<Rp>(h);
} }
} }
@@ -4907,6 +4909,7 @@ namespace detail
{ {
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
boost::unique_lock<boost::mutex> lock(this->future_->mutex); boost::unique_lock<boost::mutex> lock(this->future_->mutex);
lock.unlock();
return boost::detail::make_future_unwrap_shared_state<BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >, R2>(lock, boost::move(*this)); return boost::detail::make_future_unwrap_shared_state<BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >, R2>(lock, boost::move(*this));
} }
#endif #endif

View File

@@ -1,12 +1,13 @@
#ifndef BOOST_THREAD_PTHREAD_MUTEX_HPP #ifndef BOOST_THREAD_PTHREAD_MUTEX_HPP
#define BOOST_THREAD_PTHREAD_MUTEX_HPP #define BOOST_THREAD_PTHREAD_MUTEX_HPP
// (C) Copyright 2007-8 Anthony Williams // (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 // Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at // accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/detail/config.hpp> #include <boost/thread/detail/config.hpp>
#include <boost/assert.hpp>
#include <pthread.h> #include <pthread.h>
#include <boost/throw_exception.hpp> #include <boost/throw_exception.hpp>
#include <boost/core/ignore_unused.hpp> #include <boost/core/ignore_unused.hpp>
@@ -26,13 +27,12 @@
#endif #endif
#include <boost/thread/detail/delete.hpp> #include <boost/thread/detail/delete.hpp>
#ifdef _POSIX_TIMEOUTS #if (defined(_POSIX_TIMEOUTS) && (_POSIX_TIMEOUTS-0)>=200112L) \
#if _POSIX_TIMEOUTS >= 0 && _POSIX_TIMEOUTS>=200112L || (defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__ >= 21)
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK #ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
#define BOOST_PTHREAD_HAS_TIMEDLOCK #define BOOST_PTHREAD_HAS_TIMEDLOCK
#endif #endif
#endif #endif
#endif
#include <boost/config/abi_prefix.hpp> #include <boost/config/abi_prefix.hpp>
@@ -123,10 +123,12 @@ namespace boost
void unlock() void unlock()
{ {
int res = posix::pthread_mutex_unlock(&m); int res = posix::pthread_mutex_unlock(&m);
if (res) (void)res;
{ BOOST_ASSERT(res == 0);
boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock")); // if (res)
} // {
// boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock"));
// }
} }
bool try_lock() bool try_lock()
@@ -219,10 +221,12 @@ namespace boost
void unlock() void unlock()
{ {
int res = posix::pthread_mutex_unlock(&m); int res = posix::pthread_mutex_unlock(&m);
if (res) (void)res;
{ BOOST_ASSERT(res == 0);
boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock")); // if (res)
} // {
// boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock"));
// }
} }
bool try_lock() bool try_lock()

View File

@@ -27,16 +27,19 @@
#endif #endif
#include <boost/thread/detail/delete.hpp> #include <boost/thread/detail/delete.hpp>
#ifdef _POSIX_TIMEOUTS #if (defined _POSIX_TIMEOUTS && (_POSIX_TIMEOUTS-0)>=200112L) \
#if _POSIX_TIMEOUTS >= 0 && _POSIX_TIMEOUTS>=200112L || (defined __ANDROID__ && defined __ANDROID_API__ && __ANDROID_API__ >= 21)
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK #ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
#define BOOST_PTHREAD_HAS_TIMEDLOCK #define BOOST_PTHREAD_HAS_TIMEDLOCK
#endif #endif
#endif #endif
#if defined BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE \
|| defined __ANDROID__
#define BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
#endif #endif
#if defined BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE && defined BOOST_PTHREAD_HAS_TIMEDLOCK
#if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) && defined(BOOST_PTHREAD_HAS_TIMEDLOCK)
#define BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK #define BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
#endif #endif
@@ -48,7 +51,7 @@ namespace boost
{ {
private: private:
pthread_mutex_t m; pthread_mutex_t m;
#ifndef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE #ifndef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
pthread_cond_t cond; pthread_cond_t cond;
bool is_locked; bool is_locked;
pthread_t owner; pthread_t owner;
@@ -58,7 +61,7 @@ namespace boost
BOOST_THREAD_NO_COPYABLE(recursive_mutex) BOOST_THREAD_NO_COPYABLE(recursive_mutex)
recursive_mutex() recursive_mutex()
{ {
#ifdef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE #ifdef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
pthread_mutexattr_t attr; pthread_mutexattr_t attr;
int const init_attr_res=pthread_mutexattr_init(&attr); int const init_attr_res=pthread_mutexattr_init(&attr);
@@ -99,12 +102,12 @@ namespace boost
~recursive_mutex() ~recursive_mutex()
{ {
BOOST_VERIFY(!pthread_mutex_destroy(&m)); BOOST_VERIFY(!pthread_mutex_destroy(&m));
#ifndef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE #ifndef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
BOOST_VERIFY(!pthread_cond_destroy(&cond)); BOOST_VERIFY(!pthread_cond_destroy(&cond));
#endif #endif
} }
#ifdef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE #ifdef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
void lock() void lock()
{ {
BOOST_VERIFY(!pthread_mutex_lock(&m)); BOOST_VERIFY(!pthread_mutex_lock(&m));

View File

@@ -115,8 +115,13 @@ namespace boost
boost::detail::thread_exit_callback_node* thread_exit_callbacks; boost::detail::thread_exit_callback_node* thread_exit_callbacks;
std::map<void const*,boost::detail::tss_data_node> tss_data; std::map<void const*,boost::detail::tss_data_node> 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_mutex_t* cond_mutex;
pthread_cond_t* current_cond; pthread_cond_t* current_cond;
//#endif
typedef std::vector<std::pair<condition_variable*, mutex*> typedef std::vector<std::pair<condition_variable*, mutex*>
//, hidden_allocator<std::pair<condition_variable*, mutex*> > //, hidden_allocator<std::pair<condition_variable*, mutex*> >
> notify_list_t; > notify_list_t;
@@ -136,8 +141,10 @@ namespace boost
thread_handle(0), thread_handle(0),
done(false),join_started(false),joined(false), done(false),join_started(false),joined(false),
thread_exit_callbacks(0), thread_exit_callbacks(0),
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
cond_mutex(0), cond_mutex(0),
current_cond(0), current_cond(0),
//#endif
notify(), notify(),
async_states_() async_states_()
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS

View File

@@ -96,13 +96,10 @@ namespace boost
} }
delete current_node; delete current_node;
} }
for(std::map<void const*,tss_data_node>::iterator next=thread_info->tss_data.begin(), while (!thread_info->tss_data.empty())
current,
end=thread_info->tss_data.end();
next!=end;)
{ {
current=next; std::map<void const*,detail::tss_data_node>::iterator current
++next; = thread_info->tss_data.begin();
if(current->second.func && (current->second.value!=0)) if(current->second.func && (current->second.value!=0))
{ {
(*current->second.func)(current->second.value); (*current->second.func)(current->second.value);
@@ -162,7 +159,7 @@ namespace boost
static void* thread_proxy(void* param) static void* thread_proxy(void* param)
{ {
boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(param)->self; boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(param)->self;
thread_info->self.reset(); //thread_info->self.reset();
detail::set_current_thread_data(thread_info.get()); detail::set_current_thread_data(thread_info.get());
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
BOOST_TRY BOOST_TRY

View File

@@ -44,7 +44,7 @@
#include <wrl\ftm.h> #include <wrl\ftm.h>
#include <windows.system.threading.h> #include <windows.system.threading.h>
#pragma comment(lib, "runtimeobject.lib") #pragma comment(lib, "runtimeobject.lib")
#endif #endif
namespace boost namespace boost
{ {
@@ -198,7 +198,7 @@ namespace boost
namespace detail namespace detail
{ {
std::atomic_uint threadCount; std::atomic_uint threadCount;
bool win32::scoped_winrt_thread::start(thread_func address, void *parameter, unsigned int *thrdId) bool win32::scoped_winrt_thread::start(thread_func address, void *parameter, unsigned int *thrdId)
{ {
Microsoft::WRL::ComPtr<ABI::Windows::System::Threading::IThreadPoolStatics> threadPoolFactory; Microsoft::WRL::ComPtr<ABI::Windows::System::Threading::IThreadPoolStatics> threadPoolFactory;
@@ -220,7 +220,7 @@ namespace boost
m_completionHandle = completionHandle; m_completionHandle = completionHandle;
// Create new work item. // Create new work item.
Microsoft::WRL::ComPtr<ABI::Windows::System::Threading::IWorkItemHandler> workItem = Microsoft::WRL::ComPtr<ABI::Windows::System::Threading::IWorkItemHandler> workItem =
Microsoft::WRL::Callback<Microsoft::WRL::Implements<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, ABI::Windows::System::Threading::IWorkItemHandler, Microsoft::WRL::FtmBase>> Microsoft::WRL::Callback<Microsoft::WRL::Implements<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, ABI::Windows::System::Threading::IWorkItemHandler, Microsoft::WRL::FtmBase>>
([address, parameter, completionHandle](ABI::Windows::Foundation::IAsyncAction *) ([address, parameter, completionHandle](ABI::Windows::Foundation::IAsyncAction *)
{ {
@@ -274,13 +274,10 @@ namespace boost
} }
boost::detail::heap_delete(current_node); boost::detail::heap_delete(current_node);
} }
for(std::map<void const*,detail::tss_data_node>::iterator next=current_thread_data->tss_data.begin(), while (!current_thread_data->tss_data.empty())
current,
end=current_thread_data->tss_data.end();
next!=end;)
{ {
current=next; std::map<void const*,detail::tss_data_node>::iterator current
++next; = current_thread_data->tss_data.begin();
if(current->second.func && (current->second.value!=0)) if(current->second.func && (current->second.value!=0))
{ {
(*current->second.func)(current->second.value); (*current->second.func)(current->second.value);
@@ -346,7 +343,7 @@ namespace boost
return true; return true;
#endif #endif
} }
bool thread::start_thread_noexcept(const attributes& attr) bool thread::start_thread_noexcept(const attributes& attr)
{ {
#if BOOST_PLAT_WINDOWS_RUNTIME #if BOOST_PLAT_WINDOWS_RUNTIME
@@ -367,7 +364,7 @@ namespace boost
return true; return true;
#endif #endif
} }
thread::thread(detail::thread_data_ptr data): thread::thread(detail::thread_data_ptr data):
thread_info(data) thread_info(data)
{} {}

View File

@@ -297,6 +297,7 @@ rule thread-compile ( sources : reqs * : name )
[ thread-run test_9856.cpp ] [ thread-run test_9856.cpp ]
[ thread-compile test_10963.cpp : : test_10963_c ] [ thread-compile test_10963.cpp : : test_10963_c ]
[ thread-run test_10964.cpp ] [ thread-run test_10964.cpp ]
[ thread-test test_11053.cpp ]
; ;
@@ -949,6 +950,8 @@ rule thread-compile ( sources : reqs * : name )
explicit ts_ ; explicit ts_ ;
test-suite ts_ test-suite ts_
: :
[ thread-run2 ../example/this_executor.cpp : ex_this_executor ]
[ thread-run2 ../example/default_executor.cpp : ex_default_executor ]
; ;
} }

View File

@@ -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 // 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) // 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; std::cout << "task3" << std::endl;
}); });
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
BOOST_TEST(false); BOOST_TEST(false);
#endif
}); });
BOOST_TEST(false); BOOST_TEST(false);
} }

View File

@@ -17,6 +17,7 @@
#include <boost/thread/future.hpp> #include <boost/thread/future.hpp>
#include <boost/thread/thread.hpp> #include <boost/thread/thread.hpp>
#include <boost/core/ref.hpp>
#include <boost/detail/lightweight_test.hpp> #include <boost/detail/lightweight_test.hpp>
#if defined BOOST_THREAD_USES_CHRONO #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;
} }
} }
// BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
// { {
// typedef int& T; typedef int& T;
// { {
// boost::promise<T> p; boost::promise<T> p;
// boost::future<T> f = p.get_future(); boost::future<T> f = p.get_future();
//#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
// boost::thread(func3, boost::move(p)).detach(); boost::thread(func3, boost::move(p)).detach();
//#else #else
// int j=5; int j=5;
// p.set_value(j); p.set_value(j);
//#endif #endif
// BOOST_TEST(f.valid()); BOOST_TEST(f.valid());
// int k=4; int k=4;
// BOOST_TEST(f.get_or(k) == 5); BOOST_TEST(f.get_or(boost::ref(k)) == 5);
//#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
// BOOST_TEST(!f.valid()); BOOST_TEST(!f.valid());
//#endif #endif
// } }
// BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
// { {
// boost::promise<T> p; boost::promise<T> p;
// boost::future<T> f = p.get_future(); boost::future<T> f = p.get_future();
//#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
// boost::thread(func4, boost::move(p)).detach(); boost::thread(func4, boost::move(p)).detach();
//#else #else
// p.set_exception(boost::make_exception_ptr(3.5)); p.set_exception(boost::make_exception_ptr(3.5));
//#endif #endif
// try try
// { {
// BOOST_TEST(f.valid()); BOOST_TEST(f.valid());
// int j=4; int j=4;
// BOOST_TEST(f.get_or(j) == 4); BOOST_TEST(f.get_or(boost::ref(j)) == 4);
// } }
// catch (...) catch (...)
// { {
// BOOST_TEST(false); BOOST_TEST(false);
// } }
//#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
// BOOST_TEST(!f.valid()); BOOST_TEST(!f.valid());
//#endif #endif
// } }
// } }
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2013 Vicente J. Botet Escriba // Copyright (C) 2013,2015 Vicente J. Botet Escriba
// //
// Distributed under the Boost Software License, Version 1.0. (See accompanying // 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) // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -76,7 +76,7 @@ int main()
BOOST_TEST(! q.closed()); BOOST_TEST(! q.closed());
} }
#if 0 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
{ {
// empty queue push rvalue/non_copyable succeeds // empty queue push rvalue/non_copyable succeeds
boost::sync_deque<non_copyable> q; boost::sync_deque<non_copyable> q;
@@ -137,11 +137,11 @@ int main()
BOOST_TEST(! q.closed()); BOOST_TEST(! q.closed());
} }
#if 0 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
{ {
// empty queue try_push rvalue/non-copyable succeeds // empty queue try_push rvalue/non-copyable succeeds
boost::sync_deque<non_copyable> q; boost::sync_deque<non_copyable> q;
BOOST_TEST(boost::queue_op_status::success ==q.try_push_back(non_copyable())); BOOST_TEST(boost::queue_op_status::success ==q.try_push_back(non_copyable(1)));
BOOST_TEST(! q.empty()); BOOST_TEST(! q.empty());
BOOST_TEST(! q.full()); BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u); BOOST_TEST_EQ(q.size(), 1u);
@@ -179,8 +179,7 @@ int main()
BOOST_TEST(! q.closed()); BOOST_TEST(! q.closed());
} }
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#if 0
{ {
// empty queue nonblocking_push_back rvalue/non-copyable succeeds // empty queue nonblocking_push_back rvalue/non-copyable succeeds
boost::sync_deque<non_copyable> q; boost::sync_deque<non_copyable> q;

View File

@@ -1,5 +1,5 @@
// Copyright (C) 2014 Ian Forbed // Copyright (C) 2014 Ian Forbed
// 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 // 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) // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -149,17 +149,15 @@ int main()
//test_pull_until_when_not_empty(); //test_pull_until_when_not_empty();
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#if 0
{ {
// empty queue try_push rvalue/non-copyable succeeds // empty queue try_push rvalue/non-copyable succeeds
boost::concurrent::sync_priority_queue<non_copyable> q; boost::concurrent::sync_priority_queue<non_copyable> q;
BOOST_TEST(boost::queue_op_status::success ==q.try_push(non_copyable())); BOOST_TEST(boost::queue_op_status::success ==q.try_push(non_copyable(1)));
BOOST_TEST(! q.empty()); BOOST_TEST(! q.empty());
BOOST_TEST(! q.full()); BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u); BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed()); BOOST_TEST(! q.closed());
} }
#endif
{ {
//fixme //fixme
// empty queue try_push rvalue/non-copyable succeeds // empty queue try_push rvalue/non-copyable succeeds
@@ -183,17 +181,16 @@ int main()
BOOST_TEST_EQ(q.size(), 1u); BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed()); BOOST_TEST(! q.closed());
} }
// {
// // empty queue try_push rvalue succeeds
// boost::concurrent::sync_priority_queue<int> q;
// BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(1));
// BOOST_TEST(! q.empty());
// BOOST_TEST(! q.full());
// BOOST_TEST_EQ(q.size(), 1u);
// BOOST_TEST(! q.closed());
// }
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#if 0 #if 0
{
// empty queue try_push rvalue succeeds
boost::concurrent::sync_priority_queue<int> q;
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(1));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{ {
// empty queue nonblocking_push rvalue/non-copyable succeeds // empty queue nonblocking_push rvalue/non-copyable succeeds
boost::concurrent::sync_priority_queue<non_copyable> q; boost::concurrent::sync_priority_queue<non_copyable> q;
@@ -203,17 +200,16 @@ int main()
BOOST_TEST_EQ(q.size(), 1u); BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed()); BOOST_TEST(! q.closed());
} }
#endif {
// { // empty queue nonblocking_push rvalue/non-copyable succeeds
// // empty queue nonblocking_push rvalue/non-copyable succeeds boost::concurrent::sync_priority_queue<non_copyable> q;
// boost::concurrent::sync_priority_queue<non_copyable> q; non_copyable nc(1);
// non_copyable nc(1); BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(boost::move(nc)));
// BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(boost::move(nc))); BOOST_TEST(! q.empty());
// BOOST_TEST(! q.empty()); BOOST_TEST(! q.full());
// BOOST_TEST(! q.full()); BOOST_TEST_EQ(q.size(), 1u);
// BOOST_TEST_EQ(q.size(), 1u); BOOST_TEST(! q.closed());
// BOOST_TEST(! q.closed()); }
// }
#endif #endif
{ {

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2013 Vicente J. Botet Escriba // Copyright (C) 2013,2015 Vicente J. Botet Escriba
// //
// Distributed under the Boost Software License, Version 1.0. (See accompanying // 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) // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -47,7 +47,7 @@ int main()
BOOST_TEST(! q.closed()); BOOST_TEST(! q.closed());
} }
#if 0 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
{ {
// empty queue push rvalue/non_copyable succeeds // empty queue push rvalue/non_copyable succeeds
boost::sync_queue<non_copyable> q; boost::sync_queue<non_copyable> q;
@@ -108,11 +108,11 @@ int main()
BOOST_TEST(! q.closed()); BOOST_TEST(! q.closed());
} }
#if 0 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
{ {
// empty queue try_push rvalue/non-copyable succeeds // empty queue try_push rvalue/non-copyable succeeds
boost::sync_queue<non_copyable> q; boost::sync_queue<non_copyable> q;
BOOST_TEST(boost::queue_op_status::success ==q.try_push(non_copyable())); BOOST_TEST(boost::queue_op_status::success ==q.try_push(non_copyable(1)));
BOOST_TEST(! q.empty()); BOOST_TEST(! q.empty());
BOOST_TEST(! q.full()); BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u); BOOST_TEST_EQ(q.size(), 1u);
@@ -150,7 +150,7 @@ int main()
BOOST_TEST(! q.closed()); BOOST_TEST(! q.closed());
} }
#if 0 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
{ {
// empty queue nonblocking_push rvalue/non-copyable succeeds // empty queue nonblocking_push rvalue/non-copyable succeeds
boost::sync_queue<non_copyable> q; boost::sync_queue<non_copyable> q;

70
test/test_11053.cpp Normal file
View File

@@ -0,0 +1,70 @@
// Copyright (C) 2015 Vicente Botet
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_THREAD_VERSION 4
#include <boost/thread.hpp>
#include <boost/thread/tss.hpp>
#include <boost/shared_ptr.hpp>
#include <iostream>
struct A
{
void DoWork()
{
std::cout << "A: doing work\n";
if (!m_ptr.get())
m_ptr.reset(new WorkSpace());
// do not very much
for (size_t i = 0; i < 10; ++i)
m_ptr->a += 10;
}
private:
struct WorkSpace
{
int a;
WorkSpace() : a(0) {}
};
boost::thread_specific_ptr<WorkSpace> m_ptr;
};
struct B
{
void DoWork()
{
std::cout << "B: doing work\n";
if (!m_ptr.get())
m_ptr.reset(new A());
m_ptr->DoWork();
}
private:
boost::thread_specific_ptr<A> m_ptr;
};
struct C
{
void DoWork()
{
std::cout << "C: doing work\n";
if (!m_ptr.get())
m_ptr.reset(new B());
m_ptr->DoWork();
}
private:
boost::thread_specific_ptr<B> m_ptr;
};
int main(int ac, char** av)
{
std::cout << "test starting\n";
boost::shared_ptr<C> p_C(new C);
boost::thread cWorker(&C::DoWork, p_C);
cWorker.join();
std::cout << "test stopping\n";
return 0;
}

View File

@@ -35,6 +35,13 @@ void func(steady_clock::time_point pushed, steady_clock::duration dur)
{ {
BOOST_TEST(pushed + dur < steady_clock::now()); BOOST_TEST(pushed + dur < steady_clock::now());
} }
void func2(scheduled_tp* tp, steady_clock::duration d)
{
boost::function<void()> fn = boost::bind(func,steady_clock::now(),d);
tp->submit_after(fn, d);
}
void test_timing(const int n) void test_timing(const int n)
{ {
@@ -67,8 +74,9 @@ void test_deque_multi(const int n)
for(int i = 0; i < n; i++) for(int i = 0; i < n; i++)
{ {
steady_clock::duration d = milliseconds(i*100); steady_clock::duration d = milliseconds(i*100);
boost::function<void()> fn = boost::bind(func,steady_clock::now(),d); //boost::function<void()> fn = boost::bind(func,steady_clock::now(),d);
tg.create_thread(boost::bind(boost::mem_fn(&scheduled_tp::submit_after), &se, fn, d)); //tg.create_thread(boost::bind(boost::mem_fn(&scheduled_tp::submit_after), &se, fn, d));
tg.create_thread(boost::bind(func2, &se, d));
} }
tg.join_all(); tg.join_all();
//dtor is called here so execution will block untill all the closures //dtor is called here so execution will block untill all the closures