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

Compare commits

...

38 Commits

Author SHA1 Message Date
Vladimir Prus
dd51f97e44 Create branch to keep WIP patch for modular build.
[SVN r85883]
2013-09-25 08:12:19 +00:00
Tim Blechmann
04e3d918fb thread: implement physical_concurrency
[SVN r85864]
2013-09-24 06:41:24 +00:00
Vicente J. Botet Escriba
0073516f0a Thread: added missing function wrapper.
[SVN r85863]
2013-09-24 05:35:11 +00:00
Vicente J. Botet Escriba
89de3dcf4f Thread: make it possible to use non default constructible types in sync_queue, but sync_bounded_queue requires it yet.
[SVN r85861]
2013-09-23 21:40:08 +00:00
Vicente J. Botet Escriba
47f40f991f Thread: added first thread_pool.
[SVN r85855]
2013-09-23 16:45:00 +00:00
Vicente J. Botet Escriba
8b351fe473 Thread: fix some move semantic issues on sync_queue and sync_bounded_queue and add tests.
[SVN r85854]
2013-09-23 16:44:26 +00:00
Vicente J. Botet Escriba
24f1e620e8 Thread: fix some move issues on sync_queue.
[SVN r85841]
2013-09-22 22:23:58 +00:00
Vicente J. Botet Escriba
ed6459ecd2 Thread: make code uniform heap_new/heap_delete pairwise.
[SVN r85840]
2013-09-22 22:22:08 +00:00
Vicente J. Botet Escriba
858816b2d2 Thread: add detail:: to access detail::win32::GetTickCount64().
[SVN r85772]
2013-09-18 10:58:46 +00:00
Vicente J. Botet Escriba
4bc70444a4 Thread: try to fix SIGSEGV on win32 issue #7666.
[SVN r85734]
2013-09-17 21:17:02 +00:00
Vicente J. Botet Escriba
fcc027369f Thread: try to fix win32 condition_variable issue #7461.
[SVN r85733]
2013-09-17 21:01:05 +00:00
Vicente J. Botet Escriba
5c78582794 Thread: refactor make_ready_at_thread_exit + inhibit at_thread_exit functions from external threads.
[SVN r85732]
2013-09-17 20:57:46 +00:00
Vicente J. Botet Escriba
7f479a1dec Thread: Added test for tickets.
[SVN r85729]
2013-09-17 19:32:03 +00:00
Vicente J. Botet Escriba
4f2a7b2256 Thread: make use of explicit noncopyable constructor to avoid compile error with Intel compiler.
[SVN r85728]
2013-09-17 19:25:18 +00:00
Vicente J. Botet Escriba
5c88e6ce61 Thread: patch for #8070 to make use of GetTickCount64 when available.
[SVN r85714]
2013-09-16 19:43:37 +00:00
Vicente J. Botet Escriba
650e374492 Thread: Added ostream_buffer.
[SVN r85709]
2013-09-16 17:24:30 +00:00
Vicente J. Botet Escriba
6319080ef2 Thread: add test for get_exception_ptr.
[SVN r85708]
2013-09-16 17:15:05 +00:00
Vicente J. Botet Escriba
3ac48bdd65 Thread: patch for #8070 to make use of GetTickCount64 when available.
[SVN r85701]
2013-09-16 16:55:21 +00:00
Vicente J. Botet Escriba
c3c8ada97d Thread: replace TABS.
[SVN r85677]
2013-09-15 16:13:47 +00:00
Vicente J. Botet Escriba
fd5dd0c2ed Thread: added future<>::get_exception_ptr().
[SVN r85644]
2013-09-10 19:40:14 +00:00
Vicente J. Botet Escriba
4a83aa58ed Thread: add workaround for non compliants compilers on scoped_thread constructor.
[SVN r85643]
2013-09-10 18:55:52 +00:00
Vicente J. Botet Escriba
7d96aa625c Thread: update doc with history.
[SVN r85623]
2013-09-09 17:37:54 +00:00
Vicente J. Botet Escriba
d57a4c6565 Thread: link with boost_atomic conditionaly.
[SVN r85616]
2013-09-08 22:20:48 +00:00
Vicente J. Botet Escriba
c67e39f126 Thread: protect condition_variable/_any wait_for and wait_until from malicious input.
[SVN r85592]
2013-09-07 12:11:44 +00:00
Vicente J. Botet Escriba
5a3c301582 Thread: protect condition_variable/_any wait_for and wait_until from malicious input.
[SVN r85591]
2013-09-07 12:11:18 +00:00
Vicente J. Botet Escriba
dc5a8a9c4e Thread: try to handle with not needed definition of uintptr_t #8817.
[SVN r85540]
2013-09-01 07:25:56 +00:00
Vicente J. Botet Escriba
1e49343ff4 Thread: try to handle with call_once intel issue #8943.
[SVN r85539]
2013-09-01 07:22:21 +00:00
Vicente J. Botet Escriba
93d1855e64 Thread: fix scoped_thread variadic constructor.
[SVN r85494]
2013-08-27 22:37:15 +00:00
Vicente J. Botet Escriba
a39dd7e8b3 Thread: avoid conflict with thread symbol.
[SVN r85493]
2013-08-27 22:35:21 +00:00
Vicente J. Botet Escriba
7e5cb92bab Thread: fix some typos in doc.
[SVN r85492]
2013-08-27 22:31:32 +00:00
Vicente J. Botet Escriba
62cf0f86f6 Thread: fix more typos in doc.
[SVN r85485]
2013-08-27 11:32:24 +00:00
Vicente J. Botet Escriba
c12e07754a Thread: link with boost_chrono and boost_atomic independently of the platform.
[SVN r85464]
2013-08-25 15:13:17 +00:00
Vicente J. Botet Escriba
cbc4266774 Thread: rename wait_until parameter to avoid shadow with member function.
[SVN r85463]
2013-08-25 15:09:12 +00:00
Vicente J. Botet Escriba
3a038d33e5 Thread: rename check by cgeck_counter to avoid conflict with macro.
[SVN r85462]
2013-08-25 15:08:08 +00:00
Vicente J. Botet Escriba
51ba4be998 Thread: fix type and add BOOST_THREAD_USE_ATOMIC macro doc.
[SVN r85432]
2013-08-22 22:11:48 +00:00
Vicente J. Botet Escriba
2d50af8481 Thread: Added synchronized_value operator() to synchronize around a function call.
[SVN r85306]
2013-08-11 20:33:47 +00:00
Vicente J. Botet Escriba
e438c98070 Thread: Add mutex() to upgrade_to_unique_lock (#8891).
[SVN r85195]
2013-08-03 07:47:18 +00:00
Vicente J. Botet Escriba
1e2a76de47 Thread: apply pathc for #8931.
[SVN r85194]
2013-08-03 07:44:15 +00:00
52 changed files with 1894 additions and 178 deletions

View File

@@ -36,6 +36,7 @@ import os ;
import feature ;
import indirect ;
import path ;
import configure ;
project boost/thread
: source-location ../src
@@ -140,6 +141,8 @@ local rule default_threadapi ( )
feature.feature threadapi : pthread win32 : propagated ;
feature.set-default threadapi : [ default_threadapi ] ;
exe has_atomic_flag_lockfree : ../build/has_atomic_flag_lockfree_test.cpp ;
rule tag ( name : type ? : property-set )
{
local result = $(name) ;
@@ -236,10 +239,10 @@ rule usage-requirements ( properties * )
}
}
if ! <toolset>vacpp in $(properties) || <toolset-vacpp:version>11.1 in $(properties) || <toolset-vacpp:version>12.1.0.1 in $(properties) || <toolset-vacpp:version>12.1 in $(properties)
{
#if ! <toolset>vacpp in $(properties) || <toolset-vacpp:version>11.1 in $(properties) || <toolset-vacpp:version>12.1.0.1 in $(properties) || <toolset-vacpp:version>12.1 in $(properties)
#{
result += <library>/boost/chrono//boost_chrono ;
}
#}
return $(result) ;
}
@@ -264,16 +267,15 @@ rule requirements ( properties * )
}
}
result += <define>BOOST_THREAD_DONT_USE_CHRONO ;
if ! [ configure.builds has_atomic_flag_lockfree
: $(properties) : "lockfree boost::atomic_flag" ] {
result += <library>/boost/atomic//boost_atomic ;
}
} else {
result += <define>BOOST_THREAD_USES_CHRONO ;
result += <library>/boost/chrono//boost_chrono ;
}
if <toolset>pgi in $(properties) || <toolset>vacpp in $(properties)
{
result += <library>/boost/atomic//boost_atomic ;
}
return $(result) ;
}

View File

@@ -0,0 +1,13 @@
// Copyright (c) 2013, Petr Machata, Red Hat Inc.
//
// Use modification and distribution are subject to the boost Software
// License, Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt).
#include "../../../boost/atomic.hpp"
#include "../../../boost/static_assert.hpp"
int main(int argc, char *argv[])
{
BOOST_STATIC_ASSERT(BOOST_ATOMIC_FLAG_LOCK_FREE);
return 0;
}

View File

@@ -8,24 +8,32 @@
[section:changes History]
[/]
[heading Version 4.2.0 - boost 1.55]
[*New Features:]
* [@http://svn.boost.org/trac/boost/ticket/8274 #8274] Synchro: Add concurrent queue
* [@http://svn.boost.org/trac/boost/ticket/8518 #8518] Synchro: Add a latch class.
* [@http://svn.boost.org/trac/boost/ticket/8519 #8519] Synchro: Update class barrier with a completion function.
* [@http://svn.boost.org/trac/boost/ticket/8615 #8615] Async: Replace make_future/make_shared_future by make_ready_future.
* [@http://svn.boost.org/trac/boost/ticket/8515 #8515] Async: Add shared_future::then.
* [@http://svn.boost.org/trac/boost/ticket/8615 #8615] Async: Replace make_future/make_shared_future by make_ready_future.
* [@http://svn.boost.org/trac/boost/ticket/8627 #8627] Async: Add future<>::unwrap and unwrapping constructor.
* [@http://svn.boost.org/trac/boost/ticket/8677 #8677] Async: Add future<>::get_or.
* [@http://svn.boost.org/trac/boost/ticket/8678 #8678] Async: Add future<>::fallback_to.
* [@http://svn.boost.org/trac/boost/ticket/8955 #8955] Request for more efficient way to get exception_ptr from future.
* [@http://svn.boost.org/trac/boost/ticket/8891 #8891] upgrade_to_unique_lock: missing mutex() function.
[*Fixed Bugs:]
[/]
* [@http://svn.boost.org/trac/boost/ticket/8768 #8768] win32 condition_variable::wait_until infinite wait in rare cases.
* [@http://svn.boost.org/trac/boost/ticket/8817 #8817] Boost Thread Windows CE _createthreadex handling breaks mingw w64.
* [@http://svn.boost.org/trac/boost/ticket/8943 #8943] Failed to compile code using boost::call_once with Intel C++ Composer XE 2013 on Windows.
* [@http://svn.boost.org/trac/boost/ticket/8931 #8931] Typos in external_locking reference.
* [@http://svn.boost.org/trac/boost/ticket/9029 #9029] Misprint in documentation.
* [@http://svn.boost.org/trac/boost/ticket/9037 #9037] gcc -Wshadow gives warnings in condition_variable{,_fwd}.hpp.
* [@http://svn.boost.org/trac/boost/ticket/9041 #9041] Boost.Thread DSO's may need to link with Boost.Atomic.
* [@http://svn.boost.org/trac/boost/ticket/9048 #9048] boost::scoped_thread useless ctor with variadic template arguments.
* [@http://svn.boost.org/trac/boost/ticket/9079 #9079] Condition variable will wait forever for some timepoint values (Win).
[heading Version 4.1.0 - boost 1.54]
@@ -417,6 +425,8 @@ The following features will be included in next releases.
* [@http://svn.boost.org/trac/boost/ticket/7589 #7589] Synchro: Add polymorphic lockables.
# Add some features based on C++ proposals, in particular
* [@http://svn.boost.org/trac/boost/ticket/8274 #8274] Synchro: Add concurrent queue
* [@http://svn.boost.org/trac/boost/ticket/8518 #8518] Synchro: Add a latch class.
* [@http://svn.boost.org/trac/boost/ticket/8273 #8273] Synchro: Add externally locked streams.
* [@http://svn.boost.org/trac/boost/ticket/8513 #8513] Async: Add a basic thread_pool executor.
* [@http://svn.boost.org/trac/boost/ticket/8514 #8514] Async: Add a thread_pool executor with work stealing.

View File

@@ -78,20 +78,28 @@ When `BOOST_THREAD_VERSION>3` && defined BOOST_THREAD_PLATFORM_PTHREAD define `
[endsect]
[section:move Boost.Atomic]
[section:thread_eq `boost::thread::oprator==` deprecated]
Boost.Thread uses by default an Boost.Atomic in POSIX platforms to implement call_once..
The following nested typedefs are deprecated:
Define `BOOST_THREAD_USES_ATOMIC ` if you want to use Boost.Atomic.
Define `BOOST_THREAD_DONT_USE_ATOMIC ` if you don't want to use Boost.Atomic or if it is not supported in your platform.
* `boost::thread::oprator==`
* `boost::thread::oprator!=`
[endsect]
[section:thread_eq `boost::thread::operator==` deprecated]
The following operators are deprecated:
* `boost::thread::operator==`
* `boost::thread::operator!=`
When `BOOST_THREAD_PROVIDES_THREAD_EQ` is defined Boost.Thread provides these deprecated feature.
Use instead
* `boost::thread::id::oprator==`
* `boost::thread::id::oprator!=`
* `boost::thread::id::operator==`
* `boost::thread::id::operator!=`
[warning This is a breaking change respect to version 1.x.]

View File

@@ -217,7 +217,7 @@ Silence can be sometimes louder than words-what's forbidden to do with a `strict
* You can create a `strict_lock<T>` only starting from a valid T object. Notice that there is no other way you can create a `strict_lock<T>`.
BankAccount myAccount("John Doe", "123-45-6789");
strict_locerk<BankAccount> myLock(myAccount); // ok
strict_lock<BankAccount> myLock(myAccount); // ok
* You cannot copy `strict_lock`s to one another. In particular, you cannot pass `strict_lock`s by value to functions or have them returned by functions:
@@ -468,7 +468,7 @@ Now imagine that the AccountManager function needs to take a `unique_lock` in or
We need a way to transfer the ownership from the `unique_lock` to a `strict_lock` the time we are working with `savingsAcct_` and then restore the ownership on `unique_lock`.
void AccountManager::AMoreComplicatedChecking2Savings(int amount) {
unique_lock<AccountManager> guard(*this, defer_lock);
unique_lock<AccountManager> guard1(*this, defer_lock);
if (some_condition()) {
guard1.lock();
}
@@ -482,7 +482,7 @@ We need a way to transfer the ownership from the `unique_lock` to a `strict_lock
In order to make this code compilable we need to store either a Lockable or a `unique_lock<Lockable>` reference depending on the constructor. Store which kind of reference we have stored,and in the destructor call either to the Lockable `unlock` or restore the ownership.
This seams too complicated to me. Another possibility is to define a nested strict lock class. The drawback is that instead of having only one strict lock we have two and we need either to duplicate every function taking a `strict_lock` or make these function templates functions. The problem with template functions is that we don't profit anymore of the C++ type system. We must add some static metafunction that check that the Locker parameter is a strict lock. The problem is that we can not really check this or can we?. The `is_strict_lock` metafunction must be specialized by the strict lock developer. We need to belive it "sur parole". The advantage is that now we can manage with more than two strict locks without changing our code. Ths is really nice.
This seams too complicated to me. Another possibility is to define a nested strict lock class. The drawback is that instead of having only one strict lock we have two and we need either to duplicate every function taking a `strict_lock` or make these function templates functions. The problem with template functions is that we don't profit anymore of the C++ type system. We must add some static metafunction that check that the Locker parameter is a strict lock. The problem is that we can not really check this or can we?. The `is_strict_lock` metafunction must be specialized by the strict lock developer. We need to belive it "sur parole". The advantage is that now we can manage with more than two strict locks without changing our code. This is really nice.
Now we need to state that both classes are `strict_lock`s.

View File

@@ -301,6 +301,8 @@ The object's `name` virtual function returns a pointer to the string "future".]]
// retrieving the value
see below get();
see below get_or(see below); // EXTENSION
exception_ptr get_exception_ptr(); // EXTENSION
// functions to check state
bool valid() const noexcept;
@@ -758,6 +760,23 @@ stored exception, `false` otherwise.]]
]
[endsect]
[/////////////////////////////////////////////////////////////////]
[section:get_exception_ptr Member function `get_exception_ptr()` EXTENSION]
exception_ptr get_exception_ptr();
[variablelist
[[Effects:] [If `*this` is associated with a shared state, waits until the result is ready. If the result is not ready on
entry, and the result has a ['wait callback] set, that callback is invoked prior to waiting.]]
[[Returns:] [a exception_ptr, storring or not an exception.]]
[[Throws:] [Whatever `mutex::lock()/mutex::unlock()` can throw.]]
]
[endsect]
[/////////////////////////////////////////////////////////]
[section:get_state Member function `get_state()` EXTENSION]
@@ -925,6 +944,8 @@ There are not too much tests yet, so it is possible that you can find out some t
// retrieving the value
see below get();
exception_ptr get_exception_ptr(); // EXTENSION
// functions to check state, and wait for ready
bool valid() const noexcept;
bool is_ready() const noexcept; // EXTENSION
@@ -1185,7 +1206,7 @@ otherwise.]]
[[Returns:] [`true` if `*this` is associated with a shared state, and that result is ready for retrieval, `false`
otherwise.]]
[[Throws:] [Nothing.]]
[[Throws:] [Whatever `mutex::lock()/mutex::unlock()` can throw.]]
]
@@ -1200,7 +1221,7 @@ otherwise.]]
[[Returns:] [`true` if `*this` is associated with a shared state, that result is ready for retrieval, and the result is a
stored value, `false` otherwise.]]
[[Throws:] [Nothing.]]
[[Throws:] [Whatever `mutex::lock()/mutex::unlock()` can throw.]]
]
@@ -1215,7 +1236,24 @@ stored value, `false` otherwise.]]
[[Returns:] [`true` if `*this` is associated with a shared state, that result is ready for retrieval, and the result is a
stored exception, `false` otherwise.]]
[[Throws:] [Nothing.]]
[[Throws:] [Whatever `mutex::lock()/mutex::unlock()` can throw.]]
]
[endsect]
[/////////////////////////////////////////////////////////////////]
[section:get_exception_ptr Member function `get_exception_ptr()` EXTENSION]
exception_ptr get_exception_ptr();
[variablelist
[[Effects:] [If `*this` is associated with a shared state, waits until the result is ready. If the result is not ready on
entry, and the result has a ['wait callback] set, that callback is invoked prior to waiting.]]
[[Returns:] [a exception_ptr, storring or not an exception.]]
[[Throws:] [Whatever `mutex::lock()/mutex::unlock()` can throw.]]
]
@@ -1232,7 +1270,7 @@ stored exception, `false` otherwise.]]
[[Returns:] [__uninitialized__ if `*this` is not associated with a shared state. __ready__ if the shared state
associated with `*this` is ready for retrieval, __waiting__ otherwise.]]
[[Throws:] [Nothing.]]
[[Throws:] [Whatever `mutex::lock()/mutex::unlock()` can throw.]]
]

View File

@@ -1273,7 +1273,7 @@ The following classes are models of `StrictLock`:
explicit operator bool() const noexcept;
bool owns_lock() const noexcept;
Lockable* mutex() const noexcept;
mutex_type* mutex() const noexcept;
#if defined BOOST_THREAD_USE_DATE_TIME || defined BOOST_THREAD_DONT_USE_CHRONO
unique_lock(Lockable& m_,system_time const& target_time);
@@ -1535,7 +1535,7 @@ object associated with `*this`.]]
[endsect]
[section:mutex `Lockable* mutex() const`]
[section:mutex `Lockable* mutex() const noexcept`]
[variablelist
@@ -1907,7 +1907,7 @@ state (including the destructor) must be called by the same thread that acquired
[endsect]
[section:upgrade_to_unique_lock Class template `upgrade_to_unique_lock`]
[section:upgrade_to_unique_lock Class template `upgrade_to_unique_lock` -- EXTENSION]
// #include <boost/thread/locks.hpp>
// #include <boost/thread/lock_types.hpp>
@@ -1930,6 +1930,8 @@ state (including the destructor) must be called by the same thread that acquired
explicit operator bool() const;
bool owns_lock() const;
mutex_type* mutex() const;
};
__upgrade_to_unique_lock__ allows for a temporary upgrade of an __upgrade_lock__ to exclusive ownership. When constructed with a
@@ -1939,7 +1941,7 @@ __lockable_concept_type__ is downgraded back to ['upgrade ownership].
[endsect]
[section:scoped_try_lock Mutex-specific class `scoped_try_lock`]
[section:scoped_try_lock Mutex-specific class `scoped_try_lock` -- DEPRECATED]
class MutexType::scoped_try_lock
{

View File

@@ -190,7 +190,7 @@ This wrapper can be used to join the thread before destroying it seems a natural
explicit scoped_thread(thread&& th) noexcept;
template <typename F&&, typename ...Args>
explicit strict_scoped_thread(F&&, Args&&...);
explicit scoped_thread(F&&, Args&&...);
~scoped_thread();
@@ -216,6 +216,7 @@ This wrapper can be used to join the thread before destroying it seems a natural
void detach();
static unsigned hardware_concurrency() noexcept;
static unsigned physical_concurrency() noexcept;
typedef thread::native_handle_type native_handle_type;
native_handle_type native_handle();
@@ -323,7 +324,7 @@ any) to `*this`.
[section:call_constructor Move Constructor from a Callable]
template <typename F&&, typename ...Args>
explicit strict_scoped_thread(F&&, Args&&...);
explicit scoped_thread(F&&, Args&&...);
[variablelist
@@ -458,6 +459,20 @@ any) to `*this`.
[endsect]
[section:physical_concurrency Static member function `physical_concurrency()`]
unsigned physical_concurrency() noexecpt;
[variablelist
[[Effects:] [Equivalent to return `thread::physical_concurrency()`.]]
]
[endsect]
[section:nativehandle Member function `native_handle()`]
typedef thread::native_handle_type native_handle_type;

View File

@@ -23,16 +23,16 @@ In addition to the C++11 standard locks, Boost.Thread provides other locks and s
In particular, the library provides some lock factories.
template <class Lockable, class Function>
auto with_lock_guard(Lockable& m, Function f) -> decltype(fn())
auto with_lock_guard(Lockable& m, Function f) -> decltype(f())
{
auto&& _ = boost::make_lock_guard(f);
auto&& _ = boost::make_lock_guard(m);
f();
}
that can be used as
int i = with_lock_guard(mtx, {}() -> bool
int i = with_lock_guard(mtx, []()
{
// access the protected state
return true;

View File

@@ -239,7 +239,7 @@
[include condition_variables.qbk]
[include once.qbk]
[include barrier.qbk]
[include latch.qbk]
[/include latch.qbk]
[include futures.qbk]
[/include async_executors.qbk]
[endsect]

View File

@@ -470,6 +470,7 @@ This behavior is incompatible with the current Boost.Thread design, so the use o
void detach();
static unsigned hardware_concurrency() noexcept;
static unsigned physical_concurrency() noexcept;
typedef platform-specific-type native_handle_type;
native_handle_type native_handle();
@@ -568,7 +569,7 @@ any) to `*this`.
[variablelist
[[Requires:] [`Callable` must by Copyable and `func()` must be a valid expression.]]
[[Requires:] [`Callable` must be Copyable and `func()` must be a valid expression.]]
[[Effects:] [`func` is copied into storage managed internally by the thread library, and that copy is invoked on a newly-created
thread of execution. If this invocation results in an exception being propagated into the internals of the thread library that is
@@ -595,7 +596,7 @@ not of type __thread_interrupted__, then `std::terminate()` will be called. Any
[variablelist
[[Preconditions:] [`Callable` must by copyable.]]
[[Preconditions:] [`Callable` must be copyable.]]
[[Effects:] [`func` is copied into storage managed internally by the thread library, and that copy is invoked on a newly-created
thread of execution with the specified attributes. If this invocation results in an exception being propagated into the internals of the thread library that is
@@ -623,7 +624,7 @@ If the attributes declare the native thread as detached, the boost::thread will
[variablelist
[[Preconditions:] [`Callable` must by Movable.]]
[[Preconditions:] [`Callable` must be Movable.]]
[[Effects:] [`func` is moved into storage managed internally by the thread library, and that copy is invoked on a newly-created
thread of execution. If this invocation results in an exception being propagated into the internals of the thread library that is
@@ -650,7 +651,7 @@ not of type __thread_interrupted__, then `std::terminate()` will be called. Any
[variablelist
[[Preconditions:] [`Callable` must by copyable.]]
[[Preconditions:] [`Callable` must be copyable.]]
[[Effects:] [`func` is copied into storage managed internally by the thread library, and that copy is invoked on a newly-created
thread of execution with the specified attributes. If this invocation results in an exception being propagated into the internals of the thread library that is
@@ -679,7 +680,7 @@ If the attributes declare the native thread as detached, the boost::thread will
[variablelist
[[Preconditions:] [`F` and each `A`n must by copyable or movable.]]
[[Preconditions:] [`F` and each `A`n must be copyable or movable.]]
[[Effects:] [As if [link
thread.thread_management.thread.callable_constructor
@@ -991,6 +992,21 @@ or 0 if this information is not available.]]
[endsect]
[section:physical_concurrency Static member function `physical_concurrency()`]
unsigned physical_concurrency() noexecpt;
[variablelist
[[Returns:] [The number of physical cores available on the current system. In contrast to `hardware_concurrency()` it does not return
the number of virtual cores, but it counts only physical cores.]]
[[Throws:] [Nothing]]
]
[endsect]
[section:nativehandle Member function `native_handle()`]
typedef platform-specific-type native_handle_type;

View File

@@ -16,7 +16,7 @@ class bounded_buffer : private boost::noncopyable
public:
typedef boost::unique_lock<boost::mutex> lock;
bounded_buffer(int n) : begin(0), end(0), buffered(0), circular_buf(n) { }
bounded_buffer(int n) : boost::noncopyable(), begin(0), end(0), buffered(0), circular_buf(n) { }
void send (int m) {
lock lk(monitor);

View File

@@ -44,8 +44,8 @@ int main()
externally_locked_stream<std::ostream> mcout(std::cout, terminal_mutex);
externally_locked_stream<std::istream> mcin(std::cin, terminal_mutex);
scoped_thread<> t1(thread(use_cerr, boost::ref(mcerr)));
scoped_thread<> t2(thread(use_cout, boost::ref(mcout)));
scoped_thread<> t1(boost::thread(use_cerr, boost::ref(mcerr)));
scoped_thread<> t2(boost::thread(use_cout, boost::ref(mcout)));
this_thread::sleep_for(chrono::seconds(2));
std::string nm;
{

View File

@@ -0,0 +1,61 @@
// (C) Copyright 2012 Howard Hinnant
// (C) Copyright 2012 Vicente Botet
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// adapted from the example given by Howard Hinnant in
#define BOOST_THREAD_VERSION 4
#include <iostream>
#include <boost/thread/scoped_thread.hpp>
#include <boost/thread/ostream_buffer.hpp>
void use_cerr()
{
using namespace boost;
chrono::steady_clock::time_point tf = chrono::steady_clock::now() + chrono::seconds(5);
int i = 0;
while (chrono::steady_clock::now() < tf)
{
ostream_buffer<std::ostream> mcerr(std::cerr);
mcerr.stream() << "logging data to cerr " << i++ << "\n";
this_thread::sleep_for(chrono::milliseconds(250));
}
}
void use_cout()
{
using namespace boost;
chrono::steady_clock::time_point tf = chrono::steady_clock::now() + chrono::seconds(5);
int i = 0;
while (chrono::steady_clock::now() < tf)
{
ostream_buffer<std::ostream> mcout(std::cout);
mcout.stream() << "logging data to cout " << i++ << "\n";
this_thread::sleep_for(chrono::milliseconds(500));
}
}
int main()
{
using namespace boost;
scoped_thread<> t1(&use_cerr);
scoped_thread<> t2(&use_cout);
this_thread::sleep_for(chrono::seconds(2));
std::string nm = "he, he\n";
{
ostream_buffer<std::ostream> mcout(std::cout);
mcout.stream() << "Enter name: \n";
}
t1.join();
t2.join();
{
ostream_buffer<std::ostream> mcout(std::cout);
mcout.stream() << nm;
}
return 0;
}

View File

@@ -110,9 +110,9 @@ int main()
{
mcout << "begin of main" << std::endl;
scoped_thread<> t11(thread(producer, boost::ref(mcerr), boost::ref(sbq)));
scoped_thread<> t12(thread(producer, boost::ref(mcerr), boost::ref(sbq)));
scoped_thread<> t2(thread(consumer, boost::ref(mcout), boost::ref(sbq)));
scoped_thread<> t11(boost::thread(producer, boost::ref(mcerr), boost::ref(sbq)));
scoped_thread<> t12(boost::thread(producer, boost::ref(mcerr), boost::ref(sbq)));
scoped_thread<> t2(boost::thread(consumer, boost::ref(mcout), boost::ref(sbq)));
this_thread::sleep_for(chrono::seconds(1));

View File

@@ -110,9 +110,9 @@ int main()
{
mcout << "begin of main" << std::endl;
scoped_thread<> t11(thread(producer, boost::ref(mcerr), boost::ref(sbq)));
scoped_thread<> t12(thread(producer, boost::ref(mcerr), boost::ref(sbq)));
scoped_thread<> t2(thread(consumer, boost::ref(mcout), boost::ref(sbq)));
scoped_thread<> t11(boost::thread(producer, boost::ref(mcerr), boost::ref(sbq)));
scoped_thread<> t12(boost::thread(producer, boost::ref(mcerr), boost::ref(sbq)));
scoped_thread<> t2(boost::thread(consumer, boost::ref(mcout), boost::ref(sbq)));
this_thread::sleep_for(chrono::seconds(1));

View File

@@ -13,6 +13,9 @@ void do_something(int& i)
{
++i;
}
void f(int, int)
{
}
struct func
{
@@ -81,7 +84,10 @@ int main()
do_something_in_current_thread();
}
{
boost::scoped_thread<> g( &f, 1, 2 );
do_something_in_current_thread();
}
return 0;
}

147
example/thread_pool.cpp Normal file
View File

@@ -0,0 +1,147 @@
// Copyright (C) 2012-2013 Vicente Botet
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_THREAD_VERSION 4
#define BOOST_THREAD_USES_LOG
#define BOOST_THREAD_USES_LOG_THREAD_ID
#include <boost/thread/detail/log.hpp>
#include <boost/thread/thread_pool.hpp>
#include <boost/assert.hpp>
#include <string>
void p1()
{
BOOST_THREAD_LOG
<< boost::this_thread::get_id() << " P1" << BOOST_THREAD_END_LOG;
}
void p2()
{
BOOST_THREAD_LOG
<< boost::this_thread::get_id() << " P2" << BOOST_THREAD_END_LOG;
}
void push(boost::container::deque<boost::detail::function_wrapper> &data_, BOOST_THREAD_RV_REF(boost::detail::function_wrapper) closure)
{
try
{
BOOST_THREAD_LOG
<< boost::this_thread::get_id() << " <MAIN" << BOOST_THREAD_END_LOG;
boost::detail::function_wrapper v;
BOOST_THREAD_LOG
<< boost::this_thread::get_id() << " <MAIN" << BOOST_THREAD_END_LOG;
//v = boost::move(closure);
//v = boost::forward<boost::detail::function_wrapper>(closure);
BOOST_THREAD_LOG
<< boost::this_thread::get_id() << " <MAIN" << BOOST_THREAD_END_LOG;
data_.push_back(boost::move(closure));
BOOST_THREAD_LOG
<< boost::this_thread::get_id() << " <MAIN" << BOOST_THREAD_END_LOG;
//data_.push_back(boost::forward<boost::detail::function_wrapper>(closure));
BOOST_THREAD_LOG
<< boost::this_thread::get_id() << " <MAIN" << BOOST_THREAD_END_LOG;
}
catch (std::exception& ex)
{
BOOST_THREAD_LOG
<< "ERRORRRRR " << ex.what() << "" << BOOST_THREAD_END_LOG;
}
catch (...)
{
BOOST_THREAD_LOG
<< " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
}
}
template <typename Closure>
void submit(boost::container::deque<boost::detail::function_wrapper> &data_, BOOST_THREAD_FWD_REF(Closure) closure)
{
BOOST_THREAD_LOG
<< boost::this_thread::get_id() << " <MAIN" << BOOST_THREAD_END_LOG;
//work w =boost::move(closure);
//work_queue.push(boost::move(w));
//push(data_, boost::detail::function_wrapper(boost::forward<Closure>(closure)));
boost::detail::function_wrapper v =boost::forward<Closure>(closure);
BOOST_THREAD_LOG
<< boost::this_thread::get_id() << " <MAIN" << BOOST_THREAD_END_LOG;
push(data_, boost::move(v));
BOOST_THREAD_LOG
<< boost::this_thread::get_id() << " <MAIN" << BOOST_THREAD_END_LOG;
}
int main()
{
BOOST_THREAD_LOG
<< boost::this_thread::get_id() << " <MAIN" << BOOST_THREAD_END_LOG;
#if 0
{
try
{
boost::detail::function_wrapper f(&p1);
boost::container::deque<boost::detail::function_wrapper> data_;
data_.push_back(boost::move(f));
data_.push_back(boost::detail::function_wrapper(&p1));
submit(data_, &p1);
}
catch (std::exception& ex)
{
BOOST_THREAD_LOG
<< "ERRORRRRR " << ex.what() << "" << BOOST_THREAD_END_LOG;
}
catch (...)
{
BOOST_THREAD_LOG
<< " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
}
typedef boost::container::vector<boost::thread> thread_vector;
thread_vector threads;
}
#endif
#if 1
{
try
{
boost::thread_pool tp;
BOOST_THREAD_LOG
<< boost::this_thread::get_id() << " <MAIN" << BOOST_THREAD_END_LOG;
tp.submit(&p1);
BOOST_THREAD_LOG
<< boost::this_thread::get_id() << " <MAIN" << BOOST_THREAD_END_LOG;
tp.submit(&p2);
tp.submit(&p1);
tp.submit(&p2);
tp.submit(&p1);
tp.submit(&p2);
tp.submit(&p1);
tp.submit(&p2);
tp.submit(&p1);
tp.submit(&p2);
}
catch (std::exception& ex)
{
BOOST_THREAD_LOG
<< "ERRORRRRR " << ex.what() << "" << BOOST_THREAD_END_LOG;
return 1;
}
catch (...)
{
BOOST_THREAD_LOG
<< " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
return 2;
}
}
#endif
BOOST_THREAD_LOG
<< boost::this_thread::get_id() << "MAIN>" << BOOST_THREAD_END_LOG;
return 0;
}

View File

@@ -57,7 +57,8 @@ namespace boost
struct void_functor_barrier_reseter
{
unsigned int size_;
void_completion_function fct_;template <typename F>
void_completion_function fct_;
template <typename F>
#ifndef BOOST_NO_CXX11_HDR_FUNCTIONAL
void_functor_barrier_reseter(unsigned int size, BOOST_THREAD_RV_REF(F) funct)
: size_(size), fct_(boost::move(funct))
@@ -90,7 +91,7 @@ namespace boost
}
class barrier
{
static inline unsigned int check(unsigned int count)
static inline unsigned int check_counter(unsigned int count)
{
if (count == 0) boost::throw_exception(
thread_exception(system::errc::invalid_argument, "barrier constructor: count cannot be zero."));
@@ -104,7 +105,7 @@ namespace boost
BOOST_THREAD_NO_COPYABLE( barrier)
explicit barrier(unsigned int count) :
m_count(check(count)), m_generation(0), fct_(thread_detail::default_barrier_reseter(count))
m_count(check_counter(count)), m_generation(0), fct_(thread_detail::default_barrier_reseter(count))
{
}
@@ -120,7 +121,7 @@ namespace boost
typename is_void<typename result_of<F>::type>::type, dummy*
>::type=0
)
: m_count(check(count)),
: m_count(check_counter(count)),
m_generation(0),
fct_(thread_detail::void_functor_barrier_reseter(count,
#ifndef BOOST_NO_CXX11_HDR_FUNCTIONAL
@@ -145,7 +146,7 @@ namespace boost
typename is_same<typename result_of<F>::type, unsigned int>::type, dummy*
>::type=0
)
: m_count(check(count)),
: m_count(check_counter(count)),
m_generation(0),
fct_(
#ifndef BOOST_NO_CXX11_HDR_FUNCTIONAL
@@ -158,7 +159,7 @@ namespace boost
}
barrier(unsigned int count, void(*funct)()) :
m_count(check(count)), m_generation(0),
m_count(check_counter(count)), m_generation(0),
fct_(funct
? thread_detail::size_completion_function(thread_detail::void_fct_ptr_barrier_reseter(count, funct))
: thread_detail::size_completion_function(thread_detail::default_barrier_reseter(count))
@@ -166,7 +167,7 @@ namespace boost
{
}
barrier(unsigned int count, unsigned int(*funct)()) :
m_count(check(count)), m_generation(0),
m_count(check_counter(count)), m_generation(0),
fct_(funct
? thread_detail::size_completion_function(funct)
: thread_detail::size_completion_function(thread_detail::default_barrier_reseter(count))

View File

@@ -0,0 +1,94 @@
// Copyright (C) 2013 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// 2013/09 Vicente J. Botet Escriba
// Adapt to boost from CCIA C++11 implementation
// Make use of Boost.Move
#ifndef BOOST_THREAD_DETAIL_FUNCTION_WRAPPER_HPP
#define BOOST_THREAD_DETAIL_FUNCTION_WRAPPER_HPP
#include <boost/config.hpp>
#include <boost/thread/detail/memory.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/interprocess/smart_ptr/unique_ptr.hpp>
#include <memory>
#include <functional>
namespace boost
{
namespace detail
{
class function_wrapper
{
struct impl_base
{
virtual void call()=0;
virtual ~impl_base()
{
}
};
//typedef boost::interprocess::unique_ptr<impl_base, boost::default_delete<impl_base> > impl_base_type;
impl_base* impl;
template <typename F>
struct impl_type: impl_base
{
F f;
impl_type(F const &f_)
: f(f_)
{}
impl_type(BOOST_THREAD_RV_REF(F) f_)
: f(boost::move(f_))
{}
void call()
{
f();
}
};
public:
BOOST_THREAD_MOVABLE_ONLY(function_wrapper)
//#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
template<typename F>
function_wrapper(F const& f):
impl(new impl_type<F>(f))
{}
//#endif
template<typename F>
function_wrapper(BOOST_THREAD_RV_REF(F) f):
impl(new impl_type<F>(boost::forward<F>(f)))
{}
function_wrapper(BOOST_THREAD_RV_REF(function_wrapper) other) BOOST_NOEXCEPT :
impl(other.impl)
{
other.impl = 0;
}
function_wrapper()
: impl(0)
{
}
~function_wrapper()
{
delete impl;
}
function_wrapper& operator=(BOOST_THREAD_RV_REF(function_wrapper) other) BOOST_NOEXCEPT
{
impl=other.impl;
other.impl=0;
return *this;
}
void operator()()
{ impl->call();}
};
}
}
#endif // header

View File

@@ -546,6 +546,7 @@ namespace boost
void detach();
static unsigned hardware_concurrency() BOOST_NOEXCEPT;
static unsigned physical_concurrency() BOOST_NOEXCEPT;
#define BOOST_THREAD_DEFINES_THREAD_NATIVE_HANDLE
typedef detail::thread_data_base::native_handle_type native_handle_type;
@@ -826,6 +827,19 @@ namespace boost
};
void BOOST_THREAD_DECL add_thread_exit_function(thread_exit_function_base*);
struct shared_state_base;
#if defined(BOOST_THREAD_PLATFORM_WIN32)
inline void make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
{
detail::thread_data_base* const current_thread_data(detail::get_current_thread_data());
if(current_thread_data)
{
current_thread_data->make_ready_at_thread_exit(as);
}
}
#else
void BOOST_THREAD_DECL make_ready_at_thread_exit(shared_ptr<shared_state_base> as);
#endif
}
namespace this_thread

View File

@@ -213,7 +213,7 @@ namespace boost
bool is_deferred_;
launch policy_;
bool is_constructed;
boost::mutex mutex;
mutable boost::mutex mutex;
boost::condition_variable waiters;
waiter_list external_waiters;
boost::function<void()> callback;
@@ -418,7 +418,7 @@ namespace boost
{
throw_exception(promise_already_satisfied());
}
get_current_thread_data()->make_ready_at_thread_exit(shared_from_this());
detail::make_ready_at_thread_exit(shared_from_this());
}
#endif
@@ -431,10 +431,11 @@ namespace boost
}
exception=e;
this->is_constructed = true;
get_current_thread_data()->make_ready_at_thread_exit(shared_from_this());
detail::make_ready_at_thread_exit(shared_from_this());
}
bool has_value()
bool has_value() const
{
boost::lock_guard<boost::mutex> lock(mutex);
return done && !(exception
@@ -444,7 +445,7 @@ namespace boost
);
}
bool has_value(unique_lock<boost::mutex>& )
bool has_value(unique_lock<boost::mutex>& ) const
{
return done && !(exception
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
@@ -453,7 +454,7 @@ namespace boost
);
}
bool has_exception()
bool has_exception() const
{
boost::lock_guard<boost::mutex> lock(mutex);
return done && (exception
@@ -463,7 +464,7 @@ namespace boost
);
}
bool has_exception(unique_lock<boost::mutex>&)
bool has_exception(unique_lock<boost::mutex>&) const
{
return done && (exception
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
@@ -472,16 +473,16 @@ namespace boost
);
}
bool is_deferred() const BOOST_NOEXCEPT {
bool is_deferred(boost::lock_guard<boost::mutex>&) const {
return is_deferred_;
}
launch launch_policy() const BOOST_NOEXCEPT
launch launch_policy(boost::unique_lock<boost::mutex>&) const
{
return policy_;
}
future_state::state get_state()
future_state::state get_state() const
{
boost::lock_guard<boost::mutex> guard(mutex);
if(!done)
@@ -494,6 +495,23 @@ namespace boost
}
}
exception_ptr get_exception_ptr()
{
boost::unique_lock<boost::mutex> lock(mutex);
return get_exception_ptr(lock);
}
exception_ptr get_exception_ptr(boost::unique_lock<boost::mutex>& lock)
{
wait_internal(lock, false);
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
if(thread_was_interrupted)
{
return copy_exception(boost::thread_interrupted());
}
#endif
return exception;
}
template<typename F,typename U>
void set_wait_callback(F f,U* u)
{
@@ -671,7 +689,7 @@ namespace boost
result.reset(new T(result_));
this->is_constructed = true;
get_current_thread_data()->make_ready_at_thread_exit(shared_from_this());
detail::make_ready_at_thread_exit(shared_from_this());
}
//void set_value_at_thread_exit(BOOST_THREAD_RV_REF(T) result_)
void set_value_at_thread_exit(rvalue_source_type result_)
@@ -682,7 +700,7 @@ namespace boost
result.reset(new T(boost::move(result_)));
//future_traits<T>::init(result,static_cast<rvalue_source_type>(result_));
this->is_constructed = true;
get_current_thread_data()->make_ready_at_thread_exit(shared_from_this());
detail::make_ready_at_thread_exit(shared_from_this());
}
@@ -743,7 +761,7 @@ namespace boost
//future_traits<T>::init(result,result_);
result= &result_;
this->is_constructed = true;
get_current_thread_data()->make_ready_at_thread_exit(shared_from_this());
detail::make_ready_at_thread_exit(shared_from_this());
}
private:
@@ -789,7 +807,7 @@ namespace boost
throw_exception(promise_already_satisfied());
}
this->is_constructed = true;
get_current_thread_data()->make_ready_at_thread_exit(shared_from_this());
detail::make_ready_at_thread_exit(shared_from_this());
}
private:
shared_state(shared_state const&);
@@ -1294,7 +1312,7 @@ namespace boost
future_.swap(that.future_);
}
// functions to check state, and wait for ready
state get_state() const BOOST_NOEXCEPT
state get_state() const
{
if(!future_)
{
@@ -1303,27 +1321,34 @@ namespace boost
return future_->get_state();
}
bool is_ready() const BOOST_NOEXCEPT
bool is_ready() const
{
return get_state()==future_state::ready;
}
bool has_exception() const BOOST_NOEXCEPT
bool has_exception() const
{
return future_ && future_->has_exception();
}
bool has_value() const BOOST_NOEXCEPT
bool has_value() const
{
return future_ && future_->has_value();
}
launch launch_policy() const BOOST_NOEXCEPT
launch launch_policy(boost::unique_lock<boost::mutex>& lk) const
{
if ( future_ ) return future_->launch_policy();
if ( future_ ) return future_->launch_policy(lk);
else return launch(launch::none);
}
exception_ptr get_exception_ptr()
{
return future_
? future_->get_exception_ptr()
: exception_ptr();
}
bool valid() const BOOST_NOEXCEPT
{
return future_ != 0;
@@ -3938,13 +3963,13 @@ namespace boost
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
if (int(this->launch_policy()) & int(launch::async))
if (int(this->launch_policy(lock)) & int(launch::async))
{
return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
lock, boost::move(*this), boost::forward<F>(func)
);
}
else if (int(this->launch_policy()) & int(launch::deferred))
else if (int(this->launch_policy(lock)) & int(launch::deferred))
{
this->future_->wait_internal(lock);
return boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
@@ -4056,13 +4081,13 @@ namespace boost
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
if (int(this->launch_policy()) & int(launch::async))
if (int(this->launch_policy(lock)) & int(launch::async))
{
return boost::detail::make_future_async_continuation_shared_state<shared_future<R>, future_type, F>(
lock, boost::move(*this), boost::forward<F>(func)
);
}
else if (int(this->launch_policy()) & int(launch::deferred))
else if (int(this->launch_policy(lock)) & int(launch::deferred))
{
this->future_->wait_internal(lock);
return boost::detail::make_future_deferred_continuation_shared_state<shared_future<R>, future_type, F>(

View File

@@ -1112,6 +1112,10 @@ namespace boost
{
return exclusive.owns_lock();
}
Mutex* mutex() const BOOST_NOEXCEPT
{
return exclusive.mutex();
}
};
BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) upgrade_to_unique_lock<Mutex> BOOST_THREAD_DCL_MOVABLE_END
@@ -1187,7 +1191,7 @@ private unique_lock<Mutex>
{
return base::owns_lock();
}
Mutex* mutex() const
Mutex* mutex() const BOOST_NOEXCEPT
{
return base::mutex();
}

View File

@@ -0,0 +1,35 @@
// (C) Copyright 2013 Vicente J. Botet Escriba
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_THREAD_OSTREAM_BUFFER_HPP
#define BOOST_THREAD_OSTREAM_BUFFER_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/delete.hpp>
#include <sstream>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
template <typename OStream>
class ostream_buffer
{
public:
typedef std::basic_ostringstream<typename OStream::char_type, typename OStream::traits_type> stream_type;
ostream_buffer(OStream& os) : os_(os) {}
~ostream_buffer() { os_ << o_str_.str(); }
stream_type& stream() { return o_str_; }
private:
OStream& os_;
stream_type o_str_;
};
}
#include <boost/config/abi_suffix.hpp>
#endif // header

View File

@@ -200,15 +200,15 @@ namespace boost
#if defined BOOST_THREAD_USES_DATETIME
template<typename lock_type>
bool timed_wait(lock_type& m,boost::system_time const& wait_until)
bool timed_wait(lock_type& m,boost::system_time const& abs_time)
{
struct timespec const timeout=detail::to_timespec(wait_until);
struct timespec const timeout=detail::to_timespec(abs_time);
return do_wait_until(m, timeout);
}
template<typename lock_type>
bool timed_wait(lock_type& m,xtime const& wait_until)
bool timed_wait(lock_type& m,xtime const& abs_time)
{
return timed_wait(m,system_time(wait_until));
return timed_wait(m,system_time(abs_time));
}
template<typename lock_type,typename duration_type>
@@ -218,20 +218,20 @@ namespace boost
}
template<typename lock_type,typename predicate_type>
bool timed_wait(lock_type& m,boost::system_time const& wait_until,predicate_type pred)
bool timed_wait(lock_type& m,boost::system_time const& abs_time, predicate_type pred)
{
while (!pred())
{
if(!timed_wait(m, wait_until))
if(!timed_wait(m, abs_time))
return pred();
}
return true;
}
template<typename lock_type,typename predicate_type>
bool timed_wait(lock_type& m,xtime const& wait_until,predicate_type pred)
bool timed_wait(lock_type& m,xtime const& abs_time, predicate_type pred)
{
return timed_wait(m,system_time(wait_until),pred);
return timed_wait(m,system_time(abs_time),pred);
}
template<typename lock_type,typename duration_type,typename predicate_type>

View File

@@ -98,21 +98,21 @@ namespace boost
#if defined BOOST_THREAD_USES_DATETIME
inline bool timed_wait(
unique_lock<mutex>& m,
boost::system_time const& wait_until)
boost::system_time const& abs_time)
{
#if defined BOOST_THREAD_WAIT_BUG
struct timespec const timeout=detail::to_timespec(wait_until + BOOST_THREAD_WAIT_BUG);
struct timespec const timeout=detail::to_timespec(abs_time + BOOST_THREAD_WAIT_BUG);
return do_wait_until(m, timeout);
#else
struct timespec const timeout=detail::to_timespec(wait_until);
struct timespec const timeout=detail::to_timespec(abs_time);
return do_wait_until(m, timeout);
#endif
}
bool timed_wait(
unique_lock<mutex>& m,
xtime const& wait_until)
xtime const& abs_time)
{
return timed_wait(m,system_time(wait_until));
return timed_wait(m,system_time(abs_time));
}
template<typename duration_type>
@@ -126,11 +126,11 @@ namespace boost
template<typename predicate_type>
bool timed_wait(
unique_lock<mutex>& m,
boost::system_time const& wait_until,predicate_type pred)
boost::system_time const& abs_time,predicate_type pred)
{
while (!pred())
{
if(!timed_wait(m, wait_until))
if(!timed_wait(m, abs_time))
return pred();
}
return true;
@@ -139,9 +139,9 @@ namespace boost
template<typename predicate_type>
bool timed_wait(
unique_lock<mutex>& m,
xtime const& wait_until,predicate_type pred)
xtime const& abs_time,predicate_type pred)
{
return timed_wait(m,system_time(wait_until),pred);
return timed_wait(m,system_time(abs_time),pred);
}
template<typename duration_type,typename predicate_type>

View File

@@ -47,9 +47,8 @@ namespace boost
*
*/
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class F, class ...Args>
explicit strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Args)... args,
typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type=0) :
template <class F, class ...Args, typename = typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type>
explicit strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Args)... args) :
t_(boost::forward<F>(f), boost::forward<Args>(args)...) {}
#else
template <class F>
@@ -138,9 +137,8 @@ namespace boost
*/
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class F, class ...Args>
explicit scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Args)... args,
typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type=0) :
template <class F, class ...Args, typename = typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type>
explicit scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Args)... args) :
t_(boost::forward<F>(f), boost::forward<Args>(args)...) {}
#else
template <class F>
@@ -263,11 +261,15 @@ namespace boost
}
#endif
static unsigned hardware_concurrency()BOOST_NOEXCEPT
static unsigned hardware_concurrency() BOOST_NOEXCEPT
{
return thread::hardware_concurrency();
}
static unsigned physical_concurrency() BOOST_NOEXCEPT
{
return thread::physical_concurrency();
}
};
/**

View File

@@ -31,7 +31,9 @@ namespace boost
struct no_block_tag{};
BOOST_CONSTEXPR_OR_CONST no_block_tag no_block = {};
struct sync_queue_is_closed : std::exception {};
struct sync_queue_is_closed : std::exception
{
};
template <typename ValueType>
class sync_bounded_queue
@@ -155,6 +157,13 @@ namespace boost
out_ = inc(out_);
notify_not_full_if_needed(lk);
}
inline value_type pull(unique_lock<mutex>& lk)
{
value_type elem = boost::move(data_[out_]);
out_ = inc(out_);
notify_not_full_if_needed(lk);
return boost::move(elem);
}
inline boost::shared_ptr<value_type> ptr_pull(unique_lock<mutex>& lk)
{
shared_ptr<value_type> res = make_shared<value_type>(boost::move(data_[out_]));
@@ -408,9 +417,9 @@ namespace boost
{
try
{
value_type elem;
pull(elem);
return boost::move(elem);
unique_lock<mutex> lk(mtx_);
wait_until_not_empty(lk);
return pull(lk);
}
catch (...)
{
@@ -529,7 +538,7 @@ namespace boost
try
{
unique_lock<mutex> lk(mtx_);
return try_push(elem, lk);
return try_push(boost::move(elem), lk);
}
catch (...)
{
@@ -548,7 +557,7 @@ namespace boost
{
return false;
}
return try_push(elem, lk);
return try_push(boost::move(elem), lk);
}
catch (...)
{
@@ -563,7 +572,7 @@ namespace boost
try
{
unique_lock<mutex> lk(mtx_);
push_at(elem, wait_until_not_full(lk), lk);
push_at(boost::move(elem), wait_until_not_full(lk), lk);
}
catch (...)
{
@@ -575,7 +584,7 @@ namespace boost
template <typename ValueType>
sync_bounded_queue<ValueType>& operator<<(sync_bounded_queue<ValueType>& sbq, BOOST_THREAD_RV_REF(ValueType) elem)
{
sbq.push(boost::forward<ValueType>(elem));
sbq.push(boost::move(elem));
return sbq;
}

View File

@@ -52,10 +52,11 @@ namespace boost
inline void close();
inline void push(const value_type& x);
inline void push(BOOST_THREAD_RV_REF(value_type) x);
inline bool try_push(const value_type& x);
inline bool try_push(BOOST_THREAD_RV_REF(value_type) x);
inline bool try_push(no_block_tag, const value_type& x);
inline void push(BOOST_THREAD_RV_REF(value_type) x);
inline bool try_push(BOOST_THREAD_RV_REF(value_type) x);
inline bool try_push(no_block_tag, BOOST_THREAD_RV_REF(value_type) x);
// Observers/Modifiers
@@ -114,6 +115,12 @@ namespace boost
elem = boost::move(data_.front());
data_.pop_front();
}
inline value_type pull(unique_lock<mutex>& )
{
value_type e = boost::move(data_.front());
data_.pop_front();
return boost::move(e);
}
inline boost::shared_ptr<value_type> ptr_pull(unique_lock<mutex>& )
{
shared_ptr<value_type> res = make_shared<value_type>(boost::move(data_.front()));
@@ -129,7 +136,7 @@ namespace boost
inline void push(BOOST_THREAD_RV_REF(value_type) elem, unique_lock<mutex>& lk)
{
data_.push(boost::move(elem));
data_.push_back(boost::move(elem));
notify_not_empty_if_needed(lk);
}
};
@@ -346,9 +353,9 @@ namespace boost
{
try
{
value_type elem;
pull(elem);
return boost::move(elem);
unique_lock<mutex> lk(mtx_);
wait_until_not_empty(lk);
return pull(lk);
}
catch (...)
{
@@ -431,7 +438,7 @@ namespace boost
bool sync_queue<ValueType>::try_push(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
{
throw_if_closed(lk);
push(boost::forward<ValueType>(elem), lk);
push(boost::move(elem), lk);
return true;
}
@@ -441,7 +448,7 @@ namespace boost
try
{
unique_lock<mutex> lk(mtx_);
return try_push(elem, lk);
return try_push(boost::move(elem), lk);
}
catch (...)
{
@@ -460,7 +467,7 @@ namespace boost
{
return false;
}
return try_push(elem, lk);
return try_push(boost::move(elem), lk);
}
catch (...)
{
@@ -476,7 +483,7 @@ namespace boost
{
unique_lock<mutex> lk(mtx_);
throw_if_closed(lk);
push(elem, lk);
push(boost::move(elem), lk);
}
catch (...)
{
@@ -488,7 +495,7 @@ namespace boost
template <typename ValueType>
sync_queue<ValueType>& operator<<(sync_queue<ValueType>& sbq, BOOST_THREAD_RV_REF(ValueType) elem)
{
sbq.push(boost::forward<ValueType>(elem));
sbq.push(boost::move(elem));
return sbq;
}

View File

@@ -26,10 +26,12 @@
//#endif
#if ! defined(BOOST_THREAD_NO_SYNCHRONIZE)
#include <tuple> // todo change to <boost/tuple.hpp> once Boost.Tuple or Boost.Fusion provides Move semantics.
#include <tuple> // todo change to <boost/tuple.hpp> once Boost.Tuple or Boost.Fusion provides Move semantics on C++98 compilers.
#include <functional>
#endif
#include <boost/utility/result_of.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
@@ -593,8 +595,6 @@ namespace boost
boost::swap(value_, rhs);
}
/**
* Essentially calling a method obj->foo(x, y, z) calls the method foo(x, y, z) inside a critical section as
* long-lived as the call itself.
@@ -613,14 +613,81 @@ namespace boost
return BOOST_THREAD_MAKE_RV_REF((const_strict_lock_ptr<T,Lockable>(value_, mtx_)));
}
/**
* Call function on a locked block.
*
* @requires fct(value_) is well formed.
*
* Example
* void fun(synchronized_value<vector<int>> & v) {
* v ( [](vector<int>> & vec)
* {
* vec.push_back(42);
* assert(vec.back() == 42);
* } );
* }
*/
template <typename F>
inline
typename boost::result_of<F(value_type&)>::type
operator()(BOOST_THREAD_RV_REF(F) fct)
{
strict_lock<mutex_type> lk(mtx_);
return fct(value_);
}
template <typename F>
inline
typename boost::result_of<F(value_type const&)>::type
operator()(BOOST_THREAD_RV_REF(F) fct) const
{
strict_lock<mutex_type> lk(mtx_);
return fct(value_);
}
#if defined BOOST_NO_CXX11_RVALUE_REFERENCES
template <typename F>
inline
typename boost::result_of<F(value_type&)>::type
operator()(F const & fct)
{
strict_lock<mutex_type> lk(mtx_);
return fct(value_);
}
template <typename F>
inline
typename boost::result_of<F(value_type const&)>::type
operator()(F const & fct) const
{
strict_lock<mutex_type> lk(mtx_);
return fct(value_);
}
template <typename R>
inline
R operator()(R(*fct)(value_type&))
{
strict_lock<mutex_type> lk(mtx_);
return fct(value_);
}
template <typename R>
inline
R operator()(R(*fct)(value_type const&)) const
{
strict_lock<mutex_type> lk(mtx_);
return fct(value_);
}
#endif
/**
* The synchronize() factory make easier to lock on a scope.
* As discussed, operator-> can only lock over the duration of a call, so it is insufficient for complex operations.
* With synchronize() you get to lock the object in a scoped and to directly access the object inside that scope.
*
* Example
* void fun(synchronized_value<vector<int>> & vec) {
* auto&& vec=vec.synchronize();
* void fun(synchronized_value<vector<int>> & v) {
* auto&& vec=v.synchronize();
* vec.push_back(42);
* assert(vec.back() == 42);
* }
@@ -880,9 +947,9 @@ namespace boost
//Hash support
template <class T> struct hash;
template <typename T, typename L>
struct hash<synchronized_value<T,L> >;
// template <class T> struct hash;
// template <typename T, typename L>
// struct hash<synchronized_value<T,L> >;
// Comparison with T
template <typename T, typename L>

View File

@@ -0,0 +1,192 @@
// Copyright (C) 2013 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// 2013/09 Vicente J. Botet Escriba
// Adapt to boost from CCIA C++11 implementation
// first implementation of a simple pool thread using a vector of threads and a sync_queue.
#ifndef BOOST_THREAD_THREAD_POOL_HPP
#define BOOST_THREAD_THREAD_POOL_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/scoped_thread.hpp>
#include <boost/thread/sync_queue.hpp>
#include <boost/thread/detail/function_wrapper.hpp>
#ifdef BOOST_NO_CXX11_HDR_FUNCTIONAL
#include <boost/function.hpp>
#else
#include <functional>
#endif
#if defined BOOST_NO_CXX11_RVALUE_REFERENCES
#include <boost/container/vector.hpp>
#else
#include <vector>
#endif
#include <boost/config/abi_prefix.hpp>
namespace boost
{
class thread_pool
{
/// type-erasure to store the works to do
typedef detail::function_wrapper work;
/// the kind of stored threads are scoped threads to ensure that the threads are joined.
/// A move aware vector type
typedef scoped_thread<> thread_t;
#if defined BOOST_NO_CXX11_RVALUE_REFERENCES
typedef container::vector<thread_t> thread_vector;
#else
typedef std::vector<thread_t> thread_vector;
#endif
/// the thread safe work queue
sync_queue<work > work_queue;
/// A move aware vector
thread_vector threads;
/**
* Effects: try to execute one task.
* Returns: whether a task has been executed.
* Throws: whatever the current task constructor throws or the task() throws.
*/
bool try_executing_one()
{
work task;
try
{
if (work_queue.try_pull(task))
{
task();
return true;
}
return false;
}
catch (std::exception& ex)
{
return false;
}
catch (...)
{
return false;
}
}
/**
* Effects: schedule one task or yields
* Throws: whatever the current task constructor throws or the task() throws.
*/
void schedule_one_or_yield()
{
if ( ! try_executing_one())
{
this_thread::yield();
}
}
/**
* The main loop of the worker threads
*/
void worker_thread()
{
while (!is_closed())
{
schedule_one_or_yield();
}
}
public:
/// thread_pool is not copyable.
BOOST_THREAD_NO_COPYABLE(thread_pool)
/**
* Effects: creates a thread pool that runs closures on @c thread_count threads.
*/
thread_pool(unsigned const thread_count = thread::hardware_concurrency())
{
try
{
for (unsigned i = 0; i < thread_count; ++i)
{
threads.push_back(thread_t(&thread_pool::worker_thread, this));
}
}
catch (...)
{
close();
throw;
}
}
/**
* Effects: Destroys the thread pool.
* Synchronization: The completion of all the closures happen before the completion of the thread pool destructor.
*/
~thread_pool()
{
// signal to all the worker threads that there will be no more submissions.
close();
// joins all the threads as the threads were scoped_threads
}
/**
* Effects: close the thread_pool for submissions. The worker threads will work until
*/
void close()
{
work_queue.close();
}
/**
* Returns: whether the pool is closed for submissions.
*/
bool is_closed()
{
return work_queue.closed();
}
/**
* Effects: The specified function will be scheduled for execution at some point in the future.
* If invoking closure throws an exception the thread pool will call std::terminate, as is the case with threads.
* Synchronization: completion of closure on a particular thread happens before destruction of thread's thread local variables.
* Throws: sync_queue_is_closed if the thread pool is closed.
*
*/
template <typename Closure>
void submit(Closure const& closure)
{
work w ((closure));
work_queue.push(boost::move(w));
//work_queue.push(work(closure));
}
template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
{
work w =boost::move(closure);
work_queue.push(boost::move(w));
//work_queue.push(work(boost::move(closure)));
}
/**
* This must be called from an scheduled task.
* Effects: reschedule functions until pred()
*/
template <typename Pred>
void reschedule_until(Pred const& pred)
{
do {
schedule_one_or_yield();
} while (! pred());
}
};
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -191,18 +191,17 @@ namespace boost
struct entry_manager
{
entry_ptr const entry;
boost::mutex& internal_mutex;
BOOST_THREAD_NO_COPYABLE(entry_manager)
entry_manager(entry_ptr const& entry_):
entry(entry_)
entry_manager(entry_ptr const& entry_, boost::mutex& mutex_):
entry(entry_), internal_mutex(mutex_)
{}
~entry_manager()
{
//if(! entry->is_notified()) // several regression #7657
{
boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
entry->remove_waiter();
}
}
list_entry* operator->()
@@ -218,7 +217,7 @@ namespace boost
{
relocker<lock_type> locker(lock);
entry_manager entry(get_wait_entry());
entry_manager entry(get_wait_entry(), internal_mutex);
locker.unlock();
@@ -366,7 +365,11 @@ namespace boost
const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
do_wait(lock, ceil<milliseconds>(t-Clock::now()).count());
chrono::time_point<Clock, Duration> now = Clock::now();
if (t<=now) {
return cv_status::timeout;
}
do_wait(lock, ceil<milliseconds>(t-now).count());
return Clock::now() < t ? cv_status::no_timeout :
cv_status::timeout;
}
@@ -378,6 +381,10 @@ namespace boost
const chrono::duration<Rep, Period>& d)
{
using namespace chrono;
if (d<=chrono::duration<Rep, Period>::zero()) {
return cv_status::timeout;
}
steady_clock::time_point c_now = steady_clock::now();
do_wait(lock, ceil<milliseconds>(d).count());
return steady_clock::now() - c_now < d ? cv_status::no_timeout :
@@ -479,7 +486,11 @@ namespace boost
const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
do_wait(lock, ceil<milliseconds>(t-Clock::now()).count());
chrono::time_point<Clock, Duration> now = Clock::now();
if (t<=now) {
return cv_status::timeout;
}
do_wait(lock, ceil<milliseconds>(t-now).count());
return Clock::now() < t ? cv_status::no_timeout :
cv_status::timeout;
}
@@ -491,6 +502,9 @@ namespace boost
const chrono::duration<Rep, Period>& d)
{
using namespace chrono;
if (d<=chrono::duration<Rep, Period>::zero()) {
return cv_status::timeout;
}
steady_clock::time_point c_now = steady_clock::now();
do_wait(lock, ceil<milliseconds>(d).count());
return steady_clock::now() - c_now < d ? cv_status::no_timeout :

View File

@@ -9,33 +9,32 @@
// check if we use MFC
#ifdef _AFXDLL
# if defined(_AFXEXT)
# if defined(_AFXEXT)
// can't use ExtRawDllMain from afxdllx.h as it also defines the symbol _pRawDllMain
extern "C"
inline BOOL WINAPI ExtRawDllMain(HINSTANCE, DWORD dwReason, LPVOID)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
// save critical data pointers before running the constructors
AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
pModuleState->m_pClassInit = pModuleState->m_classList;
pModuleState->m_pFactoryInit = pModuleState->m_factoryList;
pModuleState->m_classList.m_pHead = NULL;
pModuleState->m_factoryList.m_pHead = NULL;
}
return TRUE; // ok
if (dwReason == DLL_PROCESS_ATTACH)
{
// save critical data pointers before running the constructors
AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
pModuleState->m_pClassInit = pModuleState->m_classList;
pModuleState->m_pFactoryInit = pModuleState->m_factoryList;
pModuleState->m_classList.m_pHead = NULL;
pModuleState->m_factoryList.m_pHead = NULL;
}
return TRUE; // ok
}
extern "C" __declspec(selectany) BOOL (WINAPI * const _pRawDllMainOrig)(HANDLE, DWORD, LPVOID) = &ExtRawDllMain;
# elif defined(_USRDLL)
# elif defined(_USRDLL)
extern "C" BOOL WINAPI RawDllMain(HANDLE, DWORD dwReason, LPVOID);
extern "C" __declspec(selectany) BOOL (WINAPI * const _pRawDllMainOrig)(HANDLE, DWORD, LPVOID) = &RawDllMain;
# endif
# endif
#endif
#endif

View File

@@ -363,7 +363,7 @@ namespace boost
}
}
#else
#ifndef BOOST_MSVC
#if ! defined(BOOST_MSVC) && ! defined(BOOST_INTEL)
template<typename Function>
void call_once(once_flag& flag,Function f)
{

View File

@@ -148,7 +148,7 @@ namespace boost
virtual void run()=0;
void notify_all_at_thread_exit(condition_variable* cv, mutex* m)
virtual void notify_all_at_thread_exit(condition_variable* cv, mutex* m)
{
notify.push_back(std::pair<condition_variable*, mutex*>(cv, m));
}

View File

@@ -15,11 +15,12 @@
#include <boost/assert.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/detail/interlocked.hpp>
//#include <boost/detail/win/synchronization.hpp>
#include <algorithm>
#ifndef BOOST_THREAD_WIN32_HAS_GET_TICK_COUNT_64
#if _WIN32_WINNT >= 0x0600
//#define BOOST_THREAD_WIN32_HAS_GET_TICK_COUNT_64
#if _WIN32_WINNT >= 0x0600 && ! defined _WIN32_WINNT_WS08
#define BOOST_THREAD_WIN32_HAS_GET_TICK_COUNT_64
#endif
#endif

View File

@@ -27,6 +27,15 @@
#include <unistd.h>
#endif
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/lexical_cast.hpp>
#include <fstream>
#include <string>
#include <set>
#include <vector>
#include "./timeconv.inl"
namespace boost
@@ -187,7 +196,9 @@ namespace boost
return 0;
}
}
}
namespace detail
{
struct externally_launched_thread:
detail::thread_data_base
{
@@ -197,7 +208,12 @@ namespace boost
interrupt_enabled=false;
#endif
}
~externally_launched_thread() {
BOOST_ASSERT(notify.empty());
notify.clear();
BOOST_ASSERT(async_states_.empty());
async_states_.clear();
}
void run()
{}
void notify_all_at_thread_exit(condition_variable*, mutex*)
@@ -208,18 +224,18 @@ namespace boost
void operator=(externally_launched_thread&);
};
detail::thread_data_base* make_external_thread_data()
thread_data_base* make_external_thread_data()
{
detail::thread_data_base* const me(new externally_launched_thread());
thread_data_base* const me(detail::heap_new<externally_launched_thread>());
me->self.reset(me);
set_current_thread_data(me);
return me;
}
detail::thread_data_base* get_or_make_current_thread_data()
thread_data_base* get_or_make_current_thread_data()
{
detail::thread_data_base* current_thread_data(detail::get_current_thread_data());
thread_data_base* current_thread_data(get_current_thread_data());
if(!current_thread_data)
{
current_thread_data=make_external_thread_data();
@@ -536,6 +552,56 @@ namespace boost
#endif
}
unsigned thread::physical_concurrency() BOOST_NOEXCEPT
{
#ifdef __linux__
try {
using namespace std;
ifstream proc_cpuinfo ("/proc/cpuinfo");
unsigned current_processor = 0;
const string physical_id("physical id"), core_id("core id");
typedef std::pair<unsigned, unsigned> core_entry; // [physical ID, core id]
std::set<core_entry> cores;
core_entry current_core_entry;
for (string line; getline(proc_cpuinfo, line); ) {
vector<string> key_val(2);
boost::split(key_val, line, boost::is_any_of(":"));
string key = key_val[0];
string value = key_val[1];
boost::trim(key);
boost::trim(value);
if (key == physical_id) {
current_core_entry.first = boost::lexical_cast<unsigned>(value);
continue;
}
if (key == core_id) {
current_core_entry.second = boost::lexical_cast<unsigned>(value);
cores.insert(current_core_entry);
continue;
}
}
return cores.size();
} catch(...) {
return 0;
}
#elif defined(__APPLE__)
int count;
size_t size=sizeof(count);
return sysctlbyname("hw.physicalcpu",&count,&size,NULL,0)?0:count;
#else
return hardware_concurrency();
#endif
}
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
void thread::interrupt()
{
@@ -663,7 +729,7 @@ namespace boost
{
detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data());
thread_exit_callback_node* const new_node=
new thread_exit_callback_node(func,current_thread_data->thread_exit_callbacks);
heap_new<thread_exit_callback_node>(func,current_thread_data->thread_exit_callbacks);
current_thread_data->thread_exit_callbacks=new_node;
}
@@ -701,8 +767,11 @@ namespace boost
void erase_tss_node(void const* key)
{
detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data());
current_thread_data->tss_data.erase(key);
detail::thread_data_base* const current_thread_data(get_current_thread_data());
if(current_thread_data)
{
current_thread_data->tss_data.erase(key);
}
}
void set_tss_data(void const* key,
@@ -740,6 +809,17 @@ namespace boost
current_thread_data->notify_all_at_thread_exit(&cond, lk.release());
}
}
namespace detail {
void BOOST_THREAD_DECL make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
{
detail::thread_data_base* const current_thread_data(detail::get_current_thread_data());
if(current_thread_data)
{
current_thread_data->make_ready_at_thread_exit(as);
}
}
}

View File

@@ -22,6 +22,7 @@
#include <boost/thread/future.hpp>
#include <boost/assert.hpp>
#include <boost/cstdint.hpp>
#if defined BOOST_THREAD_USES_DATETIME
#include <boost/date_time/posix_time/conversion.hpp>
#endif
@@ -128,7 +129,7 @@ namespace boost
return ret;
}
typedef void* uintptr_t;
//typedef void* uintptr_t;
inline uintptr_t _beginthreadex(void* security, unsigned stack_size, unsigned (__stdcall* start_address)(void*),
void* arglist, unsigned initflag, unsigned* thrdaddr)
@@ -278,6 +279,12 @@ namespace boost
interruption_enabled=false;
#endif
}
~externally_launched_thread() {
BOOST_ASSERT(notify.empty());
notify.clear();
BOOST_ASSERT(async_states_.empty());
async_states_.clear();
}
void run()
{}
@@ -400,6 +407,8 @@ namespace boost
return local_thread_info.get() && (detail::win32::WaitForSingleObject(local_thread_info->interruption_handle,0)==0);
}
#endif
unsigned thread::hardware_concurrency() BOOST_NOEXCEPT
{
//SYSTEM_INFO info={{0}};
@@ -407,7 +416,28 @@ namespace boost
GetSystemInfo(&info);
return info.dwNumberOfProcessors;
}
#endif
unsigned thread::physical_concurrency() BOOST_NOEXCEPT
{
unsigned cores = 0;
DWORD size = 0;
GetLogicalProcessorInformation(NULL, &size);
if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
return 0;
std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> buffer(size);
if (GetLogicalProcessorInformation(buffer.data(), &size) == FALSE)
return 0;
const size_t Elements = size / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
for (size_t i = 0; i < Elements; ++i) {
if (buffer[i].Relationship == RelationProcessorCore)
++cores;
}
return cores;
}
thread::native_handle_type thread::native_handle()
{
@@ -429,7 +459,7 @@ namespace boost
LARGE_INTEGER due_time={{0,0}};
if(target_time.relative)
{
unsigned long const elapsed_milliseconds=GetTickCount()-target_time.start;
unsigned long const elapsed_milliseconds=detail::win32::GetTickCount64()-target_time.start;
LONGLONG const remaining_milliseconds=(target_time.milliseconds-elapsed_milliseconds);
LONGLONG const hundred_nanoseconds_in_one_millisecond=10000;
@@ -747,5 +777,16 @@ namespace boost
current_thread_data->notify_all_at_thread_exit(&cond, lk.release());
}
}
//namespace detail {
//
// void BOOST_THREAD_DECL make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
// {
// detail::thread_data_base* const current_thread_data(detail::get_current_thread_data());
// if(current_thread_data)
// {
// current_thread_data->make_ready_at_thread_exit(as);
// }
// }
//}
}

View File

@@ -209,6 +209,7 @@ rule thread-compile ( sources : reqs * : name )
[ thread-test test_thread.cpp ]
[ thread-test test_thread_id.cpp ]
[ thread-test test_hardware_concurrency.cpp ]
[ thread-test test_physical_concurrency.cpp ]
[ thread-test test_thread_move.cpp ]
[ thread-test test_thread_return_local.cpp ]
[ thread-test test_thread_move_return.cpp ]
@@ -716,6 +717,8 @@ rule thread-compile ( sources : reqs * : name )
[ thread-run2 ../example/producer_consumer.cpp : ex_producer_consumer ]
[ thread-run2 ../example/not_interleaved.cpp : ex_not_interleaved ]
[ thread-run2 ../example/lambda_future.cpp : ex_lambda_future ]
[ thread-run2 ../example/not_interleaved2.cpp : ex_not_interleaved2 ]
[ thread-run2 ../example/thread_pool.cpp : ex_thread_pool ]
;
@@ -768,6 +771,7 @@ rule thread-compile ( sources : reqs * : name )
[ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/swap_pass.cpp : synchronized_value__swap_p ]
[ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/swap_T_pass.cpp : synchronized_value__swap_T_p ]
[ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/synchronize_pass.cpp : synchronized_value__synchronize_p ]
[ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/call_pass.cpp : synchronized_value__call_p ]
;
@@ -789,8 +793,14 @@ rule thread-compile ( sources : reqs * : name )
#[ thread-run test_8586.cpp ]
#[ thread-run test_8596.cpp ]
#[ thread-run test_8600.cpp ]
#[ thread-run2-noit ./sync/mutual_exclusion/sync_bounded_queue/multi_thread_pass.cpp : sync_bounded_queue__multi_thread_p ]
#[ thread-run test_8943.cpp ]
#[ thread-run test_8960.cpp ]
#[ thread-run test_9079_a.cpp ]
#[ thread-run test_9079_b.cpp ]
#[ thread-run clang_main.cpp ]
;
}

View File

@@ -189,6 +189,26 @@ int main()
BOOST_TEST(!f.valid());
#endif
}
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
{
boost::promise<T> p;
boost::future<T> f = p.get_future();
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
boost::thread(func4, boost::move(p)).detach();
#else
p.set_exception(boost::make_exception_ptr(3.5));
#endif
try
{
BOOST_TEST(f.valid());
boost::exception_ptr ptr = f.get_exception_ptr();
}
catch (...)
{
BOOST_TEST(false);
}
BOOST_TEST(f.valid());
}
}
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;

View File

@@ -15,6 +15,26 @@
#include <boost/detail/lightweight_test.hpp>
class non_copyable
{
BOOST_THREAD_MOVABLE_ONLY(non_copyable)
int val;
public:
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; }
bool operator==(non_copyable const& x) const {return val==x.val;}
template <typename OSTREAM>
friend OSTREAM& operator <<(OSTREAM& os, non_copyable const&x )
{
os << x.val;
return os;
}
};
int main()
{
@@ -55,6 +75,16 @@ int main()
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// empty queue push rvalue succeeds
boost::sync_bounded_queue<non_copyable> q(2);
non_copyable nc(1);
q.push(boost::move(nc));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// empty queue push rvalue succeeds
boost::sync_bounded_queue<int> q(2);
@@ -84,6 +114,16 @@ int main()
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// empty queue try_push rvalue succeeds
boost::sync_bounded_queue<non_copyable> q(2);
non_copyable nc(1);
BOOST_TEST(q.try_push(boost::move(nc)));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// empty queue try_push value succeeds
boost::sync_bounded_queue<int> q(2);
@@ -103,6 +143,16 @@ int main()
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// empty queue try_push rvalue succeeds
boost::sync_bounded_queue<non_copyable> q(2);
non_copyable nc(1);
BOOST_TEST(q.try_push(boost::no_block, boost::move(nc)));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue pull succeed
boost::sync_bounded_queue<int> q(2);
@@ -115,6 +165,19 @@ int main()
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue pull succeed
boost::sync_bounded_queue<non_copyable> q(2);
non_copyable nc(1);
q.push(boost::move(nc));
non_copyable nc2(2);
q.pull(nc2);
BOOST_TEST_EQ(nc, nc2);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue pull succeed
boost::sync_bounded_queue<int> q(2);

View File

@@ -15,6 +15,26 @@
#include <boost/detail/lightweight_test.hpp>
class non_copyable
{
BOOST_THREAD_MOVABLE_ONLY(non_copyable)
int val;
public:
non_copyable(int v) : val(v){}
non_copyable(BOOST_RV_REF(non_copyable) x): val(x.val) {}
non_copyable& operator=(BOOST_RV_REF(non_copyable) x) { val=x.val; return *this; }
bool operator==(non_copyable const& x) const {return val==x.val;}
template <typename OSTREAM>
friend OSTREAM& operator <<(OSTREAM& os, non_copyable const&x )
{
os << x.val;
return os;
}
};
int main()
{
@@ -46,7 +66,7 @@ int main()
BOOST_TEST(! q.closed());
}
{
// empty queue push rvalue succeeds
// empty queue push rvalue/copyable succeeds
boost::sync_queue<int> q;
q.push(1);
BOOST_TEST(! q.empty());
@@ -54,6 +74,38 @@ int main()
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// empty queue push lvalue/copyable succeeds
boost::sync_queue<int> q;
int i;
q.push(i);
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#if 0
{
// empty queue push rvalue/non_copyable succeeds
boost::sync_queue<non_copyable> q;
q.push(non_copyable(1));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#endif
{
// empty queue push rvalue/non_copyable succeeds
boost::sync_queue<non_copyable> q;
non_copyable nc(1);
q.push(boost::move(nc));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// empty queue push rvalue succeeds
boost::sync_queue<int> q;
@@ -65,7 +117,7 @@ int main()
BOOST_TEST(! q.closed());
}
{
// empty queue push value succeeds
// empty queue push lvalue succeeds
boost::sync_queue<int> q;
int i;
q.push(i);
@@ -75,7 +127,7 @@ int main()
BOOST_TEST(! q.closed());
}
{
// empty queue try_push rvalue succeeds
// empty queue try_push rvalue/copyable succeeds
boost::sync_queue<int> q;
BOOST_TEST(q.try_push(1));
BOOST_TEST(! q.empty());
@@ -84,7 +136,38 @@ int main()
BOOST_TEST(! q.closed());
}
{
// empty queue try_push value succeeds
// empty queue try_push rvalue/copyable succeeds
boost::sync_queue<int> q;
BOOST_TEST(q.try_push(1));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#if 0
{
// empty queue try_push rvalue/non-copyable succeeds
boost::sync_queue<non_copyable> q;
BOOST_TEST(q.try_push(non_copyable()));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#endif
{
// empty queue try_push rvalue/non-copyable succeeds
boost::sync_queue<non_copyable> q;
non_copyable nc(1);
BOOST_TEST(q.try_push(boost::move(nc)));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// empty queue try_push lvalue succeeds
boost::sync_queue<int> q;
int i;
BOOST_TEST(q.try_push(i));
@@ -102,6 +185,27 @@ int main()
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#if 0
{
// empty queue try_push rvalue/non-copyable succeeds
boost::sync_queue<non_copyable> q;
BOOST_TEST(q.try_push(boost::no_block, non_copyable(1)));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
#endif
{
// empty queue try_push rvalue/non-copyable succeeds
boost::sync_queue<non_copyable> q;
non_copyable nc(1);
BOOST_TEST(q.try_push(boost::no_block, boost::move(nc)));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 1u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue pull succeed
boost::sync_queue<int> q;
@@ -114,6 +218,19 @@ int main()
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue pull succeed
boost::sync_queue<non_copyable> q;
non_copyable nc1(1);
q.push(boost::move(nc1));
non_copyable nc2(2);
q.pull(nc2);
BOOST_TEST_EQ(nc1, nc2);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue pull succeed
boost::sync_queue<int> q;
@@ -125,6 +242,18 @@ int main()
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue pull succeed
boost::sync_queue<non_copyable> q;
non_copyable nc1(1);
q.push(boost::move(nc1));
non_copyable nc = q.pull();
BOOST_TEST_EQ(nc, nc1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue try_pull succeed
boost::sync_queue<int> q;
@@ -137,6 +266,19 @@ int main()
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue try_pull succeed
boost::sync_queue<non_copyable> q;
non_copyable nc1(1);
q.push(boost::move(nc1));
non_copyable nc(2);
BOOST_TEST(q.try_pull(nc));
BOOST_TEST_EQ(nc, nc1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue try_pull succeed
boost::sync_queue<int> q;
@@ -149,6 +291,19 @@ int main()
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue try_pull succeed
boost::sync_queue<non_copyable> q;
non_copyable nc1(1);
q.push(boost::move(nc1));
non_copyable nc(2);
BOOST_TEST(q.try_pull(boost::no_block, nc));
BOOST_TEST_EQ(nc, nc1);
BOOST_TEST(q.empty());
BOOST_TEST(! q.full());
BOOST_TEST_EQ(q.size(), 0u);
BOOST_TEST(! q.closed());
}
{
// 1-element queue try_pull succeed
boost::sync_queue<int> q;

View File

@@ -0,0 +1,144 @@
// Copyright (C) 2013 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// <boost/thread/synchronized_value.hpp>
// class synchronized_value<T,M>
// template <typename F>
// inline typename boost::result_of<F(value_type&)>::type
// operator()(BOOST_THREAD_RV_REF(F) fct);
// template <typename F>
// inline typename boost::result_of<F(value_type const&)>::type
// operator()(BOOST_THREAD_RV_REF(F) fct) const;
#include <boost/config.hpp>
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#define BOOST_THREAD_VERSION 4
#include <boost/thread/synchronized_value.hpp>
#include <boost/detail/lightweight_test.hpp>
struct S {
int f() const {return 1;}
int g() {return 1;}
};
void c(S const& s)
{
BOOST_TEST(s.f()==1);
}
void nc(S & s)
{
BOOST_TEST(s.f()==1);
BOOST_TEST(s.g()==1);
}
struct cfctr {
typedef void result_type;
void operator()(S const& s) const {
BOOST_TEST(s.f()==1);
}
};
struct ncfctr {
typedef void result_type;
void operator()(S& s) const {
BOOST_TEST(s.f()==1);
BOOST_TEST(s.g()==1);
}
};
struct cfctr3 {
typedef void result_type;
BOOST_THREAD_MOVABLE_ONLY(cfctr3)
cfctr3()
{}
cfctr3(BOOST_THREAD_RV_REF(cfctr3))
{}
void operator()(S const& s) const {
BOOST_TEST(s.f()==1);
}
};
struct ncfctr3 {
typedef void result_type;
BOOST_THREAD_MOVABLE_ONLY(ncfctr3)
ncfctr3()
{}
ncfctr3(BOOST_THREAD_RV_REF(ncfctr3))
{}
void operator()(S& s) const {
BOOST_TEST(s.f()==1);
BOOST_TEST(s.g()==1);
}
};
cfctr3 make_cfctr3() {
return BOOST_THREAD_MAKE_RV_REF(cfctr3());
}
ncfctr3 make_ncfctr3() {
return BOOST_THREAD_MAKE_RV_REF(ncfctr3());
}
int main()
{
{
boost::synchronized_value<S> v;
v(&nc);
//v(&c);
}
{
const boost::synchronized_value<S> v;
v(&c);
}
{
boost::synchronized_value<S> v;
v(ncfctr());
}
{
const boost::synchronized_value<S> v;
v(cfctr());
}
{
boost::synchronized_value<S> v;
ncfctr fct;
v(fct);
}
{
const boost::synchronized_value<S> v;
cfctr fct;
v(fct);
}
{
boost::synchronized_value<S> v;
v(make_ncfctr3());
}
{
const boost::synchronized_value<S> v;
v(make_cfctr3());
}
#if ! defined BOOST_NO_CXX11_LAMBDAS
{
boost::synchronized_value<S> v;
v([](S& s) {
BOOST_TEST(s.f()==1);
BOOST_TEST(s.g()==1);
});
}
{
const boost::synchronized_value<S> v;
v([](S const& s) {
BOOST_TEST(s.f()==1);
});
}
#endif
return boost::report_errors();
}

18
test/test_8586.cpp Normal file
View File

@@ -0,0 +1,18 @@
// Copyright (C) 2013 Vicente Botet
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/thread.hpp>
#include <iostream>
void hello_world()
{
std::cout << "Hello from thread!" << std::endl;
}
int main()
{
boost::thread my_thread(&hello_world);
my_thread.join();
}

140
test/test_8600.cpp Normal file
View File

@@ -0,0 +1,140 @@
// Copyright (C) 2013 Vicente Botet
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <vector>
#include <utility>
#include <type_traits>
#if 1
struct B {
int v;
B(int i) : v(i) {}
};
struct D: B {
D(int i) : B(i) {}
};
void fb(B const&) {}
void fd(D const&) {}
BOOST_STATIC_ASSERT(sizeof(B)==sizeof(D));
template <class T, class Allocator=std::allocator<T> >
class new_vector;
template <class T, class Allocator>
class new_vector : public std::vector<T,Allocator>
{
typedef std::vector<T,Allocator> base_type;
public:
new_vector() : base_type() {}
new_vector(unsigned s) : base_type(s) {}
};
template <class Allocator >
class new_vector<bool, Allocator>
{
//std::vector<char,typename Allocator::template rebind<char>::other > v;
int i;
public:
};
template <class T, class A>
typename std::enable_if<!std::is_same<T, bool>::value,
new_vector<T,A>&
>::type
new_vector_cast(std::vector<T,A> & v) {
return reinterpret_cast<new_vector<T,A>&>(v);
}
BOOST_STATIC_ASSERT(sizeof(std::vector<int>)==sizeof(new_vector<int>));
BOOST_STATIC_ASSERT(sizeof(std::vector<bool>)!=sizeof(new_vector<bool>));
void fb(std::vector<int> const&) {}
void fd(new_vector<int> const&) {}
int main() {
{
std::vector<int> b(1);
b[0] = 1;
new_vector<int> d = new_vector_cast(b);
BOOST_ASSERT(b[0] == d[0]);
}
{
//std::vector<bool> b;
//new_vector<bool> d = new_vector_cast(b); // compile fail
}
{
std::vector<int> b(1);
b[0] = 1;
fd(new_vector_cast(b));
}
{
new_vector<int> d(1);
d[0] = 1;
std::vector<int> b = d;
BOOST_ASSERT(b[0] == d[0]);
}
{
//new_vector<bool> d;
//std::vector<bool> b = d; // compile fail
}
{
new_vector<int> d(1);
d[0] = 1;
fd(d);
}
return 0;
}
#else
int main() {
{
B b(1);
D d = reinterpret_cast<D&>(b);
BOOST_ASSERT(b.v == d.v);
}
{
B b(1);
fd(reinterpret_cast<D&>(b));
}
{
D d(2);
B b = d;
BOOST_ASSERT(b.v == d.v);
}
{
D d(2);
fd(d);
}
return 0;
}
#define BOOST_THREAD_VERSION 4
#include <iostream>
#include <boost/thread.hpp>
int calculate_the_answer_to_life_the_universe_and_everything()
{
return 42;
}
int main()
{
boost::packaged_task<int()> pt(calculate_the_answer_to_life_the_universe_and_everything);
boost::shared_future<int> fi1 = boost::shared_future<int>(pt.get_future());
boost::shared_future<int> fi2 = fi1;
boost::thread task(boost::move(pt)); // launch task on a thread
boost::wait_for_any(fi1, fi2);
std::cout << "Wait for any returned\n";
return (0);
}
#endif

47
test/test_8943.cpp Normal file
View File

@@ -0,0 +1,47 @@
// Copyright (C) 2013 Vicente Botet
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/detail/lightweight_test.hpp>
#if defined(WIN32)
#include <tchar.h>
#endif
#include <cstdlib>
#include <iostream>
#include <boost/thread/once.hpp>
namespace {
class foo
{
public:
void operator()() const
{
std::cout << "foo" << std::endl;
}
}; // class foo
}
#if defined(WIN32)
int _tmain(int /*argc*/, _TCHAR* /*argv*/[])
#else
int main(int /*argc*/, char* /*argv*/[])
#endif
{
try
{
boost::once_flag once_flag = BOOST_ONCE_INIT;
boost::call_once(once_flag, foo());
return EXIT_SUCCESS;
}
catch (...)
{
std::cerr << "Unknown exception" << std::endl;
BOOST_TEST(false);
}
return boost::report_errors();
}

53
test/test_8960.cpp Normal file
View File

@@ -0,0 +1,53 @@
// Copyright (C) 2013 Vicente Botet
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/thread.hpp>
#include <iostream>
#include <iostream>
#include <boost/thread.hpp>
#include <boost/thread/locks.hpp>
#include <boost/chrono.hpp>
//#include <boost/bind.hpp>
#include <boost/detail/lightweight_test.hpp>
void do_thread()
{
try
{
boost::condition_variable c1;
boost::mutex m1;
boost::unique_lock<boost::mutex> l1(m1);
c1.wait_for(l1, boost::chrono::seconds(1));
}
catch (std::runtime_error& ex)
{
std::cout << "EXCEPTION ! " << ex.what() << std::endl;
BOOST_TEST(false);
}
catch (...)
{
std::cout << "EXCEPTION ! " << std::endl;
BOOST_TEST(false);
}
}
int main()
{
boost::thread th1(&do_thread);
th1.join();
//std::string s1;
//std::cin >> s1;
return boost::report_errors();
}

57
test/test_9079_a.cpp Normal file
View File

@@ -0,0 +1,57 @@
// Copyright (C) 2013 Vicente Botet
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// A
//#include <boost/log/trivial.hpp>
#include <boost/chrono.hpp>
#include <boost/thread.hpp>
#include <boost/thread/condition_variable.hpp>
//#if !defined(BOOST_NO_CXX11_ALIGNAS)
//#error
//# define BOOST_ALIGNMENT2(x) alignas(x)
//#elif defined(_MSC_VER)
//#error
//# define BOOST_ALIGNMENT2(x) __declspec(align(x))
//#elif defined(__GNUC__)
//#error
//# define BOOST_ALIGNMENT(x) __attribute__ ((__aligned__(x)))
//#else
//#error
//# define BOOST_NO_ALIGNMENT2
//# define BOOST_ALIGNMENT2(x)
//#endif
typedef boost::chrono::high_resolution_clock Clock;
typedef Clock::time_point TimePoint;
inline TimePoint real_time_now()
{
return Clock::now();
}
int main()
{
using namespace boost::chrono;
boost::condition_variable m_task_spawn_condition;
boost::mutex main_thread_mutex;
boost::unique_lock < boost::mutex > main_thread_lock(main_thread_mutex);
//BOOST_LOG_TRIVIAL(info) << "[TaskScheduler::run_and_wait] Scheduling loop - BEGIN";
//while (true)
{
static const milliseconds TIME_BACK = milliseconds(1);
m_task_spawn_condition.wait_until(
main_thread_lock,
real_time_now() - TIME_BACK); // wait forever
m_task_spawn_condition.wait_for( main_thread_lock, - TIME_BACK ); // same problem
//BOOST_LOG_TRIVIAL(trace) << "TICK";
}
}

81
test/test_9079_b.cpp Normal file
View File

@@ -0,0 +1,81 @@
// Copyright (C) 2013 Vicente Botet
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// B
#include <boost/atomic.hpp>
//#include <boost/log/trivial.hpp>
#include <boost/chrono.hpp>
#include <boost/thread.hpp>
#include <boost/thread/condition_variable.hpp>
typedef boost::chrono::high_resolution_clock Clock;
typedef Clock::time_point TimePoint;
inline TimePoint real_time_now()
{
return Clock::now();
}
class Foo {
boost::atomic<bool> m_is_exiting;
TimePoint m_next_tick_time;
public:
bool is_exiting() const
{
return m_is_exiting;
}
TimePoint spawn_tasks() // note that in my app, this call takes more time than here
{
using namespace boost::chrono;
const TimePoint now = real_time_now();
if (m_next_tick_time < now) {
m_next_tick_time = now + seconds(1);
//BOOST_LOG_TRIVIAL(info) << "TICK!";
}
return m_next_tick_time;
}
};
int main()
{
using namespace boost::chrono;
static const milliseconds MIN_TIME_TASKS_SPAWN_FREQUENCY = milliseconds(1);
//microseconds(1); // THE SHORTER THE QUICKER TO REPRODUCE THE BUG
boost::condition_variable m_task_spawn_condition;
Foo foo;
boost::mutex main_thread_mutex;
boost::unique_lock < boost::mutex > main_thread_lock(main_thread_mutex);
//BOOST_LOG_TRIVIAL(info) << "[TaskScheduler::run_and_wait] Scheduling loop - BEGIN";
while (!foo.is_exiting()) {
const TimePoint next_task_spawn_time = foo.spawn_tasks();
const TimePoint now = real_time_now();
const TimePoint next_minimum_spawn_time = now + MIN_TIME_TASKS_SPAWN_FREQUENCY;
const TimePoint next_spawn_time = next_task_spawn_time > TimePoint()
&& next_task_spawn_time < next_minimum_spawn_time
? next_task_spawn_time : next_minimum_spawn_time;
const TimePoint::duration wait_time = next_spawn_time - now;
if (wait_time > wait_time.zero()) {
// BOOST_LOG_TRIVIAL(trace) << "WAIT TIME: " << wait_time; // UNCOMMENT THIS: MAKES IT WORKS. WAT??????
m_task_spawn_condition.wait_until(
main_thread_lock,
next_spawn_time); // DON'T WORK: WILL WAIT IF next_spawn_time is too close!
}
}
}

View File

@@ -0,0 +1,24 @@
// Copyright (C) 2007 Anthony Williams
// Copyright (C) 2013 Tim Blechmann
//
// 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/thread/thread_only.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/thread/mutex.hpp>
void test_physical_concurrency_is_non_zero()
{
BOOST_CHECK(boost::thread::physical_concurrency()!=0);
}
boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
BOOST_TEST_SUITE("Boost.Threads: physical concurrency test suite");
test->add(BOOST_TEST_CASE(test_physical_concurrency_is_non_zero));
return test;
}

View File

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

View File

@@ -63,6 +63,7 @@ void test_thread_callable_object_no_arguments()
struct callable_noncopyable_no_args:
boost::noncopyable
{
callable_noncopyable_no_args() : boost::noncopyable() {}
static bool called;
void operator()() const