mirror of
https://github.com/boostorg/thread.git
synced 2026-02-03 09:42:16 +00:00
Compare commits
197 Commits
pr/fix-gcc
...
boost-1.67
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d268106bf8 | ||
|
|
040481760c | ||
|
|
e848363029 | ||
|
|
e3358e0925 | ||
|
|
13a1f3daaa | ||
|
|
3a95ba8559 | ||
|
|
0871d0b0a6 | ||
|
|
7edd340995 | ||
|
|
8633d7532d | ||
|
|
03acfa57a2 | ||
|
|
9be0996062 | ||
|
|
71231fb2ae | ||
|
|
526c72cb4b | ||
|
|
ff5031db9e | ||
|
|
581558868d | ||
|
|
96484ac57f | ||
|
|
7de4a7046a | ||
|
|
3b7ca04408 | ||
|
|
473648ce6c | ||
|
|
426636b1d0 | ||
|
|
cb322cfa86 | ||
|
|
51d3030a1f | ||
|
|
26f1b6d237 | ||
|
|
5ed197748e | ||
|
|
79a523390f | ||
|
|
f01b7b5013 | ||
|
|
f855cb31d1 | ||
|
|
99c2dd9cbc | ||
|
|
36807a438a | ||
|
|
f83e887d53 | ||
|
|
57d991c36b | ||
|
|
072bbee63e | ||
|
|
a3cc3a016c | ||
|
|
669f652f4d | ||
|
|
c61f3a97e2 | ||
|
|
349ec68c0f | ||
|
|
2eb9f1eb86 | ||
|
|
7ab14ac4a3 | ||
|
|
0183e3feb8 | ||
|
|
a0c23a608a | ||
|
|
610c3ae071 | ||
|
|
b2903a5d14 | ||
|
|
81f3a78b8a | ||
|
|
56c17adf7e | ||
|
|
e5224ee27a | ||
|
|
d77affc6f5 | ||
|
|
984ec57446 | ||
|
|
e96516d10d | ||
|
|
907e827046 | ||
|
|
609d1a7be0 | ||
|
|
d19a2499cd | ||
|
|
08619ef517 | ||
|
|
5141adee96 | ||
|
|
1e84b978b2 | ||
|
|
a0f216bb2b | ||
|
|
2de04292da | ||
|
|
c50428f612 | ||
|
|
b4348b3cff | ||
|
|
fea3e33128 | ||
|
|
d60a11a75b | ||
|
|
cfd93c7747 | ||
|
|
6d8c0676a1 | ||
|
|
343230cd78 | ||
|
|
44080a444c | ||
|
|
6d7bc558d0 | ||
|
|
65681f4033 | ||
|
|
d345533596 | ||
|
|
007738d22c | ||
|
|
6ddf6a8acf | ||
|
|
f9e97a68bb | ||
|
|
44d410f067 | ||
|
|
48ceff1e65 | ||
|
|
883637e0f4 | ||
|
|
3c01e39481 | ||
|
|
eef7293932 | ||
|
|
b65b2f3fea | ||
|
|
d70e1aad77 | ||
|
|
2272e9e3f5 | ||
|
|
d259e0fde4 | ||
|
|
ac99313228 | ||
|
|
7069c97a8b | ||
|
|
3b5d0c8d7f | ||
|
|
d2498547a7 | ||
|
|
c91c9e6d52 | ||
|
|
e47081faa7 | ||
|
|
f794d5a9d1 | ||
|
|
e3f586836a | ||
|
|
82e2c82e95 | ||
|
|
3479524845 | ||
|
|
178e0661ab | ||
|
|
b94c36f960 | ||
|
|
9f7e37c892 | ||
|
|
e7d6055ed3 | ||
|
|
659d309206 | ||
|
|
847dcbf237 | ||
|
|
35d25851ce | ||
|
|
5ffca91e60 | ||
|
|
51e6e654e3 | ||
|
|
3c25ad09ce | ||
|
|
a2e037bb54 | ||
|
|
a4a21b1c12 | ||
|
|
c2b207faa4 | ||
|
|
68abb96818 | ||
|
|
29c3b48da0 | ||
|
|
13713f3b9c | ||
|
|
776d42f6cb | ||
|
|
46c1ae6f96 | ||
|
|
fb0317ec7d | ||
|
|
417a2d8a46 | ||
|
|
ce7f2b09cc | ||
|
|
e6226a95ba | ||
|
|
aa221d02b5 | ||
|
|
de4ee72554 | ||
|
|
ad5ea75ddd | ||
|
|
dd1b5282b2 | ||
|
|
45321f0570 | ||
|
|
961a0689f3 | ||
|
|
bafc9f43a5 | ||
|
|
b98d022d40 | ||
|
|
f2d6d99d54 | ||
|
|
aeb54ddbe5 | ||
|
|
4d385bedd3 | ||
|
|
03a2ea4612 | ||
|
|
c290fc5f98 | ||
|
|
23861b9608 | ||
|
|
24fd5953c9 | ||
|
|
8f51d9c4a7 | ||
|
|
5dcc5f6d26 | ||
|
|
70a4ce8eb3 | ||
|
|
8207b88e97 | ||
|
|
de7e354a8e | ||
|
|
bad686d620 | ||
|
|
2f1b1c4d44 | ||
|
|
d8f24d9183 | ||
|
|
0fa843532e | ||
|
|
7b49f3f354 | ||
|
|
e6f876e830 | ||
|
|
285d35f43f | ||
|
|
a18dfa1fea | ||
|
|
f5ccff5b6e | ||
|
|
a9706f0745 | ||
|
|
8e718893e5 | ||
|
|
f56bc930bc | ||
|
|
f1dec7935f | ||
|
|
aebbcda3fe | ||
|
|
5b4d230d4a | ||
|
|
6b174a3419 | ||
|
|
9813c81ef3 | ||
|
|
e2b9ce78c2 | ||
|
|
576231942d | ||
|
|
82eed2ca6d | ||
|
|
56016e8348 | ||
|
|
b6b6a6944a | ||
|
|
739f8eeb81 | ||
|
|
14deba107f | ||
|
|
ef81bd2e0b | ||
|
|
99e2867a21 | ||
|
|
6805c7fcb6 | ||
|
|
24b1636615 | ||
|
|
c67f4b08a0 | ||
|
|
5c51abc92f | ||
|
|
078bd570c8 | ||
|
|
b1991924b7 | ||
|
|
fa1965a87c | ||
|
|
d00933d5f4 | ||
|
|
81fe14fda2 | ||
|
|
13d293829c | ||
|
|
a6d5b5e576 | ||
|
|
1063638763 | ||
|
|
a02f0ec577 | ||
|
|
32229388f5 | ||
|
|
333365aefe | ||
|
|
5363e099e4 | ||
|
|
f79d51f099 | ||
|
|
336259c36a | ||
|
|
3391bf87c6 | ||
|
|
bc6b31e1f7 | ||
|
|
84720b7664 | ||
|
|
7879a4c286 | ||
|
|
11f18980ca | ||
|
|
12e2c8aaca | ||
|
|
046d716bbf | ||
|
|
5b9c1fad85 | ||
|
|
58c6b384cc | ||
|
|
7c1570328e | ||
|
|
97895e410f | ||
|
|
2494f3fc7a | ||
|
|
159868ac77 | ||
|
|
f65e89a85a | ||
|
|
bb47c16939 | ||
|
|
02fd2d041b | ||
|
|
2661c06698 | ||
|
|
83f877a238 | ||
|
|
47f615d073 | ||
|
|
7079a80edf | ||
|
|
dbf28a4ac4 | ||
|
|
2866734b15 |
12
.travis.yml
12
.travis.yml
@@ -333,13 +333,13 @@ matrix:
|
||||
compiler: clang++
|
||||
env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++98
|
||||
|
||||
- os: osx
|
||||
compiler: clang++
|
||||
env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++11
|
||||
# - os: osx
|
||||
# compiler: clang++
|
||||
# env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++11
|
||||
|
||||
- os: osx
|
||||
compiler: clang++
|
||||
env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++14
|
||||
# - os: osx
|
||||
# compiler: clang++
|
||||
# env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++14
|
||||
|
||||
- os: osx
|
||||
compiler: clang++
|
||||
|
||||
26
appveyor.yml
26
appveyor.yml
@@ -17,23 +17,23 @@ platform:
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- ARGS: --toolset=msvc-9.0 address-model=32
|
||||
- ARGS: --toolset=msvc-10.0 address-model=32
|
||||
- ARGS: --toolset=msvc-11.0 address-model=32
|
||||
- ARGS: --toolset=msvc-12.0 address-model=32
|
||||
- ARGS: --toolset=msvc-14.0 address-model=32
|
||||
- ARGS: --toolset=msvc-12.0 address-model=64
|
||||
- ARGS: --toolset=msvc-14.0 address-model=64
|
||||
- ARGS: --toolset=msvc-14.0 address-model=64 cxxflags=-std:c++latest
|
||||
- ARGS: --toolset=msvc-9.0 address-model=32 cxxflags="/wd4244 /wd4459"
|
||||
- ARGS: --toolset=msvc-10.0 address-model=32 cxxflags="/wd4244 /wd4459"
|
||||
- ARGS: --toolset=msvc-11.0 address-model=32 cxxflags="/wd4244 /wd4459"
|
||||
- ARGS: --toolset=msvc-12.0 address-model=32 cxxflags="/wd4244 /wd4459"
|
||||
- ARGS: --toolset=msvc-14.0 address-model=32 cxxflags="/wd4244 /wd4459"
|
||||
- ARGS: --toolset=msvc-12.0 address-model=64 cxxflags="/wd4244 /wd4459"
|
||||
- ARGS: --toolset=msvc-14.0 address-model=64 cxxflags="/wd4244 /wd4459"
|
||||
- ARGS: --toolset=msvc-14.0 address-model=64 cxxflags="-std:c++latest /wd4244 /wd4459"
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
ARGS: --toolset=msvc-14.1 address-model=64
|
||||
ARGS: --toolset=msvc-14.1 address-model=64 cxxflags="/wd4244 /wd4459"
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
ARGS: --toolset=msvc-14.1 address-model=32
|
||||
ARGS: --toolset=msvc-14.1 address-model=32 cxxflags="/wd4244 /wd4459"
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
ARGS: --toolset=msvc-14.1 address-model=64 cxxflags=-std:c++latest
|
||||
ARGS: --toolset=msvc-14.1 address-model=64 cxxflags="-std:c++latest /wd4244 /wd4459"
|
||||
- ARGS: --toolset=gcc address-model=64
|
||||
PATH: C:\mingw-w64\x86_64-6.3.0-posix-seh-rt_v5-rev1\mingw64\bin;%PATH%
|
||||
- ARGS: --toolset=gcc address-model=64 cxxflags=-std=gnu++1z
|
||||
- ARGS: --toolset=gcc address-model=64 cxxflags="-std=gnu++1z
|
||||
PATH: C:\mingw-w64\x86_64-6.3.0-posix-seh-rt_v5-rev1\mingw64\bin;%PATH%
|
||||
- ARGS: --toolset=gcc address-model=32
|
||||
PATH: C:\mingw-w64\i686-5.3.0-posix-dwarf-rt_v4-rev0\mingw32\bin;%PATH%
|
||||
@@ -76,4 +76,4 @@ test_script:
|
||||
- ..\..\..\b2 config_info_travis_install %ARGS%
|
||||
- config_info_travis
|
||||
- cd ..\..\thread\test
|
||||
- ..\..\..\b2 -j3 %ARGS%
|
||||
- ..\..\..\b2 --abbreviate-paths -j3 %ARGS%
|
||||
|
||||
@@ -238,6 +238,10 @@ rule usage-requirements ( properties * )
|
||||
# in that case?
|
||||
}
|
||||
}
|
||||
if <threadapi>win32 in $(properties)
|
||||
{
|
||||
result += <define>BOOST_THREAD_WIN32 ;
|
||||
}
|
||||
|
||||
#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)
|
||||
#{
|
||||
@@ -272,6 +276,10 @@ rule requirements ( properties * )
|
||||
result += <library>/boost/atomic//boost_atomic ;
|
||||
}
|
||||
} else {
|
||||
if <threadapi>win32 in $(properties)
|
||||
{
|
||||
result += <define>BOOST_THREAD_WIN32 ;
|
||||
}
|
||||
result += <define>BOOST_THREAD_USES_CHRONO ;
|
||||
result += <library>/boost/chrono//boost_chrono ;
|
||||
}
|
||||
@@ -284,6 +292,7 @@ alias thread_sources
|
||||
win32/thread.cpp
|
||||
win32/tss_dll.cpp
|
||||
win32/tss_pe.cpp
|
||||
win32/thread_primitives.cpp
|
||||
future.cpp
|
||||
: ## requirements ##
|
||||
<threadapi>win32
|
||||
|
||||
@@ -22,14 +22,29 @@ Please take a look at [@https://svn.boost.org/trac/boost/query?status=assigned&s
|
||||
Please take a look at [@http://www.boost.org/development/tests/master/developer/thread.html thread master regression test] to see the last regression test snapshot.
|
||||
|
||||
[*Fixed Bugs:]
|
||||
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/12323 #12323] windows - boost/thread/win32/mfc_thread_init.hpp has wrong signature for _pRawDllMainOrig
|
||||
* [@http://svn.boost.org/trac/boost/ticket/12730 #12730] windows - static threads library is incompatible with MSVC 2017 RC
|
||||
* [@http://svn.boost.org/trac/boost/ticket/12976 #12976] Boost Thread Executors documentation mistakes
|
||||
* [@http://svn.boost.org/trac/boost/ticket/12949 #12949] using sleep_for in a thread context without including boost/thread/thread.hpp yields incorrect behaviour when BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC is defined
|
||||
* [@http://svn.boost.org/trac/boost/ticket/13019 #13019] ABI compatibility for BOOST_THREAD_PROVIDES_INTERRUPTIONS incomplete
|
||||
* [@http://svn.boost.org/trac/boost/ticket/13069 #13069] Boost unit test "sync_pq_multi_thread_p_lib.exe" hung in thread library
|
||||
* [@http://svn.boost.org/trac/boost/ticket/13163 #13163] boost::detail::heap_new does not have a variadic variant
|
||||
* [@http://svn.boost.org/trac/boost/ticket/13226 #13226] getpagesize() is deprecated since 199506L
|
||||
|
||||
* [@https://github.com/boostorg/thread/issues/132 #132] VS 2017.4 Preview deadlocks on Test 10964
|
||||
* [@https://github.com/boostorg/thread/issues/133 #133] windows - Spurious timing test failures on windows
|
||||
* [@https://github.com/boostorg/thread/issues/134 #134] VS 2017.4 Preview deadlock in sync_pq_multi_thread_p_lib.exe
|
||||
* [@https://github.com/boostorg/thread/issues/135 #135] VS 2017.4 Preview test_scheduled_tp_p.exe deadlock
|
||||
* [@https://github.com/boostorg/thread/issues/136 #136] VS 2017.4 Preview test_scheduler_p.exe deadlock
|
||||
* [@https://github.com/boostorg/thread/issues/137 #137] VS 2017.4 Preview executor_ex.exe deadlock
|
||||
* [@https://github.com/boostorg/thread/issues/143 #143] Failures on msvc-12.0
|
||||
* [@https://github.com/boostorg/thread/issues/145 #145] Clang build error with BOOST_THREAD_ATTRIBUTE_MAY_ALIAS
|
||||
|
||||
[*New Experimental Features:]
|
||||
|
||||
* [@https://github.com/boostorg/thread/issues/116 #116] [Proposal] Add APIs for deferred set_value/exception
|
||||
|
||||
[heading Version 4.7.5 - boost 1.65.1]
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
@@ -84,10 +86,13 @@ namespace detail
|
||||
inline void throw_if_closed(unique_lock<mutex>&);
|
||||
inline void throw_if_closed(lock_guard<mutex>&);
|
||||
|
||||
inline void wait_until_not_empty(unique_lock<mutex>& lk);
|
||||
inline bool not_empty_or_closed(unique_lock<mutex>& ) const;
|
||||
|
||||
inline bool wait_until_not_empty_or_closed(unique_lock<mutex>& lk);
|
||||
template <class WClock, class Duration>
|
||||
queue_op_status wait_until_not_empty_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&);
|
||||
queue_op_status wait_until_not_empty_or_closed_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&tp);
|
||||
template <class WClock, class Duration>
|
||||
queue_op_status wait_until_closed_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&tp);
|
||||
|
||||
inline void notify_not_empty_if_needed(unique_lock<mutex>& )
|
||||
{
|
||||
@@ -176,39 +181,38 @@ namespace detail
|
||||
}
|
||||
|
||||
template <class ValueType, class Queue>
|
||||
void sync_deque_base<ValueType, Queue>::wait_until_not_empty(unique_lock<mutex>& lk)
|
||||
bool sync_deque_base<ValueType, Queue>::not_empty_or_closed(unique_lock<mutex>& ) const
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (! empty(lk)) break;
|
||||
throw_if_closed(lk);
|
||||
not_empty_.wait(lk);
|
||||
}
|
||||
return ! data_.empty() || closed_;
|
||||
}
|
||||
|
||||
template <class ValueType, class Queue>
|
||||
bool sync_deque_base<ValueType, Queue>::wait_until_not_empty_or_closed(unique_lock<mutex>& lk)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (! empty(lk)) break;
|
||||
if (closed(lk)) return true;
|
||||
not_empty_.wait(lk);
|
||||
}
|
||||
return false;
|
||||
not_empty_.wait(lk, boost::bind(&sync_deque_base<ValueType, Queue>::not_empty_or_closed, boost::ref(*this), boost::ref(lk)));
|
||||
if (! empty(lk)) return false; // success
|
||||
return true; // closed
|
||||
}
|
||||
|
||||
template <class ValueType, class Queue>
|
||||
template <class WClock, class Duration>
|
||||
queue_op_status sync_deque_base<ValueType, Queue>::wait_until_not_empty_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&tp)
|
||||
queue_op_status sync_deque_base<ValueType, Queue>::wait_until_not_empty_or_closed_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&tp)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (! empty(lk)) return queue_op_status::success;
|
||||
throw_if_closed(lk);
|
||||
if (not_empty_.wait_until(lk, tp) == cv_status::timeout ) return queue_op_status::timeout;
|
||||
}
|
||||
if (! not_empty_.wait_until(lk, tp, boost::bind(&sync_deque_base<ValueType, Queue>::not_empty_or_closed, boost::ref(*this), boost::ref(lk))))
|
||||
return queue_op_status::timeout;
|
||||
if (! empty(lk)) return queue_op_status::success;
|
||||
return queue_op_status::closed;
|
||||
}
|
||||
|
||||
template <class ValueType, class Queue>
|
||||
template <class WClock, class Duration>
|
||||
queue_op_status sync_deque_base<ValueType, Queue>::wait_until_closed_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&tp)
|
||||
{
|
||||
bool (sync_queue_base<ValueType, Queue>::*closed_function_ptr)(unique_lock<mutex>&) const = &sync_queue_base<ValueType, Queue>::closed;
|
||||
if (! not_empty_.wait_until(lk, tp, boost::bind(closed_function_ptr, boost::ref(*this), boost::ref(lk))))
|
||||
return queue_op_status::timeout;
|
||||
return queue_op_status::closed;
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // concurrent
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
@@ -84,10 +86,13 @@ namespace detail
|
||||
inline void throw_if_closed(unique_lock<mutex>&);
|
||||
inline void throw_if_closed(lock_guard<mutex>&);
|
||||
|
||||
inline void wait_until_not_empty(unique_lock<mutex>& lk);
|
||||
inline bool not_empty_or_closed(unique_lock<mutex>& ) const;
|
||||
|
||||
inline bool wait_until_not_empty_or_closed(unique_lock<mutex>& lk);
|
||||
template <class WClock, class Duration>
|
||||
queue_op_status wait_until_not_empty_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&);
|
||||
queue_op_status wait_until_not_empty_or_closed_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&tp);
|
||||
template <class WClock, class Duration>
|
||||
queue_op_status wait_until_closed_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&tp);
|
||||
|
||||
inline void notify_not_empty_if_needed(unique_lock<mutex>& )
|
||||
{
|
||||
@@ -176,39 +181,38 @@ namespace detail
|
||||
}
|
||||
|
||||
template <class ValueType, class Queue>
|
||||
void sync_queue_base<ValueType, Queue>::wait_until_not_empty(unique_lock<mutex>& lk)
|
||||
bool sync_queue_base<ValueType, Queue>::not_empty_or_closed(unique_lock<mutex>& ) const
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (! empty(lk)) break;
|
||||
throw_if_closed(lk);
|
||||
not_empty_.wait(lk);
|
||||
}
|
||||
return ! data_.empty() || closed_;
|
||||
}
|
||||
|
||||
template <class ValueType, class Queue>
|
||||
bool sync_queue_base<ValueType, Queue>::wait_until_not_empty_or_closed(unique_lock<mutex>& lk)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (! empty(lk)) break;
|
||||
if (closed(lk)) return true;
|
||||
not_empty_.wait(lk);
|
||||
}
|
||||
return false;
|
||||
not_empty_.wait(lk, boost::bind(&sync_queue_base<ValueType, Queue>::not_empty_or_closed, boost::ref(*this), boost::ref(lk)));
|
||||
if (! empty(lk)) return false; // success
|
||||
return true; // closed
|
||||
}
|
||||
|
||||
template <class ValueType, class Queue>
|
||||
template <class WClock, class Duration>
|
||||
queue_op_status sync_queue_base<ValueType, Queue>::wait_until_not_empty_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&tp)
|
||||
queue_op_status sync_queue_base<ValueType, Queue>::wait_until_not_empty_or_closed_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&tp)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (! empty(lk)) return queue_op_status::success;
|
||||
throw_if_closed(lk);
|
||||
if (not_empty_.wait_until(lk, tp) == cv_status::timeout ) return queue_op_status::timeout;
|
||||
}
|
||||
if (! not_empty_.wait_until(lk, tp, boost::bind(&sync_queue_base<ValueType, Queue>::not_empty_or_closed, boost::ref(*this), boost::ref(lk))))
|
||||
return queue_op_status::timeout;
|
||||
if (! empty(lk)) return queue_op_status::success;
|
||||
return queue_op_status::closed;
|
||||
}
|
||||
|
||||
template <class ValueType, class Queue>
|
||||
template <class WClock, class Duration>
|
||||
queue_op_status sync_queue_base<ValueType, Queue>::wait_until_closed_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&tp)
|
||||
{
|
||||
bool (sync_queue_base<ValueType, Queue>::*closed_function_ptr)(unique_lock<mutex>&) const = &sync_queue_base<ValueType, Queue>::closed;
|
||||
if (! not_empty_.wait_until(lk, tp, boost::bind(closed_function_ptr, boost::ref(*this), boost::ref(lk))))
|
||||
return queue_op_status::timeout;
|
||||
return queue_op_status::closed;
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // concurrent
|
||||
|
||||
@@ -149,11 +149,7 @@ namespace concurrent
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_deque<ValueType, Container>::wait_pull_front(ValueType& elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
if (super::empty(lk))
|
||||
{
|
||||
if (super::closed(lk)) return queue_op_status::closed;
|
||||
}
|
||||
bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
|
||||
const bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
|
||||
if (has_been_closed) return queue_op_status::closed;
|
||||
pull_front(elem, lk);
|
||||
return queue_op_status::success;
|
||||
@@ -188,7 +184,8 @@ namespace concurrent
|
||||
void sync_deque<ValueType, Container>::pull_front(ValueType& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
super::wait_until_not_empty(lk);
|
||||
const bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
|
||||
if (has_been_closed) super::throw_if_closed(lk);
|
||||
pull_front(elem, lk);
|
||||
}
|
||||
|
||||
@@ -197,7 +194,8 @@ namespace concurrent
|
||||
ValueType sync_deque<ValueType, Container>::pull_front()
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
super::wait_until_not_empty(lk);
|
||||
const bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
|
||||
if (has_been_closed) super::throw_if_closed(lk);
|
||||
return pull_front(lk);
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ namespace detail {
|
||||
return boost::move(result);
|
||||
}
|
||||
|
||||
Type const& top()
|
||||
Type const& top() const
|
||||
{
|
||||
return _elements.front();
|
||||
}
|
||||
@@ -249,7 +249,8 @@ namespace concurrent
|
||||
T sync_priority_queue<T,Container,Cmp>::pull()
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
super::wait_until_not_empty(lk);
|
||||
const bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
|
||||
if (has_been_closed) super::throw_if_closed(lk);
|
||||
return pull(lk);
|
||||
}
|
||||
|
||||
@@ -269,7 +270,8 @@ namespace concurrent
|
||||
void sync_priority_queue<T,Container,Cmp>::pull(T& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
super::wait_until_not_empty(lk);
|
||||
const bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
|
||||
if (has_been_closed) super::throw_if_closed(lk);
|
||||
pull(lk, elem);
|
||||
}
|
||||
|
||||
@@ -280,10 +282,9 @@ namespace concurrent
|
||||
sync_priority_queue<T,Cont,Cmp>::pull_until(const chrono::time_point<WClock,Duration>& tp, T& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
if (queue_op_status::timeout == super::wait_until_not_empty_until(lk, tp))
|
||||
return queue_op_status::timeout;
|
||||
pull(lk, elem);
|
||||
return queue_op_status::success;
|
||||
const queue_op_status rc = super::wait_until_not_empty_or_closed_until(lk, tp);
|
||||
if (rc == queue_op_status::success) pull(lk, elem);
|
||||
return rc;
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
@@ -292,7 +293,7 @@ namespace concurrent
|
||||
queue_op_status
|
||||
sync_priority_queue<T,Cont,Cmp>::pull_for(const chrono::duration<Rep,Period>& dura, T& elem)
|
||||
{
|
||||
return pull_until(clock::now() + dura, elem);
|
||||
return pull_until(chrono::steady_clock::now() + dura, elem);
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
@@ -334,11 +335,7 @@ namespace concurrent
|
||||
template <class T,class Container, class Cmp>
|
||||
queue_op_status sync_priority_queue<T,Container,Cmp>::wait_pull(unique_lock<mutex>& lk, T& elem)
|
||||
{
|
||||
if (super::empty(lk))
|
||||
{
|
||||
if (super::closed(lk)) return queue_op_status::closed;
|
||||
}
|
||||
bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
|
||||
const bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
|
||||
if (has_been_closed) return queue_op_status::closed;
|
||||
pull(lk, elem);
|
||||
return queue_op_status::success;
|
||||
@@ -352,7 +349,6 @@ namespace concurrent
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
|
||||
template <class T,class Container, class Cmp>
|
||||
queue_op_status sync_priority_queue<T,Container,Cmp>::nonblocking_pull(T& elem)
|
||||
{
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
// See http://www.boost.org/libs/thread for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/concurrent_queues/detail/sync_queue_base.hpp>
|
||||
@@ -51,7 +50,6 @@ namespace concurrent
|
||||
inline ~sync_queue();
|
||||
|
||||
// Modifiers
|
||||
|
||||
inline void push(const value_type& x);
|
||||
inline queue_op_status try_push(const value_type& x);
|
||||
inline queue_op_status nonblocking_push(const value_type& x);
|
||||
@@ -151,19 +149,9 @@ namespace concurrent
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_queue<ValueType, Container>::wait_pull(ValueType& elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
//std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
if (super::empty(lk))
|
||||
{
|
||||
//std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
if (super::closed(lk)) return queue_op_status::closed;
|
||||
}
|
||||
//std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
|
||||
//std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
const bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
|
||||
if (has_been_closed) return queue_op_status::closed;
|
||||
//std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
pull(elem, lk);
|
||||
//std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
return queue_op_status::success;
|
||||
}
|
||||
|
||||
@@ -196,7 +184,8 @@ namespace concurrent
|
||||
void sync_queue<ValueType, Container>::pull(ValueType& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
super::wait_until_not_empty(lk);
|
||||
const bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
|
||||
if (has_been_closed) super::throw_if_closed(lk);
|
||||
pull(elem, lk);
|
||||
}
|
||||
|
||||
@@ -205,7 +194,8 @@ namespace concurrent
|
||||
ValueType sync_queue<ValueType, Container>::pull()
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
super::wait_until_not_empty(lk);
|
||||
const bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
|
||||
if (has_been_closed) super::throw_if_closed(lk);
|
||||
return pull(lk);
|
||||
}
|
||||
|
||||
|
||||
@@ -53,11 +53,6 @@ namespace detail
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool time_not_reached() const
|
||||
{
|
||||
return time > clock::now();
|
||||
}
|
||||
|
||||
bool operator <(const scheduled_type & other) const
|
||||
{
|
||||
return this->time > other.time;
|
||||
@@ -123,6 +118,13 @@ namespace detail
|
||||
queue_op_status try_push(BOOST_THREAD_RV_REF(T) elem, chrono::duration<Rep,Period> const& dura);
|
||||
|
||||
private:
|
||||
inline bool not_empty_and_time_reached(unique_lock<mutex>& lk) const;
|
||||
inline bool not_empty_and_time_reached(lock_guard<mutex>& lk) const;
|
||||
|
||||
bool wait_to_pull(unique_lock<mutex>&);
|
||||
template <class WClock, class Duration>
|
||||
queue_op_status wait_to_pull_until(unique_lock<mutex>&, chrono::time_point<WClock, Duration> const& tp);
|
||||
|
||||
T pull(unique_lock<mutex>&);
|
||||
T pull(lock_guard<mutex>&);
|
||||
|
||||
@@ -134,15 +136,6 @@ namespace detail
|
||||
|
||||
queue_op_status wait_pull(unique_lock<mutex>& lk, T& elem);
|
||||
|
||||
bool wait_until_not_empty_time_reached_or_closed(unique_lock<mutex>&);
|
||||
T pull_when_time_reached(unique_lock<mutex>&);
|
||||
template <class WClock, class Duration>
|
||||
queue_op_status pull_when_time_reached_until(unique_lock<mutex>&, chrono::time_point<WClock,Duration> const& tp, T& elem);
|
||||
bool time_not_reached(unique_lock<mutex>&);
|
||||
bool time_not_reached(lock_guard<mutex>&);
|
||||
bool empty_or_time_not_reached(unique_lock<mutex>&);
|
||||
bool empty_or_time_not_reached(lock_guard<mutex>&);
|
||||
|
||||
sync_timed_queue(const sync_timed_queue&);
|
||||
sync_timed_queue& operator=(const sync_timed_queue&);
|
||||
sync_timed_queue(BOOST_THREAD_RV_REF(sync_timed_queue));
|
||||
@@ -210,82 +203,55 @@ namespace detail
|
||||
|
||||
///////////////////////////
|
||||
template <class T, class Clock, class TimePoint>
|
||||
bool sync_timed_queue<T, Clock, TimePoint>::time_not_reached(unique_lock<mutex>&)
|
||||
bool sync_timed_queue<T, Clock, TimePoint>::not_empty_and_time_reached(unique_lock<mutex>& lk) const
|
||||
{
|
||||
return super::data_.top().time_not_reached();
|
||||
return ! super::empty(lk) && clock::now() >= super::data_.top().time;
|
||||
}
|
||||
|
||||
template <class T, class Clock, class TimePoint>
|
||||
bool sync_timed_queue<T, Clock, TimePoint>::time_not_reached(lock_guard<mutex>&)
|
||||
bool sync_timed_queue<T, Clock, TimePoint>::not_empty_and_time_reached(lock_guard<mutex>& lk) const
|
||||
{
|
||||
return super::data_.top().time_not_reached();
|
||||
return ! super::empty(lk) && clock::now() >= super::data_.top().time;
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
template <class T, class Clock, class TimePoint>
|
||||
bool sync_timed_queue<T, Clock, TimePoint>::wait_until_not_empty_time_reached_or_closed(unique_lock<mutex>& lk)
|
||||
bool sync_timed_queue<T, Clock, TimePoint>::wait_to_pull(unique_lock<mutex>& lk)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (super::closed(lk)) return true;
|
||||
while (! super::empty(lk)) {
|
||||
if (! time_not_reached(lk)) return false;
|
||||
time_point tp = super::data_.top().time;
|
||||
super::not_empty_.wait_until(lk, tp);
|
||||
if (super::closed(lk)) return true;
|
||||
}
|
||||
if (super::closed(lk)) return true;
|
||||
super::not_empty_.wait(lk);
|
||||
}
|
||||
//return false;
|
||||
}
|
||||
if (not_empty_and_time_reached(lk)) return false; // success
|
||||
if (super::closed(lk)) return true; // closed
|
||||
|
||||
///////////////////////////
|
||||
template <class T, class Clock, class TimePoint>
|
||||
T sync_timed_queue<T, Clock, TimePoint>::pull_when_time_reached(unique_lock<mutex>& lk)
|
||||
{
|
||||
while (time_not_reached(lk))
|
||||
{
|
||||
super::throw_if_closed(lk);
|
||||
time_point tp = super::data_.top().time;
|
||||
super::not_empty_.wait_until(lk,tp);
|
||||
super::wait_until_not_empty(lk);
|
||||
super::wait_until_not_empty_or_closed(lk);
|
||||
|
||||
if (not_empty_and_time_reached(lk)) return false; // success
|
||||
if (super::closed(lk)) return true; // closed
|
||||
|
||||
const time_point tp(super::data_.top().time);
|
||||
super::wait_until_closed_until(lk, tp);
|
||||
}
|
||||
return pull(lk);
|
||||
}
|
||||
|
||||
template <class T, class Clock, class TimePoint>
|
||||
template <class WClock, class Duration>
|
||||
queue_op_status
|
||||
sync_timed_queue<T, Clock, TimePoint>::pull_when_time_reached_until(unique_lock<mutex>& lk, chrono::time_point<WClock, Duration> const& tp, T& elem)
|
||||
queue_op_status sync_timed_queue<T, Clock, TimePoint>::wait_to_pull_until(unique_lock<mutex>& lk, chrono::time_point<WClock, Duration> const& tp)
|
||||
{
|
||||
chrono::time_point<WClock, Duration> tpmin = (tp < super::data_.top().time) ? tp : super::data_.top().time;
|
||||
while (time_not_reached(lk))
|
||||
for (;;)
|
||||
{
|
||||
super::throw_if_closed(lk);
|
||||
if (cv_status::timeout == super::not_empty_.wait_until(lk, tpmin)) {
|
||||
if (time_not_reached(lk)) return queue_op_status::not_ready;
|
||||
return queue_op_status::timeout;
|
||||
}
|
||||
}
|
||||
pull(lk, elem);
|
||||
return queue_op_status::success;
|
||||
}
|
||||
if (not_empty_and_time_reached(lk)) return queue_op_status::success;
|
||||
if (super::closed(lk)) return queue_op_status::closed;
|
||||
if (clock::now() >= tp) return super::empty(lk) ? queue_op_status::timeout : queue_op_status::not_ready;
|
||||
|
||||
///////////////////////////
|
||||
template <class T, class Clock, class TimePoint>
|
||||
bool sync_timed_queue<T, Clock, TimePoint>::empty_or_time_not_reached(unique_lock<mutex>& lk)
|
||||
{
|
||||
if ( super::empty(lk) ) return true;
|
||||
if ( time_not_reached(lk) ) return true;
|
||||
return false;
|
||||
}
|
||||
template <class T, class Clock, class TimePoint>
|
||||
bool sync_timed_queue<T, Clock, TimePoint>::empty_or_time_not_reached(lock_guard<mutex>& lk)
|
||||
{
|
||||
if ( super::empty(lk) ) return true;
|
||||
if ( time_not_reached(lk) ) return true;
|
||||
return false;
|
||||
super::wait_until_not_empty_or_closed_until(lk, tp);
|
||||
|
||||
if (not_empty_and_time_reached(lk)) return queue_op_status::success;
|
||||
if (super::closed(lk)) return queue_op_status::closed;
|
||||
if (clock::now() >= tp) return super::empty(lk) ? queue_op_status::timeout : queue_op_status::not_ready;
|
||||
|
||||
const time_point tpmin(tp < super::data_.top().time ? tp : super::data_.top().time);
|
||||
super::wait_until_closed_until(lk, tpmin);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
@@ -312,8 +278,9 @@ namespace detail
|
||||
T sync_timed_queue<T, Clock, TimePoint>::pull()
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
super::wait_until_not_empty(lk);
|
||||
return pull_when_time_reached(lk);
|
||||
const bool has_been_closed = wait_to_pull(lk);
|
||||
if (has_been_closed) super::throw_if_closed(lk);
|
||||
return pull(lk);
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
@@ -341,8 +308,9 @@ namespace detail
|
||||
void sync_timed_queue<T, Clock, TimePoint>::pull(T& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
super::wait_until_not_empty(lk);
|
||||
elem = pull_when_time_reached(lk);
|
||||
const bool has_been_closed = wait_to_pull(lk);
|
||||
if (has_been_closed) super::throw_if_closed(lk);
|
||||
pull(lk, elem);
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
@@ -352,10 +320,9 @@ namespace detail
|
||||
sync_timed_queue<T, Clock, TimePoint>::pull_until(chrono::time_point<WClock, Duration> const& tp, T& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
|
||||
if (queue_op_status::timeout == super::wait_until_not_empty_until(lk, tp))
|
||||
return queue_op_status::timeout;
|
||||
return pull_when_time_reached_until(lk, tp, elem);
|
||||
const queue_op_status rc = wait_to_pull_until(lk, tp);
|
||||
if (rc == queue_op_status::success) pull(lk, elem);
|
||||
return rc;
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
@@ -371,35 +338,26 @@ namespace detail
|
||||
template <class T, class Clock, class TimePoint>
|
||||
queue_op_status sync_timed_queue<T, Clock, TimePoint>::try_pull(unique_lock<mutex>& lk, T& elem)
|
||||
{
|
||||
if ( super::empty(lk) )
|
||||
if (not_empty_and_time_reached(lk))
|
||||
{
|
||||
if (super::closed(lk)) return queue_op_status::closed;
|
||||
return queue_op_status::empty;
|
||||
pull(lk, elem);
|
||||
return queue_op_status::success;
|
||||
}
|
||||
if ( time_not_reached(lk) )
|
||||
{
|
||||
if (super::closed(lk)) return queue_op_status::closed;
|
||||
return queue_op_status::not_ready;
|
||||
}
|
||||
|
||||
pull(lk, elem);
|
||||
return queue_op_status::success;
|
||||
if (super::closed(lk)) return queue_op_status::closed;
|
||||
if (super::empty(lk)) return queue_op_status::empty;
|
||||
return queue_op_status::not_ready;
|
||||
}
|
||||
template <class T, class Clock, class TimePoint>
|
||||
queue_op_status sync_timed_queue<T, Clock, TimePoint>::try_pull(lock_guard<mutex>& lk, T& elem)
|
||||
{
|
||||
if ( super::empty(lk) )
|
||||
if (not_empty_and_time_reached(lk))
|
||||
{
|
||||
if (super::closed(lk)) return queue_op_status::closed;
|
||||
return queue_op_status::empty;
|
||||
pull(lk, elem);
|
||||
return queue_op_status::success;
|
||||
}
|
||||
if ( time_not_reached(lk) )
|
||||
{
|
||||
if (super::closed(lk)) return queue_op_status::closed;
|
||||
return queue_op_status::not_ready;
|
||||
}
|
||||
pull(lk, elem);
|
||||
return queue_op_status::success;
|
||||
if (super::closed(lk)) return queue_op_status::closed;
|
||||
if (super::empty(lk)) return queue_op_status::empty;
|
||||
return queue_op_status::not_ready;
|
||||
}
|
||||
|
||||
template <class T, class Clock, class TimePoint>
|
||||
@@ -413,11 +371,7 @@ namespace detail
|
||||
template <class T, class Clock, class TimePoint>
|
||||
queue_op_status sync_timed_queue<T, Clock, TimePoint>::wait_pull(unique_lock<mutex>& lk, T& elem)
|
||||
{
|
||||
if (super::empty(lk))
|
||||
{
|
||||
if (super::closed(lk)) return queue_op_status::closed;
|
||||
}
|
||||
bool has_been_closed = wait_until_not_empty_time_reached_or_closed(lk);
|
||||
const bool has_been_closed = wait_to_pull(lk);
|
||||
if (has_been_closed) return queue_op_status::closed;
|
||||
pull(lk, elem);
|
||||
return queue_op_status::success;
|
||||
@@ -430,26 +384,6 @@ namespace detail
|
||||
return wait_pull(lk, elem);
|
||||
}
|
||||
|
||||
// ///////////////////////////
|
||||
// template <class T, class Clock, class TimePoint>
|
||||
// queue_op_status sync_timed_queue<T, Clock, TimePoint>::wait_pull(unique_lock<mutex> &lk, T& elem)
|
||||
// {
|
||||
// if (super::empty(lk))
|
||||
// {
|
||||
// if (super::closed(lk)) return queue_op_status::closed;
|
||||
// }
|
||||
// bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
|
||||
// if (has_been_closed) return queue_op_status::closed;
|
||||
// pull(lk, elem);
|
||||
// return queue_op_status::success;
|
||||
// }
|
||||
// template <class T, class Clock, class TimePoint>
|
||||
// queue_op_status sync_timed_queue<T, Clock, TimePoint>::wait_pull(T& elem)
|
||||
// {
|
||||
// unique_lock<mutex> lk(super::mtx_);
|
||||
// return wait_pull(lk, elem);
|
||||
// }
|
||||
|
||||
///////////////////////////
|
||||
template <class T, class Clock, class TimePoint>
|
||||
queue_op_status sync_timed_queue<T, Clock, TimePoint>::nonblocking_pull(T& elem)
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/thread/detail/platform.hpp>
|
||||
|
||||
//#define BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
|
||||
//#define BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS
|
||||
// ATTRIBUTE_MAY_ALIAS
|
||||
|
||||
@@ -30,6 +29,34 @@
|
||||
#define BOOST_THREAD_ATTRIBUTE_MAY_ALIAS
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_THREAD_CHRONO_WINDOWS_API)
|
||||
# warning Boost.Thread will use the Windows API for time
|
||||
#elif defined(BOOST_THREAD_CHRONO_MAC_API)
|
||||
# warning Boost.Thread will use the Mac API for time
|
||||
#elif defined(BOOST_THREAD_CHRONO_POSIX_API)
|
||||
# warning Boost.Thread will use the POSIX API for time
|
||||
#endif
|
||||
|
||||
# if defined( BOOST_THREAD_CHRONO_WINDOWS_API ) && defined( BOOST_THREAD_CHRONO_POSIX_API )
|
||||
# error both BOOST_THREAD_CHRONO_WINDOWS_API and BOOST_THREAD_CHRONO_POSIX_API are defined
|
||||
# elif defined( BOOST_THREAD_CHRONO_WINDOWS_API ) && defined( BOOST_THREAD_CHRONO_MAC_API )
|
||||
# error both BOOST_THREAD_CHRONO_WINDOWS_API and BOOST_THREAD_CHRONO_MAC_API are defined
|
||||
# elif defined( BOOST_THREAD_CHRONO_MAC_API ) && defined( BOOST_THREAD_CHRONO_POSIX_API )
|
||||
# error both BOOST_THREAD_CHRONO_MAC_API and BOOST_THREAD_CHRONO_POSIX_API are defined
|
||||
# elif !defined( BOOST_THREAD_CHRONO_WINDOWS_API ) && !defined( BOOST_THREAD_CHRONO_MAC_API ) && !defined( BOOST_THREAD_CHRONO_POSIX_API )
|
||||
# if (defined(_WIN32) || defined(__WIN32__) || defined(WIN32))
|
||||
# define BOOST_THREAD_CHRONO_WINDOWS_API
|
||||
# elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
|
||||
# define BOOST_THREAD_CHRONO_MAC_API
|
||||
# else
|
||||
# define BOOST_THREAD_CHRONO_POSIX_API
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#if !defined(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)
|
||||
#define BOOST_THREAD_POLL_INTERVAL_MILLISECONDS 100
|
||||
#endif
|
||||
|
||||
#if defined BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
|
||||
#define BOOST_THREAD_ASSERT_PRECONDITION(EXPR, EX) \
|
||||
if (EXPR) {} else boost::throw_exception(EX)
|
||||
@@ -96,7 +123,7 @@
|
||||
|
||||
/// RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
|
||||
//#if defined BOOST_NO_CXX11_RVALUE_REFERENCES || defined BOOST_MSVC
|
||||
#define BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
|
||||
#define BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR
|
||||
//#endif
|
||||
|
||||
// Default version
|
||||
@@ -385,6 +412,29 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_THREAD_CHRONO_WINDOWS_API)
|
||||
#define BOOST_THREAD_HAS_MONO_CLOCK
|
||||
#define BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
|
||||
#elif defined(BOOST_THREAD_CHRONO_MAC_API)
|
||||
#define BOOST_THREAD_HAS_MONO_CLOCK
|
||||
#else
|
||||
#include <time.h> // check for CLOCK_MONOTONIC
|
||||
#if defined(CLOCK_MONOTONIC)
|
||||
#define BOOST_THREAD_HAS_MONO_CLOCK
|
||||
#define BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_THREAD_PLATFORM_WIN32)
|
||||
#elif ! defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
|
||||
#if defined BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||
#define BOOST_THREAD_USES_PTHREAD_TIMEDLOCK
|
||||
#elif (defined(_POSIX_TIMEOUTS) && (_POSIX_TIMEOUTS-0)>=200112L) \
|
||||
|| (defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__ >= 21)
|
||||
#define BOOST_THREAD_USES_PTHREAD_TIMEDLOCK
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// provided for backwards compatibility, since this
|
||||
// macro was used for several releases by mistake.
|
||||
#if defined(BOOST_THREAD_DYN_DLL) && ! defined(BOOST_THREAD_DYN_LINK)
|
||||
|
||||
@@ -31,7 +31,9 @@
|
||||
#elif defined(__CYGWIN__)
|
||||
# define BOOST_THREAD_CYGWIN
|
||||
#elif (defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) && !defined(BOOST_DISABLE_WIN32)
|
||||
#if ! defined BOOST_THREAD_WIN32
|
||||
# define BOOST_THREAD_WIN32
|
||||
#endif
|
||||
#elif defined(__BEOS__)
|
||||
# define BOOST_THREAD_BEOS
|
||||
#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
|
||||
|
||||
478
include/boost/thread/detail/platform_time.hpp
Normal file
478
include/boost/thread/detail/platform_time.hpp
Normal file
@@ -0,0 +1,478 @@
|
||||
#ifndef BOOST_THREAD_DETAIL_PLATFORM_TIME_HPP
|
||||
#define BOOST_THREAD_DETAIL_PLATFORM_TIME_HPP
|
||||
// (C) Copyright 2007-8 Anthony Williams
|
||||
// (C) Copyright 2012 Vicente J. Botet Escriba
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/thread_time.hpp>
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
#include <boost/date_time/posix_time/conversion.hpp>
|
||||
#endif
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
#include <boost/chrono/duration.hpp>
|
||||
#include <boost/chrono/system_clocks.hpp>
|
||||
#include <boost/chrono/ceil.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_THREAD_CHRONO_WINDOWS_API)
|
||||
#include <boost/detail/winapi/time.hpp>
|
||||
#include <boost/detail/winapi/timers.hpp>
|
||||
#include <boost/thread/win32/thread_primitives.hpp>
|
||||
#elif defined(BOOST_THREAD_CHRONO_MAC_API)
|
||||
#include <sys/time.h> //for gettimeofday and timeval
|
||||
#include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t
|
||||
|
||||
#else
|
||||
#include <time.h> // for clock_gettime
|
||||
#endif
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
//typedef boost::int_least64_t time_max_t;
|
||||
typedef boost::intmax_t time_max_t;
|
||||
|
||||
#if defined BOOST_THREAD_CHRONO_MAC_API
|
||||
namespace threads
|
||||
{
|
||||
|
||||
namespace chrono_details
|
||||
{
|
||||
|
||||
// steady_clock
|
||||
|
||||
// Note, in this implementation steady_clock and high_resolution_clock
|
||||
// are the same clock. They are both based on mach_absolute_time().
|
||||
// mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of
|
||||
// nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom
|
||||
// are run time constants supplied by the OS. This clock has no relationship
|
||||
// to the Gregorian calendar. It's main use is as a high resolution timer.
|
||||
|
||||
// MachInfo.numer / MachInfo.denom is often 1 on the latest equipment. Specialize
|
||||
// for that case as an optimization.
|
||||
|
||||
inline time_max_t
|
||||
steady_simplified()
|
||||
{
|
||||
return mach_absolute_time();
|
||||
}
|
||||
|
||||
inline double compute_steady_factor(kern_return_t& err)
|
||||
{
|
||||
mach_timebase_info_data_t MachInfo;
|
||||
err = mach_timebase_info(&MachInfo);
|
||||
if ( err != 0 ) {
|
||||
return 0;
|
||||
}
|
||||
return static_cast<double>(MachInfo.numer) / MachInfo.denom;
|
||||
}
|
||||
|
||||
inline time_max_t steady_full()
|
||||
{
|
||||
kern_return_t err;
|
||||
const double factor = chrono_details::compute_steady_factor(err);
|
||||
if (err != 0)
|
||||
{
|
||||
BOOST_ASSERT(0 && "Boost::Chrono - Internal Error");
|
||||
}
|
||||
return static_cast<time_max_t>(mach_absolute_time() * factor);
|
||||
}
|
||||
|
||||
|
||||
typedef time_max_t (*FP)();
|
||||
|
||||
inline FP init_steady_clock(kern_return_t & err)
|
||||
{
|
||||
mach_timebase_info_data_t MachInfo;
|
||||
err = mach_timebase_info(&MachInfo);
|
||||
if ( err != 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (MachInfo.numer == MachInfo.denom)
|
||||
{
|
||||
return &chrono_details::steady_simplified;
|
||||
}
|
||||
return &chrono_details::steady_full;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace detail
|
||||
{
|
||||
#if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API
|
||||
inline timespec ns_to_timespec(boost::time_max_t const& ns)
|
||||
{
|
||||
boost::time_max_t s = ns / 1000000000l;
|
||||
timespec ts;
|
||||
ts.tv_sec = static_cast<long> (s);
|
||||
ts.tv_nsec = static_cast<long> (ns - s * 1000000000l);
|
||||
return ts;
|
||||
}
|
||||
inline boost::time_max_t timespec_to_ns(timespec const& ts)
|
||||
{
|
||||
return static_cast<boost::time_max_t>(ts.tv_sec) * 1000000000l + ts.tv_nsec;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct platform_duration
|
||||
{
|
||||
#if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API
|
||||
explicit platform_duration(timespec const& v) : ts_val(v) {}
|
||||
timespec const& getTs() const { return ts_val; }
|
||||
|
||||
explicit platform_duration(boost::time_max_t const& ns = 0) : ts_val(ns_to_timespec(ns)) {}
|
||||
boost::time_max_t getNs() const { return timespec_to_ns(ts_val); }
|
||||
#else
|
||||
explicit platform_duration(boost::time_max_t const& ns = 0) : ns_val(ns) {}
|
||||
boost::time_max_t getNs() const { return ns_val; }
|
||||
#endif
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
platform_duration(boost::posix_time::time_duration const& rel_time)
|
||||
{
|
||||
#if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API
|
||||
ts_val.tv_sec = rel_time.total_seconds();
|
||||
ts_val.tv_nsec = static_cast<long>(rel_time.fractional_seconds() * (1000000000l / rel_time.ticks_per_second()));
|
||||
#else
|
||||
ns_val = static_cast<boost::time_max_t>(rel_time.total_seconds()) * 1000000000l;
|
||||
ns_val += rel_time.fractional_seconds() * (1000000000l / rel_time.ticks_per_second());
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
template <class Rep, class Period>
|
||||
platform_duration(chrono::duration<Rep, Period> const& d)
|
||||
{
|
||||
#if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API
|
||||
ts_val = ns_to_timespec(chrono::ceil<chrono::nanoseconds>(d).count());
|
||||
#else
|
||||
ns_val = chrono::ceil<chrono::nanoseconds>(d).count();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
boost::time_max_t getMs() const
|
||||
{
|
||||
const boost::time_max_t ns = getNs();
|
||||
// ceil/floor away from zero
|
||||
if (ns >= 0)
|
||||
{
|
||||
// return ceiling of positive numbers
|
||||
return (ns + 999999) / 1000000;
|
||||
}
|
||||
else
|
||||
{
|
||||
// return floor of negative numbers
|
||||
return (ns - 999999) / 1000000;
|
||||
}
|
||||
}
|
||||
|
||||
static platform_duration zero()
|
||||
{
|
||||
return platform_duration(0);
|
||||
}
|
||||
|
||||
private:
|
||||
#if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API
|
||||
timespec ts_val;
|
||||
#else
|
||||
boost::time_max_t ns_val;
|
||||
#endif
|
||||
};
|
||||
|
||||
inline bool operator==(platform_duration const& lhs, platform_duration const& rhs)
|
||||
{
|
||||
return lhs.getNs() == rhs.getNs();
|
||||
}
|
||||
inline bool operator!=(platform_duration const& lhs, platform_duration const& rhs)
|
||||
{
|
||||
return lhs.getNs() != rhs.getNs();
|
||||
}
|
||||
inline bool operator<(platform_duration const& lhs, platform_duration const& rhs)
|
||||
{
|
||||
return lhs.getNs() < rhs.getNs();
|
||||
}
|
||||
inline bool operator<=(platform_duration const& lhs, platform_duration const& rhs)
|
||||
{
|
||||
return lhs.getNs() <= rhs.getNs();
|
||||
}
|
||||
inline bool operator>(platform_duration const& lhs, platform_duration const& rhs)
|
||||
{
|
||||
return lhs.getNs() > rhs.getNs();
|
||||
}
|
||||
inline bool operator>=(platform_duration const& lhs, platform_duration const& rhs)
|
||||
{
|
||||
return lhs.getNs() >= rhs.getNs();
|
||||
}
|
||||
|
||||
static inline platform_duration platform_milliseconds(long const& ms)
|
||||
{
|
||||
return platform_duration(ms * 1000000l);
|
||||
}
|
||||
|
||||
struct real_platform_timepoint
|
||||
{
|
||||
#if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API
|
||||
explicit real_platform_timepoint(timespec const& v) : dur(v) {}
|
||||
timespec const& getTs() const { return dur.getTs(); }
|
||||
#endif
|
||||
|
||||
explicit real_platform_timepoint(boost::time_max_t const& ns) : dur(ns) {}
|
||||
boost::time_max_t getNs() const { return dur.getNs(); }
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
real_platform_timepoint(boost::system_time const& abs_time)
|
||||
: dur(abs_time - boost::posix_time::from_time_t(0)) {}
|
||||
#endif
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
template <class Duration>
|
||||
real_platform_timepoint(chrono::time_point<chrono::system_clock, Duration> const& abs_time)
|
||||
: dur(abs_time.time_since_epoch()) {}
|
||||
#endif
|
||||
|
||||
private:
|
||||
platform_duration dur;
|
||||
};
|
||||
|
||||
inline bool operator==(real_platform_timepoint const& lhs, real_platform_timepoint const& rhs)
|
||||
{
|
||||
return lhs.getNs() == rhs.getNs();
|
||||
}
|
||||
inline bool operator!=(real_platform_timepoint const& lhs, real_platform_timepoint const& rhs)
|
||||
{
|
||||
return lhs.getNs() != rhs.getNs();
|
||||
}
|
||||
inline bool operator<(real_platform_timepoint const& lhs, real_platform_timepoint const& rhs)
|
||||
{
|
||||
return lhs.getNs() < rhs.getNs();
|
||||
}
|
||||
inline bool operator<=(real_platform_timepoint const& lhs, real_platform_timepoint const& rhs)
|
||||
{
|
||||
return lhs.getNs() <= rhs.getNs();
|
||||
}
|
||||
inline bool operator>(real_platform_timepoint const& lhs, real_platform_timepoint const& rhs)
|
||||
{
|
||||
return lhs.getNs() > rhs.getNs();
|
||||
}
|
||||
inline bool operator>=(real_platform_timepoint const& lhs, real_platform_timepoint const& rhs)
|
||||
{
|
||||
return lhs.getNs() >= rhs.getNs();
|
||||
}
|
||||
|
||||
inline real_platform_timepoint operator+(real_platform_timepoint const& lhs, platform_duration const& rhs)
|
||||
{
|
||||
return real_platform_timepoint(lhs.getNs() + rhs.getNs());
|
||||
}
|
||||
inline real_platform_timepoint operator+(platform_duration const& lhs, real_platform_timepoint const& rhs)
|
||||
{
|
||||
return real_platform_timepoint(lhs.getNs() + rhs.getNs());
|
||||
}
|
||||
inline platform_duration operator-(real_platform_timepoint const& lhs, real_platform_timepoint const& rhs)
|
||||
{
|
||||
return platform_duration(lhs.getNs() - rhs.getNs());
|
||||
}
|
||||
|
||||
struct real_platform_clock
|
||||
{
|
||||
static real_platform_timepoint now()
|
||||
{
|
||||
#if defined(BOOST_THREAD_CHRONO_WINDOWS_API)
|
||||
boost::detail::winapi::FILETIME_ ft;
|
||||
boost::detail::winapi::GetSystemTimeAsFileTime(&ft); // never fails
|
||||
boost::time_max_t ns = ((((static_cast<boost::time_max_t>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime) - 116444736000000000LL) * 100LL);
|
||||
return real_platform_timepoint(ns);
|
||||
#elif defined(BOOST_THREAD_CHRONO_MAC_API)
|
||||
timeval tv;
|
||||
::gettimeofday(&tv, 0);
|
||||
timespec ts;
|
||||
ts.tv_sec = tv.tv_sec;
|
||||
ts.tv_nsec = tv.tv_usec * 1000;
|
||||
return real_platform_timepoint(ts);
|
||||
#else
|
||||
timespec ts;
|
||||
if ( ::clock_gettime( CLOCK_REALTIME, &ts ) )
|
||||
{
|
||||
BOOST_ASSERT(0 && "Boost::Thread - clock_gettime(CLOCK_REALTIME) Internal Error");
|
||||
return real_platform_timepoint(0);
|
||||
}
|
||||
return real_platform_timepoint(ts);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(BOOST_THREAD_HAS_MONO_CLOCK)
|
||||
|
||||
struct mono_platform_timepoint
|
||||
{
|
||||
#if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API
|
||||
|
||||
explicit mono_platform_timepoint(timespec const& v) : dur(v) {}
|
||||
timespec const& getTs() const { return dur.getTs(); }
|
||||
#endif
|
||||
|
||||
explicit mono_platform_timepoint(boost::time_max_t const& ns) : dur(ns) {}
|
||||
boost::time_max_t getNs() const { return dur.getNs(); }
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
// This conversion assumes that chrono::steady_clock::time_point and mono_platform_timepoint share the same epoch.
|
||||
template <class Duration>
|
||||
mono_platform_timepoint(chrono::time_point<chrono::steady_clock, Duration> const& abs_time)
|
||||
: dur(abs_time.time_since_epoch()) {}
|
||||
#endif
|
||||
|
||||
// can't name this max() since that is a macro on some Windows systems
|
||||
static mono_platform_timepoint getMax()
|
||||
{
|
||||
#if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API
|
||||
timespec ts;
|
||||
ts.tv_sec = (std::numeric_limits<time_t>::max)();
|
||||
ts.tv_nsec = 999999999;
|
||||
return mono_platform_timepoint(ts);
|
||||
#else
|
||||
boost::time_max_t ns = (std::numeric_limits<boost::time_max_t>::max)();
|
||||
return mono_platform_timepoint(ns);
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
platform_duration dur;
|
||||
};
|
||||
|
||||
inline bool operator==(mono_platform_timepoint const& lhs, mono_platform_timepoint const& rhs)
|
||||
{
|
||||
return lhs.getNs() == rhs.getNs();
|
||||
}
|
||||
inline bool operator!=(mono_platform_timepoint const& lhs, mono_platform_timepoint const& rhs)
|
||||
{
|
||||
return lhs.getNs() != rhs.getNs();
|
||||
}
|
||||
inline bool operator<(mono_platform_timepoint const& lhs, mono_platform_timepoint const& rhs)
|
||||
{
|
||||
return lhs.getNs() < rhs.getNs();
|
||||
}
|
||||
inline bool operator<=(mono_platform_timepoint const& lhs, mono_platform_timepoint const& rhs)
|
||||
{
|
||||
return lhs.getNs() <= rhs.getNs();
|
||||
}
|
||||
inline bool operator>(mono_platform_timepoint const& lhs, mono_platform_timepoint const& rhs)
|
||||
{
|
||||
return lhs.getNs() > rhs.getNs();
|
||||
}
|
||||
inline bool operator>=(mono_platform_timepoint const& lhs, mono_platform_timepoint const& rhs)
|
||||
{
|
||||
return lhs.getNs() >= rhs.getNs();
|
||||
}
|
||||
|
||||
inline mono_platform_timepoint operator+(mono_platform_timepoint const& lhs, platform_duration const& rhs)
|
||||
{
|
||||
return mono_platform_timepoint(lhs.getNs() + rhs.getNs());
|
||||
}
|
||||
inline mono_platform_timepoint operator+(platform_duration const& lhs, mono_platform_timepoint const& rhs)
|
||||
{
|
||||
return mono_platform_timepoint(lhs.getNs() + rhs.getNs());
|
||||
}
|
||||
inline platform_duration operator-(mono_platform_timepoint const& lhs, mono_platform_timepoint const& rhs)
|
||||
{
|
||||
return platform_duration(lhs.getNs() - rhs.getNs());
|
||||
}
|
||||
|
||||
struct mono_platform_clock
|
||||
{
|
||||
static mono_platform_timepoint now()
|
||||
{
|
||||
#if defined(BOOST_THREAD_CHRONO_WINDOWS_API)
|
||||
#if defined(BOOST_THREAD_USES_CHRONO)
|
||||
// Use QueryPerformanceCounter() to match the implementation in Boost
|
||||
// Chrono so that chrono::steady_clock::now() and this function share the
|
||||
// same epoch and so can be converted between each other.
|
||||
boost::detail::winapi::LARGE_INTEGER_ freq;
|
||||
if ( !boost::detail::winapi::QueryPerformanceFrequency( &freq ) )
|
||||
{
|
||||
BOOST_ASSERT(0 && "Boost::Thread - QueryPerformanceFrequency Internal Error");
|
||||
return mono_platform_timepoint(0);
|
||||
}
|
||||
if ( freq.QuadPart <= 0 )
|
||||
{
|
||||
BOOST_ASSERT(0 && "Boost::Thread - QueryPerformanceFrequency Internal Error");
|
||||
return mono_platform_timepoint(0);
|
||||
}
|
||||
|
||||
boost::detail::winapi::LARGE_INTEGER_ pcount;
|
||||
unsigned times=0;
|
||||
while ( ! boost::detail::winapi::QueryPerformanceCounter( &pcount ) )
|
||||
{
|
||||
if ( ++times > 3 )
|
||||
{
|
||||
BOOST_ASSERT(0 && "Boost::Thread - QueryPerformanceCounter Internal Error");
|
||||
return mono_platform_timepoint(0);
|
||||
}
|
||||
}
|
||||
|
||||
long double ns = 1000000000.0L * pcount.QuadPart / freq.QuadPart;
|
||||
return mono_platform_timepoint(static_cast<boost::time_max_t>(ns));
|
||||
#else
|
||||
// Use GetTickCount64() because it's more reliable on older
|
||||
// systems like Windows XP and Windows Server 2003.
|
||||
win32::ticks_type msec = win32::gettickcount64();
|
||||
return mono_platform_timepoint(msec * 1000000);
|
||||
#endif
|
||||
#elif defined(BOOST_THREAD_CHRONO_MAC_API)
|
||||
kern_return_t err;
|
||||
threads::chrono_details::FP fp = threads::chrono_details::init_steady_clock(err);
|
||||
if ( err != 0 )
|
||||
{
|
||||
BOOST_ASSERT(0 && "Boost::Chrono - Internal Error");
|
||||
}
|
||||
return mono_platform_timepoint(fp());
|
||||
#else
|
||||
timespec ts;
|
||||
if ( ::clock_gettime( CLOCK_MONOTONIC, &ts ) )
|
||||
{
|
||||
BOOST_ASSERT(0 && "Boost::Thread - clock_gettime(CLOCK_MONOTONIC) Internal Error");
|
||||
return mono_platform_timepoint(0);
|
||||
}
|
||||
return mono_platform_timepoint(ts);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO)
|
||||
typedef mono_platform_clock internal_platform_clock;
|
||||
typedef mono_platform_timepoint internal_platform_timepoint;
|
||||
#else
|
||||
typedef real_platform_clock internal_platform_clock;
|
||||
typedef real_platform_timepoint internal_platform_timepoint;
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
#ifdef BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
|
||||
typedef chrono::steady_clock internal_chrono_clock;
|
||||
#else
|
||||
typedef chrono::system_clock internal_chrono_clock;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/decay.hpp>
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <boost/thread/detail/platform_time.hpp>
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
#include <boost/chrono/system_clocks.hpp>
|
||||
#include <boost/chrono/ceil.hpp>
|
||||
@@ -155,15 +156,7 @@ namespace boost
|
||||
};
|
||||
#endif
|
||||
}
|
||||
namespace thread_detail {
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
#if defined(BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC)
|
||||
typedef chrono::steady_clock internal_clock_t;
|
||||
#else
|
||||
typedef chrono::system_clock internal_clock_t;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
class BOOST_THREAD_DECL thread
|
||||
{
|
||||
public:
|
||||
@@ -462,105 +455,80 @@ namespace thread_detail {
|
||||
}
|
||||
|
||||
class id;
|
||||
#ifdef BOOST_THREAD_PLATFORM_PTHREAD
|
||||
inline id get_id() const BOOST_NOEXCEPT;
|
||||
#else
|
||||
id get_id() const BOOST_NOEXCEPT;
|
||||
#endif
|
||||
|
||||
|
||||
bool joinable() const BOOST_NOEXCEPT;
|
||||
private:
|
||||
bool join_noexcept();
|
||||
bool do_try_join_until_noexcept(detail::internal_platform_timepoint const &timeout, bool& res);
|
||||
bool do_try_join_until(detail::internal_platform_timepoint const &timeout);
|
||||
public:
|
||||
inline void join();
|
||||
void join();
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
#if defined(BOOST_THREAD_PLATFORM_WIN32)
|
||||
template <class Rep, class Period>
|
||||
bool try_join_for(const chrono::duration<Rep, Period>& rel_time)
|
||||
template <class Duration>
|
||||
bool try_join_until(const chrono::time_point<detail::internal_chrono_clock, Duration>& t)
|
||||
{
|
||||
chrono::milliseconds rel_time2= chrono::ceil<chrono::milliseconds>(rel_time);
|
||||
return do_try_join_until(rel_time2.count());
|
||||
return do_try_join_until(boost::detail::internal_platform_timepoint(t));
|
||||
}
|
||||
#else
|
||||
|
||||
template <class Clock, class Duration>
|
||||
bool try_join_until(const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
|
||||
common_duration d(t - Clock::now());
|
||||
d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
|
||||
while ( ! try_join_until(detail::internal_chrono_clock::now() + d) )
|
||||
{
|
||||
d = t - Clock::now();
|
||||
if ( d <= common_duration::zero() ) return false; // timeout occurred
|
||||
d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class Rep, class Period>
|
||||
bool try_join_for(const chrono::duration<Rep, Period>& rel_time)
|
||||
{
|
||||
return try_join_until(chrono::steady_clock::now() + rel_time);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class Clock, class Duration>
|
||||
bool try_join_until(const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
using namespace chrono;
|
||||
bool joined= false;
|
||||
do {
|
||||
thread_detail::internal_clock_t::time_point s_now = thread_detail::internal_clock_t::now();
|
||||
typename Clock::duration d = ceil<nanoseconds>(t-Clock::now());
|
||||
if (d <= Clock::duration::zero()) return false; // in case the Clock::time_point t is already reached
|
||||
joined = try_join_until(s_now + d);
|
||||
} while (! joined);
|
||||
return true;
|
||||
}
|
||||
template <class Duration>
|
||||
bool try_join_until(const chrono::time_point<thread_detail::internal_clock_t, Duration>& t)
|
||||
{
|
||||
using namespace chrono;
|
||||
typedef time_point<thread_detail::internal_clock_t, nanoseconds> nano_sys_tmpt;
|
||||
return try_join_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
|
||||
}
|
||||
#endif
|
||||
#if defined(BOOST_THREAD_PLATFORM_WIN32)
|
||||
private:
|
||||
bool do_try_join_until_noexcept(uintmax_t milli, bool& res);
|
||||
inline bool do_try_join_until(uintmax_t milli);
|
||||
public:
|
||||
bool timed_join(const system_time& abs_time);
|
||||
//{
|
||||
// return do_try_join_until(get_milliseconds_until(wait_until));
|
||||
//}
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
bool try_join_until(const chrono::time_point<thread_detail::internal_clock_t, chrono::nanoseconds>& tp)
|
||||
{
|
||||
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now());
|
||||
return do_try_join_until(rel_time.count());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#else
|
||||
private:
|
||||
bool do_try_join_until_noexcept(struct timespec const &timeout, bool& res);
|
||||
inline bool do_try_join_until(struct timespec const &timeout);
|
||||
public:
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
bool timed_join(const system_time& abs_time)
|
||||
{
|
||||
struct timespec const ts=detail::to_timespec(abs_time);
|
||||
const detail::real_platform_timepoint ts(abs_time);
|
||||
#if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
|
||||
detail::platform_duration d(ts - detail::real_platform_clock::now());
|
||||
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
while ( ! do_try_join_until(detail::internal_platform_clock::now() + d) )
|
||||
{
|
||||
d = ts - detail::real_platform_clock::now();
|
||||
if ( d <= detail::platform_duration::zero() ) return false; // timeout occurred
|
||||
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
return do_try_join_until(ts);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
bool try_join_until(const chrono::time_point<thread_detail::internal_clock_t, chrono::nanoseconds>& tp)
|
||||
{
|
||||
using namespace chrono;
|
||||
nanoseconds d = tp.time_since_epoch();
|
||||
timespec ts = boost::detail::to_timespec(d);
|
||||
return do_try_join_until(ts);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
public:
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
template<typename TimeDuration>
|
||||
inline bool timed_join(TimeDuration const& rel_time)
|
||||
bool timed_join(TimeDuration const& rel_time)
|
||||
{
|
||||
return timed_join(get_system_time()+rel_time);
|
||||
detail::platform_duration d(rel_time);
|
||||
#if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO)
|
||||
const detail::mono_platform_timepoint ts(detail::mono_platform_clock::now() + d);
|
||||
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
while ( ! do_try_join_until(detail::internal_platform_clock::now() + d) )
|
||||
{
|
||||
d = ts - detail::mono_platform_clock::now();
|
||||
if ( d <= detail::platform_duration::zero() ) return false; // timeout occurred
|
||||
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
return do_try_join_until(detail::internal_platform_clock::now() + d);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
void detach();
|
||||
@@ -614,7 +582,7 @@ namespace thread_detail {
|
||||
namespace this_thread
|
||||
{
|
||||
#ifdef BOOST_THREAD_PLATFORM_PTHREAD
|
||||
inline thread::id get_id() BOOST_NOEXCEPT;
|
||||
thread::id get_id() BOOST_NOEXCEPT;
|
||||
#else
|
||||
thread::id BOOST_THREAD_DECL get_id() BOOST_NOEXCEPT;
|
||||
#endif
|
||||
@@ -745,7 +713,7 @@ namespace thread_detail {
|
||||
};
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_PTHREAD
|
||||
thread::id thread::get_id() const BOOST_NOEXCEPT
|
||||
inline thread::id thread::get_id() const BOOST_NOEXCEPT
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
|
||||
return const_cast<thread*>(this)->native_handle();
|
||||
@@ -768,7 +736,7 @@ namespace thread_detail {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
void thread::join() {
|
||||
inline void thread::join() {
|
||||
if (this_thread::get_id() == get_id())
|
||||
boost::throw_exception(thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost thread: trying joining itself"));
|
||||
|
||||
@@ -777,11 +745,7 @@ namespace thread_detail {
|
||||
);
|
||||
}
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_PTHREAD
|
||||
bool thread::do_try_join_until(struct timespec const &timeout)
|
||||
#else
|
||||
bool thread::do_try_join_until(uintmax_t timeout)
|
||||
#endif
|
||||
inline bool thread::do_try_join_until(detail::internal_platform_timepoint const &timeout)
|
||||
{
|
||||
if (this_thread::get_id() == get_id())
|
||||
boost::throw_exception(thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost thread: trying joining itself"));
|
||||
|
||||
@@ -159,7 +159,7 @@ namespace boost
|
||||
boost::function<void()> callback;
|
||||
// This declaration should be only included conditionally, but is included to maintain the same layout.
|
||||
continuations_type continuations;
|
||||
executor_ptr_type ex;
|
||||
executor_ptr_type ex_;
|
||||
|
||||
// This declaration should be only included conditionally, but is included to maintain the same layout.
|
||||
virtual void launch_continuation()
|
||||
@@ -173,43 +173,49 @@ namespace boost
|
||||
is_constructed(false),
|
||||
policy_(launch::none),
|
||||
continuations(),
|
||||
ex()
|
||||
ex_()
|
||||
{}
|
||||
|
||||
shared_state_base(exceptional_ptr const& ex_):
|
||||
exception(ex_.ptr_),
|
||||
shared_state_base(exceptional_ptr const& ex):
|
||||
exception(ex.ptr_),
|
||||
done(true),
|
||||
is_valid_(true),
|
||||
is_deferred_(false),
|
||||
is_constructed(false),
|
||||
policy_(launch::none),
|
||||
continuations(),
|
||||
ex()
|
||||
ex_()
|
||||
{}
|
||||
|
||||
|
||||
virtual ~shared_state_base()
|
||||
{
|
||||
}
|
||||
|
||||
bool is_done()
|
||||
{
|
||||
return done;
|
||||
}
|
||||
|
||||
executor_ptr_type get_executor()
|
||||
{
|
||||
return ex;
|
||||
return ex_;
|
||||
}
|
||||
|
||||
void set_executor_policy(executor_ptr_type aex)
|
||||
{
|
||||
set_executor();
|
||||
ex = aex;
|
||||
ex_ = aex;
|
||||
}
|
||||
void set_executor_policy(executor_ptr_type aex, boost::lock_guard<boost::mutex>&)
|
||||
{
|
||||
set_executor();
|
||||
ex = aex;
|
||||
ex_ = aex;
|
||||
}
|
||||
void set_executor_policy(executor_ptr_type aex, boost::unique_lock<boost::mutex>&)
|
||||
{
|
||||
set_executor();
|
||||
ex = aex;
|
||||
ex_ = aex;
|
||||
}
|
||||
|
||||
bool valid(boost::unique_lock<boost::mutex>&) { return is_valid_; }
|
||||
@@ -262,6 +268,10 @@ namespace boost
|
||||
external_waiters.erase(it);
|
||||
}
|
||||
|
||||
#if 0
|
||||
// this inline definition results in ODR. See https://github.com/boostorg/thread/issues/193
|
||||
// to avoid it, we define the function on the derived templates using the macro BOOST_THREAD_DO_CONTINUATION
|
||||
#define BOOST_THREAD_DO_CONTINUATION
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
||||
void do_continuation(boost::unique_lock<boost::mutex>& lock)
|
||||
{
|
||||
@@ -279,6 +289,31 @@ namespace boost
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
||||
#define BOOST_THREAD_DO_CONTINUATION \
|
||||
void do_continuation(boost::unique_lock<boost::mutex>& lock) \
|
||||
{ \
|
||||
if (! this->continuations.empty()) { \
|
||||
continuations_type the_continuations = this->continuations; \
|
||||
this->continuations.clear(); \
|
||||
relocker rlk(lock); \
|
||||
for (continuations_type::iterator it = the_continuations.begin(); it != the_continuations.end(); ++it) { \
|
||||
(*it)->launch_continuation(); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define BOOST_THREAD_DO_CONTINUATION \
|
||||
void do_continuation(boost::unique_lock<boost::mutex>&) \
|
||||
{ \
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual void do_continuation(boost::unique_lock<boost::mutex>&) = 0;
|
||||
#endif
|
||||
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
||||
virtual void set_continuation_ptr(continuation_ptr_type continuation, boost::unique_lock<boost::mutex>& lock)
|
||||
{
|
||||
@@ -348,10 +383,7 @@ namespace boost
|
||||
is_deferred_=false;
|
||||
execute(lk);
|
||||
}
|
||||
while(!done)
|
||||
{
|
||||
waiters.wait(lk);
|
||||
}
|
||||
waiters.wait(lk, boost::bind(&shared_state_base::is_done, boost::ref(*this)));
|
||||
if(rethrow && exception)
|
||||
{
|
||||
boost::rethrow_exception(exception);
|
||||
@@ -370,6 +402,17 @@ namespace boost
|
||||
}
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
template<typename Duration>
|
||||
bool timed_wait(Duration const& rel_time)
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lock(this->mutex);
|
||||
if (is_deferred_)
|
||||
return false;
|
||||
|
||||
do_callback(lock);
|
||||
return waiters.timed_wait(lock, rel_time, boost::bind(&shared_state_base::is_done, boost::ref(*this)));
|
||||
}
|
||||
|
||||
bool timed_wait_until(boost::system_time const& target_time)
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lock(this->mutex);
|
||||
@@ -377,15 +420,7 @@ namespace boost
|
||||
return false;
|
||||
|
||||
do_callback(lock);
|
||||
while(!done)
|
||||
{
|
||||
bool const success=waiters.timed_wait(lock,target_time);
|
||||
if(!success && !done)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return waiters.timed_wait(lock, target_time, boost::bind(&shared_state_base::is_done, boost::ref(*this)));
|
||||
}
|
||||
#endif
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
@@ -398,13 +433,9 @@ namespace boost
|
||||
if (is_deferred_)
|
||||
return future_status::deferred;
|
||||
do_callback(lock);
|
||||
while(!done)
|
||||
if(!waiters.wait_until(lock, abs_time, boost::bind(&shared_state_base::is_done, boost::ref(*this))))
|
||||
{
|
||||
cv_status const st=waiters.wait_until(lock,abs_time);
|
||||
if(st==cv_status::timeout && !done)
|
||||
{
|
||||
return future_status::timeout;
|
||||
}
|
||||
return future_status::timeout;
|
||||
}
|
||||
return future_status::ready;
|
||||
}
|
||||
@@ -546,10 +577,8 @@ namespace boost
|
||||
detail::shared_state_base(ex), result()
|
||||
{}
|
||||
|
||||
|
||||
~shared_state()
|
||||
{
|
||||
}
|
||||
// locating this definition on the template avoid the ODR issue. See https://github.com/boostorg/thread/issues/193
|
||||
BOOST_THREAD_DO_CONTINUATION
|
||||
|
||||
void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock)
|
||||
{
|
||||
@@ -732,9 +761,8 @@ namespace boost
|
||||
detail::shared_state_base(ex), result(0)
|
||||
{}
|
||||
|
||||
~shared_state()
|
||||
{
|
||||
}
|
||||
// locating this definition on the template avoid the ODR issue. See https://github.com/boostorg/thread/issues/193
|
||||
BOOST_THREAD_DO_CONTINUATION
|
||||
|
||||
void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock)
|
||||
{
|
||||
@@ -811,6 +839,9 @@ namespace boost
|
||||
detail::shared_state_base(ex)
|
||||
{}
|
||||
|
||||
// locating this definition on the template avoid the ODR issue. See https://github.com/boostorg/thread/issues/193
|
||||
BOOST_THREAD_DO_CONTINUATION
|
||||
|
||||
void mark_finished_with_result_internal(boost::unique_lock<boost::mutex>& lock)
|
||||
{
|
||||
mark_finished_internal(lock);
|
||||
@@ -899,10 +930,7 @@ namespace boost
|
||||
join();
|
||||
#elif defined BOOST_THREAD_ASYNC_FUTURE_WAITS
|
||||
unique_lock<boost::mutex> lk(this->mutex);
|
||||
while(!this->done)
|
||||
{
|
||||
this->waiters.wait(lk);
|
||||
}
|
||||
this->waiters.wait(lk, boost::bind(&shared_state_base::is_done, boost::ref(*this)));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1007,10 +1035,8 @@ namespace boost
|
||||
template<typename Rp, typename Fp>
|
||||
struct future_deferred_shared_state: shared_state<Rp>
|
||||
{
|
||||
typedef shared_state<Rp> base_type;
|
||||
Fp func_;
|
||||
|
||||
public:
|
||||
explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
|
||||
: func_(boost::move(f))
|
||||
{
|
||||
@@ -1035,10 +1061,8 @@ namespace boost
|
||||
template<typename Rp, typename Fp>
|
||||
struct future_deferred_shared_state<Rp&,Fp>: shared_state<Rp&>
|
||||
{
|
||||
typedef shared_state<Rp&> base_type;
|
||||
Fp func_;
|
||||
|
||||
public:
|
||||
explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
|
||||
: func_(boost::move(f))
|
||||
{
|
||||
@@ -1060,10 +1084,8 @@ namespace boost
|
||||
template<typename Fp>
|
||||
struct future_deferred_shared_state<void,Fp>: shared_state<void>
|
||||
{
|
||||
typedef shared_state<void> base_type;
|
||||
Fp func_;
|
||||
|
||||
public:
|
||||
explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
|
||||
: func_(boost::move(f))
|
||||
{
|
||||
@@ -1091,7 +1113,6 @@ namespace boost
|
||||
public:
|
||||
typedef std::vector<int>::size_type count_type;
|
||||
private:
|
||||
struct registered_waiter;
|
||||
struct registered_waiter
|
||||
{
|
||||
boost::shared_ptr<detail::shared_state_base> future_;
|
||||
@@ -1452,7 +1473,11 @@ namespace boost
|
||||
template<typename Duration>
|
||||
bool timed_wait(Duration const& rel_time) const
|
||||
{
|
||||
return timed_wait_until(boost::get_system_time()+rel_time);
|
||||
if(!future_)
|
||||
{
|
||||
boost::throw_exception(future_uninitialized());
|
||||
}
|
||||
return future_->timed_wait(rel_time);
|
||||
}
|
||||
|
||||
bool timed_wait_until(boost::system_time const& abs_time) const
|
||||
@@ -2238,13 +2263,13 @@ namespace boost
|
||||
void lazy_init()
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
|
||||
#include <boost/detail/atomic_undef_macros.hpp>
|
||||
#include <boost/thread/detail/atomic_undef_macros.hpp>
|
||||
if(!atomic_load(&future_))
|
||||
{
|
||||
future_ptr blank;
|
||||
atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<R>));
|
||||
}
|
||||
#include <boost/detail/atomic_redef_macros.hpp>
|
||||
#include <boost/thread/detail/atomic_redef_macros.hpp>
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -2529,13 +2554,13 @@ namespace boost
|
||||
void lazy_init()
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
|
||||
#include <boost/detail/atomic_undef_macros.hpp>
|
||||
#include <boost/thread/detail/atomic_undef_macros.hpp>
|
||||
if(!atomic_load(&future_))
|
||||
{
|
||||
future_ptr blank;
|
||||
atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<R&>));
|
||||
}
|
||||
#include <boost/detail/atomic_redef_macros.hpp>
|
||||
#include <boost/thread/detail/atomic_redef_macros.hpp>
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -3155,7 +3180,7 @@ namespace boost
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
|
||||
#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR)
|
||||
|
||||
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
||||
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
@@ -3497,7 +3522,7 @@ namespace boost
|
||||
{}
|
||||
|
||||
// construction and destruction
|
||||
#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
|
||||
#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR)
|
||||
|
||||
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
||||
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
@@ -3587,7 +3612,7 @@ namespace boost
|
||||
#endif
|
||||
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
|
||||
#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
|
||||
#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR)
|
||||
template <class Allocator>
|
||||
packaged_task(boost::allocator_arg_t, Allocator a, R(*f)())
|
||||
{
|
||||
@@ -3608,7 +3633,7 @@ namespace boost
|
||||
task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(f), D(a2, 1) );
|
||||
future_obtained = false;
|
||||
}
|
||||
#endif // BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
|
||||
#endif // BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR
|
||||
|
||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
template <class F, class Allocator>
|
||||
@@ -3825,7 +3850,7 @@ namespace detail
|
||||
// future<R> async(launch policy, F&&, ArgTypes&&...);
|
||||
////////////////////////////////
|
||||
|
||||
#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
|
||||
#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR
|
||||
|
||||
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
template <class R, class... ArgTypes>
|
||||
@@ -3884,7 +3909,7 @@ namespace detail
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif // defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
|
||||
#endif // defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR)
|
||||
|
||||
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
|
||||
@@ -4113,7 +4138,7 @@ namespace detail {
|
||||
//#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#if defined(BOOST_THREAD_PROVIDES_INVOKE) && ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && ! defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
|
||||
#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
|
||||
#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR
|
||||
|
||||
template <class Executor, class R, class... ArgTypes>
|
||||
BOOST_THREAD_FUTURE<R>
|
||||
@@ -4129,7 +4154,7 @@ namespace detail {
|
||||
)
|
||||
));
|
||||
}
|
||||
#endif // defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
|
||||
#endif // defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR
|
||||
|
||||
template <class Executor, class F, class ...ArgTypes>
|
||||
BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
|
||||
@@ -4148,7 +4173,7 @@ namespace detail {
|
||||
}
|
||||
|
||||
#else // ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
|
||||
#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR
|
||||
|
||||
template <class Executor, class R>
|
||||
BOOST_THREAD_FUTURE<R>
|
||||
@@ -4178,7 +4203,7 @@ namespace detail {
|
||||
)
|
||||
));
|
||||
}
|
||||
#endif // defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
|
||||
#endif // defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR
|
||||
|
||||
template <class Executor, class F>
|
||||
BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
|
||||
@@ -4234,7 +4259,7 @@ namespace detail {
|
||||
// future<R> async(F&&, ArgTypes&&...);
|
||||
////////////////////////////////
|
||||
|
||||
#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
|
||||
#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR
|
||||
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
template <class R, class... ArgTypes>
|
||||
BOOST_THREAD_FUTURE<R>
|
||||
@@ -4956,6 +4981,10 @@ namespace detail {
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
|
||||
lock, boost::move(*this), boost::forward<F>(func)
|
||||
)));
|
||||
} else if (underlying_cast<int>(policy) & int(launch::sync)) {
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_sync_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
|
||||
lock, boost::move(*this), boost::forward<F>(func)
|
||||
)));
|
||||
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
} else if (underlying_cast<int>(policy) & int(launch::executor)) {
|
||||
assert(this->future_->get_executor());
|
||||
@@ -4976,6 +5005,10 @@ namespace detail {
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
|
||||
lock, boost::move(*this), boost::forward<F>(func)
|
||||
)));
|
||||
} else if (underlying_cast<int>(policy_) & int(launch::sync)) {
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_sync_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
|
||||
lock, boost::move(*this), boost::forward<F>(func)
|
||||
)));
|
||||
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
} else if (underlying_cast<int>(policy_) & int(launch::executor)) {
|
||||
assert(this->future_->get_executor());
|
||||
|
||||
@@ -6,8 +6,10 @@
|
||||
// (C) Copyright 2007-10 Anthony Williams
|
||||
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
|
||||
|
||||
#include <boost/thread/pthread/timespec.hpp>
|
||||
#include <boost/thread/detail/platform_time.hpp>
|
||||
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
|
||||
#include <boost/thread/pthread/pthread_helpers.hpp>
|
||||
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
#include <boost/thread/pthread/thread_data.hpp>
|
||||
#endif
|
||||
@@ -18,6 +20,8 @@
|
||||
#endif
|
||||
#include <boost/thread/detail/delete.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
@@ -95,9 +99,18 @@ namespace boost
|
||||
}
|
||||
}
|
||||
|
||||
// When this function returns true:
|
||||
// * A notification (or sometimes a spurious OS signal) has been received
|
||||
// * Do not assume that the timeout has not been reached
|
||||
// * Do not assume that the predicate has been changed
|
||||
//
|
||||
// When this function returns false:
|
||||
// * The timeout has been reached
|
||||
// * Do not assume that a notification has not been received
|
||||
// * Do not assume that the predicate has not been changed
|
||||
inline bool condition_variable::do_wait_until(
|
||||
unique_lock<mutex>& m,
|
||||
struct timespec const &timeout)
|
||||
detail::internal_platform_timepoint const &timeout)
|
||||
{
|
||||
#if defined BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
|
||||
if (!m.owns_lock())
|
||||
@@ -112,12 +125,12 @@ namespace boost
|
||||
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
|
||||
pthread_mutex_t* the_mutex = &internal_mutex;
|
||||
guard.activate(m);
|
||||
cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout);
|
||||
cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout.getTs());
|
||||
check_for_interruption.unlock_if_locked();
|
||||
guard.deactivate();
|
||||
#else
|
||||
pthread_mutex_t* the_mutex = m.mutex()->native_handle();
|
||||
cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout);
|
||||
cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout.getTs());
|
||||
#endif
|
||||
}
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
@@ -164,11 +177,11 @@ namespace boost
|
||||
{
|
||||
boost::throw_exception(thread_resource_error(res, "boost::condition_variable_any::condition_variable_any() failed in pthread_mutex_init"));
|
||||
}
|
||||
int const res2 = detail::monotonic_pthread_cond_init(cond);
|
||||
int const res2 = pthread::cond_init(cond);
|
||||
if(res2)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
|
||||
boost::throw_exception(thread_resource_error(res2, "boost::condition_variable_any::condition_variable_any() failed in detail::monotonic_pthread_cond_init"));
|
||||
boost::throw_exception(thread_resource_error(res2, "boost::condition_variable_any::condition_variable_any() failed in pthread::cond_init"));
|
||||
}
|
||||
}
|
||||
~condition_variable_any()
|
||||
@@ -205,15 +218,35 @@ namespace boost
|
||||
template<typename lock_type,typename predicate_type>
|
||||
void wait(lock_type& m,predicate_type pred)
|
||||
{
|
||||
while(!pred()) wait(m);
|
||||
while (!pred())
|
||||
{
|
||||
wait(m);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
template<typename lock_type>
|
||||
bool timed_wait(lock_type& m,boost::system_time const& abs_time)
|
||||
{
|
||||
struct timespec const timeout=detail::to_timespec(abs_time);
|
||||
return do_wait_until(m, timeout);
|
||||
#if defined BOOST_THREAD_WAIT_BUG
|
||||
const detail::real_platform_timepoint ts(abs_time + BOOST_THREAD_WAIT_BUG);
|
||||
#else
|
||||
const detail::real_platform_timepoint ts(abs_time);
|
||||
#endif
|
||||
#if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
|
||||
// The system time may jump while this function is waiting. To compensate for this and time
|
||||
// out near the correct time, we could call do_wait_until() in a loop with a short timeout
|
||||
// and recheck the time remaining each time through the loop. However, because we can't
|
||||
// check the predicate each time do_wait_until() completes, this introduces the possibility
|
||||
// of not exiting the function when a notification occurs, since do_wait_until() may report
|
||||
// that it timed out even though a notification was received. The best this function can do
|
||||
// is report correctly whether or not it reached the timeout time.
|
||||
const detail::platform_duration d(ts - detail::real_platform_clock::now());
|
||||
do_wait_until(m, detail::internal_platform_clock::now() + d);
|
||||
return ts > detail::real_platform_clock::now();
|
||||
#else
|
||||
return do_wait_until(m, ts);
|
||||
#endif
|
||||
}
|
||||
template<typename lock_type>
|
||||
bool timed_wait(lock_type& m,xtime const& abs_time)
|
||||
@@ -224,18 +257,55 @@ namespace boost
|
||||
template<typename lock_type,typename duration_type>
|
||||
bool timed_wait(lock_type& m,duration_type const& wait_duration)
|
||||
{
|
||||
return timed_wait(m,get_system_time()+wait_duration);
|
||||
if (wait_duration.is_pos_infinity())
|
||||
{
|
||||
wait(m);
|
||||
return true;
|
||||
}
|
||||
if (wait_duration.is_special())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
detail::platform_duration d(wait_duration);
|
||||
#if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO)
|
||||
// The system time may jump while this function is waiting. To compensate for this and time
|
||||
// out near the correct time, we could call do_wait_until() in a loop with a short timeout
|
||||
// and recheck the time remaining each time through the loop. However, because we can't
|
||||
// check the predicate each time do_wait_until() completes, this introduces the possibility
|
||||
// of not exiting the function when a notification occurs, since do_wait_until() may report
|
||||
// that it timed out even though a notification was received. The best this function can do
|
||||
// is report correctly whether or not it reached the timeout time.
|
||||
const detail::mono_platform_timepoint ts(detail::mono_platform_clock::now() + d);
|
||||
do_wait_until(m, detail::internal_platform_clock::now() + d);
|
||||
return ts > detail::mono_platform_clock::now();
|
||||
#else
|
||||
return do_wait_until(m, detail::internal_platform_clock::now() + d);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename lock_type,typename predicate_type>
|
||||
bool timed_wait(lock_type& m,boost::system_time const& abs_time, predicate_type pred)
|
||||
{
|
||||
#if defined BOOST_THREAD_WAIT_BUG
|
||||
const detail::real_platform_timepoint ts(abs_time + BOOST_THREAD_WAIT_BUG);
|
||||
#else
|
||||
const detail::real_platform_timepoint ts(abs_time);
|
||||
#endif
|
||||
while (!pred())
|
||||
{
|
||||
if(!timed_wait(m, abs_time))
|
||||
return pred();
|
||||
#if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
|
||||
// The system time may jump while this function is waiting. To compensate for this
|
||||
// and time out near the correct time, we call do_wait_until() in a loop with a
|
||||
// short timeout and recheck the time remaining each time through the loop.
|
||||
detail::platform_duration d(ts - detail::real_platform_clock::now());
|
||||
if (d <= detail::platform_duration::zero()) break; // timeout occurred
|
||||
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
do_wait_until(m, detail::internal_platform_clock::now() + d);
|
||||
#else
|
||||
if (!do_wait_until(m, ts)) break; // timeout occurred
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
return pred();
|
||||
}
|
||||
|
||||
template<typename lock_type,typename predicate_type>
|
||||
@@ -247,24 +317,52 @@ namespace boost
|
||||
template<typename lock_type,typename duration_type,typename predicate_type>
|
||||
bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred)
|
||||
{
|
||||
return timed_wait(m,get_system_time()+wait_duration,pred);
|
||||
if (wait_duration.is_pos_infinity())
|
||||
{
|
||||
while (!pred())
|
||||
{
|
||||
wait(m);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (wait_duration.is_special())
|
||||
{
|
||||
return pred();
|
||||
}
|
||||
detail::platform_duration d(wait_duration);
|
||||
#if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO)
|
||||
// The system time may jump while this function is waiting. To compensate for this
|
||||
// and time out near the correct time, we call do_wait_until() in a loop with a
|
||||
// short timeout and recheck the time remaining each time through the loop.
|
||||
const detail::mono_platform_timepoint ts(detail::mono_platform_clock::now() + d);
|
||||
while (!pred())
|
||||
{
|
||||
if (d <= detail::platform_duration::zero()) break; // timeout occurred
|
||||
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
do_wait_until(m, detail::internal_platform_clock::now() + d);
|
||||
d = ts - detail::mono_platform_clock::now();
|
||||
}
|
||||
#else
|
||||
const detail::internal_platform_timepoint ts(detail::internal_platform_clock::now() + d);
|
||||
while (!pred())
|
||||
{
|
||||
if (!do_wait_until(m, ts)) break; // timeout occurred
|
||||
}
|
||||
#endif
|
||||
return pred();
|
||||
}
|
||||
#endif
|
||||
#ifndef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class lock_type,class Duration>
|
||||
cv_status
|
||||
wait_until(
|
||||
lock_type& lock,
|
||||
const chrono::time_point<chrono::system_clock, Duration>& t)
|
||||
const chrono::time_point<detail::internal_chrono_clock, Duration>& t)
|
||||
{
|
||||
using namespace chrono;
|
||||
typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
|
||||
wait_until(lock,
|
||||
nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
|
||||
return system_clock::now() < t ? cv_status::no_timeout :
|
||||
cv_status::timeout;
|
||||
const boost::detail::internal_platform_timepoint ts(t);
|
||||
if (do_wait_until(lock, ts)) return cv_status::no_timeout;
|
||||
else return cv_status::timeout;
|
||||
}
|
||||
|
||||
template <class lock_type, class Clock, class Duration>
|
||||
@@ -273,11 +371,18 @@ namespace boost
|
||||
lock_type& lock,
|
||||
const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
using namespace chrono;
|
||||
system_clock::time_point s_now = system_clock::now();
|
||||
typename Clock::time_point c_now = Clock::now();
|
||||
wait_until(lock, s_now + ceil<nanoseconds>(t - c_now));
|
||||
return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
|
||||
// The system time may jump while this function is waiting. To compensate for this and time
|
||||
// out near the correct time, we could call do_wait_until() in a loop with a short timeout
|
||||
// and recheck the time remaining each time through the loop. However, because we can't
|
||||
// check the predicate each time do_wait_until() completes, this introduces the possibility
|
||||
// of not exiting the function when a notification occurs, since do_wait_until() may report
|
||||
// that it timed out even though a notification was received. The best this function can do
|
||||
// is report correctly whether or not it reached the timeout time.
|
||||
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
|
||||
common_duration d(t - Clock::now());
|
||||
do_wait_until(lock, detail::internal_chrono_clock::now() + d);
|
||||
if (t > Clock::now()) return cv_status::no_timeout;
|
||||
else return cv_status::timeout;
|
||||
}
|
||||
|
||||
template <class lock_type, class Rep, class Period>
|
||||
@@ -286,86 +391,24 @@ namespace boost
|
||||
lock_type& lock,
|
||||
const chrono::duration<Rep, Period>& d)
|
||||
{
|
||||
using namespace chrono;
|
||||
system_clock::time_point s_now = system_clock::now();
|
||||
steady_clock::time_point c_now = steady_clock::now();
|
||||
wait_until(lock, s_now + ceil<nanoseconds>(d));
|
||||
return steady_clock::now() - c_now < d ? cv_status::no_timeout :
|
||||
cv_status::timeout;
|
||||
|
||||
return wait_until(lock, chrono::steady_clock::now() + d);
|
||||
}
|
||||
|
||||
template <class lock_type>
|
||||
cv_status wait_until(
|
||||
lock_type& lk,
|
||||
chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp)
|
||||
{
|
||||
using namespace chrono;
|
||||
nanoseconds d = tp.time_since_epoch();
|
||||
timespec ts = boost::detail::to_timespec(d);
|
||||
if (do_wait_until(lk, ts)) return cv_status::no_timeout;
|
||||
else return cv_status::timeout;
|
||||
}
|
||||
#endif
|
||||
#else // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
|
||||
template <class lock_type, class Duration>
|
||||
cv_status
|
||||
template <class lock_type, class Duration, class Predicate>
|
||||
bool
|
||||
wait_until(
|
||||
lock_type& lock,
|
||||
const chrono::time_point<chrono::steady_clock, Duration>& t)
|
||||
lock_type& lock,
|
||||
const chrono::time_point<detail::internal_chrono_clock, Duration>& t,
|
||||
Predicate pred)
|
||||
{
|
||||
using namespace chrono;
|
||||
typedef time_point<steady_clock, nanoseconds> nano_sys_tmpt;
|
||||
wait_until(lock,
|
||||
nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
|
||||
return steady_clock::now() < t ? cv_status::no_timeout :
|
||||
cv_status::timeout;
|
||||
const detail::internal_platform_timepoint ts(t);
|
||||
while (!pred())
|
||||
{
|
||||
if (!do_wait_until(lock, ts)) break; // timeout occurred
|
||||
}
|
||||
return pred();
|
||||
}
|
||||
|
||||
template <class lock_type, class Clock, class Duration>
|
||||
cv_status
|
||||
wait_until(
|
||||
lock_type& lock,
|
||||
const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
using namespace chrono;
|
||||
steady_clock::time_point s_now = steady_clock::now();
|
||||
typename Clock::time_point c_now = Clock::now();
|
||||
wait_until(lock, s_now + ceil<nanoseconds>(t - c_now));
|
||||
return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
|
||||
}
|
||||
|
||||
template <class lock_type, class Rep, class Period>
|
||||
cv_status
|
||||
wait_for(
|
||||
lock_type& lock,
|
||||
const chrono::duration<Rep, Period>& d)
|
||||
{
|
||||
using namespace chrono;
|
||||
steady_clock::time_point c_now = steady_clock::now();
|
||||
wait_until(lock, c_now + ceil<nanoseconds>(d));
|
||||
return steady_clock::now() - c_now < d ? cv_status::no_timeout :
|
||||
cv_status::timeout;
|
||||
}
|
||||
|
||||
template <class lock_type>
|
||||
inline cv_status wait_until(
|
||||
lock_type& lock,
|
||||
chrono::time_point<chrono::steady_clock, chrono::nanoseconds> tp)
|
||||
{
|
||||
using namespace chrono;
|
||||
nanoseconds d = tp.time_since_epoch();
|
||||
timespec ts = boost::detail::to_timespec(d);
|
||||
if (do_wait_until(lock, ts)) return cv_status::no_timeout;
|
||||
else return cv_status::timeout;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class lock_type, class Clock, class Duration, class Predicate>
|
||||
bool
|
||||
wait_until(
|
||||
@@ -373,12 +416,18 @@ namespace boost
|
||||
const chrono::time_point<Clock, Duration>& t,
|
||||
Predicate pred)
|
||||
{
|
||||
// The system time may jump while this function is waiting. To compensate for this
|
||||
// and time out near the correct time, we call do_wait_until() in a loop with a
|
||||
// short timeout and recheck the time remaining each time through the loop.
|
||||
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
|
||||
while (!pred())
|
||||
{
|
||||
if (wait_until(lock, t) == cv_status::timeout)
|
||||
return pred();
|
||||
common_duration d(t - Clock::now());
|
||||
if (d <= common_duration::zero()) break; // timeout occurred
|
||||
d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
|
||||
do_wait_until(lock, detail::internal_platform_clock::now() + detail::platform_duration(d));
|
||||
}
|
||||
return true;
|
||||
return pred();
|
||||
}
|
||||
|
||||
template <class lock_type, class Rep, class Period, class Predicate>
|
||||
@@ -388,7 +437,7 @@ namespace boost
|
||||
const chrono::duration<Rep, Period>& d,
|
||||
Predicate pred)
|
||||
{
|
||||
return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
|
||||
return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -403,12 +452,21 @@ namespace boost
|
||||
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&cond));
|
||||
}
|
||||
private: // used by boost::thread::try_join_until
|
||||
private:
|
||||
|
||||
// When this function returns true:
|
||||
// * A notification (or sometimes a spurious OS signal) has been received
|
||||
// * Do not assume that the timeout has not been reached
|
||||
// * Do not assume that the predicate has been changed
|
||||
//
|
||||
// When this function returns false:
|
||||
// * The timeout has been reached
|
||||
// * Do not assume that a notification has not been received
|
||||
// * Do not assume that the predicate has not been changed
|
||||
template <class lock_type>
|
||||
bool do_wait_until(
|
||||
lock_type& m,
|
||||
struct timespec const &timeout)
|
||||
detail::internal_platform_timepoint const &timeout)
|
||||
{
|
||||
int res=0;
|
||||
{
|
||||
@@ -419,7 +477,7 @@ namespace boost
|
||||
boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
|
||||
#endif
|
||||
guard.activate(m);
|
||||
res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
|
||||
res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout.getTs());
|
||||
check_for_interruption.unlock_if_locked();
|
||||
guard.deactivate();
|
||||
}
|
||||
@@ -437,7 +495,6 @@ namespace boost
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
@@ -13,7 +13,9 @@
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/lock_types.hpp>
|
||||
#include <boost/thread/thread_time.hpp>
|
||||
#include <boost/thread/pthread/timespec.hpp>
|
||||
#include <boost/thread/detail/platform_time.hpp>
|
||||
#include <boost/thread/pthread/pthread_helpers.hpp>
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
#include <boost/thread/xtime.hpp>
|
||||
#endif
|
||||
@@ -25,31 +27,12 @@
|
||||
#include <boost/thread/detail/delete.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time_duration.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail {
|
||||
inline int monotonic_pthread_cond_init(pthread_cond_t& cond) {
|
||||
|
||||
#ifdef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
|
||||
pthread_condattr_t attr;
|
||||
int res = pthread_condattr_init(&attr);
|
||||
if (res)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
|
||||
res=pthread_cond_init(&cond,&attr);
|
||||
pthread_condattr_destroy(&attr);
|
||||
return res;
|
||||
#else
|
||||
return pthread_cond_init(&cond,NULL);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class condition_variable
|
||||
{
|
||||
private:
|
||||
@@ -61,21 +44,9 @@ namespace boost
|
||||
public:
|
||||
//private: // used by boost::thread::try_join_until
|
||||
|
||||
inline bool do_wait_until(
|
||||
bool do_wait_until(
|
||||
unique_lock<mutex>& lock,
|
||||
struct timespec const &timeout);
|
||||
|
||||
bool do_wait_for(
|
||||
unique_lock<mutex>& lock,
|
||||
struct timespec const &timeout)
|
||||
{
|
||||
#if defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
|
||||
return do_wait_until(lock, boost::detail::timespec_plus(timeout, boost::detail::timespec_now_monotonic()));
|
||||
#else
|
||||
// old behavior was fine for monotonic
|
||||
return do_wait_until(lock, boost::detail::timespec_plus(timeout, boost::detail::timespec_now_realtime()));
|
||||
#endif
|
||||
}
|
||||
detail::internal_platform_timepoint const &timeout);
|
||||
|
||||
public:
|
||||
BOOST_THREAD_NO_COPYABLE(condition_variable)
|
||||
@@ -93,14 +64,14 @@ namespace boost
|
||||
boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread_mutex_init"));
|
||||
}
|
||||
//#endif
|
||||
res = detail::monotonic_pthread_cond_init(cond);
|
||||
res = pthread::cond_init(cond);
|
||||
if (res)
|
||||
{
|
||||
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
// ditto
|
||||
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
|
||||
//#endif
|
||||
boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in detail::monotonic_pthread_cond_init"));
|
||||
boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread::cond_init"));
|
||||
}
|
||||
}
|
||||
~condition_variable()
|
||||
@@ -124,20 +95,35 @@ namespace boost
|
||||
template<typename predicate_type>
|
||||
void wait(unique_lock<mutex>& m,predicate_type pred)
|
||||
{
|
||||
while(!pred()) wait(m);
|
||||
while (!pred())
|
||||
{
|
||||
wait(m);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
inline bool timed_wait(
|
||||
bool timed_wait(
|
||||
unique_lock<mutex>& m,
|
||||
boost::system_time const& abs_time)
|
||||
{
|
||||
#if defined BOOST_THREAD_WAIT_BUG
|
||||
struct timespec const timeout=detail::to_timespec(abs_time + BOOST_THREAD_WAIT_BUG);
|
||||
return do_wait_until(m, timeout);
|
||||
const detail::real_platform_timepoint ts(abs_time + BOOST_THREAD_WAIT_BUG);
|
||||
#else
|
||||
struct timespec const timeout=detail::to_timespec(abs_time);
|
||||
return do_wait_until(m, timeout);
|
||||
const detail::real_platform_timepoint ts(abs_time);
|
||||
#endif
|
||||
#if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
|
||||
// The system time may jump while this function is waiting. To compensate for this and time
|
||||
// out near the correct time, we could call do_wait_until() in a loop with a short timeout
|
||||
// and recheck the time remaining each time through the loop. However, because we can't
|
||||
// check the predicate each time do_wait_until() completes, this introduces the possibility
|
||||
// of not exiting the function when a notification occurs, since do_wait_until() may report
|
||||
// that it timed out even though a notification was received. The best this function can do
|
||||
// is report correctly whether or not it reached the timeout time.
|
||||
const detail::platform_duration d(ts - detail::real_platform_clock::now());
|
||||
do_wait_until(m, detail::internal_platform_clock::now() + d);
|
||||
return ts > detail::real_platform_clock::now();
|
||||
#else
|
||||
return do_wait_until(m, ts);
|
||||
#endif
|
||||
}
|
||||
bool timed_wait(
|
||||
@@ -154,14 +140,28 @@ namespace boost
|
||||
{
|
||||
if (wait_duration.is_pos_infinity())
|
||||
{
|
||||
wait(m); // or do_wait(m,detail::timeout::sentinel());
|
||||
wait(m);
|
||||
return true;
|
||||
}
|
||||
if (wait_duration.is_special())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return timed_wait(m,get_system_time()+wait_duration);
|
||||
detail::platform_duration d(wait_duration);
|
||||
#if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO)
|
||||
// The system time may jump while this function is waiting. To compensate for this and time
|
||||
// out near the correct time, we could call do_wait_until() in a loop with a short timeout
|
||||
// and recheck the time remaining each time through the loop. However, because we can't
|
||||
// check the predicate each time do_wait_until() completes, this introduces the possibility
|
||||
// of not exiting the function when a notification occurs, since do_wait_until() may report
|
||||
// that it timed out even though a notification was received. The best this function can do
|
||||
// is report correctly whether or not it reached the timeout time.
|
||||
const detail::mono_platform_timepoint ts(detail::mono_platform_clock::now() + d);
|
||||
do_wait_until(m, detail::internal_platform_clock::now() + d);
|
||||
return ts > detail::mono_platform_clock::now();
|
||||
#else
|
||||
return do_wait_until(m, detail::internal_platform_clock::now() + d);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename predicate_type>
|
||||
@@ -169,12 +169,26 @@ namespace boost
|
||||
unique_lock<mutex>& m,
|
||||
boost::system_time const& abs_time,predicate_type pred)
|
||||
{
|
||||
#if defined BOOST_THREAD_WAIT_BUG
|
||||
const detail::real_platform_timepoint ts(abs_time + BOOST_THREAD_WAIT_BUG);
|
||||
#else
|
||||
const detail::real_platform_timepoint ts(abs_time);
|
||||
#endif
|
||||
while (!pred())
|
||||
{
|
||||
if(!timed_wait(m, abs_time))
|
||||
return pred();
|
||||
#if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
|
||||
// The system time may jump while this function is waiting. To compensate for this
|
||||
// and time out near the correct time, we call do_wait_until() in a loop with a
|
||||
// short timeout and recheck the time remaining each time through the loop.
|
||||
detail::platform_duration d(ts - detail::real_platform_clock::now());
|
||||
if (d <= detail::platform_duration::zero()) break; // timeout occurred
|
||||
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
do_wait_until(m, detail::internal_platform_clock::now() + d);
|
||||
#else
|
||||
if (!do_wait_until(m, ts)) break; // timeout occurred
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
return pred();
|
||||
}
|
||||
|
||||
template<typename predicate_type>
|
||||
@@ -194,7 +208,7 @@ namespace boost
|
||||
{
|
||||
while (!pred())
|
||||
{
|
||||
wait(m); // or do_wait(m,detail::timeout::sentinel());
|
||||
wait(m);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -202,26 +216,41 @@ namespace boost
|
||||
{
|
||||
return pred();
|
||||
}
|
||||
return timed_wait(m,get_system_time()+wait_duration,pred);
|
||||
detail::platform_duration d(wait_duration);
|
||||
#if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO)
|
||||
// The system time may jump while this function is waiting. To compensate for this
|
||||
// and time out near the correct time, we call do_wait_until() in a loop with a
|
||||
// short timeout and recheck the time remaining each time through the loop.
|
||||
const detail::mono_platform_timepoint ts(detail::mono_platform_clock::now() + d);
|
||||
while (!pred())
|
||||
{
|
||||
if (d <= detail::platform_duration::zero()) break; // timeout occurred
|
||||
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
do_wait_until(m, detail::internal_platform_clock::now() + d);
|
||||
d = ts - detail::mono_platform_clock::now();
|
||||
}
|
||||
#else
|
||||
const detail::internal_platform_timepoint ts(detail::internal_platform_clock::now() + d);
|
||||
while (!pred())
|
||||
{
|
||||
if (!do_wait_until(m, ts)) break; // timeout occurred
|
||||
}
|
||||
#endif
|
||||
return pred();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
|
||||
template <class Duration>
|
||||
cv_status
|
||||
wait_until(
|
||||
unique_lock<mutex>& lock,
|
||||
const chrono::time_point<chrono::system_clock, Duration>& t)
|
||||
const chrono::time_point<detail::internal_chrono_clock, Duration>& t)
|
||||
{
|
||||
using namespace chrono;
|
||||
typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
|
||||
wait_until(lock,
|
||||
nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
|
||||
return system_clock::now() < t ? cv_status::no_timeout :
|
||||
cv_status::timeout;
|
||||
const detail::internal_platform_timepoint ts(t);
|
||||
if (do_wait_until(lock, ts)) return cv_status::no_timeout;
|
||||
else return cv_status::timeout;
|
||||
}
|
||||
|
||||
template <class Clock, class Duration>
|
||||
@@ -230,100 +259,44 @@ namespace boost
|
||||
unique_lock<mutex>& lock,
|
||||
const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
using namespace chrono;
|
||||
system_clock::time_point s_now = system_clock::now();
|
||||
typename Clock::time_point c_now = Clock::now();
|
||||
wait_until(lock, s_now + ceil<nanoseconds>(t - c_now));
|
||||
return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
|
||||
// The system time may jump while this function is waiting. To compensate for this and time
|
||||
// out near the correct time, we could call do_wait_until() in a loop with a short timeout
|
||||
// and recheck the time remaining each time through the loop. However, because we can't
|
||||
// check the predicate each time do_wait_until() completes, this introduces the possibility
|
||||
// of not exiting the function when a notification occurs, since do_wait_until() may report
|
||||
// that it timed out even though a notification was received. The best this function can do
|
||||
// is report correctly whether or not it reached the timeout time.
|
||||
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
|
||||
common_duration d(t - Clock::now());
|
||||
do_wait_until(lock, detail::internal_chrono_clock::now() + d);
|
||||
if (t > Clock::now()) return cv_status::no_timeout;
|
||||
else return cv_status::timeout;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class Rep, class Period>
|
||||
cv_status
|
||||
wait_for(
|
||||
unique_lock<mutex>& lock,
|
||||
const chrono::duration<Rep, Period>& d)
|
||||
{
|
||||
using namespace chrono;
|
||||
system_clock::time_point s_now = system_clock::now();
|
||||
steady_clock::time_point c_now = steady_clock::now();
|
||||
wait_until(lock, s_now + ceil<nanoseconds>(d));
|
||||
return steady_clock::now() - c_now < d ? cv_status::no_timeout :
|
||||
cv_status::timeout;
|
||||
|
||||
return wait_until(lock, chrono::steady_clock::now() + d);
|
||||
}
|
||||
|
||||
inline cv_status wait_until(
|
||||
unique_lock<mutex>& lk,
|
||||
chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp)
|
||||
{
|
||||
using namespace chrono;
|
||||
nanoseconds d = tp.time_since_epoch();
|
||||
timespec ts = boost::detail::to_timespec(d);
|
||||
if (do_wait_until(lk, ts)) return cv_status::no_timeout;
|
||||
else return cv_status::timeout;
|
||||
}
|
||||
#endif
|
||||
|
||||
#else // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
|
||||
template <class Duration>
|
||||
cv_status
|
||||
template <class Duration, class Predicate>
|
||||
bool
|
||||
wait_until(
|
||||
unique_lock<mutex>& lock,
|
||||
const chrono::time_point<chrono::steady_clock, Duration>& t)
|
||||
unique_lock<mutex>& lock,
|
||||
const chrono::time_point<detail::internal_chrono_clock, Duration>& t,
|
||||
Predicate pred)
|
||||
{
|
||||
using namespace chrono;
|
||||
typedef time_point<steady_clock, nanoseconds> nano_sys_tmpt;
|
||||
wait_until(lock,
|
||||
nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
|
||||
return steady_clock::now() < t ? cv_status::no_timeout :
|
||||
cv_status::timeout;
|
||||
const detail::internal_platform_timepoint ts(t);
|
||||
while (!pred())
|
||||
{
|
||||
if (!do_wait_until(lock, ts)) break; // timeout occurred
|
||||
}
|
||||
return pred();
|
||||
}
|
||||
|
||||
template <class Clock, class Duration>
|
||||
cv_status
|
||||
wait_until(
|
||||
unique_lock<mutex>& lock,
|
||||
const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
using namespace chrono;
|
||||
steady_clock::time_point s_now = steady_clock::now();
|
||||
typename Clock::time_point c_now = Clock::now();
|
||||
wait_until(lock, s_now + ceil<nanoseconds>(t - c_now));
|
||||
return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
|
||||
}
|
||||
|
||||
template <class Rep, class Period>
|
||||
cv_status
|
||||
wait_for(
|
||||
unique_lock<mutex>& lock,
|
||||
const chrono::duration<Rep, Period>& d)
|
||||
{
|
||||
using namespace chrono;
|
||||
steady_clock::time_point c_now = steady_clock::now();
|
||||
wait_until(lock, c_now + ceil<nanoseconds>(d));
|
||||
return steady_clock::now() - c_now < d ? cv_status::no_timeout :
|
||||
cv_status::timeout;
|
||||
}
|
||||
|
||||
inline cv_status wait_until(
|
||||
unique_lock<mutex>& lk,
|
||||
chrono::time_point<chrono::steady_clock, chrono::nanoseconds> tp)
|
||||
{
|
||||
using namespace chrono;
|
||||
nanoseconds d = tp.time_since_epoch();
|
||||
timespec ts = boost::detail::to_timespec(d);
|
||||
if (do_wait_until(lk, ts)) return cv_status::no_timeout;
|
||||
else return cv_status::timeout;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class Clock, class Duration, class Predicate>
|
||||
bool
|
||||
wait_until(
|
||||
@@ -331,12 +304,18 @@ namespace boost
|
||||
const chrono::time_point<Clock, Duration>& t,
|
||||
Predicate pred)
|
||||
{
|
||||
// The system time may jump while this function is waiting. To compensate for this
|
||||
// and time out near the correct time, we call do_wait_until() in a loop with a
|
||||
// short timeout and recheck the time remaining each time through the loop.
|
||||
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
|
||||
while (!pred())
|
||||
{
|
||||
if (wait_until(lock, t) == cv_status::timeout)
|
||||
return pred();
|
||||
common_duration d(t - Clock::now());
|
||||
if (d <= common_duration::zero()) break; // timeout occurred
|
||||
d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
|
||||
do_wait_until(lock, detail::internal_platform_clock::now() + detail::platform_duration(d));
|
||||
}
|
||||
return true;
|
||||
return pred();
|
||||
}
|
||||
|
||||
template <class Rep, class Period, class Predicate>
|
||||
@@ -346,7 +325,7 @@ namespace boost
|
||||
const chrono::duration<Rep, Period>& d,
|
||||
Predicate pred)
|
||||
{
|
||||
return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
|
||||
return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -359,15 +338,11 @@ namespace boost
|
||||
|
||||
void notify_one() BOOST_NOEXCEPT;
|
||||
void notify_all() BOOST_NOEXCEPT;
|
||||
|
||||
|
||||
};
|
||||
|
||||
BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
|
||||
|
||||
}
|
||||
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,24 +16,20 @@
|
||||
#include <boost/thread/lock_types.hpp>
|
||||
#endif
|
||||
#include <boost/thread/thread_time.hpp>
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
#include <boost/thread/xtime.hpp>
|
||||
#endif
|
||||
#include <boost/assert.hpp>
|
||||
#include <errno.h>
|
||||
#include <boost/thread/pthread/timespec.hpp>
|
||||
#include <boost/thread/detail/platform_time.hpp>
|
||||
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
|
||||
#include <boost/thread/pthread/pthread_helpers.hpp>
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
#include <boost/chrono/system_clocks.hpp>
|
||||
#include <boost/chrono/ceil.hpp>
|
||||
#endif
|
||||
#include <boost/thread/detail/delete.hpp>
|
||||
|
||||
#if (defined(_POSIX_TIMEOUTS) && (_POSIX_TIMEOUTS-0)>=200112L) \
|
||||
|| (defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__ >= 21)
|
||||
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||
#define BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
@@ -165,7 +161,7 @@ namespace boost
|
||||
{
|
||||
private:
|
||||
pthread_mutex_t m;
|
||||
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||
#ifndef BOOST_THREAD_USES_PTHREAD_TIMEDLOCK
|
||||
pthread_cond_t cond;
|
||||
bool is_locked;
|
||||
#endif
|
||||
@@ -178,13 +174,12 @@ namespace boost
|
||||
{
|
||||
boost::throw_exception(thread_resource_error(res, "boost:: timed_mutex constructor failed in pthread_mutex_init"));
|
||||
}
|
||||
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||
int const res2=pthread_cond_init(&cond,NULL);
|
||||
#ifndef BOOST_THREAD_USES_PTHREAD_TIMEDLOCK
|
||||
int const res2=pthread::cond_init(cond);
|
||||
if(res2)
|
||||
{
|
||||
BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
|
||||
//BOOST_VERIFY(!pthread_mutex_destroy(&m));
|
||||
boost::throw_exception(thread_resource_error(res2, "boost:: timed_mutex constructor failed in pthread_cond_init"));
|
||||
boost::throw_exception(thread_resource_error(res2, "boost:: timed_mutex constructor failed in pthread::cond_init"));
|
||||
}
|
||||
is_locked=false;
|
||||
#endif
|
||||
@@ -192,7 +187,7 @@ namespace boost
|
||||
~timed_mutex()
|
||||
{
|
||||
BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
|
||||
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||
#ifndef BOOST_THREAD_USES_PTHREAD_TIMEDLOCK
|
||||
BOOST_VERIFY(!pthread_cond_destroy(&cond));
|
||||
#endif
|
||||
}
|
||||
@@ -201,14 +196,36 @@ namespace boost
|
||||
template<typename TimeDuration>
|
||||
bool timed_lock(TimeDuration const & relative_time)
|
||||
{
|
||||
return timed_lock(get_system_time()+relative_time);
|
||||
if (relative_time.is_pos_infinity())
|
||||
{
|
||||
lock();
|
||||
return true;
|
||||
}
|
||||
if (relative_time.is_special())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
detail::platform_duration d(relative_time);
|
||||
#if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO)
|
||||
const detail::mono_platform_timepoint ts(detail::mono_platform_clock::now() + d);
|
||||
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
while ( ! do_try_lock_until(detail::internal_platform_clock::now() + d) )
|
||||
{
|
||||
d = ts - detail::mono_platform_clock::now();
|
||||
if ( d <= detail::platform_duration::zero() ) return false; // timeout occurred
|
||||
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
return do_try_lock_until(detail::internal_platform_clock::now() + d);
|
||||
#endif
|
||||
}
|
||||
bool timed_lock(boost::xtime const & absolute_time)
|
||||
{
|
||||
return timed_lock(system_time(absolute_time));
|
||||
}
|
||||
#endif
|
||||
#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||
#ifdef BOOST_THREAD_USES_PTHREAD_TIMEDLOCK
|
||||
void lock()
|
||||
{
|
||||
int res = posix::pthread_mutex_lock(&m);
|
||||
@@ -246,9 +263,9 @@ namespace boost
|
||||
|
||||
|
||||
private:
|
||||
bool do_try_lock_until(struct timespec const &timeout)
|
||||
bool do_try_lock_until(detail::internal_platform_timepoint const &timeout)
|
||||
{
|
||||
int const res=pthread_mutex_timedlock(&m,&timeout);
|
||||
int const res=pthread_mutex_timedlock(&m,&timeout.getTs());
|
||||
BOOST_ASSERT(!res || res==ETIMEDOUT);
|
||||
return !res;
|
||||
}
|
||||
@@ -284,18 +301,22 @@ namespace boost
|
||||
}
|
||||
|
||||
private:
|
||||
bool do_try_lock_until(struct timespec const &timeout)
|
||||
bool do_try_lock_until(detail::internal_platform_timepoint const &timeout)
|
||||
{
|
||||
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
|
||||
while(is_locked)
|
||||
{
|
||||
int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout);
|
||||
int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout.getTs());
|
||||
if(cond_res==ETIMEDOUT)
|
||||
{
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
BOOST_ASSERT(!cond_res);
|
||||
}
|
||||
if(is_locked)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
is_locked=true;
|
||||
return true;
|
||||
}
|
||||
@@ -305,8 +326,20 @@ namespace boost
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
bool timed_lock(system_time const & abs_time)
|
||||
{
|
||||
struct timespec const ts=boost::detail::to_timespec(abs_time);
|
||||
const detail::real_platform_timepoint ts(abs_time);
|
||||
#if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
|
||||
detail::platform_duration d(ts - detail::real_platform_clock::now());
|
||||
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
while ( ! do_try_lock_until(detail::internal_platform_clock::now() + d) )
|
||||
{
|
||||
d = ts - detail::real_platform_clock::now();
|
||||
if ( d <= detail::platform_duration::zero() ) return false; // timeout occurred
|
||||
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
return do_try_lock_until(ts);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
@@ -318,23 +351,21 @@ namespace boost
|
||||
template <class Clock, class Duration>
|
||||
bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
using namespace chrono;
|
||||
system_clock::time_point s_now = system_clock::now();
|
||||
typename Clock::time_point c_now = Clock::now();
|
||||
return try_lock_until(s_now + ceil<nanoseconds>(t - c_now));
|
||||
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
|
||||
common_duration d(t - Clock::now());
|
||||
d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
|
||||
while ( ! try_lock_until(detail::internal_chrono_clock::now() + d))
|
||||
{
|
||||
d = t - Clock::now();
|
||||
if ( d <= common_duration::zero() ) return false; // timeout occurred
|
||||
d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
template <class Duration>
|
||||
bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t)
|
||||
bool try_lock_until(const chrono::time_point<detail::internal_chrono_clock, Duration>& t)
|
||||
{
|
||||
using namespace chrono;
|
||||
typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
|
||||
return try_lock_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
|
||||
}
|
||||
bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
|
||||
{
|
||||
//using namespace chrono;
|
||||
chrono::nanoseconds d = tp.time_since_epoch();
|
||||
timespec ts = boost::detail::to_timespec(d);
|
||||
detail::internal_platform_timepoint ts(t);
|
||||
return do_try_lock_until(ts);
|
||||
}
|
||||
#endif
|
||||
@@ -352,7 +383,6 @@ namespace boost
|
||||
typedef scoped_timed_lock scoped_lock;
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
42
include/boost/thread/pthread/pthread_helpers.hpp
Normal file
42
include/boost/thread/pthread/pthread_helpers.hpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#ifndef BOOST_THREAD_PTHREAD_PTHREAD_HELPERS_HPP
|
||||
#define BOOST_THREAD_PTHREAD_PTHREAD_HELPERS_HPP
|
||||
// Copyright (C) 2017
|
||||
// Vicente J. Botet Escriba
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace pthread
|
||||
{
|
||||
inline int cond_init(pthread_cond_t& cond) {
|
||||
|
||||
#ifdef BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
|
||||
pthread_condattr_t attr;
|
||||
int res = pthread_condattr_init(&attr);
|
||||
if (res)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
|
||||
res=pthread_cond_init(&cond,&attr);
|
||||
pthread_condattr_destroy(&attr);
|
||||
return res;
|
||||
#else
|
||||
return pthread_cond_init(&cond,NULL);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
@@ -19,27 +19,22 @@
|
||||
#endif
|
||||
#include <boost/date_time/posix_time/conversion.hpp>
|
||||
#include <errno.h>
|
||||
#include <boost/thread/pthread/timespec.hpp>
|
||||
#include <boost/thread/detail/platform_time.hpp>
|
||||
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
|
||||
#include <boost/thread/pthread/pthread_helpers.hpp>
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
#include <boost/chrono/system_clocks.hpp>
|
||||
#include <boost/chrono/ceil.hpp>
|
||||
#endif
|
||||
#include <boost/thread/detail/delete.hpp>
|
||||
|
||||
#if (defined _POSIX_TIMEOUTS && (_POSIX_TIMEOUTS-0)>=200112L) \
|
||||
|| (defined __ANDROID__ && defined __ANDROID_API__ && __ANDROID_API__ >= 21)
|
||||
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||
#define BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE \
|
||||
|| defined __ANDROID__
|
||||
#define BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
|
||||
#endif
|
||||
|
||||
#if defined BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE && defined BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||
#if defined BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE && defined BOOST_THREAD_USES_PTHREAD_TIMEDLOCK
|
||||
#define BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
|
||||
#endif
|
||||
|
||||
@@ -89,11 +84,11 @@ namespace boost
|
||||
{
|
||||
boost::throw_exception(thread_resource_error(res, "boost:: recursive_mutex constructor failed in pthread_mutex_init"));
|
||||
}
|
||||
int const res2=pthread_cond_init(&cond,NULL);
|
||||
int const res2=pthread::cond_init(cond);
|
||||
if(res2)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_destroy(&m));
|
||||
boost::throw_exception(thread_resource_error(res2, "boost:: recursive_mutex constructor failed in pthread_cond_init"));
|
||||
boost::throw_exception(thread_resource_error(res2, "boost:: recursive_mutex constructor failed in pthread::cond_init"));
|
||||
}
|
||||
is_locked=false;
|
||||
count=0;
|
||||
@@ -224,11 +219,11 @@ namespace boost
|
||||
{
|
||||
boost::throw_exception(thread_resource_error(res, "boost:: recursive_timed_mutex constructor failed in pthread_mutex_init"));
|
||||
}
|
||||
int const res2=pthread_cond_init(&cond,NULL);
|
||||
int const res2=pthread::cond_init(cond);
|
||||
if(res2)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_destroy(&m));
|
||||
boost::throw_exception(thread_resource_error(res2, "boost:: recursive_timed_mutex constructor failed in pthread_cond_init"));
|
||||
boost::throw_exception(thread_resource_error(res2, "boost:: recursive_timed_mutex constructor failed in pthread::cond_init"));
|
||||
}
|
||||
is_locked=false;
|
||||
count=0;
|
||||
@@ -246,7 +241,29 @@ namespace boost
|
||||
template<typename TimeDuration>
|
||||
bool timed_lock(TimeDuration const & relative_time)
|
||||
{
|
||||
return timed_lock(get_system_time()+relative_time);
|
||||
if (relative_time.is_pos_infinity())
|
||||
{
|
||||
lock();
|
||||
return true;
|
||||
}
|
||||
if (relative_time.is_special())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
detail::platform_duration d(relative_time);
|
||||
#if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO)
|
||||
const detail::mono_platform_timepoint ts(detail::mono_platform_clock::now() + d);
|
||||
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
while ( ! do_try_lock_until(detail::internal_platform_clock::now() + d) )
|
||||
{
|
||||
d = ts - detail::mono_platform_clock::now();
|
||||
if ( d <= detail::platform_duration::zero() ) return false; // timeout occurred
|
||||
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
return do_try_lock_until(detail::internal_platform_clock::now() + d);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -268,9 +285,9 @@ namespace boost
|
||||
return !res;
|
||||
}
|
||||
private:
|
||||
bool do_try_lock_until(struct timespec const &timeout)
|
||||
bool do_try_lock_until(detail::internal_platform_timepoint const &timeout)
|
||||
{
|
||||
int const res=pthread_mutex_timedlock(&m,&timeout);
|
||||
int const res=pthread_mutex_timedlock(&m,&timeout.getTs());
|
||||
BOOST_ASSERT(!res || res==ETIMEDOUT);
|
||||
return !res;
|
||||
}
|
||||
@@ -320,7 +337,7 @@ namespace boost
|
||||
}
|
||||
|
||||
private:
|
||||
bool do_try_lock_until(struct timespec const &timeout)
|
||||
bool do_try_lock_until(detail::internal_platform_timepoint const &timeout)
|
||||
{
|
||||
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
|
||||
if(is_locked && pthread_equal(owner,pthread_self()))
|
||||
@@ -330,13 +347,17 @@ namespace boost
|
||||
}
|
||||
while(is_locked)
|
||||
{
|
||||
int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout);
|
||||
int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout.getTs());
|
||||
if(cond_res==ETIMEDOUT)
|
||||
{
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
BOOST_ASSERT(!cond_res);
|
||||
}
|
||||
if(is_locked)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
is_locked=true;
|
||||
++count;
|
||||
owner=pthread_self();
|
||||
@@ -349,8 +370,20 @@ namespace boost
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
bool timed_lock(system_time const & abs_time)
|
||||
{
|
||||
struct timespec const ts=detail::to_timespec(abs_time);
|
||||
const detail::real_platform_timepoint ts(abs_time);
|
||||
#if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
|
||||
detail::platform_duration d(ts - detail::real_platform_clock::now());
|
||||
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
while ( ! do_try_lock_until(detail::internal_platform_clock::now() + d) )
|
||||
{
|
||||
d = ts - detail::real_platform_clock::now();
|
||||
if ( d <= detail::platform_duration::zero() ) return false; // timeout occurred
|
||||
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
return do_try_lock_until(ts);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
@@ -362,23 +395,22 @@ namespace boost
|
||||
template <class Clock, class Duration>
|
||||
bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
using namespace chrono;
|
||||
system_clock::time_point s_now = system_clock::now();
|
||||
typename Clock::time_point c_now = Clock::now();
|
||||
return try_lock_until(s_now + ceil<nanoseconds>(t - c_now));
|
||||
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
|
||||
common_duration d(t - Clock::now());
|
||||
d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
|
||||
while ( ! try_lock_until(detail::internal_chrono_clock::now() + d))
|
||||
{
|
||||
d = t - Clock::now();
|
||||
if ( d <= common_duration::zero() ) return false; // timeout occurred
|
||||
d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
template <class Duration>
|
||||
bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t)
|
||||
bool try_lock_until(const chrono::time_point<detail::internal_chrono_clock, Duration>& t)
|
||||
{
|
||||
using namespace chrono;
|
||||
typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
|
||||
return try_lock_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
|
||||
}
|
||||
bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
|
||||
{
|
||||
//using namespace chrono;
|
||||
chrono::nanoseconds d = tp.time_since_epoch();
|
||||
timespec ts = boost::detail::to_timespec(d);
|
||||
detail::internal_platform_timepoint ts(t);
|
||||
return do_try_lock_until(ts);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
@@ -78,11 +79,6 @@ namespace boost
|
||||
return ! (shared_count || exclusive);
|
||||
}
|
||||
|
||||
void exclusive_blocked (bool blocked)
|
||||
{
|
||||
exclusive_waiting_blocked = blocked;
|
||||
}
|
||||
|
||||
void lock ()
|
||||
{
|
||||
exclusive = true;
|
||||
@@ -99,17 +95,19 @@ namespace boost
|
||||
return ! (exclusive || exclusive_waiting_blocked);
|
||||
}
|
||||
|
||||
bool more_shared () const
|
||||
bool no_shared () const
|
||||
{
|
||||
return shared_count > 0 ;
|
||||
return shared_count==0;
|
||||
}
|
||||
unsigned get_shared_count () const
|
||||
|
||||
bool one_shared () const
|
||||
{
|
||||
return shared_count ;
|
||||
return shared_count==1;
|
||||
}
|
||||
unsigned lock_shared ()
|
||||
|
||||
void lock_shared ()
|
||||
{
|
||||
return ++shared_count;
|
||||
++shared_count;
|
||||
}
|
||||
|
||||
|
||||
@@ -118,18 +116,6 @@ namespace boost
|
||||
--shared_count;
|
||||
}
|
||||
|
||||
bool unlock_shared_downgrades()
|
||||
{
|
||||
if (upgrade) {
|
||||
upgrade=false;
|
||||
exclusive=true;
|
||||
return true;
|
||||
} else {
|
||||
exclusive_waiting_blocked=false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void lock_upgrade ()
|
||||
{
|
||||
++shared_count;
|
||||
@@ -185,10 +171,7 @@ namespace boost
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
while(!state.can_lock_shared())
|
||||
{
|
||||
shared_cond.wait(lk);
|
||||
}
|
||||
shared_cond.wait(lk, boost::bind(&state_data::can_lock_shared, boost::ref(state)));
|
||||
state.lock_shared();
|
||||
}
|
||||
|
||||
@@ -211,13 +194,9 @@ namespace boost
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
|
||||
while(!state.can_lock_shared())
|
||||
if(!shared_cond.timed_wait(lk, timeout, boost::bind(&state_data::can_lock_shared, boost::ref(state))))
|
||||
{
|
||||
if(!shared_cond.timed_wait(lk,timeout))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
state.lock_shared();
|
||||
return true;
|
||||
@@ -226,7 +205,16 @@ namespace boost
|
||||
template<typename TimeDuration>
|
||||
bool timed_lock_shared(TimeDuration const & relative_time)
|
||||
{
|
||||
return timed_lock_shared(get_system_time()+relative_time);
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
if(!shared_cond.timed_wait(lk, relative_time, boost::bind(&state_data::can_lock_shared, boost::ref(state))))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
state.lock_shared();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
@@ -242,14 +230,9 @@ namespace boost
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
|
||||
while(!state.can_lock_shared())
|
||||
//while(state.exclusive || state.exclusive_waiting_blocked)
|
||||
if(!shared_cond.wait_until(lk, abs_time, boost::bind(&state_data::can_lock_shared, boost::ref(state))))
|
||||
{
|
||||
if(cv_status::timeout==shared_cond.wait_until(lk,abs_time))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
state.lock_shared();
|
||||
return true;
|
||||
@@ -260,11 +243,11 @@ namespace boost
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.assert_lock_shared();
|
||||
state.unlock_shared();
|
||||
if (! state.more_shared())
|
||||
if (state.no_shared())
|
||||
{
|
||||
if (state.upgrade)
|
||||
{
|
||||
// As there is a thread doing a unlock_upgrade_and_lock that is waiting for ! state.more_shared()
|
||||
// As there is a thread doing a unlock_upgrade_and_lock that is waiting for state.no_shared()
|
||||
// avoid other threads to lock, lock_upgrade or lock_shared, so only this thread is notified.
|
||||
state.upgrade=false;
|
||||
state.exclusive=true;
|
||||
@@ -286,12 +269,8 @@ namespace boost
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
|
||||
while (state.shared_count || state.exclusive)
|
||||
{
|
||||
state.exclusive_waiting_blocked=true;
|
||||
exclusive_cond.wait(lk);
|
||||
}
|
||||
state.exclusive_waiting_blocked=true;
|
||||
exclusive_cond.wait(lk, boost::bind(&state_data::can_lock, boost::ref(state)));
|
||||
state.exclusive=true;
|
||||
}
|
||||
|
||||
@@ -302,20 +281,12 @@ namespace boost
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
|
||||
while(state.shared_count || state.exclusive)
|
||||
state.exclusive_waiting_blocked=true;
|
||||
if(!exclusive_cond.timed_wait(lk, timeout, boost::bind(&state_data::can_lock, boost::ref(state))))
|
||||
{
|
||||
state.exclusive_waiting_blocked=true;
|
||||
if(!exclusive_cond.timed_wait(lk,timeout))
|
||||
{
|
||||
if(state.shared_count || state.exclusive)
|
||||
{
|
||||
state.exclusive_waiting_blocked=false;
|
||||
release_waiters();
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
state.exclusive_waiting_blocked=false;
|
||||
release_waiters();
|
||||
return false;
|
||||
}
|
||||
state.exclusive=true;
|
||||
return true;
|
||||
@@ -324,7 +295,19 @@ namespace boost
|
||||
template<typename TimeDuration>
|
||||
bool timed_lock(TimeDuration const & relative_time)
|
||||
{
|
||||
return timed_lock(get_system_time()+relative_time);
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.exclusive_waiting_blocked=true;
|
||||
if(!exclusive_cond.timed_wait(lk, relative_time, boost::bind(&state_data::can_lock, boost::ref(state))))
|
||||
{
|
||||
state.exclusive_waiting_blocked=false;
|
||||
release_waiters();
|
||||
return false;
|
||||
}
|
||||
state.exclusive=true;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
@@ -340,20 +323,12 @@ namespace boost
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
|
||||
while(state.shared_count || state.exclusive)
|
||||
state.exclusive_waiting_blocked=true;
|
||||
if(!exclusive_cond.wait_until(lk, abs_time, boost::bind(&state_data::can_lock, boost::ref(state))))
|
||||
{
|
||||
state.exclusive_waiting_blocked=true;
|
||||
if(cv_status::timeout == exclusive_cond.wait_until(lk,abs_time))
|
||||
{
|
||||
if(state.shared_count || state.exclusive)
|
||||
{
|
||||
state.exclusive_waiting_blocked=false;
|
||||
release_waiters();
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
state.exclusive_waiting_blocked=false;
|
||||
release_waiters();
|
||||
return false;
|
||||
}
|
||||
state.exclusive=true;
|
||||
return true;
|
||||
@@ -363,17 +338,12 @@ namespace boost
|
||||
bool try_lock()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
|
||||
if(state.shared_count || state.exclusive)
|
||||
if(!state.can_lock())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
state.exclusive=true;
|
||||
return true;
|
||||
}
|
||||
|
||||
state.exclusive=true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void unlock()
|
||||
@@ -392,10 +362,7 @@ namespace boost
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
|
||||
{
|
||||
shared_cond.wait(lk);
|
||||
}
|
||||
shared_cond.wait(lk, boost::bind(&state_data::can_lock_upgrade, boost::ref(state)));
|
||||
state.lock_shared();
|
||||
state.upgrade=true;
|
||||
}
|
||||
@@ -407,16 +374,9 @@ namespace boost
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
|
||||
if(!shared_cond.timed_wait(lk, timeout, boost::bind(&state_data::can_lock_upgrade, boost::ref(state))))
|
||||
{
|
||||
if(!shared_cond.timed_wait(lk,timeout))
|
||||
{
|
||||
if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
state.lock_shared();
|
||||
state.upgrade=true;
|
||||
@@ -426,7 +386,17 @@ namespace boost
|
||||
template<typename TimeDuration>
|
||||
bool timed_lock_upgrade(TimeDuration const & relative_time)
|
||||
{
|
||||
return timed_lock_upgrade(get_system_time()+relative_time);
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
if(!shared_cond.timed_wait(lk, relative_time, boost::bind(&state_data::can_lock_upgrade, boost::ref(state))))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
state.lock_shared();
|
||||
state.upgrade=true;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
@@ -442,16 +412,9 @@ namespace boost
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
|
||||
if(!shared_cond.wait_until(lk, abs_time, boost::bind(&state_data::can_lock_upgrade, boost::ref(state))))
|
||||
{
|
||||
if(cv_status::timeout == shared_cond.wait_until(lk,abs_time))
|
||||
{
|
||||
if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
state.lock_shared();
|
||||
state.upgrade=true;
|
||||
@@ -461,17 +424,14 @@ namespace boost
|
||||
bool try_lock_upgrade()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
|
||||
if(!state.can_lock_upgrade())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
state.lock_shared();
|
||||
state.upgrade=true;
|
||||
state.assert_lock_upgraded();
|
||||
return true;
|
||||
}
|
||||
state.lock_shared();
|
||||
state.upgrade=true;
|
||||
state.assert_lock_upgraded();
|
||||
return true;
|
||||
}
|
||||
|
||||
void unlock_upgrade()
|
||||
@@ -479,7 +439,7 @@ namespace boost
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
//state.upgrade=false;
|
||||
state.unlock_upgrade();
|
||||
if(! state.more_shared() )
|
||||
if(state.no_shared())
|
||||
{
|
||||
state.exclusive_waiting_blocked=false;
|
||||
release_waiters();
|
||||
@@ -497,10 +457,7 @@ namespace boost
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.assert_lock_upgraded();
|
||||
state.unlock_shared();
|
||||
while (state.more_shared())
|
||||
{
|
||||
upgrade_cond.wait(lk);
|
||||
}
|
||||
upgrade_cond.wait(lk, boost::bind(&state_data::no_shared, boost::ref(state)));
|
||||
state.upgrade=false;
|
||||
state.exclusive=true;
|
||||
state.assert_locked();
|
||||
@@ -554,16 +511,9 @@ namespace boost
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.assert_lock_upgraded();
|
||||
if (state.shared_count != 1)
|
||||
if(!shared_cond.wait_until(lk, abs_time, boost::bind(&state_data::one_shared, boost::ref(state))))
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
cv_status status = shared_cond.wait_until(lk,abs_time);
|
||||
if (state.shared_count == 1)
|
||||
break;
|
||||
if(status == cv_status::timeout)
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
state.upgrade=false;
|
||||
state.exclusive=true;
|
||||
@@ -619,16 +569,9 @@ namespace boost
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.assert_lock_shared();
|
||||
if (state.shared_count != 1)
|
||||
if(!shared_cond.wait_until(lk, abs_time, boost::bind(&state_data::one_shared, boost::ref(state))))
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
cv_status status = shared_cond.wait_until(lk,abs_time);
|
||||
if (state.shared_count == 1)
|
||||
break;
|
||||
if(status == cv_status::timeout)
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
state.upgrade=false;
|
||||
state.exclusive=true;
|
||||
@@ -654,10 +597,7 @@ namespace boost
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.assert_lock_shared();
|
||||
if( !state.exclusive
|
||||
&& !state.exclusive_waiting_blocked
|
||||
&& !state.upgrade
|
||||
)
|
||||
if(state.can_lock_upgrade())
|
||||
{
|
||||
state.upgrade=true;
|
||||
return true;
|
||||
@@ -683,22 +623,9 @@ namespace boost
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.assert_lock_shared();
|
||||
if( state.exclusive
|
||||
|| state.exclusive_waiting_blocked
|
||||
|| state.upgrade
|
||||
)
|
||||
if(!exclusive_cond.wait_until(lk, abs_time, boost::bind(&state_data::can_lock_upgrade, boost::ref(state))))
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
cv_status status = exclusive_cond.wait_until(lk,abs_time);
|
||||
if( ! state.exclusive
|
||||
&& ! state.exclusive_waiting_blocked
|
||||
&& ! state.upgrade
|
||||
)
|
||||
break;
|
||||
if(status == cv_status::timeout)
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
state.upgrade=true;
|
||||
return true;
|
||||
|
||||
@@ -1,724 +0,0 @@
|
||||
#ifndef BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP
|
||||
#define BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP
|
||||
|
||||
// (C) Copyright 2006-8 Anthony Williams
|
||||
// (C) Copyright 2012 Vicente J. Botet Escriba
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
#include <boost/thread/detail/thread_interruption.hpp>
|
||||
#endif
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
#include <boost/chrono/system_clocks.hpp>
|
||||
#include <boost/chrono/ceil.hpp>
|
||||
#endif
|
||||
#include <boost/thread/detail/delete.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class shared_mutex
|
||||
{
|
||||
private:
|
||||
class state_data
|
||||
{
|
||||
public:
|
||||
state_data () :
|
||||
shared_count(0),
|
||||
exclusive(false),
|
||||
upgrade(false),
|
||||
exclusive_waiting_blocked(false)
|
||||
{}
|
||||
|
||||
void assert_free() const
|
||||
{
|
||||
BOOST_ASSERT( ! exclusive );
|
||||
BOOST_ASSERT( ! upgrade );
|
||||
BOOST_ASSERT( shared_count==0 );
|
||||
}
|
||||
|
||||
void assert_locked() const
|
||||
{
|
||||
BOOST_ASSERT( exclusive );
|
||||
BOOST_ASSERT( shared_count==0 );
|
||||
BOOST_ASSERT( ! upgrade );
|
||||
}
|
||||
|
||||
void assert_lock_shared () const
|
||||
{
|
||||
BOOST_ASSERT( ! exclusive );
|
||||
BOOST_ASSERT( shared_count>0 );
|
||||
//BOOST_ASSERT( (! upgrade) || (shared_count>1));
|
||||
// if upgraded there are at least 2 threads sharing the mutex,
|
||||
// except when unlock_upgrade_and_lock has decreased the number of readers but has not taken yet exclusive ownership.
|
||||
}
|
||||
|
||||
void assert_lock_upgraded () const
|
||||
{
|
||||
BOOST_ASSERT( ! exclusive );
|
||||
BOOST_ASSERT( upgrade );
|
||||
BOOST_ASSERT( shared_count>0 );
|
||||
}
|
||||
|
||||
void assert_lock_not_upgraded () const
|
||||
{
|
||||
BOOST_ASSERT( ! upgrade );
|
||||
}
|
||||
|
||||
bool can_lock () const
|
||||
{
|
||||
return ! (shared_count || exclusive);
|
||||
}
|
||||
|
||||
void exclusive_blocked (bool blocked)
|
||||
{
|
||||
exclusive_waiting_blocked = blocked;
|
||||
}
|
||||
|
||||
void lock ()
|
||||
{
|
||||
exclusive = true;
|
||||
}
|
||||
|
||||
void unlock ()
|
||||
{
|
||||
exclusive = false;
|
||||
exclusive_waiting_blocked = false;
|
||||
}
|
||||
|
||||
bool can_lock_shared () const
|
||||
{
|
||||
return ! (exclusive || exclusive_waiting_blocked);
|
||||
}
|
||||
|
||||
bool is_last_shared () const
|
||||
{
|
||||
return !shared_count ;
|
||||
}
|
||||
unsigned get_shared_count () const
|
||||
{
|
||||
return shared_count ;
|
||||
}
|
||||
unsigned lock_shared ()
|
||||
{
|
||||
return ++shared_count;
|
||||
}
|
||||
|
||||
|
||||
void unlock_shared ()
|
||||
{
|
||||
--shared_count;
|
||||
}
|
||||
|
||||
bool unlock_shared_downgrades()
|
||||
{
|
||||
if (upgrade) {
|
||||
upgrade=false;
|
||||
exclusive=true;
|
||||
return true;
|
||||
} else {
|
||||
exclusive_waiting_blocked=false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void lock_upgrade ()
|
||||
{
|
||||
lock_shared ();
|
||||
upgrade=true;
|
||||
}
|
||||
bool can_lock_upgrade () const
|
||||
{
|
||||
return ! (exclusive || exclusive_waiting_blocked || upgrade);
|
||||
}
|
||||
|
||||
void unlock_upgrade ()
|
||||
{
|
||||
upgrade=false;
|
||||
unlock_shared();
|
||||
}
|
||||
|
||||
//private:
|
||||
unsigned shared_count;
|
||||
bool exclusive;
|
||||
bool upgrade;
|
||||
bool exclusive_waiting_blocked;
|
||||
};
|
||||
|
||||
|
||||
|
||||
state_data state;
|
||||
boost::mutex state_change;
|
||||
boost::condition_variable shared_cond;
|
||||
boost::condition_variable exclusive_cond;
|
||||
boost::condition_variable upgrade_cond;
|
||||
|
||||
void release_waiters()
|
||||
{
|
||||
exclusive_cond.notify_one();
|
||||
shared_cond.notify_all();
|
||||
}
|
||||
|
||||
public:
|
||||
BOOST_THREAD_NO_COPYABLE(shared_mutex)
|
||||
|
||||
shared_mutex()
|
||||
{
|
||||
}
|
||||
|
||||
~shared_mutex()
|
||||
{
|
||||
}
|
||||
|
||||
void lock_shared()
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
|
||||
while(!state.can_lock_shared())
|
||||
{
|
||||
shared_cond.wait(lk);
|
||||
}
|
||||
state.lock_shared();
|
||||
}
|
||||
|
||||
bool try_lock_shared()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
if(!state.can_lock_shared())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
state.lock_shared();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
bool timed_lock_shared(system_time const& timeout)
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
|
||||
while(!state.can_lock_shared())
|
||||
{
|
||||
if(!shared_cond.timed_wait(lk,timeout))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
state.lock_shared();
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename TimeDuration>
|
||||
bool timed_lock_shared(TimeDuration const & relative_time)
|
||||
{
|
||||
return timed_lock_shared(get_system_time()+relative_time);
|
||||
}
|
||||
#endif
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class Rep, class Period>
|
||||
bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time)
|
||||
{
|
||||
return try_lock_shared_until(chrono::steady_clock::now() + rel_time);
|
||||
}
|
||||
template <class Clock, class Duration>
|
||||
bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time)
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
|
||||
while(!state.can_lock_shared())
|
||||
{
|
||||
if(cv_status::timeout==shared_cond.wait_until(lk,abs_time))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
state.lock_shared();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
void unlock_shared()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.assert_lock_shared();
|
||||
state.unlock_shared();
|
||||
if (state.get_shared_count () == 0)
|
||||
{
|
||||
if (state.unlock_shared_downgrades())
|
||||
{
|
||||
lk.unlock();
|
||||
upgrade_cond.notify_one();
|
||||
} else {
|
||||
lk.unlock();
|
||||
}
|
||||
release_waiters();
|
||||
}
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
|
||||
while(!state.can_lock())
|
||||
{
|
||||
state.exclusive_blocked(true);
|
||||
exclusive_cond.wait(lk);
|
||||
}
|
||||
state.lock();
|
||||
}
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
bool timed_lock(system_time const& timeout)
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
|
||||
while(!state.can_lock())
|
||||
{
|
||||
state.exclusive_blocked(true);
|
||||
if(!exclusive_cond.timed_wait(lk,timeout))
|
||||
{
|
||||
if(!state.can_lock())
|
||||
{
|
||||
state.exclusive_blocked(false);
|
||||
release_waiters();
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
state.exclusive=true;
|
||||
//state.lock();
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename TimeDuration>
|
||||
bool timed_lock(TimeDuration const & relative_time)
|
||||
{
|
||||
return timed_lock(get_system_time()+relative_time);
|
||||
}
|
||||
#endif
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class Rep, class Period>
|
||||
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
|
||||
{
|
||||
return try_lock_until(chrono::steady_clock::now() + rel_time);
|
||||
}
|
||||
template <class Clock, class Duration>
|
||||
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
|
||||
while(!state.can_lock())
|
||||
{
|
||||
state.exclusive_blocked(true);
|
||||
if(cv_status::timeout == exclusive_cond.wait_until(lk,abs_time))
|
||||
{
|
||||
if(!state.can_lock())
|
||||
{
|
||||
state.exclusive_blocked(false);
|
||||
release_waiters();
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
state.exclusive=true;
|
||||
//state.lock();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool try_lock()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
|
||||
if(!state.can_lock())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
state.lock();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.assert_locked();
|
||||
state.unlock();
|
||||
state.assert_free();
|
||||
release_waiters();
|
||||
}
|
||||
|
||||
void lock_upgrade()
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
while(!state.can_lock_upgrade())
|
||||
{
|
||||
shared_cond.wait(lk);
|
||||
}
|
||||
state.lock_upgrade();
|
||||
}
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
bool timed_lock_upgrade(system_time const& timeout)
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
while(!state.can_lock_upgrade())
|
||||
{
|
||||
if(!shared_cond.timed_wait(lk,timeout))
|
||||
{
|
||||
if(!state.can_lock_upgrade())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
state.lock_upgrade();
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename TimeDuration>
|
||||
bool timed_lock_upgrade(TimeDuration const & relative_time)
|
||||
{
|
||||
return timed_lock_upgrade(get_system_time()+relative_time);
|
||||
}
|
||||
#endif
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class Rep, class Period>
|
||||
bool try_lock_upgrade_for(const chrono::duration<Rep, Period>& rel_time)
|
||||
{
|
||||
return try_lock_upgrade_until(chrono::steady_clock::now() + rel_time);
|
||||
}
|
||||
template <class Clock, class Duration>
|
||||
bool try_lock_upgrade_until(const chrono::time_point<Clock, Duration>& abs_time)
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
while(!state.can_lock_upgrade())
|
||||
{
|
||||
if(cv_status::timeout == shared_cond.wait_until(lk,abs_time))
|
||||
{
|
||||
if(!state.can_lock_upgrade())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
state.lock_upgrade();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
bool try_lock_upgrade()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
if(!state.can_lock_upgrade())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
state.lock_upgrade();
|
||||
state.assert_lock_upgraded();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void unlock_upgrade()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.assert_lock_upgraded();
|
||||
state.unlock_upgrade();
|
||||
state.assert_lock_not_upgraded ();
|
||||
if(state.get_shared_count () == 0)
|
||||
{
|
||||
state.exclusive_blocked(false);
|
||||
lk.unlock();
|
||||
release_waiters();
|
||||
} else {
|
||||
lk.unlock();
|
||||
shared_cond.notify_all();
|
||||
}
|
||||
}
|
||||
|
||||
// Upgrade <-> Exclusive
|
||||
void unlock_upgrade_and_lock()
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.assert_lock_upgraded();
|
||||
// assert state.get_shared_count() >=1
|
||||
while(
|
||||
//! state.exclusive_waiting_blocked // Fixme: is this needed?
|
||||
//&&
|
||||
state.get_shared_count()!=1)
|
||||
{
|
||||
upgrade_cond.wait(lk);
|
||||
}
|
||||
state.unlock_upgrade();
|
||||
state.lock();
|
||||
state.assert_locked();
|
||||
}
|
||||
|
||||
void unlock_and_lock_upgrade()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.assert_locked();
|
||||
state.unlock();
|
||||
state.lock_upgrade();
|
||||
state.assert_lock_upgraded();
|
||||
release_waiters();
|
||||
}
|
||||
|
||||
bool try_unlock_upgrade_and_lock()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.assert_lock_upgraded();
|
||||
if( //!state.exclusive // this should be removed once the assertion work
|
||||
! state.exclusive_waiting_blocked // Fixme: why this is needed?
|
||||
//&& state.upgrade // this should be removed once the assertion work
|
||||
&& state.get_shared_count()==1)
|
||||
{
|
||||
state.unlock_upgrade();
|
||||
state.lock();
|
||||
state.assert_locked();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class Rep, class Period>
|
||||
bool
|
||||
try_unlock_upgrade_and_lock_for(
|
||||
const chrono::duration<Rep, Period>& rel_time)
|
||||
{
|
||||
return try_unlock_upgrade_and_lock_until(
|
||||
chrono::steady_clock::now() + rel_time);
|
||||
}
|
||||
template <class Clock, class Duration>
|
||||
bool
|
||||
try_unlock_upgrade_and_lock_until(
|
||||
const chrono::time_point<Clock, Duration>& abs_time)
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.assert_lock_upgraded();
|
||||
if (//state.exclusive // this should be removed once the assertion work
|
||||
state.exclusive_waiting_blocked // Fixme: is this needed?
|
||||
//|| ! state.upgrade // this should be removed once the assertion work
|
||||
|| state.get_shared_count() != 1)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
//cv_status status = shared_cond.wait_until(lk,abs_time);
|
||||
cv_status status = upgrade_cond.wait_until(lk,abs_time);
|
||||
if (//!state.exclusive // this should be removed once the assertion work
|
||||
! state.exclusive_waiting_blocked // Fixme: is this needed?
|
||||
//&& ! state.upgrade // this should be removed once the assertion work
|
||||
&& state.get_shared_count() == 1)
|
||||
break;
|
||||
if(status == cv_status::timeout)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
state.unlock_upgrade();
|
||||
state.lock();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Shared <-> Exclusive
|
||||
void unlock_and_lock_shared()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.assert_locked();
|
||||
state.unlock();
|
||||
state.lock_shared();
|
||||
release_waiters();
|
||||
}
|
||||
|
||||
#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
|
||||
bool try_unlock_shared_and_lock()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.assert_lock_shared();
|
||||
if( //!state.exclusive // this should be removed once the assertion work
|
||||
! state.exclusive_waiting_blocked // Fixme: why this is needed?
|
||||
//&& ! state.upgrade // Fixme: why this is needed if state.get_shared_count()==1?
|
||||
&& state.get_shared_count()==1)
|
||||
{
|
||||
state.unlock_shared();
|
||||
state.lock();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class Rep, class Period>
|
||||
bool
|
||||
try_unlock_shared_and_lock_for(
|
||||
const chrono::duration<Rep, Period>& rel_time)
|
||||
{
|
||||
return try_unlock_shared_and_lock_until(
|
||||
chrono::steady_clock::now() + rel_time);
|
||||
}
|
||||
template <class Clock, class Duration>
|
||||
bool
|
||||
try_unlock_shared_and_lock_until(
|
||||
const chrono::time_point<Clock, Duration>& abs_time)
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.assert_lock_shared();
|
||||
if ( // !state.exclusive // this should be removed once the assertion work
|
||||
state.exclusive_waiting_blocked // Fixme: is this needed?
|
||||
//|| state.upgrade // Fixme: why this is needed if state.get_shared_count()==1?
|
||||
|| state.get_shared_count() != 1)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
cv_status status = shared_cond.wait_until(lk,abs_time);
|
||||
if ( //! state.exclusive // this should be removed once the assertion work
|
||||
! state.exclusive_waiting_blocked // Fixme: is this needed?
|
||||
//&& ! state.upgrade
|
||||
&& state.get_shared_count() == 1)
|
||||
break;
|
||||
if(status == cv_status::timeout)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
state.unlock_shared();
|
||||
state.lock();
|
||||
state.upgrade=false; // Is this absolutely needed?
|
||||
state.exclusive_waiting_blocked=false; // Is this absolutely needed?
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Shared <-> Upgrade
|
||||
void unlock_upgrade_and_lock_shared()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.assert_lock_upgraded();
|
||||
//state.unlock_upgrade();
|
||||
//state.lock_shared(); // less efficient
|
||||
state.upgrade=false;
|
||||
state.exclusive_waiting_blocked=false; // Is this absolutely needed?
|
||||
release_waiters();
|
||||
}
|
||||
|
||||
#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
|
||||
bool try_unlock_shared_and_lock_upgrade()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.assert_lock_shared();
|
||||
if( //! state.exclusive // this should be removed once the assertion work
|
||||
! state.exclusive_waiting_blocked // Fixme: is this needed?
|
||||
&& ! state.upgrade
|
||||
)
|
||||
{
|
||||
state.upgrade=true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class Rep, class Period>
|
||||
bool
|
||||
try_unlock_shared_and_lock_upgrade_for(
|
||||
const chrono::duration<Rep, Period>& rel_time)
|
||||
{
|
||||
return try_unlock_shared_and_lock_upgrade_until(
|
||||
chrono::steady_clock::now() + rel_time);
|
||||
}
|
||||
template <class Clock, class Duration>
|
||||
bool
|
||||
try_unlock_shared_and_lock_upgrade_until(
|
||||
const chrono::time_point<Clock, Duration>& abs_time)
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.assert_lock_shared();
|
||||
if( //state.exclusive // this should be removed once the assertion work
|
||||
state.exclusive_waiting_blocked // Fixme: is this needed?
|
||||
|| state.upgrade
|
||||
)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
cv_status status = exclusive_cond.wait_until(lk,abs_time);
|
||||
if( //! state.exclusive // this should be removed once the assertion work
|
||||
! state.exclusive_waiting_blocked // Fixme: is this needed?
|
||||
&& ! state.upgrade
|
||||
)
|
||||
break;
|
||||
if(status == cv_status::timeout)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//state.unlock_shared();
|
||||
//state.lock_upgrade(); // less efficient
|
||||
state.upgrade=true;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef shared_mutex upgrade_mutex;
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/thread/detail/platform_time.hpp>
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
#include <boost/chrono/system_clocks.hpp>
|
||||
#endif
|
||||
@@ -111,8 +112,6 @@ namespace boost
|
||||
pthread_t thread_handle;
|
||||
boost::mutex data_mutex;
|
||||
boost::condition_variable done_condition;
|
||||
boost::mutex sleep_mutex;
|
||||
boost::condition_variable sleep_condition;
|
||||
bool done;
|
||||
bool join_started;
|
||||
bool joined;
|
||||
@@ -241,49 +240,15 @@ namespace boost
|
||||
|
||||
namespace this_thread
|
||||
{
|
||||
void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT;
|
||||
|
||||
namespace hidden
|
||||
{
|
||||
void BOOST_THREAD_DECL sleep_for(const timespec& ts);
|
||||
void BOOST_THREAD_DECL sleep_until_realtime(const timespec& ts);
|
||||
}
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class Rep, class Period>
|
||||
void sleep_for(const chrono::duration<Rep, Period>& d);
|
||||
#ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY
|
||||
|
||||
inline
|
||||
void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns)
|
||||
{
|
||||
return boost::this_thread::hidden::sleep_for(boost::detail::to_timespec(ns));
|
||||
}
|
||||
#endif
|
||||
#endif // BOOST_THREAD_USES_CHRONO
|
||||
|
||||
namespace no_interruption_point
|
||||
{
|
||||
namespace hidden
|
||||
inline bool always_false()
|
||||
{
|
||||
void BOOST_THREAD_DECL sleep_for(const timespec& ts);
|
||||
void BOOST_THREAD_DECL sleep_until_realtime(const timespec& ts);
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class Rep, class Period>
|
||||
void sleep_for(const chrono::duration<Rep, Period>& d);
|
||||
#ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY
|
||||
|
||||
inline
|
||||
void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns)
|
||||
{
|
||||
return boost::this_thread::no_interruption_point::hidden::sleep_for(boost::detail::to_timespec(ns));
|
||||
}
|
||||
#endif
|
||||
#endif // BOOST_THREAD_USES_CHRONO
|
||||
|
||||
} // no_interruption_point
|
||||
|
||||
void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT;
|
||||
}
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
#ifdef __DECXXX
|
||||
@@ -292,15 +257,141 @@ namespace boost
|
||||
#endif
|
||||
inline void sleep(system_time const& abs_time)
|
||||
{
|
||||
return boost::this_thread::hidden::sleep_until_realtime(boost::detail::to_timespec(abs_time));
|
||||
mutex mx;
|
||||
unique_lock<mutex> lock(mx);
|
||||
condition_variable cond;
|
||||
cond.timed_wait(lock, abs_time, hidden::always_false);
|
||||
}
|
||||
|
||||
template<typename TimeDuration>
|
||||
inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time)
|
||||
void sleep(TimeDuration const& rel_time)
|
||||
{
|
||||
this_thread::sleep(get_system_time()+rel_time);
|
||||
mutex mx;
|
||||
unique_lock<mutex> lock(mx);
|
||||
condition_variable cond;
|
||||
cond.timed_wait(lock, rel_time, hidden::always_false);
|
||||
}
|
||||
#endif // BOOST_THREAD_USES_DATETIME
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class Clock, class Duration>
|
||||
void sleep_until(const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
mutex mut;
|
||||
unique_lock<mutex> lk(mut);
|
||||
condition_variable cv;
|
||||
cv.wait_until(lk, t, hidden::always_false);
|
||||
}
|
||||
|
||||
template <class Rep, class Period>
|
||||
void sleep_for(const chrono::duration<Rep, Period>& d)
|
||||
{
|
||||
mutex mut;
|
||||
unique_lock<mutex> lk(mut);
|
||||
condition_variable cv;
|
||||
cv.wait_for(lk, d, hidden::always_false);
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace no_interruption_point
|
||||
{
|
||||
#if defined BOOST_THREAD_SLEEP_FOR_IS_STEADY
|
||||
// Use pthread_delay_np or nanosleep when available
|
||||
// because they do not provide an interruption point.
|
||||
|
||||
namespace hidden
|
||||
{
|
||||
void BOOST_THREAD_DECL sleep_for_internal(const detail::platform_duration& ts);
|
||||
}
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
#ifdef __DECXXX
|
||||
/// Workaround of DECCXX issue of incorrect template substitution
|
||||
template<>
|
||||
#endif
|
||||
inline void sleep(system_time const& abs_time)
|
||||
{
|
||||
const detail::real_platform_timepoint ts(abs_time);
|
||||
detail::platform_duration d(ts - detail::real_platform_clock::now());
|
||||
while (d > detail::platform_duration::zero())
|
||||
{
|
||||
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
hidden::sleep_for_internal(d);
|
||||
d = ts - detail::real_platform_clock::now();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename TimeDuration>
|
||||
void sleep(TimeDuration const& rel_time)
|
||||
{
|
||||
hidden::sleep_for_internal(detail::platform_duration(rel_time));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class Rep, class Period>
|
||||
void sleep_for(const chrono::duration<Rep, Period>& d)
|
||||
{
|
||||
hidden::sleep_for_internal(detail::platform_duration(d));
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
void sleep_until(const chrono::time_point<chrono::steady_clock, Duration>& t)
|
||||
{
|
||||
sleep_for(t - chrono::steady_clock::now());
|
||||
}
|
||||
|
||||
template <class Clock, class Duration>
|
||||
void sleep_until(const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
|
||||
common_duration d(t - Clock::now());
|
||||
while (d > common_duration::zero())
|
||||
{
|
||||
d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
|
||||
hidden::sleep_for_internal(detail::platform_duration(d));
|
||||
d = t - Clock::now();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#else // BOOST_THREAD_SLEEP_FOR_IS_STEADY
|
||||
// When pthread_delay_np and nanosleep are not available,
|
||||
// fall back to using the interruptible sleep functions.
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
#ifdef __DECXXX
|
||||
/// Workaround of DECCXX issue of incorrect template substitution
|
||||
template<>
|
||||
#endif
|
||||
inline void sleep(system_time const& abs_time)
|
||||
{
|
||||
this_thread::sleep(abs_time);
|
||||
}
|
||||
|
||||
template<typename TimeDuration>
|
||||
void sleep(TimeDuration const& rel_time)
|
||||
{
|
||||
this_thread::sleep(rel_time);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class Clock, class Duration>
|
||||
void sleep_until(const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
this_thread::sleep_until(t);
|
||||
}
|
||||
|
||||
template <class Rep, class Period>
|
||||
void sleep_for(const chrono::duration<Rep, Period>& d)
|
||||
{
|
||||
this_thread::sleep_for(d);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // BOOST_THREAD_SLEEP_FOR_IS_STEADY
|
||||
} // no_interruption_point
|
||||
} // this_thread
|
||||
}
|
||||
|
||||
|
||||
@@ -1,138 +0,0 @@
|
||||
#ifndef BOOST_THREAD_PTHREAD_TIMESPEC_HPP
|
||||
#define BOOST_THREAD_PTHREAD_TIMESPEC_HPP
|
||||
// (C) Copyright 2007-8 Anthony Williams
|
||||
// (C) Copyright 2012 Vicente J. Botet Escriba
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/thread_time.hpp>
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
#include <boost/date_time/posix_time/conversion.hpp>
|
||||
#endif
|
||||
#include <pthread.h>
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
#include <boost/chrono/duration.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
|
||||
# define BOOST_THREAD_TIMESPEC_MAC_API
|
||||
#include <sys/time.h> //for gettimeofday and timeval
|
||||
#else
|
||||
#include <time.h> // for clock_gettime
|
||||
#endif
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
inline struct timespec to_timespec(boost::system_time const& abs_time)
|
||||
{
|
||||
struct timespec timeout = { 0,0};
|
||||
boost::posix_time::time_duration const time_since_epoch=abs_time-boost::posix_time::from_time_t(0);
|
||||
|
||||
timeout.tv_sec=time_since_epoch.total_seconds();
|
||||
timeout.tv_nsec=(long)(time_since_epoch.fractional_seconds()*(1000000000l/time_since_epoch.ticks_per_second()));
|
||||
return timeout;
|
||||
}
|
||||
#endif
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
inline timespec to_timespec(chrono::nanoseconds const& ns)
|
||||
{
|
||||
struct timespec ts;
|
||||
ts.tv_sec = static_cast<long>(chrono::duration_cast<chrono::seconds>(ns).count());
|
||||
ts.tv_nsec = static_cast<long>((ns - chrono::duration_cast<chrono::seconds>(ns)).count());
|
||||
return ts;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
inline timespec to_timespec(boost::intmax_t const& ns)
|
||||
{
|
||||
boost::intmax_t s = ns / 1000000000l;
|
||||
struct timespec ts;
|
||||
ts.tv_sec = static_cast<long> (s);
|
||||
ts.tv_nsec = static_cast<long> (ns - s * 1000000000l);
|
||||
return ts;
|
||||
}
|
||||
inline boost::intmax_t to_nanoseconds_int_max(timespec const& ts)
|
||||
{
|
||||
return static_cast<boost::intmax_t>(ts.tv_sec) * 1000000000l + ts.tv_nsec;
|
||||
}
|
||||
inline bool timespec_ge_zero(timespec const& ts)
|
||||
{
|
||||
return (ts.tv_sec >= 0) || (ts.tv_nsec >= 0);
|
||||
}
|
||||
#if defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
|
||||
|
||||
inline timespec timespec_now_monotonic()
|
||||
{
|
||||
timespec ts;
|
||||
|
||||
if ( ::clock_gettime( CLOCK_MONOTONIC, &ts ) )
|
||||
{
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 0;
|
||||
BOOST_ASSERT(0 && "Boost::Thread - Internal Error");
|
||||
}
|
||||
return ts;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline timespec timespec_now_realtime()
|
||||
{
|
||||
timespec ts;
|
||||
|
||||
#if defined(BOOST_THREAD_TIMESPEC_MAC_API)
|
||||
timeval tv;
|
||||
::gettimeofday(&tv, 0);
|
||||
ts.tv_sec = tv.tv_sec;
|
||||
ts.tv_nsec = tv.tv_usec * 1000;
|
||||
#else
|
||||
if ( ::clock_gettime( CLOCK_REALTIME, &ts ) )
|
||||
{
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 0;
|
||||
BOOST_ASSERT(0 && "Boost::Thread - Internal Error");
|
||||
}
|
||||
#endif
|
||||
return ts;
|
||||
}
|
||||
inline timespec timespec_zero()
|
||||
{
|
||||
timespec ts;
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 0;
|
||||
return ts;
|
||||
}
|
||||
inline timespec timespec_plus(timespec const& lhs, timespec const& rhs)
|
||||
{
|
||||
return to_timespec(to_nanoseconds_int_max(lhs) + to_nanoseconds_int_max(rhs));
|
||||
}
|
||||
inline timespec timespec_minus(timespec const& lhs, timespec const& rhs)
|
||||
{
|
||||
return to_timespec(to_nanoseconds_int_max(lhs) - to_nanoseconds_int_max(rhs));
|
||||
}
|
||||
inline bool timespec_gt(timespec const& lhs, timespec const& rhs)
|
||||
{
|
||||
return to_nanoseconds_int_max(lhs) > to_nanoseconds_int_max(rhs);
|
||||
}
|
||||
inline bool timespec_ge(timespec const& lhs, timespec const& rhs)
|
||||
{
|
||||
return to_nanoseconds_int_max(lhs) >= to_nanoseconds_int_max(rhs);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
@@ -13,13 +13,20 @@
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#if defined(BOOST_THREAD_PLATFORM_WIN32)
|
||||
#if defined(BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN)
|
||||
#if defined(BOOST_THREAD_V2_SHARED_MUTEX)
|
||||
#include <boost/thread/v2/shared_mutex.hpp>
|
||||
#else
|
||||
#include <boost/thread/pthread/shared_mutex.hpp>
|
||||
#endif
|
||||
#else
|
||||
#include <boost/thread/win32/shared_mutex.hpp>
|
||||
#endif
|
||||
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
|
||||
//#include <boost/thread/v2/shared_mutex.hpp>
|
||||
#if defined(BOOST_THREAD_V2_SHARED_MUTEX)
|
||||
#include <boost/thread/v2/shared_mutex.hpp>
|
||||
#else
|
||||
#include <boost/thread/pthread/shared_mutex.hpp>
|
||||
#endif
|
||||
#else
|
||||
#error "Boost threads unavailable on this platform"
|
||||
#endif
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
#include <boost/thread/detail/thread_interruption.hpp>
|
||||
#endif
|
||||
#include <boost/thread/v2/thread.hpp>
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,155 +0,0 @@
|
||||
// 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)
|
||||
// (C) Copyright 2011 Vicente J. Botet Escriba
|
||||
|
||||
#ifndef BOOST_THREAD_V2_THREAD_HPP
|
||||
#define BOOST_THREAD_V2_THREAD_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
#include <boost/chrono/system_clocks.hpp>
|
||||
#include <boost/chrono/ceil.hpp>
|
||||
#endif
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
#include <boost/thread/lock_types.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace this_thread
|
||||
{
|
||||
namespace no_interruption_point
|
||||
{
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
|
||||
template <class Clock, class Duration>
|
||||
void sleep_until(const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
using namespace chrono;
|
||||
mutex mut;
|
||||
condition_variable cv;
|
||||
unique_lock<mutex> lk(mut);
|
||||
while (Clock::now() < t)
|
||||
cv.wait_until(lk, t);
|
||||
}
|
||||
|
||||
#ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY
|
||||
|
||||
template <class Rep, class Period>
|
||||
void sleep_for(const chrono::duration<Rep, Period>& d)
|
||||
{
|
||||
using namespace chrono;
|
||||
if (d > duration<Rep, Period>::zero())
|
||||
{
|
||||
duration<long double> Max = nanoseconds::max BOOST_PREVENT_MACRO_SUBSTITUTION ();
|
||||
nanoseconds ns;
|
||||
if (d < Max)
|
||||
{
|
||||
ns = duration_cast<nanoseconds>(d);
|
||||
if (ns < d)
|
||||
++ns;
|
||||
}
|
||||
else
|
||||
ns = nanoseconds:: max BOOST_PREVENT_MACRO_SUBSTITUTION ();
|
||||
sleep_for(ns);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
inline BOOST_SYMBOL_VISIBLE
|
||||
void sleep_until(const chrono::time_point<chrono::steady_clock, Duration>& t)
|
||||
{
|
||||
using namespace chrono;
|
||||
sleep_for(t - steady_clock::now());
|
||||
}
|
||||
#else
|
||||
template <class Rep, class Period>
|
||||
void sleep_for(const chrono::duration<Rep, Period>& d)
|
||||
{
|
||||
using namespace chrono;
|
||||
if (d > duration<Rep, Period>::zero())
|
||||
{
|
||||
steady_clock::time_point c_timeout = steady_clock::now() + ceil<nanoseconds>(d);
|
||||
sleep_until(c_timeout);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
|
||||
template <class Clock, class Duration>
|
||||
void sleep_until(const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
using namespace chrono;
|
||||
mutex mut;
|
||||
condition_variable cv;
|
||||
unique_lock<mutex> lk(mut);
|
||||
while (Clock::now() < t)
|
||||
cv.wait_until(lk, t);
|
||||
}
|
||||
|
||||
#if defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC && defined BOOST_CHRONO_HAS_CLOCK_STEADY
|
||||
template <class Rep, class Period>
|
||||
void sleep_for(const chrono::duration<Rep, Period>& d)
|
||||
{
|
||||
using namespace chrono;
|
||||
if (d > duration<Rep, Period>::zero())
|
||||
{
|
||||
steady_clock::time_point c_timeout = steady_clock::now() + ceil<nanoseconds>(d);
|
||||
sleep_until(c_timeout);
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined BOOST_THREAD_SLEEP_FOR_IS_STEADY
|
||||
|
||||
template <class Rep, class Period>
|
||||
void sleep_for(const chrono::duration<Rep, Period>& d)
|
||||
{
|
||||
using namespace chrono;
|
||||
if (d > duration<Rep, Period>::zero())
|
||||
{
|
||||
duration<long double> Max = nanoseconds::max BOOST_PREVENT_MACRO_SUBSTITUTION ();
|
||||
nanoseconds ns;
|
||||
if (d < Max)
|
||||
{
|
||||
ns = duration_cast<nanoseconds>(d);
|
||||
if (ns < d)
|
||||
++ns;
|
||||
}
|
||||
else
|
||||
ns = nanoseconds:: max BOOST_PREVENT_MACRO_SUBSTITUTION ();
|
||||
sleep_for(ns);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
inline BOOST_SYMBOL_VISIBLE
|
||||
void sleep_until(const chrono::time_point<chrono::steady_clock, Duration>& t)
|
||||
{
|
||||
using namespace chrono;
|
||||
sleep_for(t - steady_clock::now());
|
||||
}
|
||||
#else
|
||||
template <class Rep, class Period>
|
||||
void sleep_for(const chrono::duration<Rep, Period>& d)
|
||||
{
|
||||
using namespace chrono;
|
||||
if (d > duration<Rep, Period>::zero())
|
||||
{
|
||||
//system_clock::time_point c_timeout = time_point_cast<system_clock::duration>(system_clock::now() + ceil<nanoseconds>(d));
|
||||
system_clock::time_point c_timeout = system_clock::now() + ceil<system_clock::duration>(d);
|
||||
sleep_until(c_timeout);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -4,7 +4,7 @@
|
||||
// basic_recursive_mutex.hpp
|
||||
//
|
||||
// (C) Copyright 2006-8 Anthony Williams
|
||||
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
|
||||
// (C) Copyright 2011-2012,2017-2018 Vicente J. Botet Escriba
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -44,13 +44,13 @@ namespace boost
|
||||
|
||||
bool try_lock() BOOST_NOEXCEPT
|
||||
{
|
||||
long const current_thread_id=boost::detail::winapi::GetCurrentThreadId();
|
||||
long const current_thread_id=boost::winapi::GetCurrentThreadId();
|
||||
return try_recursive_lock(current_thread_id) || try_basic_lock(current_thread_id);
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
long const current_thread_id=boost::detail::winapi::GetCurrentThreadId();
|
||||
long const current_thread_id=boost::winapi::GetCurrentThreadId();
|
||||
if(!try_recursive_lock(current_thread_id))
|
||||
{
|
||||
mutex.lock();
|
||||
@@ -61,29 +61,30 @@ namespace boost
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
bool timed_lock(::boost::system_time const& target)
|
||||
{
|
||||
long const current_thread_id=boost::detail::winapi::GetCurrentThreadId();
|
||||
long const current_thread_id=boost::winapi::GetCurrentThreadId();
|
||||
return try_recursive_lock(current_thread_id) || try_timed_lock(current_thread_id,target);
|
||||
}
|
||||
template<typename Duration>
|
||||
bool timed_lock(Duration const& timeout)
|
||||
bool timed_lock(Duration const& target)
|
||||
{
|
||||
return timed_lock(get_system_time()+timeout);
|
||||
long const current_thread_id=boost::detail::winapi::GetCurrentThreadId();
|
||||
return try_recursive_lock(current_thread_id) || try_timed_lock(current_thread_id,target);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class Rep, class Period>
|
||||
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
|
||||
{
|
||||
template <class Rep, class Period>
|
||||
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
|
||||
{
|
||||
long const current_thread_id=boost::detail::winapi::GetCurrentThreadId();
|
||||
return try_recursive_lock(current_thread_id) || try_timed_lock_for(current_thread_id,rel_time);
|
||||
}
|
||||
template <class Clock, class Duration>
|
||||
bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
}
|
||||
template <class Clock, class Duration>
|
||||
bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
long const current_thread_id=boost::detail::winapi::GetCurrentThreadId();
|
||||
return try_recursive_lock(current_thread_id) || try_timed_lock_until(current_thread_id,t);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
void unlock()
|
||||
{
|
||||
@@ -127,6 +128,17 @@ namespace boost
|
||||
}
|
||||
return false;
|
||||
}
|
||||
template<typename Duration>
|
||||
bool try_timed_lock(long current_thread_id,Duration const& target)
|
||||
{
|
||||
if(mutex.timed_lock(target))
|
||||
{
|
||||
BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id);
|
||||
recursion_count=1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
template <typename TP>
|
||||
bool try_timed_lock_until(long current_thread_id,TP const& target)
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include <boost/chrono/system_clocks.hpp>
|
||||
#include <boost/chrono/ceil.hpp>
|
||||
#endif
|
||||
#include <boost/thread/detail/platform_time.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
@@ -59,7 +61,7 @@ namespace boost
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Take the lock flag if it's available
|
||||
bool try_lock() BOOST_NOEXCEPT
|
||||
{
|
||||
return !win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit);
|
||||
@@ -76,21 +78,21 @@ namespace boost
|
||||
|
||||
if(old_count&lock_flag_value)
|
||||
{
|
||||
bool lock_acquired=false;
|
||||
void* const sem=get_event();
|
||||
|
||||
do
|
||||
{
|
||||
unsigned const retval(winapi::WaitForSingleObjectEx(sem, ::boost::detail::win32::infinite,0));
|
||||
BOOST_VERIFY(0 == retval || ::boost::detail::win32::wait_abandoned == retval);
|
||||
// BOOST_VERIFY(winapi::WaitForSingleObject(
|
||||
// sem,::boost::detail::win32::infinite)==0);
|
||||
clear_waiting_and_try_lock(old_count);
|
||||
lock_acquired=!(old_count&lock_flag_value);
|
||||
if(winapi::WaitForSingleObjectEx(sem,::boost::detail::win32::infinite,0)==0)
|
||||
{
|
||||
clear_waiting_and_try_lock(old_count);
|
||||
}
|
||||
}
|
||||
while(!lock_acquired);
|
||||
while(old_count&lock_flag_value);
|
||||
}
|
||||
}
|
||||
|
||||
// Loop until the number of waiters has been incremented or we've taken the lock flag
|
||||
// The loop is necessary since this function may be called by multiple threads simultaneously
|
||||
void mark_waiting_and_try_lock(long& old_count)
|
||||
{
|
||||
for(;;)
|
||||
@@ -102,12 +104,19 @@ namespace boost
|
||||
{
|
||||
if(was_locked)
|
||||
old_count=new_count;
|
||||
// else we've taken the lock flag
|
||||
// don't update old_count so that the calling function can see that
|
||||
// the old lock flag was 0 and know that we've taken the lock flag
|
||||
break;
|
||||
}
|
||||
old_count=current;
|
||||
}
|
||||
}
|
||||
|
||||
// Loop until someone else has taken the lock flag and cleared the event set flag or
|
||||
// until we've taken the lock flag and cleared the event set flag and decremented the
|
||||
// number of waiters
|
||||
// The loop is necessary since this function may be called by multiple threads simultaneously
|
||||
void clear_waiting_and_try_lock(long& old_count)
|
||||
{
|
||||
old_count&=~lock_flag_value;
|
||||
@@ -118,117 +127,124 @@ namespace boost
|
||||
long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count);
|
||||
if(current==old_count)
|
||||
{
|
||||
// if someone else has taken the lock flag
|
||||
// no need to update old_count since old_count == new_count (ignoring
|
||||
// event_set_flag_value which the calling function doesn't care about)
|
||||
// else we've taken the lock flag
|
||||
// don't update old_count so that the calling function can see that
|
||||
// the old lock flag was 0 and know that we've taken the lock flag
|
||||
break;
|
||||
}
|
||||
old_count=current;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned long getMs(detail::platform_duration const& d)
|
||||
{
|
||||
return static_cast<unsigned long>(d.getMs());
|
||||
}
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
bool timed_lock(::boost::system_time const& wait_until)
|
||||
template <typename Duration>
|
||||
unsigned long getMs(Duration const& d)
|
||||
{
|
||||
return static_cast<unsigned long>(chrono::ceil<chrono::milliseconds>(d).count());
|
||||
}
|
||||
|
||||
template <typename Clock, typename Timepoint, typename Duration>
|
||||
bool do_lock_until(Timepoint const& t, Duration const& max)
|
||||
{
|
||||
if(try_lock())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
long old_count=active_count;
|
||||
mark_waiting_and_try_lock(old_count);
|
||||
|
||||
if(old_count&lock_flag_value)
|
||||
{
|
||||
bool lock_acquired=false;
|
||||
void* const sem=get_event();
|
||||
|
||||
// If the clock is the system clock, it may jump while this function
|
||||
// is waiting. To compensate for this and time out near the correct
|
||||
// time, we call WaitForSingleObjectEx() in a loop with a short
|
||||
// timeout and recheck the time remaining each time through the loop.
|
||||
do
|
||||
{
|
||||
if(winapi::WaitForSingleObjectEx(sem,::boost::detail::get_milliseconds_until(wait_until),0)!=0)
|
||||
Duration d(t - Clock::now());
|
||||
if(d <= Duration::zero()) // timeout occurred
|
||||
{
|
||||
BOOST_INTERLOCKED_DECREMENT(&active_count);
|
||||
return false;
|
||||
}
|
||||
clear_waiting_and_try_lock(old_count);
|
||||
lock_acquired=!(old_count&lock_flag_value);
|
||||
if(max != Duration::zero())
|
||||
{
|
||||
d = (std::min)(d, max);
|
||||
}
|
||||
if(winapi::WaitForSingleObjectEx(sem,getMs(d),0)==0)
|
||||
{
|
||||
clear_waiting_and_try_lock(old_count);
|
||||
}
|
||||
}
|
||||
while(!lock_acquired);
|
||||
while(old_count&lock_flag_value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public:
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
bool timed_lock(::boost::system_time const& wait_until)
|
||||
{
|
||||
const detail::real_platform_timepoint t(wait_until);
|
||||
return do_lock_until<detail::real_platform_clock>(t, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
}
|
||||
|
||||
template<typename Duration>
|
||||
bool timed_lock(Duration const& timeout)
|
||||
{
|
||||
return timed_lock(get_system_time()+timeout);
|
||||
const detail::mono_platform_timepoint t(detail::mono_platform_clock::now() + detail::platform_duration(timeout));
|
||||
// The reference clock is steady and so no need to poll periodically, thus 0 ms max (i.e. no max)
|
||||
return do_lock_until<detail::mono_platform_clock>(t, detail::platform_duration::zero());
|
||||
}
|
||||
|
||||
bool timed_lock(boost::xtime const& timeout)
|
||||
{
|
||||
return timed_lock(system_time(timeout));
|
||||
return timed_lock(boost::system_time(timeout));
|
||||
}
|
||||
#endif
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class Rep, class Period>
|
||||
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
|
||||
{
|
||||
return try_lock_until(chrono::steady_clock::now() + rel_time);
|
||||
const chrono::steady_clock::time_point t(chrono::steady_clock::now() + rel_time);
|
||||
typedef typename chrono::duration<Rep, Period> Duration;
|
||||
typedef typename common_type<Duration, typename chrono::steady_clock::duration>::type common_duration;
|
||||
// The reference clock is steady and so no need to poll periodically, thus 0 ms max (i.e. no max)
|
||||
return do_lock_until<chrono::steady_clock>(t, common_duration::zero());
|
||||
}
|
||||
template <class Duration>
|
||||
bool try_lock_until(const chrono::time_point<chrono::steady_clock, Duration>& t)
|
||||
{
|
||||
typedef typename common_type<Duration, typename chrono::steady_clock::duration>::type common_duration;
|
||||
// The reference clock is steady and so no need to poll periodically, thus 0 ms max (i.e. no max)
|
||||
return do_lock_until<chrono::steady_clock>(t, common_duration::zero());
|
||||
}
|
||||
template <class Clock, class Duration>
|
||||
bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
using namespace chrono;
|
||||
system_clock::time_point s_now = system_clock::now();
|
||||
typename Clock::time_point c_now = Clock::now();
|
||||
return try_lock_until(s_now + ceil<system_clock::duration>(t - c_now));
|
||||
}
|
||||
template <class Duration>
|
||||
bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t)
|
||||
{
|
||||
using namespace chrono;
|
||||
typedef time_point<chrono::system_clock, chrono::system_clock::duration> sys_tmpt;
|
||||
return try_lock_until(sys_tmpt(chrono::ceil<chrono::system_clock::duration>(t.time_since_epoch())));
|
||||
}
|
||||
bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::system_clock::duration>& tp)
|
||||
{
|
||||
if(try_lock())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
long old_count=active_count;
|
||||
mark_waiting_and_try_lock(old_count);
|
||||
|
||||
if(old_count&lock_flag_value)
|
||||
{
|
||||
bool lock_acquired=false;
|
||||
void* const sem=get_event();
|
||||
|
||||
do
|
||||
{
|
||||
chrono::time_point<chrono::system_clock, chrono::system_clock::duration> now = chrono::system_clock::now();
|
||||
if (tp<=now) {
|
||||
BOOST_INTERLOCKED_DECREMENT(&active_count);
|
||||
return false;
|
||||
}
|
||||
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-now);
|
||||
|
||||
if(winapi::WaitForSingleObjectEx(sem,static_cast<unsigned long>(rel_time.count()),0)!=0)
|
||||
{
|
||||
BOOST_INTERLOCKED_DECREMENT(&active_count);
|
||||
return false;
|
||||
}
|
||||
clear_waiting_and_try_lock(old_count);
|
||||
lock_acquired=!(old_count&lock_flag_value);
|
||||
}
|
||||
while(!lock_acquired);
|
||||
}
|
||||
return true;
|
||||
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
|
||||
return do_lock_until<Clock>(t, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
|
||||
}
|
||||
#endif
|
||||
|
||||
void unlock()
|
||||
{
|
||||
long const offset=lock_flag_value;
|
||||
// Clear the lock flag using atomic addition (works since long is always 32 bits on Windows)
|
||||
long const old_count=BOOST_INTERLOCKED_EXCHANGE_ADD(&active_count,lock_flag_value);
|
||||
if(!(old_count&event_set_flag_value) && (old_count>offset))
|
||||
// If someone is waiting to take the lock, set the event set flag and, if
|
||||
// the event set flag hadn't already been set, send an event.
|
||||
if(!(old_count&event_set_flag_value) && (old_count>lock_flag_value))
|
||||
{
|
||||
if(!win32::interlocked_bit_test_and_set(&active_count,event_set_flag_bit))
|
||||
{
|
||||
@@ -238,6 +254,8 @@ namespace boost
|
||||
}
|
||||
|
||||
private:
|
||||
// Create an event in a thread-safe way
|
||||
// The first thread to create the event wins and all other thread will use that event
|
||||
void* get_event()
|
||||
{
|
||||
void* current_event=::boost::detail::interlocked_read_acquire(&event);
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <boost/thread/thread_time.hpp>
|
||||
#include <boost/thread/lock_guard.hpp>
|
||||
#include <boost/thread/lock_types.hpp>
|
||||
#include <boost/thread/detail/platform_time.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
@@ -76,7 +77,7 @@ namespace boost
|
||||
void release(unsigned count_to_release)
|
||||
{
|
||||
notified=true;
|
||||
detail::winapi::ReleaseSemaphore(semaphore,count_to_release,0);
|
||||
winapi::ReleaseSemaphore(semaphore,count_to_release,0);
|
||||
}
|
||||
|
||||
void release_waiters()
|
||||
@@ -89,14 +90,14 @@ namespace boost
|
||||
return notified;
|
||||
}
|
||||
|
||||
bool wait(timeout abs_time)
|
||||
bool interruptible_wait(detail::internal_platform_timepoint const &timeout)
|
||||
{
|
||||
return this_thread::interruptible_wait(semaphore,abs_time);
|
||||
return this_thread::interruptible_wait(semaphore, timeout);
|
||||
}
|
||||
|
||||
bool woken()
|
||||
{
|
||||
unsigned long const woken_result=detail::winapi::WaitForSingleObjectEx(wake_sem,0,0);
|
||||
unsigned long const woken_result=winapi::WaitForSingleObjectEx(wake_sem,0,0);
|
||||
BOOST_ASSERT((woken_result==detail::win32::timeout) || (woken_result==0));
|
||||
return woken_result==0;
|
||||
}
|
||||
@@ -135,7 +136,7 @@ namespace boost
|
||||
void wake_waiters(long count_to_wake)
|
||||
{
|
||||
detail::interlocked_write_release(&total_count,total_count-count_to_wake);
|
||||
detail::winapi::ReleaseSemaphore(wake_sem,count_to_wake,0);
|
||||
winapi::ReleaseSemaphore(wake_sem,count_to_wake,0);
|
||||
}
|
||||
|
||||
template<typename lock_type>
|
||||
@@ -230,42 +231,7 @@ namespace boost
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
protected:
|
||||
template<typename lock_type>
|
||||
bool do_wait(lock_type& lock,timeout abs_time)
|
||||
{
|
||||
relocker<lock_type> locker(lock);
|
||||
entry_manager entry(get_wait_entry(), internal_mutex);
|
||||
locker.unlock();
|
||||
|
||||
bool woken=false;
|
||||
while(!woken)
|
||||
{
|
||||
if(!entry->wait(abs_time))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
woken=entry->woken();
|
||||
}
|
||||
// do it here to avoid throwing on the destructor
|
||||
entry.remove_waiter_and_reset();
|
||||
locker.lock();
|
||||
return woken;
|
||||
}
|
||||
|
||||
template<typename lock_type,typename predicate_type>
|
||||
bool do_wait(lock_type& m,timeout const& abs_time,predicate_type pred)
|
||||
{
|
||||
while (!pred())
|
||||
{
|
||||
if(!do_wait(m, abs_time))
|
||||
return pred();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
basic_condition_variable(const basic_condition_variable& other);
|
||||
basic_condition_variable& operator=(const basic_condition_variable& other);
|
||||
|
||||
@@ -277,6 +243,38 @@ namespace boost
|
||||
~basic_condition_variable()
|
||||
{}
|
||||
|
||||
// When this function returns true:
|
||||
// * A notification (or sometimes a spurious OS signal) has been received
|
||||
// * Do not assume that the timeout has not been reached
|
||||
// * Do not assume that the predicate has been changed
|
||||
//
|
||||
// When this function returns false:
|
||||
// * The timeout has been reached
|
||||
// * Do not assume that a notification has not been received
|
||||
// * Do not assume that the predicate has not been changed
|
||||
template<typename lock_type>
|
||||
bool do_wait_until(lock_type& lock, detail::internal_platform_timepoint const &timeout)
|
||||
{
|
||||
relocker<lock_type> locker(lock);
|
||||
entry_manager entry(get_wait_entry(), internal_mutex);
|
||||
locker.unlock();
|
||||
|
||||
bool woken=false;
|
||||
while(!woken)
|
||||
{
|
||||
if(!entry->interruptible_wait(timeout))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
woken=entry->woken();
|
||||
}
|
||||
// do it here to avoid throwing on the destructor
|
||||
entry.remove_waiter_and_reset();
|
||||
locker.lock();
|
||||
return true;
|
||||
}
|
||||
|
||||
void notify_one() BOOST_NOEXCEPT
|
||||
{
|
||||
if(detail::interlocked_read_acquire(&total_count))
|
||||
@@ -330,75 +328,115 @@ namespace boost
|
||||
condition_variable()
|
||||
{}
|
||||
|
||||
using detail::basic_condition_variable::do_wait_until;
|
||||
using detail::basic_condition_variable::notify_one;
|
||||
using detail::basic_condition_variable::notify_all;
|
||||
|
||||
void wait(unique_lock<mutex>& m)
|
||||
{
|
||||
do_wait(m,detail::timeout::sentinel());
|
||||
do_wait_until(m, detail::internal_platform_timepoint::getMax());
|
||||
}
|
||||
|
||||
template<typename predicate_type>
|
||||
void wait(unique_lock<mutex>& m,predicate_type pred)
|
||||
{
|
||||
while(!pred()) wait(m);
|
||||
while (!pred())
|
||||
{
|
||||
wait(m);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& abs_time)
|
||||
{
|
||||
return do_wait(m,abs_time);
|
||||
// The system time may jump while this function is waiting. To compensate for this and time
|
||||
// out near the correct time, we could call do_wait_until() in a loop with a short timeout
|
||||
// and recheck the time remaining each time through the loop. However, because we can't
|
||||
// check the predicate each time do_wait_until() completes, this introduces the possibility
|
||||
// of not exiting the function when a notification occurs, since do_wait_until() may report
|
||||
// that it timed out even though a notification was received. The best this function can do
|
||||
// is report correctly whether or not it reached the timeout time.
|
||||
const detail::real_platform_timepoint ts(abs_time);
|
||||
const detail::platform_duration d(ts - detail::real_platform_clock::now());
|
||||
do_wait_until(m, detail::internal_platform_clock::now() + d);
|
||||
return ts > detail::real_platform_clock::now();
|
||||
}
|
||||
|
||||
bool timed_wait(unique_lock<mutex>& m,boost::xtime const& abs_time)
|
||||
{
|
||||
return do_wait(m,system_time(abs_time));
|
||||
return timed_wait(m, system_time(abs_time));
|
||||
}
|
||||
template<typename duration_type>
|
||||
bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration)
|
||||
{
|
||||
if (wait_duration.is_pos_infinity())
|
||||
{
|
||||
wait(m); // or do_wait(m,detail::timeout::sentinel());
|
||||
return true;
|
||||
}
|
||||
if (wait_duration.is_special())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return do_wait(m,wait_duration.total_milliseconds());
|
||||
if (wait_duration.is_pos_infinity())
|
||||
{
|
||||
wait(m);
|
||||
return true;
|
||||
}
|
||||
if (wait_duration.is_special())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
const detail::platform_duration d(wait_duration);
|
||||
return do_wait_until(m, detail::internal_platform_clock::now() + d);
|
||||
}
|
||||
|
||||
template<typename predicate_type>
|
||||
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& abs_time,predicate_type pred)
|
||||
{
|
||||
return do_wait(m,abs_time,pred);
|
||||
// The system time may jump while this function is waiting. To compensate for this
|
||||
// and time out near the correct time, we call do_wait_until() in a loop with a
|
||||
// short timeout and recheck the time remaining each time through the loop.
|
||||
const detail::real_platform_timepoint ts(abs_time);
|
||||
while (!pred())
|
||||
{
|
||||
detail::platform_duration d(ts - detail::real_platform_clock::now());
|
||||
if (d <= detail::platform_duration::zero()) break; // timeout occurred
|
||||
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
do_wait_until(m, detail::internal_platform_clock::now() + d);
|
||||
}
|
||||
return pred();
|
||||
}
|
||||
template<typename predicate_type>
|
||||
bool timed_wait(unique_lock<mutex>& m,boost::xtime const& abs_time,predicate_type pred)
|
||||
{
|
||||
return do_wait(m,system_time(abs_time),pred);
|
||||
return timed_wait(m, system_time(abs_time), pred);
|
||||
}
|
||||
template<typename duration_type,typename predicate_type>
|
||||
bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration,predicate_type pred)
|
||||
{
|
||||
if (wait_duration.is_pos_infinity())
|
||||
{
|
||||
while (!pred())
|
||||
{
|
||||
wait(m); // or do_wait(m,detail::timeout::sentinel());
|
||||
}
|
||||
return true;
|
||||
while (!pred())
|
||||
{
|
||||
wait(m);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (wait_duration.is_special())
|
||||
{
|
||||
return pred();
|
||||
return pred();
|
||||
}
|
||||
return do_wait(m,wait_duration.total_milliseconds(),pred);
|
||||
const detail::platform_duration d(wait_duration);
|
||||
const detail::internal_platform_timepoint ts(detail::internal_platform_clock::now() + d);
|
||||
while (!pred())
|
||||
{
|
||||
if (!do_wait_until(m, ts)) break; // timeout occurred
|
||||
}
|
||||
return pred();
|
||||
}
|
||||
#endif
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class Duration>
|
||||
cv_status
|
||||
wait_until(
|
||||
unique_lock<mutex>& lock,
|
||||
const chrono::time_point<detail::internal_chrono_clock, Duration>& t)
|
||||
{
|
||||
const detail::internal_platform_timepoint ts(t);
|
||||
if (do_wait_until(lock, ts)) return cv_status::no_timeout;
|
||||
else return cv_status::timeout;
|
||||
}
|
||||
|
||||
template <class Clock, class Duration>
|
||||
cv_status
|
||||
@@ -406,14 +444,18 @@ namespace boost
|
||||
unique_lock<mutex>& lock,
|
||||
const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
using namespace chrono;
|
||||
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;
|
||||
// The system time may jump while this function is waiting. To compensate for this and time
|
||||
// out near the correct time, we could call do_wait_until() in a loop with a short timeout
|
||||
// and recheck the time remaining each time through the loop. However, because we can't
|
||||
// check the predicate each time do_wait_until() completes, this introduces the possibility
|
||||
// of not exiting the function when a notification occurs, since do_wait_until() may report
|
||||
// that it timed out even though a notification was received. The best this function can do
|
||||
// is report correctly whether or not it reached the timeout time.
|
||||
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
|
||||
common_duration d(t - Clock::now());
|
||||
do_wait_until(lock, detail::internal_chrono_clock::now() + d);
|
||||
if (t > Clock::now()) return cv_status::no_timeout;
|
||||
else return cv_status::timeout;
|
||||
}
|
||||
|
||||
template <class Rep, class Period>
|
||||
@@ -422,15 +464,22 @@ namespace boost
|
||||
unique_lock<mutex>& lock,
|
||||
const chrono::duration<Rep, Period>& d)
|
||||
{
|
||||
using namespace chrono;
|
||||
if (d<=chrono::duration<Rep, Period>::zero()) {
|
||||
return cv_status::timeout;
|
||||
}
|
||||
return wait_until(lock, chrono::steady_clock::now() + d);
|
||||
}
|
||||
|
||||
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 :
|
||||
cv_status::timeout;
|
||||
template <class Duration, class Predicate>
|
||||
bool
|
||||
wait_until(
|
||||
unique_lock<mutex>& lock,
|
||||
const chrono::time_point<detail::internal_chrono_clock, Duration>& t,
|
||||
Predicate pred)
|
||||
{
|
||||
const detail::internal_platform_timepoint ts(t);
|
||||
while (!pred())
|
||||
{
|
||||
if (!do_wait_until(lock, ts)) break; // timeout occurred
|
||||
}
|
||||
return pred();
|
||||
}
|
||||
|
||||
template <class Clock, class Duration, class Predicate>
|
||||
@@ -440,13 +489,20 @@ namespace boost
|
||||
const chrono::time_point<Clock, Duration>& t,
|
||||
Predicate pred)
|
||||
{
|
||||
// The system time may jump while this function is waiting. To compensate for this
|
||||
// and time out near the correct time, we call do_wait_until() in a loop with a
|
||||
// short timeout and recheck the time remaining each time through the loop.
|
||||
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
|
||||
while (!pred())
|
||||
{
|
||||
if (wait_until(lock, t) == cv_status::timeout)
|
||||
return pred();
|
||||
common_duration d(t - Clock::now());
|
||||
if (d <= common_duration::zero()) break; // timeout occurred
|
||||
d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
|
||||
do_wait_until(lock, detail::internal_platform_clock::now() + detail::platform_duration(d));
|
||||
}
|
||||
return true;
|
||||
return pred();
|
||||
}
|
||||
|
||||
template <class Rep, class Period, class Predicate>
|
||||
bool
|
||||
wait_for(
|
||||
@@ -467,59 +523,122 @@ namespace boost
|
||||
condition_variable_any()
|
||||
{}
|
||||
|
||||
using detail::basic_condition_variable::do_wait_until;
|
||||
using detail::basic_condition_variable::notify_one;
|
||||
using detail::basic_condition_variable::notify_all;
|
||||
|
||||
template<typename lock_type>
|
||||
void wait(lock_type& m)
|
||||
{
|
||||
do_wait(m,detail::timeout::sentinel());
|
||||
do_wait_until(m, detail::internal_platform_timepoint::getMax());
|
||||
}
|
||||
|
||||
template<typename lock_type,typename predicate_type>
|
||||
void wait(lock_type& m,predicate_type pred)
|
||||
{
|
||||
while(!pred()) wait(m);
|
||||
while (!pred())
|
||||
{
|
||||
wait(m);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
template<typename lock_type>
|
||||
bool timed_wait(lock_type& m,boost::system_time const& abs_time)
|
||||
{
|
||||
return do_wait(m,abs_time);
|
||||
// The system time may jump while this function is waiting. To compensate for this and time
|
||||
// out near the correct time, we could call do_wait_until() in a loop with a short timeout
|
||||
// and recheck the time remaining each time through the loop. However, because we can't
|
||||
// check the predicate each time do_wait_until() completes, this introduces the possibility
|
||||
// of not exiting the function when a notification occurs, since do_wait_until() may report
|
||||
// that it timed out even though a notification was received. The best this function can do
|
||||
// is report correctly whether or not it reached the timeout time.
|
||||
const detail::real_platform_timepoint ts(abs_time);
|
||||
const detail::platform_duration d(ts - detail::real_platform_clock::now());
|
||||
do_wait_until(m, detail::internal_platform_clock::now() + d);
|
||||
return ts > detail::real_platform_clock::now();
|
||||
}
|
||||
|
||||
template<typename lock_type>
|
||||
bool timed_wait(lock_type& m,boost::xtime const& abs_time)
|
||||
{
|
||||
return do_wait(m,system_time(abs_time));
|
||||
return timed_wait(m, system_time(abs_time));
|
||||
}
|
||||
|
||||
template<typename lock_type,typename duration_type>
|
||||
bool timed_wait(lock_type& m,duration_type const& wait_duration)
|
||||
{
|
||||
return do_wait(m,wait_duration.total_milliseconds());
|
||||
if (wait_duration.is_pos_infinity())
|
||||
{
|
||||
wait(m);
|
||||
return true;
|
||||
}
|
||||
if (wait_duration.is_special())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
const detail::platform_duration d(wait_duration);
|
||||
return do_wait_until(m, detail::internal_platform_clock::now() + d);
|
||||
}
|
||||
|
||||
template<typename lock_type,typename predicate_type>
|
||||
bool timed_wait(lock_type& m,boost::system_time const& abs_time,predicate_type pred)
|
||||
{
|
||||
return do_wait(m,abs_time,pred);
|
||||
// The system time may jump while this function is waiting. To compensate for this
|
||||
// and time out near the correct time, we call do_wait_until() in a loop with a
|
||||
// short timeout and recheck the time remaining each time through the loop.
|
||||
const detail::real_platform_timepoint ts(abs_time);
|
||||
while (!pred())
|
||||
{
|
||||
detail::platform_duration d(ts - detail::real_platform_clock::now());
|
||||
if (d <= detail::platform_duration::zero()) break; // timeout occurred
|
||||
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
do_wait_until(m, detail::internal_platform_clock::now() + d);
|
||||
}
|
||||
return pred();
|
||||
}
|
||||
|
||||
template<typename lock_type,typename predicate_type>
|
||||
bool timed_wait(lock_type& m,boost::xtime const& abs_time,predicate_type pred)
|
||||
{
|
||||
return do_wait(m,system_time(abs_time),pred);
|
||||
return timed_wait(m, system_time(abs_time), pred);
|
||||
}
|
||||
|
||||
template<typename lock_type,typename duration_type,typename predicate_type>
|
||||
bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred)
|
||||
{
|
||||
return do_wait(m,wait_duration.total_milliseconds(),pred);
|
||||
if (wait_duration.is_pos_infinity())
|
||||
{
|
||||
while (!pred())
|
||||
{
|
||||
wait(m);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (wait_duration.is_special())
|
||||
{
|
||||
return pred();
|
||||
}
|
||||
const detail::platform_duration d(wait_duration);
|
||||
const detail::internal_platform_timepoint ts(detail::internal_platform_clock::now() + d);
|
||||
while (!pred())
|
||||
{
|
||||
if (!do_wait_until(m, ts)) break; // timeout occurred
|
||||
}
|
||||
return pred();
|
||||
}
|
||||
#endif
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class lock_type,class Duration>
|
||||
cv_status
|
||||
wait_until(
|
||||
lock_type& lock,
|
||||
const chrono::time_point<detail::internal_chrono_clock, Duration>& t)
|
||||
{
|
||||
const detail::internal_platform_timepoint ts(t);
|
||||
if (do_wait_until(lock, ts)) return cv_status::no_timeout;
|
||||
else return cv_status::timeout;
|
||||
}
|
||||
|
||||
template <class lock_type, class Clock, class Duration>
|
||||
cv_status
|
||||
@@ -527,14 +646,18 @@ namespace boost
|
||||
lock_type& lock,
|
||||
const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
using namespace chrono;
|
||||
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;
|
||||
// The system time may jump while this function is waiting. To compensate for this and time
|
||||
// out near the correct time, we could call do_wait_until() in a loop with a short timeout
|
||||
// and recheck the time remaining each time through the loop. However, because we can't
|
||||
// check the predicate each time do_wait_until() completes, this introduces the possibility
|
||||
// of not exiting the function when a notification occurs, since do_wait_until() may report
|
||||
// that it timed out even though a notification was received. The best this function can do
|
||||
// is report correctly whether or not it reached the timeout time.
|
||||
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
|
||||
common_duration d(t - Clock::now());
|
||||
do_wait_until(lock, detail::internal_chrono_clock::now() + d);
|
||||
if (t > Clock::now()) return cv_status::no_timeout;
|
||||
else return cv_status::timeout;
|
||||
}
|
||||
|
||||
template <class lock_type, class Rep, class Period>
|
||||
@@ -543,14 +666,22 @@ namespace boost
|
||||
lock_type& lock,
|
||||
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 :
|
||||
cv_status::timeout;
|
||||
return wait_until(lock, chrono::steady_clock::now() + d);
|
||||
}
|
||||
|
||||
template <class lock_type, class Clock, class Duration, class Predicate>
|
||||
bool
|
||||
wait_until(
|
||||
lock_type& lock,
|
||||
const chrono::time_point<detail::internal_chrono_clock, Duration>& t,
|
||||
Predicate pred)
|
||||
{
|
||||
const detail::internal_platform_timepoint ts(t);
|
||||
while (!pred())
|
||||
{
|
||||
if (!do_wait_until(lock, ts)) break; // timeout occurred
|
||||
}
|
||||
return pred();
|
||||
}
|
||||
|
||||
template <class lock_type, class Clock, class Duration, class Predicate>
|
||||
@@ -560,12 +691,18 @@ namespace boost
|
||||
const chrono::time_point<Clock, Duration>& t,
|
||||
Predicate pred)
|
||||
{
|
||||
// The system time may jump while this function is waiting. To compensate for this
|
||||
// and time out near the correct time, we call do_wait_until() in a loop with a
|
||||
// short timeout and recheck the time remaining each time through the loop.
|
||||
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
|
||||
while (!pred())
|
||||
{
|
||||
if (wait_until(lock, t) == cv_status::timeout)
|
||||
return pred();
|
||||
common_duration d(t - Clock::now());
|
||||
if (d <= common_duration::zero()) break; // timeout occurred
|
||||
d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
|
||||
do_wait_until(lock, detail::internal_platform_clock::now() + detail::platform_duration(d));
|
||||
}
|
||||
return true;
|
||||
return pred();
|
||||
}
|
||||
|
||||
template <class lock_type, class Rep, class Period, class Predicate>
|
||||
|
||||
@@ -136,9 +136,9 @@ namespace boost
|
||||
}
|
||||
|
||||
#ifdef BOOST_NO_ANSI_APIS
|
||||
return ::boost::detail::winapi::OpenEventW(
|
||||
return ::boost::winapi::OpenEventW(
|
||||
#else
|
||||
return ::boost::detail::winapi::OpenEventA(
|
||||
return ::boost::winapi::OpenEventA(
|
||||
#endif
|
||||
::boost::detail::win32::synchronize |
|
||||
::boost::detail::win32::event_modify_state,
|
||||
@@ -186,7 +186,7 @@ namespace boost
|
||||
}
|
||||
if(ctx.event_handle)
|
||||
{
|
||||
::boost::detail::winapi::ResetEvent(ctx.event_handle);
|
||||
::boost::winapi::ResetEvent(ctx.event_handle);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -207,7 +207,7 @@ namespace boost
|
||||
}
|
||||
if(ctx.event_handle)
|
||||
{
|
||||
::boost::detail::winapi::SetEvent(ctx.event_handle);
|
||||
::boost::winapi::SetEvent(ctx.event_handle);
|
||||
}
|
||||
}
|
||||
inline void rollback_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT
|
||||
@@ -219,13 +219,13 @@ namespace boost
|
||||
}
|
||||
if(ctx.event_handle)
|
||||
{
|
||||
::boost::detail::winapi::SetEvent(ctx.event_handle);
|
||||
::boost::winapi::SetEvent(ctx.event_handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
//#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
|
||||
//#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR)
|
||||
inline void call_once(once_flag& flag, void (*f)())
|
||||
{
|
||||
// Try for a quick win: if the procedure has already been called
|
||||
@@ -264,7 +264,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite, 0));
|
||||
}
|
||||
}
|
||||
@@ -308,7 +308,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -355,7 +355,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -400,7 +400,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -443,7 +443,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -486,7 +486,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -529,7 +529,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -574,7 +574,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -617,7 +617,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -660,7 +660,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -703,13 +703,13 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if 1
|
||||
#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
|
||||
#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR)
|
||||
inline void call_once(once_flag& flag, void (*f)())
|
||||
{
|
||||
// Try for a quick win: if the procedure has already been called
|
||||
@@ -748,7 +748,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -793,7 +793,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -839,7 +839,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -886,7 +886,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -930,7 +930,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -977,7 +977,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -1024,7 +1024,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -1073,7 +1073,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define BOOST_THREAD_WIN32_SHARED_MUTEX_HPP
|
||||
|
||||
// (C) Copyright 2006-8 Anthony Williams
|
||||
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
|
||||
// (C) Copyright 2011-2012,2017-2018 Vicente J. Botet Escriba
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <boost/chrono/ceil.hpp>
|
||||
#endif
|
||||
#include <boost/thread/detail/delete.hpp>
|
||||
#include <boost/thread/detail/platform_time.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
@@ -29,7 +30,7 @@ namespace boost
|
||||
private:
|
||||
struct state_data
|
||||
{
|
||||
unsigned shared_count:11,
|
||||
unsigned long shared_count:11,
|
||||
shared_waiting:11,
|
||||
exclusive:1,
|
||||
upgrade:1,
|
||||
@@ -38,19 +39,16 @@ namespace boost
|
||||
|
||||
friend bool operator==(state_data const& lhs,state_data const& rhs)
|
||||
{
|
||||
return *reinterpret_cast<unsigned const*>(&lhs)==*reinterpret_cast<unsigned const*>(&rhs);
|
||||
return *reinterpret_cast<unsigned long const*>(&lhs)==*reinterpret_cast<unsigned long const*>(&rhs);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
T interlocked_compare_exchange(T* target,T new_value,T comparand)
|
||||
state_data interlocked_compare_exchange(state_data* target, state_data new_value, state_data comparand)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(sizeof(T)==sizeof(long));
|
||||
long const res=BOOST_INTERLOCKED_COMPARE_EXCHANGE(reinterpret_cast<long*>(target),
|
||||
*reinterpret_cast<long*>(&new_value),
|
||||
*reinterpret_cast<long*>(&comparand));
|
||||
return *reinterpret_cast<T const*>(&res);
|
||||
return *reinterpret_cast<state_data const*>(&res);
|
||||
}
|
||||
|
||||
enum
|
||||
@@ -67,19 +65,19 @@ namespace boost
|
||||
{
|
||||
if(old_state.exclusive_waiting)
|
||||
{
|
||||
BOOST_VERIFY(detail::winapi::ReleaseSemaphore(semaphores[exclusive_sem],1,0)!=0);
|
||||
BOOST_VERIFY(winapi::ReleaseSemaphore(semaphores[exclusive_sem],1,0)!=0);
|
||||
}
|
||||
|
||||
if(old_state.shared_waiting || old_state.exclusive_waiting)
|
||||
{
|
||||
BOOST_VERIFY(detail::winapi::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
|
||||
BOOST_VERIFY(winapi::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
|
||||
}
|
||||
}
|
||||
void release_shared_waiters(state_data old_state)
|
||||
{
|
||||
if(old_state.shared_waiting || old_state.exclusive_waiting)
|
||||
{
|
||||
BOOST_VERIFY(detail::winapi::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
|
||||
BOOST_VERIFY(winapi::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,9 +105,9 @@ namespace boost
|
||||
|
||||
~shared_mutex()
|
||||
{
|
||||
detail::winapi::CloseHandle(upgrade_sem);
|
||||
detail::winapi::CloseHandle(semaphores[unlock_sem]);
|
||||
detail::winapi::CloseHandle(semaphores[exclusive_sem]);
|
||||
winapi::CloseHandle(upgrade_sem);
|
||||
winapi::CloseHandle(semaphores[unlock_sem]);
|
||||
winapi::CloseHandle(semaphores[exclusive_sem]);
|
||||
}
|
||||
|
||||
bool try_lock_shared()
|
||||
@@ -139,21 +137,60 @@ namespace boost
|
||||
|
||||
void lock_shared()
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
state_data old_state=state;
|
||||
for(;;)
|
||||
{
|
||||
state_data new_state=old_state;
|
||||
if(new_state.exclusive || new_state.exclusive_waiting_blocked)
|
||||
{
|
||||
++new_state.shared_waiting;
|
||||
if(!new_state.shared_waiting)
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++new_state.shared_count;
|
||||
if(!new_state.shared_count)
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
}
|
||||
}
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
BOOST_VERIFY(timed_lock_shared(::boost::detail::get_system_time_sentinel()));
|
||||
#else
|
||||
BOOST_VERIFY(try_lock_shared_until(chrono::steady_clock::now()));
|
||||
#endif
|
||||
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
|
||||
if(current_state==old_state)
|
||||
{
|
||||
break;
|
||||
}
|
||||
old_state=current_state;
|
||||
}
|
||||
|
||||
if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
BOOST_VERIFY(winapi::WaitForSingleObjectEx(semaphores[unlock_sem],::boost::detail::win32::infinite,0)==0);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
template<typename TimeDuration>
|
||||
bool timed_lock_shared(TimeDuration const & relative_time)
|
||||
private:
|
||||
unsigned long getMs(detail::platform_duration const& d)
|
||||
{
|
||||
return timed_lock_shared(get_system_time()+relative_time);
|
||||
return static_cast<unsigned long>(d.getMs());
|
||||
}
|
||||
bool timed_lock_shared(boost::system_time const& wait_until)
|
||||
|
||||
template <typename Duration>
|
||||
unsigned long getMs(Duration const& d)
|
||||
{
|
||||
return static_cast<unsigned long>(chrono::ceil<chrono::milliseconds>(d).count());
|
||||
}
|
||||
|
||||
template <typename Clock, typename Timepoint, typename Duration>
|
||||
bool do_lock_shared_until(Timepoint const& t, Duration const& max)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
@@ -191,7 +228,30 @@ namespace boost
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned long const res=detail::winapi::WaitForSingleObjectEx(semaphores[unlock_sem],::boost::detail::get_milliseconds_until(wait_until), 0);
|
||||
// If the clock is the system clock, it may jump while this function
|
||||
// is waiting. To compensate for this and time out near the correct
|
||||
// time, we call WaitForSingleObjectEx() in a loop with a short
|
||||
// timeout and recheck the time remaining each time through the loop.
|
||||
unsigned long res=0;
|
||||
for(;;)
|
||||
{
|
||||
Duration d(t - Clock::now());
|
||||
if(d <= Duration::zero()) // timeout occurred
|
||||
{
|
||||
res=detail::win32::timeout;
|
||||
break;
|
||||
}
|
||||
if(max != Duration::zero())
|
||||
{
|
||||
d = (std::min)(d, max);
|
||||
}
|
||||
res=winapi::WaitForSingleObjectEx(semaphores[unlock_sem],getMs(d),0);
|
||||
if(res!=detail::win32::timeout) // semaphore released
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(res==detail::win32::timeout)
|
||||
{
|
||||
for(;;)
|
||||
@@ -231,114 +291,45 @@ namespace boost
|
||||
BOOST_ASSERT(res==0);
|
||||
}
|
||||
}
|
||||
public:
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
template<typename TimeDuration>
|
||||
bool timed_lock_shared(TimeDuration const & relative_time)
|
||||
{
|
||||
const detail::mono_platform_timepoint t(detail::mono_platform_clock::now() + detail::platform_duration(relative_time));
|
||||
// The reference clock is steady and so no need to poll periodically, thus 0 ms max (i.e. no max)
|
||||
return do_lock_shared_until<detail::mono_platform_clock>(t, detail::platform_duration::zero());
|
||||
}
|
||||
bool timed_lock_shared(boost::system_time const& wait_until)
|
||||
{
|
||||
const detail::real_platform_timepoint t(wait_until);
|
||||
return do_lock_shared_until<detail::real_platform_clock>(t, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class Rep, class Period>
|
||||
bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time)
|
||||
{
|
||||
return try_lock_shared_until(chrono::steady_clock::now() + rel_time);
|
||||
const chrono::steady_clock::time_point t(chrono::steady_clock::now() + rel_time);
|
||||
typedef typename chrono::duration<Rep, Period> Duration;
|
||||
typedef typename common_type<Duration, typename chrono::steady_clock::duration>::type common_duration;
|
||||
// The reference clock is steady and so no need to poll periodically, thus 0 ms max (i.e. no max)
|
||||
return do_lock_shared_until<chrono::steady_clock>(t, common_duration::zero());
|
||||
}
|
||||
template <class Duration>
|
||||
bool try_lock_shared_until(const chrono::time_point<chrono::steady_clock, Duration>& t)
|
||||
{
|
||||
typedef typename common_type<Duration, typename chrono::steady_clock::duration>::type common_duration;
|
||||
// The reference clock is steady and so no need to poll periodically, thus 0 ms max (i.e. no max)
|
||||
return do_lock_shared_until<chrono::steady_clock>(t, common_duration::zero());
|
||||
}
|
||||
template <class Clock, class Duration>
|
||||
bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
using namespace chrono;
|
||||
system_clock::time_point s_now = system_clock::now();
|
||||
typename Clock::time_point c_now = Clock::now();
|
||||
return try_lock_shared_until(s_now + ceil<system_clock::duration>(t - c_now));
|
||||
}
|
||||
template <class Duration>
|
||||
bool try_lock_shared_until(const chrono::time_point<chrono::system_clock, Duration>& t)
|
||||
{
|
||||
using namespace chrono;
|
||||
typedef time_point<chrono::system_clock, chrono::system_clock::duration> sys_tmpt;
|
||||
return try_lock_shared_until(sys_tmpt(chrono::ceil<chrono::system_clock::duration>(t.time_since_epoch())));
|
||||
}
|
||||
bool try_lock_shared_until(const chrono::time_point<chrono::system_clock, chrono::system_clock::duration>& tp)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
state_data old_state=state;
|
||||
for(;;)
|
||||
{
|
||||
state_data new_state=old_state;
|
||||
if(new_state.exclusive || new_state.exclusive_waiting_blocked)
|
||||
{
|
||||
++new_state.shared_waiting;
|
||||
if(!new_state.shared_waiting)
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++new_state.shared_count;
|
||||
if(!new_state.shared_count)
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
}
|
||||
}
|
||||
|
||||
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
|
||||
if(current_state==old_state)
|
||||
{
|
||||
break;
|
||||
}
|
||||
old_state=current_state;
|
||||
}
|
||||
|
||||
if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
chrono::system_clock::time_point n = chrono::system_clock::now();
|
||||
unsigned long res;
|
||||
if (tp>n) {
|
||||
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-n);
|
||||
res=detail::winapi::WaitForSingleObjectEx(semaphores[unlock_sem],
|
||||
static_cast<unsigned long>(rel_time.count()), 0);
|
||||
} else {
|
||||
res=detail::win32::timeout;
|
||||
}
|
||||
if(res==detail::win32::timeout)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
state_data new_state=old_state;
|
||||
if(new_state.exclusive || new_state.exclusive_waiting_blocked)
|
||||
{
|
||||
if(new_state.shared_waiting)
|
||||
{
|
||||
--new_state.shared_waiting;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++new_state.shared_count;
|
||||
if(!new_state.shared_count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
|
||||
if(current_state==old_state)
|
||||
{
|
||||
break;
|
||||
}
|
||||
old_state=current_state;
|
||||
}
|
||||
|
||||
if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
BOOST_ASSERT(res==0);
|
||||
}
|
||||
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
|
||||
return do_lock_shared_until<Clock>(t, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -375,7 +366,7 @@ namespace boost
|
||||
{
|
||||
if(old_state.upgrade)
|
||||
{
|
||||
BOOST_VERIFY(detail::winapi::ReleaseSemaphore(upgrade_sem,1,0)!=0);
|
||||
BOOST_VERIFY(winapi::ReleaseSemaphore(upgrade_sem,1,0)!=0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -388,24 +379,6 @@ namespace boost
|
||||
}
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
BOOST_VERIFY(timed_lock(::boost::detail::get_system_time_sentinel()));
|
||||
#else
|
||||
BOOST_VERIFY(try_lock_until(chrono::steady_clock::now()));
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
template<typename TimeDuration>
|
||||
bool timed_lock(TimeDuration const & relative_time)
|
||||
{
|
||||
return timed_lock(get_system_time()+relative_time);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool try_lock()
|
||||
{
|
||||
state_data old_state=state;
|
||||
@@ -431,14 +404,58 @@ namespace boost
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
bool timed_lock(boost::system_time const& wait_until)
|
||||
void lock()
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
state_data old_state=state;
|
||||
for(;;)
|
||||
{
|
||||
state_data new_state=old_state;
|
||||
if(new_state.shared_count || new_state.exclusive)
|
||||
{
|
||||
++new_state.exclusive_waiting;
|
||||
if(!new_state.exclusive_waiting)
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
}
|
||||
|
||||
new_state.exclusive_waiting_blocked=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_state.exclusive=true;
|
||||
}
|
||||
|
||||
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
|
||||
if(current_state==old_state)
|
||||
{
|
||||
break;
|
||||
}
|
||||
old_state=current_state;
|
||||
}
|
||||
|
||||
if(!old_state.shared_count && !old_state.exclusive)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef UNDER_CE
|
||||
const bool wait_all = true;
|
||||
#else
|
||||
const bool wait_all = false;
|
||||
#endif
|
||||
BOOST_VERIFY(winapi::WaitForMultipleObjectsEx(2,semaphores,wait_all,::boost::detail::win32::infinite,0)<2);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Clock, typename Timepoint, typename Duration>
|
||||
bool do_lock_until(Timepoint const& t, Duration const& max)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
state_data old_state=state;
|
||||
for(;;)
|
||||
{
|
||||
state_data new_state=old_state;
|
||||
@@ -469,12 +486,37 @@ namespace boost
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#ifndef UNDER_CE
|
||||
const bool wait_all = true;
|
||||
#else
|
||||
const bool wait_all = false;
|
||||
#endif
|
||||
unsigned long const wait_res=detail::winapi::WaitForMultipleObjectsEx(2,semaphores,wait_all,::boost::detail::get_milliseconds_until(wait_until), 0);
|
||||
|
||||
// If the clock is the system clock, it may jump while this function
|
||||
// is waiting. To compensate for this and time out near the correct
|
||||
// time, we call WaitForMultipleObjectsEx() in a loop with a short
|
||||
// timeout and recheck the time remaining each time through the loop.
|
||||
unsigned long wait_res=0;
|
||||
for(;;)
|
||||
{
|
||||
Duration d(t - Clock::now());
|
||||
if(d <= Duration::zero()) // timeout occurred
|
||||
{
|
||||
wait_res=detail::win32::timeout;
|
||||
break;
|
||||
}
|
||||
if(max != Duration::zero())
|
||||
{
|
||||
d = (std::min)(d, max);
|
||||
}
|
||||
#ifndef UNDER_CE
|
||||
wait_res=winapi::WaitForMultipleObjectsEx(2,semaphores,true,getMs(d),0);
|
||||
#else
|
||||
wait_res=winapi::WaitForMultipleObjectsEx(2,semaphores,false,getMs(d),0);
|
||||
#endif
|
||||
//wait_res=winapi::WaitForMultipleObjectsEx(2,semaphores,wait_all,getMs(d), 0);
|
||||
|
||||
if(wait_res!=detail::win32::timeout) // semaphore released
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(wait_res==detail::win32::timeout)
|
||||
{
|
||||
for(;;)
|
||||
@@ -500,7 +542,7 @@ namespace boost
|
||||
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
|
||||
if (must_notify)
|
||||
{
|
||||
BOOST_VERIFY(detail::winapi::ReleaseSemaphore(semaphores[unlock_sem],1,0)!=0);
|
||||
BOOST_VERIFY(winapi::ReleaseSemaphore(semaphores[unlock_sem],1,0)!=0);
|
||||
}
|
||||
|
||||
if(current_state==old_state)
|
||||
@@ -515,123 +557,48 @@ namespace boost
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
BOOST_ASSERT(wait_res<2);
|
||||
}
|
||||
}
|
||||
public:
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
bool timed_lock(boost::system_time const& wait_until)
|
||||
{
|
||||
const detail::real_platform_timepoint t(wait_until);
|
||||
return do_lock_until<detail::real_platform_clock>(t, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
}
|
||||
template<typename TimeDuration>
|
||||
bool timed_lock(TimeDuration const & relative_time)
|
||||
{
|
||||
const detail::mono_platform_timepoint t(detail::mono_platform_clock::now() + detail::platform_duration(relative_time));
|
||||
// The reference clock is steady and so no need to poll periodically, thus 0 ms max (i.e. no max)
|
||||
return do_lock_until<detail::mono_platform_clock>(t, detail::platform_duration::zero());
|
||||
}
|
||||
#endif
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class Rep, class Period>
|
||||
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
|
||||
{
|
||||
return try_lock_until(chrono::steady_clock::now() + rel_time);
|
||||
const chrono::steady_clock::time_point t(chrono::steady_clock::now() + rel_time);
|
||||
typedef typename chrono::duration<Rep, Period> Duration;
|
||||
typedef typename common_type<Duration, typename chrono::steady_clock::duration>::type common_duration;
|
||||
// The reference clock is steady and so no need to poll periodically, thus 0 ms max (i.e. no max)
|
||||
return do_lock_until<chrono::steady_clock>(t, common_duration::zero());
|
||||
}
|
||||
template <class Duration>
|
||||
bool try_lock_until(const chrono::time_point<chrono::steady_clock, Duration>& t)
|
||||
{
|
||||
typedef typename common_type<Duration, typename chrono::steady_clock::duration>::type common_duration;
|
||||
// The reference clock is steady and so no need to poll periodically, thus 0 ms max (i.e. no max)
|
||||
return do_lock_until<chrono::steady_clock>(t, common_duration::zero());
|
||||
}
|
||||
template <class Clock, class Duration>
|
||||
bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
using namespace chrono;
|
||||
system_clock::time_point s_now = system_clock::now();
|
||||
typename Clock::time_point c_now = Clock::now();
|
||||
return try_lock_until(s_now + ceil<system_clock::duration>(t - c_now));
|
||||
}
|
||||
template <class Duration>
|
||||
bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t)
|
||||
{
|
||||
using namespace chrono;
|
||||
typedef time_point<chrono::system_clock, chrono::system_clock::duration> sys_tmpt;
|
||||
return try_lock_until(sys_tmpt(chrono::ceil<chrono::system_clock::duration>(t.time_since_epoch())));
|
||||
}
|
||||
bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::system_clock::duration>& tp)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
state_data old_state=state;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
state_data new_state=old_state;
|
||||
if(new_state.shared_count || new_state.exclusive)
|
||||
{
|
||||
++new_state.exclusive_waiting;
|
||||
if(!new_state.exclusive_waiting)
|
||||
{
|
||||
boost::throw_exception(boost::lock_error());
|
||||
}
|
||||
|
||||
new_state.exclusive_waiting_blocked=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_state.exclusive=true;
|
||||
}
|
||||
|
||||
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
|
||||
if(current_state==old_state)
|
||||
{
|
||||
break;
|
||||
}
|
||||
old_state=current_state;
|
||||
}
|
||||
|
||||
if(!old_state.shared_count && !old_state.exclusive)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#ifndef UNDER_CE
|
||||
const bool wait_all = true;
|
||||
#else
|
||||
const bool wait_all = false;
|
||||
#endif
|
||||
|
||||
chrono::system_clock::time_point n = chrono::system_clock::now();
|
||||
unsigned long wait_res;
|
||||
if (tp>n) {
|
||||
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now());
|
||||
wait_res=detail::winapi::WaitForMultipleObjectsEx(2,semaphores,wait_all,
|
||||
static_cast<unsigned long>(rel_time.count()), 0);
|
||||
} else {
|
||||
wait_res=detail::win32::timeout;
|
||||
}
|
||||
if(wait_res==detail::win32::timeout)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
bool must_notify = false;
|
||||
state_data new_state=old_state;
|
||||
if(new_state.shared_count || new_state.exclusive)
|
||||
{
|
||||
if(new_state.exclusive_waiting)
|
||||
{
|
||||
if(!--new_state.exclusive_waiting)
|
||||
{
|
||||
new_state.exclusive_waiting_blocked=false;
|
||||
must_notify = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
new_state.exclusive=true;
|
||||
}
|
||||
|
||||
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
|
||||
if (must_notify)
|
||||
{
|
||||
BOOST_VERIFY(detail::winapi::ReleaseSemaphore(semaphores[unlock_sem],1,0)!=0);
|
||||
}
|
||||
if(current_state==old_state)
|
||||
{
|
||||
break;
|
||||
}
|
||||
old_state=current_state;
|
||||
}
|
||||
if(!old_state.shared_count && !old_state.exclusive)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
BOOST_ASSERT(wait_res<2);
|
||||
}
|
||||
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
|
||||
return do_lock_until<Clock>(t, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -698,7 +665,7 @@ namespace boost
|
||||
return;
|
||||
}
|
||||
|
||||
BOOST_VERIFY(!detail::winapi::WaitForSingleObjectEx(semaphores[unlock_sem],detail::winapi::infinite, 0));
|
||||
BOOST_VERIFY(winapi::WaitForSingleObjectEx(semaphores[unlock_sem],winapi::infinite,0)==0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -790,7 +757,7 @@ namespace boost
|
||||
{
|
||||
if(!last_reader)
|
||||
{
|
||||
BOOST_VERIFY(!detail::winapi::WaitForSingleObjectEx(upgrade_sem,detail::win32::infinite, 0));
|
||||
BOOST_VERIFY(winapi::WaitForSingleObjectEx(upgrade_sem,detail::win32::infinite,0)==0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -823,27 +790,6 @@ namespace boost
|
||||
}
|
||||
release_waiters(old_state);
|
||||
}
|
||||
// bool try_unlock_upgrade_and_lock()
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
//#ifdef BOOST_THREAD_USES_CHRONO
|
||||
// template <class Rep, class Period>
|
||||
// bool
|
||||
// try_unlock_upgrade_and_lock_for(
|
||||
// const chrono::duration<Rep, Period>& rel_time)
|
||||
// {
|
||||
// return try_unlock_upgrade_and_lock_until(
|
||||
// chrono::steady_clock::now() + rel_time);
|
||||
// }
|
||||
// template <class Clock, class Duration>
|
||||
// bool
|
||||
// try_unlock_upgrade_and_lock_until(
|
||||
// const chrono::time_point<Clock, Duration>& abs_time)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
//#endif
|
||||
|
||||
void unlock_and_lock_shared()
|
||||
{
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <boost/thread/thread_time.hpp>
|
||||
#include <boost/thread/win32/thread_primitives.hpp>
|
||||
#include <boost/thread/win32/thread_heap_alloc.hpp>
|
||||
#include <boost/thread/detail/platform_time.hpp>
|
||||
|
||||
#include <boost/predef/platform.h>
|
||||
|
||||
@@ -153,7 +154,7 @@ namespace boost
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
void interrupt()
|
||||
{
|
||||
BOOST_VERIFY(detail::winapi::SetEvent(interruption_handle)!=0);
|
||||
BOOST_VERIFY(winapi::SetEvent(interruption_handle)!=0);
|
||||
}
|
||||
#endif
|
||||
typedef detail::win32::handle native_handle_type;
|
||||
@@ -174,146 +175,111 @@ namespace boost
|
||||
BOOST_THREAD_DECL thread_data_base* get_current_thread_data();
|
||||
|
||||
typedef boost::intrusive_ptr<detail::thread_data_base> thread_data_ptr;
|
||||
|
||||
struct BOOST_SYMBOL_VISIBLE timeout
|
||||
{
|
||||
win32::ticks_type start;
|
||||
uintmax_t milliseconds;
|
||||
bool relative;
|
||||
boost::system_time abs_time;
|
||||
|
||||
static unsigned long const max_non_infinite_wait=0xfffffffe;
|
||||
|
||||
timeout(uintmax_t milliseconds_):
|
||||
start(win32::GetTickCount64_()()),
|
||||
milliseconds(milliseconds_),
|
||||
relative(true)
|
||||
//,
|
||||
// abs_time(boost::get_system_time())
|
||||
{}
|
||||
|
||||
timeout(boost::system_time const& abs_time_):
|
||||
start(win32::GetTickCount64_()()),
|
||||
milliseconds(0),
|
||||
relative(false),
|
||||
abs_time(abs_time_)
|
||||
{}
|
||||
|
||||
struct BOOST_SYMBOL_VISIBLE remaining_time
|
||||
{
|
||||
bool more;
|
||||
unsigned long milliseconds;
|
||||
|
||||
remaining_time(uintmax_t remaining):
|
||||
more(remaining>max_non_infinite_wait),
|
||||
milliseconds(more?max_non_infinite_wait:(unsigned long)remaining)
|
||||
{}
|
||||
};
|
||||
|
||||
remaining_time remaining_milliseconds() const
|
||||
{
|
||||
if(is_sentinel())
|
||||
{
|
||||
return remaining_time(win32::infinite);
|
||||
}
|
||||
else if(relative)
|
||||
{
|
||||
win32::ticks_type const now=win32::GetTickCount64_()();
|
||||
win32::ticks_type const elapsed=now-start;
|
||||
return remaining_time((elapsed<milliseconds)?(milliseconds-elapsed):0);
|
||||
}
|
||||
else
|
||||
{
|
||||
system_time const now=get_system_time();
|
||||
if(abs_time<=now)
|
||||
{
|
||||
return remaining_time(0);
|
||||
}
|
||||
return remaining_time((abs_time-now).total_milliseconds()+1);
|
||||
}
|
||||
}
|
||||
|
||||
bool is_sentinel() const
|
||||
{
|
||||
return milliseconds==~uintmax_t(0);
|
||||
}
|
||||
|
||||
|
||||
static timeout sentinel()
|
||||
{
|
||||
return timeout(sentinel_type());
|
||||
}
|
||||
private:
|
||||
struct sentinel_type
|
||||
{};
|
||||
|
||||
explicit timeout(sentinel_type):
|
||||
start(0),milliseconds(~uintmax_t(0)),relative(true)
|
||||
{}
|
||||
};
|
||||
|
||||
inline uintmax_t pin_to_zero(intmax_t value)
|
||||
{
|
||||
return (value<0)?0u:(uintmax_t)value;
|
||||
}
|
||||
}
|
||||
|
||||
namespace this_thread
|
||||
{
|
||||
void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT;
|
||||
|
||||
bool BOOST_THREAD_DECL interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time);
|
||||
inline void interruptible_wait(uintmax_t milliseconds)
|
||||
{
|
||||
interruptible_wait(detail::win32::invalid_handle_value,milliseconds);
|
||||
}
|
||||
inline BOOST_SYMBOL_VISIBLE void interruptible_wait(system_time const& abs_time)
|
||||
{
|
||||
interruptible_wait(detail::win32::invalid_handle_value,abs_time);
|
||||
}
|
||||
bool BOOST_THREAD_DECL interruptible_wait(detail::win32::handle handle_to_wait_for, detail::internal_platform_timepoint const &timeout);
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
template<typename TimeDuration>
|
||||
inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time)
|
||||
BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time)
|
||||
{
|
||||
interruptible_wait(detail::pin_to_zero(rel_time.total_milliseconds()));
|
||||
interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + detail::platform_duration(rel_time));
|
||||
}
|
||||
|
||||
inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time)
|
||||
{
|
||||
interruptible_wait(abs_time);
|
||||
const detail::real_platform_timepoint ts(abs_time);
|
||||
detail::platform_duration d(ts - detail::real_platform_clock::now());
|
||||
while (d > detail::platform_duration::zero())
|
||||
{
|
||||
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + d);
|
||||
d = ts - detail::real_platform_clock::now();
|
||||
}
|
||||
}
|
||||
// #11322 sleep_for() nanoseconds overload will always return too early on windows
|
||||
//#ifdef BOOST_THREAD_USES_CHRONO
|
||||
// inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns)
|
||||
// {
|
||||
// interruptible_wait(chrono::duration_cast<chrono::milliseconds>(ns).count());
|
||||
// }
|
||||
//#endif
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class Rep, class Period>
|
||||
void sleep_for(const chrono::duration<Rep, Period>& d)
|
||||
{
|
||||
interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + detail::platform_duration(d));
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
void sleep_until(const chrono::time_point<chrono::steady_clock, Duration>& t)
|
||||
{
|
||||
sleep_for(t - chrono::steady_clock::now());
|
||||
}
|
||||
|
||||
template <class Clock, class Duration>
|
||||
void sleep_until(const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
|
||||
common_duration d(t - Clock::now());
|
||||
while (d > common_duration::zero())
|
||||
{
|
||||
d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
|
||||
sleep_for(d);
|
||||
d = t - Clock::now();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace no_interruption_point
|
||||
{
|
||||
bool BOOST_THREAD_DECL non_interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time);
|
||||
inline void non_interruptible_wait(uintmax_t milliseconds)
|
||||
{
|
||||
non_interruptible_wait(detail::win32::invalid_handle_value,milliseconds);
|
||||
}
|
||||
inline BOOST_SYMBOL_VISIBLE void non_interruptible_wait(system_time const& abs_time)
|
||||
{
|
||||
non_interruptible_wait(detail::win32::invalid_handle_value,abs_time);
|
||||
}
|
||||
bool BOOST_THREAD_DECL non_interruptible_wait(detail::win32::handle handle_to_wait_for, detail::internal_platform_timepoint const &timeout);
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
template<typename TimeDuration>
|
||||
inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time)
|
||||
BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time)
|
||||
{
|
||||
non_interruptible_wait(detail::pin_to_zero(rel_time.total_milliseconds()));
|
||||
non_interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + detail::platform_duration(rel_time));
|
||||
}
|
||||
|
||||
inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time)
|
||||
{
|
||||
non_interruptible_wait(abs_time);
|
||||
const detail::real_platform_timepoint ts(abs_time);
|
||||
detail::platform_duration d(ts - detail::real_platform_clock::now());
|
||||
while (d > detail::platform_duration::zero())
|
||||
{
|
||||
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
non_interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + d);
|
||||
d = ts - detail::real_platform_clock::now();
|
||||
}
|
||||
}
|
||||
// #11322 sleep_for() nanoseconds overload will always return too early on windows
|
||||
//#ifdef BOOST_THREAD_USES_CHRONO
|
||||
// inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns)
|
||||
// {
|
||||
// non_interruptible_wait(chrono::duration_cast<chrono::milliseconds>(ns).count());
|
||||
// }
|
||||
//#endif
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class Rep, class Period>
|
||||
void sleep_for(const chrono::duration<Rep, Period>& d)
|
||||
{
|
||||
non_interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + detail::platform_duration(d));
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
void sleep_until(const chrono::time_point<chrono::steady_clock, Duration>& t)
|
||||
{
|
||||
sleep_for(t - chrono::steady_clock::now());
|
||||
}
|
||||
|
||||
template <class Clock, class Duration>
|
||||
void sleep_until(const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
|
||||
common_duration d(t - Clock::now());
|
||||
while (d > common_duration::zero())
|
||||
{
|
||||
d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
|
||||
sleep_for(d);
|
||||
d = t - Clock::now();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/core/no_exceptions_support.hpp>
|
||||
|
||||
#include <boost/detail/winapi/heap_memory.hpp>
|
||||
#include <boost/winapi/heap_memory.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace boost
|
||||
{
|
||||
inline void* allocate_raw_heap_memory(unsigned size)
|
||||
{
|
||||
void* const heap_memory=detail::winapi::HeapAlloc(detail::winapi::GetProcessHeap(),0,size);
|
||||
void* const heap_memory=winapi::HeapAlloc(winapi::GetProcessHeap(),0,size);
|
||||
if(!heap_memory)
|
||||
{
|
||||
boost::throw_exception(std::bad_alloc());
|
||||
@@ -32,7 +32,7 @@ namespace boost
|
||||
|
||||
inline void free_raw_heap_memory(void* heap_memory)
|
||||
{
|
||||
BOOST_VERIFY(detail::winapi::HeapFree(detail::winapi::GetProcessHeap(),0,heap_memory)!=0);
|
||||
BOOST_VERIFY(winapi::HeapFree(winapi::GetProcessHeap(),0,heap_memory)!=0);
|
||||
}
|
||||
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) && ! defined (BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
template<typename T,typename... Args>
|
||||
|
||||
@@ -16,23 +16,22 @@
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#include <boost/detail/interlocked.hpp>
|
||||
#include <boost/detail/winapi/config.hpp>
|
||||
|
||||
#include <boost/detail/winapi/semaphore.hpp>
|
||||
#include <boost/detail/winapi/dll.hpp>
|
||||
#include <boost/detail/winapi/system.hpp>
|
||||
#include <boost/detail/winapi/time.hpp>
|
||||
#include <boost/detail/winapi/event.hpp>
|
||||
#include <boost/detail/winapi/thread.hpp>
|
||||
#include <boost/detail/winapi/get_current_thread.hpp>
|
||||
#include <boost/detail/winapi/get_current_thread_id.hpp>
|
||||
#include <boost/detail/winapi/get_current_process.hpp>
|
||||
#include <boost/detail/winapi/get_current_process_id.hpp>
|
||||
#include <boost/detail/winapi/wait.hpp>
|
||||
#include <boost/detail/winapi/handles.hpp>
|
||||
#include <boost/detail/winapi/access_rights.hpp>
|
||||
#include <boost/winapi/config.hpp>
|
||||
#include <boost/winapi/basic_types.hpp>
|
||||
#include <boost/winapi/semaphore.hpp>
|
||||
#include <boost/winapi/system.hpp>
|
||||
#include <boost/winapi/event.hpp>
|
||||
#include <boost/winapi/thread.hpp>
|
||||
#include <boost/winapi/get_current_thread.hpp>
|
||||
#include <boost/winapi/get_current_thread_id.hpp>
|
||||
#include <boost/winapi/get_current_process.hpp>
|
||||
#include <boost/winapi/get_current_process_id.hpp>
|
||||
#include <boost/winapi/wait.hpp>
|
||||
#include <boost/winapi/handles.hpp>
|
||||
#include <boost/winapi/access_rights.hpp>
|
||||
|
||||
//#include <boost/detail/winapi/synchronization.hpp>
|
||||
//#include <boost/winapi/synchronization.hpp>
|
||||
#include <boost/thread/win32/interlocked_read.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
@@ -46,20 +45,19 @@ namespace boost
|
||||
{
|
||||
namespace win32
|
||||
{
|
||||
typedef ::boost::detail::winapi::HANDLE_ handle;
|
||||
typedef ::boost::detail::winapi::SYSTEM_INFO_ system_info;
|
||||
typedef unsigned __int64 ticks_type;
|
||||
typedef ::boost::detail::winapi::FARPROC_ farproc_t;
|
||||
unsigned const infinite=::boost::detail::winapi::INFINITE_;
|
||||
unsigned const timeout=::boost::detail::winapi::WAIT_TIMEOUT_;
|
||||
handle const invalid_handle_value=::boost::detail::winapi::INVALID_HANDLE_VALUE_;
|
||||
unsigned const event_modify_state=::boost::detail::winapi::EVENT_MODIFY_STATE_;
|
||||
unsigned const synchronize=::boost::detail::winapi::SYNCHRONIZE_;
|
||||
unsigned const wait_abandoned=::boost::detail::winapi::WAIT_ABANDONED_;
|
||||
typedef ::boost::winapi::HANDLE_ handle;
|
||||
typedef ::boost::winapi::SYSTEM_INFO_ system_info;
|
||||
typedef ::boost::winapi::ULONGLONG_ ticks_type;
|
||||
unsigned const infinite=::boost::winapi::INFINITE_;
|
||||
unsigned const timeout=::boost::winapi::WAIT_TIMEOUT_;
|
||||
handle const invalid_handle_value=::boost::winapi::INVALID_HANDLE_VALUE_;
|
||||
unsigned const event_modify_state=::boost::winapi::EVENT_MODIFY_STATE_;
|
||||
unsigned const synchronize=::boost::winapi::SYNCHRONIZE_;
|
||||
unsigned const wait_abandoned=::boost::winapi::WAIT_ABANDONED_;
|
||||
unsigned const create_event_initial_set = 0x00000002;
|
||||
unsigned const create_event_manual_reset = 0x00000001;
|
||||
unsigned const event_all_access = ::boost::detail::winapi::EVENT_ALL_ACCESS_;
|
||||
unsigned const semaphore_all_access = boost::detail::winapi::SEMAPHORE_ALL_ACCESS_;
|
||||
unsigned const event_all_access = ::boost::winapi::EVENT_ALL_ACCESS_;
|
||||
unsigned const semaphore_all_access = boost::winapi::SEMAPHORE_ALL_ACCESS_;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,96 +70,8 @@ namespace boost
|
||||
{
|
||||
namespace win32
|
||||
{
|
||||
namespace detail { typedef ticks_type (__stdcall *gettickcount64_t)(); }
|
||||
#if !BOOST_PLAT_WINDOWS_RUNTIME
|
||||
extern "C"
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
long _InterlockedCompareExchange(long volatile *, long, long);
|
||||
#pragma intrinsic(_InterlockedCompareExchange)
|
||||
#elif defined(__MINGW64_VERSION_MAJOR)
|
||||
long _InterlockedCompareExchange(long volatile *, long, long);
|
||||
#else
|
||||
// Mingw doesn't provide intrinsics
|
||||
#define _InterlockedCompareExchange InterlockedCompareExchange
|
||||
#endif
|
||||
}
|
||||
// Borrowed from https://stackoverflow.com/questions/8211820/userland-interrupt-timer-access-such-as-via-kequeryinterrupttime-or-similar
|
||||
inline ticks_type __stdcall GetTickCount64emulation()
|
||||
{
|
||||
static long count = -1l;
|
||||
unsigned long previous_count, current_tick32, previous_count_zone, current_tick32_zone;
|
||||
ticks_type current_tick64;
|
||||
|
||||
previous_count = (unsigned long) boost::detail::interlocked_read_acquire(&count);
|
||||
current_tick32 = ::boost::detail::winapi::GetTickCount();
|
||||
|
||||
if(previous_count == (unsigned long)-1l)
|
||||
{
|
||||
// count has never been written
|
||||
unsigned long initial_count;
|
||||
initial_count = current_tick32 >> 28;
|
||||
previous_count = (unsigned long) _InterlockedCompareExchange(&count, (long)initial_count, -1l);
|
||||
|
||||
current_tick64 = initial_count;
|
||||
current_tick64 <<= 28;
|
||||
current_tick64 += current_tick32 & 0x0FFFFFFF;
|
||||
return current_tick64;
|
||||
}
|
||||
|
||||
previous_count_zone = previous_count & 15;
|
||||
current_tick32_zone = current_tick32 >> 28;
|
||||
|
||||
if(current_tick32_zone == previous_count_zone)
|
||||
{
|
||||
// The top four bits of the 32-bit tick count haven't changed since count was last written.
|
||||
current_tick64 = previous_count;
|
||||
current_tick64 <<= 28;
|
||||
current_tick64 += current_tick32 & 0x0FFFFFFF;
|
||||
return current_tick64;
|
||||
}
|
||||
|
||||
if(current_tick32_zone == previous_count_zone + 1 || (current_tick32_zone == 0 && previous_count_zone == 15))
|
||||
{
|
||||
// The top four bits of the 32-bit tick count have been incremented since count was last written.
|
||||
unsigned long new_count = previous_count + 1;
|
||||
_InterlockedCompareExchange(&count, (long)new_count, (long)previous_count);
|
||||
current_tick64 = new_count;
|
||||
current_tick64 <<= 28;
|
||||
current_tick64 += current_tick32 & 0x0FFFFFFF;
|
||||
return current_tick64;
|
||||
}
|
||||
|
||||
// Oops, we weren't called often enough, we're stuck
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
inline detail::gettickcount64_t GetTickCount64_()
|
||||
{
|
||||
static detail::gettickcount64_t gettickcount64impl;
|
||||
if(gettickcount64impl)
|
||||
return gettickcount64impl;
|
||||
|
||||
// GetTickCount and GetModuleHandle are not allowed in the Windows Runtime,
|
||||
// and kernel32 isn't used in Windows Phone.
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
gettickcount64impl = &::boost::detail::winapi::GetTickCount64;
|
||||
#else
|
||||
farproc_t addr=GetProcAddress(
|
||||
#if !defined(BOOST_NO_ANSI_APIS)
|
||||
::boost::detail::winapi::GetModuleHandleA("KERNEL32.DLL"),
|
||||
#else
|
||||
::boost::detail::winapi::GetModuleHandleW(L"KERNEL32.DLL"),
|
||||
#endif
|
||||
"GetTickCount64");
|
||||
if(addr)
|
||||
gettickcount64impl=(detail::gettickcount64_t) addr;
|
||||
else
|
||||
gettickcount64impl=&GetTickCount64emulation;
|
||||
#endif
|
||||
return gettickcount64impl;
|
||||
}
|
||||
namespace detail { typedef ticks_type (WINAPI *gettickcount64_t)(); }
|
||||
extern BOOST_THREAD_DECL boost::detail::win32::detail::gettickcount64_t gettickcount64;
|
||||
|
||||
enum event_type
|
||||
{
|
||||
@@ -185,11 +95,11 @@ namespace boost
|
||||
initial_event_state state)
|
||||
{
|
||||
#if !defined(BOOST_NO_ANSI_APIS)
|
||||
handle const res = ::boost::detail::winapi::CreateEventA(0, type, state, mutex_name);
|
||||
handle const res = ::boost::winapi::CreateEventA(0, type, state, mutex_name);
|
||||
#elif BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA
|
||||
handle const res = ::boost::detail::winapi::CreateEventW(0, type, state, mutex_name);
|
||||
handle const res = ::boost::winapi::CreateEventW(0, type, state, mutex_name);
|
||||
#else
|
||||
handle const res = ::boost::detail::winapi::CreateEventExW(
|
||||
handle const res = ::boost::winapi::CreateEventExW(
|
||||
0,
|
||||
mutex_name,
|
||||
type ? create_event_manual_reset : 0 | state ? create_event_initial_set : 0,
|
||||
@@ -211,12 +121,12 @@ namespace boost
|
||||
inline handle create_anonymous_semaphore_nothrow(long initial_count,long max_count)
|
||||
{
|
||||
#if !defined(BOOST_NO_ANSI_APIS)
|
||||
handle const res=::boost::detail::winapi::CreateSemaphoreA(0,initial_count,max_count,0);
|
||||
handle const res=::boost::winapi::CreateSemaphoreA(0,initial_count,max_count,0);
|
||||
#else
|
||||
#if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA
|
||||
handle const res=::boost::detail::winapi::CreateSemaphoreEx(0,initial_count,max_count,0,0);
|
||||
handle const res=::boost::winapi::CreateSemaphoreEx(0,initial_count,max_count,0,0);
|
||||
#else
|
||||
handle const res=::boost::detail::winapi::CreateSemaphoreExW(0,initial_count,max_count,0,0,semaphore_all_access);
|
||||
handle const res=::boost::winapi::CreateSemaphoreExW(0,initial_count,max_count,0,0,semaphore_all_access);
|
||||
#endif
|
||||
#endif
|
||||
return res;
|
||||
@@ -234,10 +144,10 @@ namespace boost
|
||||
|
||||
inline handle duplicate_handle(handle source)
|
||||
{
|
||||
handle const current_process=::boost::detail::winapi::GetCurrentProcess();
|
||||
handle const current_process=::boost::winapi::GetCurrentProcess();
|
||||
long const same_access_flag=2;
|
||||
handle new_handle=0;
|
||||
bool const success=::boost::detail::winapi::DuplicateHandle(current_process,source,current_process,&new_handle,0,false,same_access_flag)!=0;
|
||||
bool const success=::boost::winapi::DuplicateHandle(current_process,source,current_process,&new_handle,0,false,same_access_flag)!=0;
|
||||
if(!success)
|
||||
{
|
||||
boost::throw_exception(thread_resource_error());
|
||||
@@ -247,15 +157,15 @@ namespace boost
|
||||
|
||||
inline void release_semaphore(handle semaphore,long count)
|
||||
{
|
||||
BOOST_VERIFY(::boost::detail::winapi::ReleaseSemaphore(semaphore,count,0)!=0);
|
||||
BOOST_VERIFY(::boost::winapi::ReleaseSemaphore(semaphore,count,0)!=0);
|
||||
}
|
||||
|
||||
inline void get_system_info(system_info *info)
|
||||
{
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
::boost::detail::winapi::GetNativeSystemInfo(info);
|
||||
::boost::winapi::GetNativeSystemInfo(info);
|
||||
#else
|
||||
::boost::detail::winapi::GetSystemInfo(info);
|
||||
::boost::winapi::GetSystemInfo(info);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -266,15 +176,15 @@ namespace boost
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
std::this_thread::yield();
|
||||
#else
|
||||
::boost::detail::winapi::Sleep(0);
|
||||
::boost::winapi::Sleep(0);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
::boost::detail::winapi::WaitForSingleObjectEx(::boost::detail::winapi::GetCurrentThread(), milliseconds, 0);
|
||||
::boost::winapi::WaitForSingleObjectEx(::boost::winapi::GetCurrentThread(), milliseconds, 0);
|
||||
#else
|
||||
::boost::detail::winapi::Sleep(milliseconds);
|
||||
::boost::winapi::Sleep(milliseconds);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -290,7 +200,7 @@ namespace boost
|
||||
{
|
||||
if (m_completionHandle != ::boost::detail::win32::invalid_handle_value)
|
||||
{
|
||||
::boost::detail::winapi::CloseHandle(m_completionHandle);
|
||||
::boost::winapi::CloseHandle(m_completionHandle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,7 +228,7 @@ namespace boost
|
||||
{
|
||||
if(handle_to_manage && handle_to_manage!=invalid_handle_value)
|
||||
{
|
||||
BOOST_VERIFY(::boost::detail::winapi::CloseHandle(handle_to_manage));
|
||||
BOOST_VERIFY(::boost::winapi::CloseHandle(handle_to_manage));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,10 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined(__VXWORKS__)
|
||||
#include <vxCpuLib.h>
|
||||
#endif
|
||||
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/algorithm/string/trim.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
@@ -350,7 +354,7 @@ namespace boost
|
||||
}
|
||||
}
|
||||
|
||||
bool thread::do_try_join_until_noexcept(struct timespec const &timeout, bool& res)
|
||||
bool thread::do_try_join_until_noexcept(detail::internal_platform_timepoint const &timeout, bool& res)
|
||||
{
|
||||
detail::thread_data_ptr const local_thread_info=(get_thread_info)();
|
||||
if(local_thread_info)
|
||||
@@ -361,11 +365,12 @@ namespace boost
|
||||
unique_lock<mutex> lock(local_thread_info->data_mutex);
|
||||
while(!local_thread_info->done)
|
||||
{
|
||||
if(!local_thread_info->done_condition.do_wait_until(lock,timeout))
|
||||
{
|
||||
res=false;
|
||||
return true;
|
||||
}
|
||||
if(!local_thread_info->done_condition.do_wait_until(lock,timeout)) break; // timeout occurred
|
||||
}
|
||||
if(!local_thread_info->done)
|
||||
{
|
||||
res=false;
|
||||
return true;
|
||||
}
|
||||
do_join=!local_thread_info->join_started;
|
||||
|
||||
@@ -432,99 +437,28 @@ namespace boost
|
||||
{
|
||||
namespace hidden
|
||||
{
|
||||
void BOOST_THREAD_DECL sleep_for(const timespec& ts)
|
||||
void BOOST_THREAD_DECL sleep_for_internal(const detail::platform_duration& ts)
|
||||
{
|
||||
|
||||
if (boost::detail::timespec_ge(ts, boost::detail::timespec_zero()))
|
||||
if (ts > detail::platform_duration::zero())
|
||||
{
|
||||
|
||||
// Use pthread_delay_np or nanosleep whenever possible here in the no_interruption_point
|
||||
// namespace because they do not provide an interruption point.
|
||||
# if defined(BOOST_HAS_PTHREAD_DELAY_NP)
|
||||
# if defined(__IBMCPP__) || defined(_AIX)
|
||||
BOOST_VERIFY(!pthread_delay_np(const_cast<timespec*>(&ts)));
|
||||
BOOST_VERIFY(!pthread_delay_np(const_cast<timespec*>(&ts.getTs())));
|
||||
# else
|
||||
BOOST_VERIFY(!pthread_delay_np(&ts));
|
||||
BOOST_VERIFY(!pthread_delay_np(&ts.getTs()));
|
||||
# endif
|
||||
# elif defined(BOOST_HAS_NANOSLEEP)
|
||||
// nanosleep takes a timespec that is an offset, not
|
||||
// an absolute time.
|
||||
nanosleep(&ts, 0);
|
||||
nanosleep(&ts.getTs(), 0);
|
||||
# else
|
||||
mutex mx;
|
||||
unique_lock<mutex> lock(mx);
|
||||
condition_variable cond;
|
||||
cond.do_wait_for(lock, ts);
|
||||
// This should never be reached due to BOOST_THREAD_SLEEP_FOR_IS_STEADY
|
||||
# endif
|
||||
}
|
||||
}
|
||||
|
||||
void BOOST_THREAD_DECL sleep_until_realtime(const timespec& ts)
|
||||
{
|
||||
timespec now = boost::detail::timespec_now_realtime();
|
||||
if (boost::detail::timespec_gt(ts, now))
|
||||
{
|
||||
for (int foo=0; foo < 5; ++foo)
|
||||
{
|
||||
|
||||
# if defined(BOOST_HAS_PTHREAD_DELAY_NP)
|
||||
timespec d = boost::detail::timespec_minus(ts, now);
|
||||
BOOST_VERIFY(!pthread_delay_np(&d));
|
||||
# elif defined(BOOST_HAS_NANOSLEEP)
|
||||
// nanosleep takes a timespec that is an offset, not
|
||||
// an absolute time.
|
||||
timespec d = boost::detail::timespec_minus(ts, now);
|
||||
nanosleep(&d, 0);
|
||||
# else
|
||||
mutex mx;
|
||||
unique_lock<mutex> lock(mx);
|
||||
condition_variable cond;
|
||||
cond.do_wait_until(lock, ts);
|
||||
# endif
|
||||
timespec now2 = boost::detail::timespec_now_realtime();
|
||||
if (boost::detail::timespec_ge(now2, ts))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace hidden
|
||||
{
|
||||
void BOOST_THREAD_DECL sleep_for(const timespec& ts)
|
||||
{
|
||||
boost::detail::thread_data_base* const thread_info=boost::detail::get_current_thread_data();
|
||||
|
||||
if(thread_info)
|
||||
{
|
||||
unique_lock<mutex> lk(thread_info->sleep_mutex);
|
||||
while( thread_info->sleep_condition.do_wait_for(lk,ts)) {}
|
||||
}
|
||||
else
|
||||
{
|
||||
boost::this_thread::no_interruption_point::hidden::sleep_for(ts);
|
||||
}
|
||||
}
|
||||
|
||||
void BOOST_THREAD_DECL sleep_until_realtime(const timespec& ts)
|
||||
{
|
||||
boost::detail::thread_data_base* const thread_info=boost::detail::get_current_thread_data();
|
||||
|
||||
if(thread_info)
|
||||
{
|
||||
unique_lock<mutex> lk(thread_info->sleep_mutex);
|
||||
while(thread_info->sleep_condition.do_wait_until(lk,ts)) {}
|
||||
}
|
||||
else
|
||||
{
|
||||
boost::this_thread::no_interruption_point::hidden::sleep_until_realtime(ts);
|
||||
}
|
||||
}
|
||||
} // hidden
|
||||
} // this_thread
|
||||
|
||||
namespace this_thread
|
||||
{
|
||||
void yield() BOOST_NOEXCEPT
|
||||
{
|
||||
# if defined(BOOST_HAS_SCHED_YIELD)
|
||||
@@ -537,11 +471,10 @@ namespace boost
|
||||
// sleep(xt);
|
||||
// sleep_for(chrono::milliseconds(0));
|
||||
# else
|
||||
#error
|
||||
timespec ts;
|
||||
ts.tv_sec= 0;
|
||||
ts.tv_nsec= 0;
|
||||
hidden::sleep_for(ts);
|
||||
mutex mx;
|
||||
unique_lock<mutex> lock(mx);
|
||||
condition_variable cond;
|
||||
cond.do_wait_until(lock, detail::internal_platform_clock::now())
|
||||
# endif
|
||||
}
|
||||
}
|
||||
@@ -556,6 +489,18 @@ namespace boost
|
||||
#elif defined(BOOST_HAS_UNISTD_H) && defined(_SC_NPROCESSORS_ONLN)
|
||||
int const count=sysconf(_SC_NPROCESSORS_ONLN);
|
||||
return (count>0)?count:0;
|
||||
#elif defined(__VXWORKS__)
|
||||
cpuset_t set = ::vxCpuEnabledGet();
|
||||
#ifdef __DCC__
|
||||
int i;
|
||||
for( i = 0; set; ++i)
|
||||
{
|
||||
set &= set -1;
|
||||
}
|
||||
return(i);
|
||||
#else
|
||||
return (__builtin_popcount(set) );
|
||||
#endif
|
||||
#elif defined(__GLIBC__)
|
||||
return get_nprocs();
|
||||
#else
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// (C) Copyright 2007 Anthony Williams
|
||||
// (C) Copyright 2007 David Deakins
|
||||
// (C) Copyright 2011-2017 Vicente J. Botet Escriba
|
||||
// (C) Copyright 2011-2018 Vicente J. Botet Escriba
|
||||
|
||||
//#define BOOST_THREAD_VERSION 3
|
||||
|
||||
#include <boost/detail/winapi/config.hpp>
|
||||
#include <boost/winapi/config.hpp>
|
||||
#include <boost/thread/thread_only.hpp>
|
||||
#include <boost/thread/once.hpp>
|
||||
#include <boost/thread/tss.hpp>
|
||||
@@ -439,7 +439,7 @@ namespace boost
|
||||
detail::thread_data_ptr local_thread_info=(get_thread_info)();
|
||||
if(local_thread_info)
|
||||
{
|
||||
this_thread::interruptible_wait(this->native_handle(),detail::timeout::sentinel());
|
||||
this_thread::interruptible_wait(this->native_handle(), detail::internal_platform_timepoint::getMax());
|
||||
release_handle();
|
||||
return true;
|
||||
}
|
||||
@@ -449,18 +449,12 @@ namespace boost
|
||||
}
|
||||
}
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
bool thread::timed_join(boost::system_time const& wait_until)
|
||||
{
|
||||
return do_try_join_until(boost::detail::get_milliseconds_until(wait_until));
|
||||
}
|
||||
#endif
|
||||
bool thread::do_try_join_until_noexcept(uintmax_t milli, bool& res)
|
||||
bool thread::do_try_join_until_noexcept(detail::internal_platform_timepoint const &timeout, bool& res)
|
||||
{
|
||||
detail::thread_data_ptr local_thread_info=(get_thread_info)();
|
||||
if(local_thread_info)
|
||||
{
|
||||
if(!this_thread::interruptible_wait(this->native_handle(),milli))
|
||||
if(!this_thread::interruptible_wait(this->native_handle(), timeout))
|
||||
{
|
||||
res=false;
|
||||
return true;
|
||||
@@ -498,7 +492,7 @@ namespace boost
|
||||
bool thread::interruption_requested() const BOOST_NOEXCEPT
|
||||
{
|
||||
detail::thread_data_ptr local_thread_info=(get_thread_info)();
|
||||
return local_thread_info.get() && (detail::winapi::WaitForSingleObjectEx(local_thread_info->interruption_handle,0,0)==0);
|
||||
return local_thread_info.get() && (winapi::WaitForSingleObjectEx(local_thread_info->interruption_handle,0,0)==0);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -561,62 +555,6 @@ namespace boost
|
||||
|
||||
namespace this_thread
|
||||
{
|
||||
namespace
|
||||
{
|
||||
LARGE_INTEGER get_due_time(detail::timeout const& target_time)
|
||||
{
|
||||
LARGE_INTEGER due_time={{0,0}};
|
||||
if(target_time.relative)
|
||||
{
|
||||
detail::win32::ticks_type const elapsed_milliseconds=detail::win32::GetTickCount64_()()-target_time.start;
|
||||
LONGLONG const remaining_milliseconds=(target_time.milliseconds-elapsed_milliseconds);
|
||||
LONGLONG const hundred_nanoseconds_in_one_millisecond=10000;
|
||||
|
||||
if(remaining_milliseconds>0)
|
||||
{
|
||||
due_time.QuadPart=-(remaining_milliseconds*hundred_nanoseconds_in_one_millisecond);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SYSTEMTIME target_system_time={0,0,0,0,0,0,0,0};
|
||||
target_system_time.wYear=target_time.abs_time.date().year();
|
||||
target_system_time.wMonth=target_time.abs_time.date().month();
|
||||
target_system_time.wDay=target_time.abs_time.date().day();
|
||||
target_system_time.wHour=(WORD)target_time.abs_time.time_of_day().hours();
|
||||
target_system_time.wMinute=(WORD)target_time.abs_time.time_of_day().minutes();
|
||||
target_system_time.wSecond=(WORD)target_time.abs_time.time_of_day().seconds();
|
||||
|
||||
if(!SystemTimeToFileTime(&target_system_time,((FILETIME*)&due_time)))
|
||||
{
|
||||
due_time.QuadPart=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
long const hundred_nanoseconds_in_one_second=10000000;
|
||||
posix_time::time_duration::tick_type const ticks_per_second=
|
||||
target_time.abs_time.time_of_day().ticks_per_second();
|
||||
if(ticks_per_second>hundred_nanoseconds_in_one_second)
|
||||
{
|
||||
posix_time::time_duration::tick_type const
|
||||
ticks_per_hundred_nanoseconds=
|
||||
ticks_per_second/hundred_nanoseconds_in_one_second;
|
||||
due_time.QuadPart+=
|
||||
target_time.abs_time.time_of_day().fractional_seconds()/
|
||||
ticks_per_hundred_nanoseconds;
|
||||
}
|
||||
else
|
||||
{
|
||||
due_time.QuadPart+=
|
||||
target_time.abs_time.time_of_day().fractional_seconds()*
|
||||
(hundred_nanoseconds_in_one_second/ticks_per_second);
|
||||
}
|
||||
}
|
||||
}
|
||||
return due_time;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef UNDER_CE
|
||||
#if !BOOST_PLAT_WINDOWS_RUNTIME
|
||||
namespace detail_
|
||||
@@ -667,7 +605,7 @@ namespace boost
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
bool interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time)
|
||||
bool interruptible_wait(detail::win32::handle handle_to_wait_for, detail::internal_platform_timepoint const &timeout)
|
||||
{
|
||||
detail::win32::handle handles[4]={0};
|
||||
unsigned handle_count=0;
|
||||
@@ -693,16 +631,20 @@ namespace boost
|
||||
#ifndef UNDER_CE
|
||||
#if !BOOST_PLAT_WINDOWS_RUNTIME
|
||||
// Preferentially use coalescing timers for better power consumption and timer accuracy
|
||||
if(!target_time.is_sentinel())
|
||||
if(timeout != detail::internal_platform_timepoint::getMax())
|
||||
{
|
||||
detail::timeout::remaining_time const time_left=target_time.remaining_milliseconds();
|
||||
boost::intmax_t const time_left_msec = (timeout - detail::internal_platform_clock::now()).getMs();
|
||||
timer_handle=CreateWaitableTimer(NULL,false,NULL);
|
||||
if(timer_handle!=0)
|
||||
{
|
||||
ULONG tolerable=32; // Empirical testing shows Windows ignores this when <= 26
|
||||
if(time_left.milliseconds/20>tolerable) // 5%
|
||||
tolerable=time_left.milliseconds/20;
|
||||
LARGE_INTEGER due_time=get_due_time(target_time);
|
||||
if(time_left_msec/20>tolerable) // 5%
|
||||
tolerable=static_cast<ULONG>(time_left_msec/20);
|
||||
LARGE_INTEGER due_time={{0,0}};
|
||||
if(time_left_msec>0)
|
||||
{
|
||||
due_time.QuadPart=-(time_left_msec*10000); // negative indicates relative time
|
||||
}
|
||||
bool const set_time_succeeded=detail_::SetWaitableTimerEx()(timer_handle,&due_time,0,0,0,NULL,tolerable)!=0;
|
||||
if(set_time_succeeded)
|
||||
{
|
||||
@@ -715,18 +657,21 @@ namespace boost
|
||||
#endif
|
||||
|
||||
bool const using_timer=timeout_index!=~0u;
|
||||
detail::timeout::remaining_time time_left(0);
|
||||
boost::intmax_t time_left_msec(INFINITE);
|
||||
if(!using_timer && timeout != detail::internal_platform_timepoint::getMax())
|
||||
{
|
||||
time_left_msec = (timeout - detail::internal_platform_clock::now()).getMs();
|
||||
if(time_left_msec < 0)
|
||||
{
|
||||
time_left_msec = 0;
|
||||
}
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if(!using_timer)
|
||||
{
|
||||
time_left=target_time.remaining_milliseconds();
|
||||
}
|
||||
|
||||
if(handle_count)
|
||||
{
|
||||
unsigned long const notified_index=detail::winapi::WaitForMultipleObjectsEx(handle_count,handles,false,using_timer?INFINITE:time_left.milliseconds, 0);
|
||||
unsigned long const notified_index=winapi::WaitForMultipleObjectsEx(handle_count,handles,false,static_cast<DWORD>(time_left_msec), 0);
|
||||
if(notified_index<handle_count)
|
||||
{
|
||||
if(notified_index==wait_handle_index)
|
||||
@@ -736,7 +681,7 @@ namespace boost
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
else if(notified_index==interruption_index)
|
||||
{
|
||||
detail::winapi::ResetEvent(detail::get_current_thread_data()->interruption_handle);
|
||||
winapi::ResetEvent(detail::get_current_thread_data()->interruption_handle);
|
||||
throw thread_interrupted();
|
||||
}
|
||||
#endif
|
||||
@@ -748,20 +693,21 @@ namespace boost
|
||||
}
|
||||
else
|
||||
{
|
||||
detail::win32::sleep(time_left.milliseconds);
|
||||
detail::win32::sleep(static_cast<unsigned long>(time_left_msec));
|
||||
}
|
||||
if(target_time.relative)
|
||||
|
||||
if(!using_timer && timeout != detail::internal_platform_timepoint::getMax())
|
||||
{
|
||||
target_time.milliseconds-=detail::timeout::max_non_infinite_wait;
|
||||
time_left_msec = (timeout - detail::internal_platform_clock::now()).getMs();
|
||||
}
|
||||
}
|
||||
while(time_left.more);
|
||||
while(time_left_msec == INFINITE || time_left_msec > 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace no_interruption_point
|
||||
{
|
||||
bool non_interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time)
|
||||
bool non_interruptible_wait(detail::win32::handle handle_to_wait_for, detail::internal_platform_timepoint const &timeout)
|
||||
{
|
||||
detail::win32::handle handles[3]={0};
|
||||
unsigned handle_count=0;
|
||||
@@ -777,16 +723,20 @@ namespace boost
|
||||
#ifndef UNDER_CE
|
||||
#if !BOOST_PLAT_WINDOWS_RUNTIME
|
||||
// Preferentially use coalescing timers for better power consumption and timer accuracy
|
||||
if(!target_time.is_sentinel())
|
||||
if(timeout != detail::internal_platform_timepoint::getMax())
|
||||
{
|
||||
detail::timeout::remaining_time const time_left=target_time.remaining_milliseconds();
|
||||
boost::intmax_t const time_left_msec = (timeout - detail::internal_platform_clock::now()).getMs();
|
||||
timer_handle=CreateWaitableTimer(NULL,false,NULL);
|
||||
if(timer_handle!=0)
|
||||
{
|
||||
ULONG tolerable=32; // Empirical testing shows Windows ignores this when <= 26
|
||||
if(time_left.milliseconds/20>tolerable) // 5%
|
||||
tolerable=time_left.milliseconds/20;
|
||||
LARGE_INTEGER due_time=get_due_time(target_time);
|
||||
if(time_left_msec/20>tolerable) // 5%
|
||||
tolerable=static_cast<ULONG>(time_left_msec/20);
|
||||
LARGE_INTEGER due_time={{0,0}};
|
||||
if(time_left_msec>0)
|
||||
{
|
||||
due_time.QuadPart=-(time_left_msec*10000); // negative indicates relative time
|
||||
}
|
||||
bool const set_time_succeeded=detail_::SetWaitableTimerEx()(timer_handle,&due_time,0,0,0,NULL,tolerable)!=0;
|
||||
if(set_time_succeeded)
|
||||
{
|
||||
@@ -799,18 +749,21 @@ namespace boost
|
||||
#endif
|
||||
|
||||
bool const using_timer=timeout_index!=~0u;
|
||||
detail::timeout::remaining_time time_left(0);
|
||||
boost::intmax_t time_left_msec(INFINITE);
|
||||
if(!using_timer && timeout != detail::internal_platform_timepoint::getMax())
|
||||
{
|
||||
time_left_msec = (timeout - detail::internal_platform_clock::now()).getMs();
|
||||
if(time_left_msec < 0)
|
||||
{
|
||||
time_left_msec = 0;
|
||||
}
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if(!using_timer)
|
||||
{
|
||||
time_left=target_time.remaining_milliseconds();
|
||||
}
|
||||
|
||||
if(handle_count)
|
||||
{
|
||||
unsigned long const notified_index=detail::winapi::WaitForMultipleObjectsEx(handle_count,handles,false,using_timer?INFINITE:time_left.milliseconds, 0);
|
||||
unsigned long const notified_index=winapi::WaitForMultipleObjectsEx(handle_count,handles,false,static_cast<DWORD>(time_left_msec), 0);
|
||||
if(notified_index<handle_count)
|
||||
{
|
||||
if(notified_index==wait_handle_index)
|
||||
@@ -825,14 +778,15 @@ namespace boost
|
||||
}
|
||||
else
|
||||
{
|
||||
detail::win32::sleep(time_left.milliseconds);
|
||||
detail::win32::sleep(static_cast<unsigned long>(time_left_msec));
|
||||
}
|
||||
if(target_time.relative)
|
||||
|
||||
if(!using_timer && timeout != detail::internal_platform_timepoint::getMax())
|
||||
{
|
||||
target_time.milliseconds-=detail::timeout::max_non_infinite_wait;
|
||||
time_left_msec = (timeout - detail::internal_platform_clock::now()).getMs();
|
||||
}
|
||||
}
|
||||
while(time_left.more);
|
||||
while(time_left_msec == INFINITE || time_left_msec > 0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -847,7 +801,7 @@ namespace boost
|
||||
return current_thread_data->id;
|
||||
}
|
||||
#endif
|
||||
return detail::winapi::GetCurrentThreadId();
|
||||
return winapi::GetCurrentThreadId();
|
||||
#else
|
||||
return thread::id(get_or_make_current_thread_data());
|
||||
#endif
|
||||
@@ -858,7 +812,7 @@ namespace boost
|
||||
{
|
||||
if(interruption_enabled() && interruption_requested())
|
||||
{
|
||||
detail::winapi::ResetEvent(detail::get_current_thread_data()->interruption_handle);
|
||||
winapi::ResetEvent(detail::get_current_thread_data()->interruption_handle);
|
||||
throw thread_interrupted();
|
||||
}
|
||||
}
|
||||
@@ -870,7 +824,7 @@ namespace boost
|
||||
|
||||
bool interruption_requested() BOOST_NOEXCEPT
|
||||
{
|
||||
return detail::get_current_thread_data() && (detail::winapi::WaitForSingleObjectEx(detail::get_current_thread_data()->interruption_handle,0,0)==0);
|
||||
return detail::get_current_thread_data() && (winapi::WaitForSingleObjectEx(detail::get_current_thread_data()->interruption_handle,0,0)==0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
140
src/win32/thread_primitives.cpp
Normal file
140
src/win32/thread_primitives.cpp
Normal file
@@ -0,0 +1,140 @@
|
||||
// thread_primitives.cpp
|
||||
//
|
||||
// (C) Copyright 2018 Andrey Semashev
|
||||
//
|
||||
// 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/winapi/config.hpp>
|
||||
#include <boost/winapi/dll.hpp>
|
||||
#include <boost/winapi/time.hpp>
|
||||
#include <boost/winapi/event.hpp>
|
||||
#include <boost/winapi/handles.hpp>
|
||||
#include <boost/winapi/thread_pool.hpp>
|
||||
#include <cstdlib>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/memory_order.hpp>
|
||||
#include <boost/atomic/atomic.hpp>
|
||||
#include <boost/thread/win32/interlocked_read.hpp>
|
||||
#include <boost/thread/win32/thread_primitives.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace detail {
|
||||
namespace win32 {
|
||||
|
||||
#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
|
||||
|
||||
// Directly use API from Vista and later
|
||||
BOOST_THREAD_DECL boost::detail::win32::detail::gettickcount64_t gettickcount64 = &::boost::winapi::GetTickCount64;
|
||||
|
||||
#else // BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
|
||||
|
||||
namespace {
|
||||
|
||||
enum init_state
|
||||
{
|
||||
uninitialized = 0,
|
||||
in_progress,
|
||||
initialized
|
||||
};
|
||||
|
||||
struct get_tick_count64_state
|
||||
{
|
||||
boost::atomic< uint64_t > ticks;
|
||||
boost::atomic< init_state > init;
|
||||
boost::winapi::HANDLE_ wait_event;
|
||||
boost::winapi::HANDLE_ wait_handle;
|
||||
};
|
||||
|
||||
// Zero-initialized initially
|
||||
BOOST_ALIGNMENT(64) static get_tick_count64_state g_state;
|
||||
|
||||
//! Artifical implementation of GetTickCount64
|
||||
ticks_type WINAPI get_tick_count64()
|
||||
{
|
||||
uint64_t old_state = g_state.ticks.load(boost::memory_order_acquire);
|
||||
|
||||
uint32_t new_ticks = boost::winapi::GetTickCount();
|
||||
|
||||
uint32_t old_ticks = static_cast< uint32_t >(old_state & UINT64_C(0x00000000ffffffff));
|
||||
uint64_t new_state = ((old_state & UINT64_C(0xffffffff00000000)) + (static_cast< uint64_t >(new_ticks < old_ticks) << 32)) | static_cast< uint64_t >(new_ticks);
|
||||
|
||||
g_state.ticks.store(new_state, boost::memory_order_release);
|
||||
|
||||
return new_state;
|
||||
}
|
||||
|
||||
//! The function is called periodically in the system thread pool to make sure g_state.ticks is timely updated
|
||||
void NTAPI refresh_get_tick_count64(boost::winapi::PVOID_, boost::winapi::BOOLEAN_)
|
||||
{
|
||||
get_tick_count64();
|
||||
}
|
||||
|
||||
//! Cleanup function to stop get_tick_count64 refreshes
|
||||
void cleanup_get_tick_count64()
|
||||
{
|
||||
if (g_state.wait_handle)
|
||||
{
|
||||
boost::winapi::UnregisterWait(g_state.wait_handle);
|
||||
g_state.wait_handle = NULL;
|
||||
}
|
||||
|
||||
if (g_state.wait_event)
|
||||
{
|
||||
boost::winapi::CloseHandle(g_state.wait_event);
|
||||
g_state.wait_event = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ticks_type WINAPI get_tick_count_init()
|
||||
{
|
||||
boost::winapi::HMODULE_ hKernel32 = boost::winapi::GetModuleHandleW(L"kernel32.dll");
|
||||
if (hKernel32)
|
||||
{
|
||||
boost::detail::win32::detail::gettickcount64_t p =
|
||||
(boost::detail::win32::detail::gettickcount64_t)boost::winapi::get_proc_address(hKernel32, "GetTickCount64");
|
||||
if (p)
|
||||
{
|
||||
// Use native API
|
||||
boost::detail::interlocked_write_release((void**)&gettickcount64, (void*)p);
|
||||
return p();
|
||||
}
|
||||
}
|
||||
|
||||
// No native API available. Use emulation with periodic refreshes to make sure the GetTickCount wrap arounds are properly counted.
|
||||
init_state old_init = uninitialized;
|
||||
if (g_state.init.compare_exchange_strong(old_init, in_progress, boost::memory_order_acq_rel, boost::memory_order_relaxed))
|
||||
{
|
||||
if (!g_state.wait_event)
|
||||
g_state.wait_event = boost::winapi::create_anonymous_event(NULL, false, false);
|
||||
if (g_state.wait_event)
|
||||
{
|
||||
boost::winapi::BOOL_ res = boost::winapi::RegisterWaitForSingleObject(&g_state.wait_handle, g_state.wait_event, &refresh_get_tick_count64, NULL, 0x7fffffff, boost::winapi::WT_EXECUTEINWAITTHREAD_);
|
||||
if (res)
|
||||
{
|
||||
std::atexit(&cleanup_get_tick_count64);
|
||||
|
||||
boost::detail::interlocked_write_release((void**)&gettickcount64, (void*)&get_tick_count64);
|
||||
g_state.init.store(initialized, boost::memory_order_release);
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
|
||||
g_state.init.store(uninitialized, boost::memory_order_release);
|
||||
}
|
||||
|
||||
finish:
|
||||
return get_tick_count64();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
BOOST_THREAD_DECL boost::detail::win32::detail::gettickcount64_t gettickcount64 = &get_tick_count_init;
|
||||
|
||||
#endif // BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
|
||||
|
||||
} // namespace win32
|
||||
} // namespace detail
|
||||
} // namespace boost
|
||||
@@ -3,7 +3,7 @@
|
||||
// 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/winapi/config.hpp>
|
||||
#include <boost/winapi/config.hpp>
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
// 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/winapi/config.hpp>
|
||||
#include <boost/winapi/config.hpp>
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB)
|
||||
|
||||
@@ -325,6 +325,7 @@ rule thread-compile ( sources : reqs * : name )
|
||||
[ thread-run2-noit ./sync/conditions/condition_variable/wait_for_pred_pass.cpp : condition_variable__wait_for_pred_p ]
|
||||
[ thread-run2-noit ./sync/conditions/condition_variable/wait_until_pass.cpp : condition_variable__wait_until_p ]
|
||||
[ thread-run2-noit ./sync/conditions/condition_variable/wait_until_pred_pass.cpp : condition_variable__wait_until_pred_p ]
|
||||
[ thread-run2-noit ./sync/conditions/condition_variable/lost_notif_pass.cpp : condition_variable__lost_notif_p ]
|
||||
|
||||
[ thread-compile-fail ./sync/conditions/condition_variable_any/assign_fail.cpp : : condition_variable_any__assign_f ]
|
||||
[ thread-compile-fail ./sync/conditions/condition_variable_any/copy_fail.cpp : : condition_variable_any__copy_f ]
|
||||
@@ -334,6 +335,7 @@ rule thread-compile ( sources : reqs * : name )
|
||||
[ thread-run2-noit ./sync/conditions/condition_variable_any/wait_for_pred_pass.cpp : condition_variable_any__wait_for_pred_p ]
|
||||
[ thread-run2-noit ./sync/conditions/condition_variable_any/wait_until_pass.cpp : condition_variable_any__wait_until_p ]
|
||||
[ thread-run2-noit ./sync/conditions/condition_variable_any/wait_until_pred_pass.cpp : condition_variable_any__wait_until_pred_p ]
|
||||
[ thread-run2-noit ./sync/conditions/condition_variable_any/lost_notif_pass.cpp : condition_variable_any__lost_notif_p ]
|
||||
[ thread-run2-noit ./sync/conditions/cv_status/cv_status_pass.cpp : cv_status__cv_status_p ]
|
||||
[ thread-run2-noit ./sync/conditions/notify_all_at_thread_exit_pass.cpp : notify_all_at_thread_exit_p ]
|
||||
;
|
||||
@@ -972,5 +974,39 @@ rule thread-compile ( sources : reqs * : name )
|
||||
|
||||
;
|
||||
|
||||
explicit test_time_jumps_1_obj ;
|
||||
obj test_time_jumps_1_obj : test_time_jumps.cpp :
|
||||
# BOOST_THREAD_USES_MOVE is required to prevent ambiguity between the two definitions
|
||||
# of boost::move when using sync_priority_queue/sync_timed_queue with POD data types.
|
||||
<define>BOOST_THREAD_USES_MOVE
|
||||
<define>BOOST_THREAD_PROVIDES_FUTURE
|
||||
;
|
||||
|
||||
explicit test_time_jumps_2_obj ;
|
||||
obj test_time_jumps_2_obj : test_time_jumps.cpp :
|
||||
# BOOST_THREAD_USES_MOVE is required to prevent ambiguity between the two definitions
|
||||
# of boost::move when using sync_priority_queue/sync_timed_queue with POD data types.
|
||||
<define>BOOST_THREAD_USES_MOVE
|
||||
<define>BOOST_THREAD_PROVIDES_FUTURE
|
||||
<define>BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
|
||||
;
|
||||
|
||||
explicit test_time_jumps_3_obj ;
|
||||
obj test_time_jumps_3_obj : test_time_jumps.cpp :
|
||||
# BOOST_THREAD_USES_MOVE is required to prevent ambiguity between the two definitions
|
||||
# of boost::move when using sync_priority_queue/sync_timed_queue with POD data types.
|
||||
<define>BOOST_THREAD_USES_MOVE
|
||||
<define>BOOST_THREAD_PROVIDES_FUTURE
|
||||
<define>BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
|
||||
<define>BOOST_THREAD_V2_SHARED_MUTEX
|
||||
;
|
||||
|
||||
explicit test_time_jumps ;
|
||||
test-suite test_time_jumps
|
||||
:
|
||||
[ exe test_time_jumps_1 : test_time_jumps_1_obj ../build//boost_thread ]
|
||||
[ exe test_time_jumps_2 : test_time_jumps_2_obj ../build//boost_thread ]
|
||||
[ exe test_time_jumps_3 : test_time_jumps_3_obj ../build//boost_thread ]
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
241
test/sync/conditions/condition_variable/lost_notif_pass.cpp
Normal file
241
test/sync/conditions/condition_variable/lost_notif_pass.cpp
Normal file
@@ -0,0 +1,241 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Copyright (C) 2017 Austin J. Beer
|
||||
//
|
||||
// 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/condition_variable>
|
||||
|
||||
// class condition_variable;
|
||||
|
||||
// condition_variable(const condition_variable&) = delete;
|
||||
|
||||
#include <iostream>
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <cassert>
|
||||
|
||||
// Summary of each test:
|
||||
// 1. Start the test thread and wait for it to start up.
|
||||
// The test thread waits for the flag to be set using a large timeout.
|
||||
// 2. The main thread takes the lock and then sleeps for a long time while holding
|
||||
// the lock before setting the flag and calling notify_one(). If the wait
|
||||
// function being tested is polling pthread_cond_timedwait() internally, any
|
||||
// notifications sent after pthread_cond_timedwait() times out but before it can
|
||||
// reacquire the lock may be "lost". pthread_cond_timedwait() will report that
|
||||
// it timed out and the wait function may incorrectly assume that no
|
||||
// notification was received. This test ensures that that doesn't happen.
|
||||
// 3. Measure how it takes the test thread to return. If it received the
|
||||
// notification, it will return fairly quickly. If it missed the notification,
|
||||
// the test thread won't return until the wait function being tested times out.
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
boost::condition_variable cv;
|
||||
boost::mutex mut;
|
||||
|
||||
bool flag;
|
||||
bool waiting;
|
||||
|
||||
bool flagIsSet()
|
||||
{
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool threadIsWaiting()
|
||||
{
|
||||
return waiting;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifdef BOOST_THREAD_USES_DATETIME
|
||||
|
||||
boost::posix_time::milliseconds posix_wait_time(1000);
|
||||
|
||||
template <typename F>
|
||||
void test_posix_wait_function(F f)
|
||||
{
|
||||
flag = false;
|
||||
waiting = false;
|
||||
boost::thread t(f);
|
||||
while (!threadIsWaiting())
|
||||
{
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(1));
|
||||
}
|
||||
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(500));
|
||||
boost::posix_time::ptime t0 = boost::posix_time::microsec_clock::universal_time();
|
||||
flag = true;
|
||||
cv.notify_one();
|
||||
lk.unlock();
|
||||
t.join();
|
||||
boost::posix_time::ptime t1 = boost::posix_time::microsec_clock::universal_time();
|
||||
|
||||
BOOST_TEST(t1 - t0 < boost::posix_time::milliseconds(250));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void timed_wait_absolute_without_pred()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
waiting = true;
|
||||
while (!flagIsSet())
|
||||
{
|
||||
cv.timed_wait(lk, boost::posix_time::microsec_clock::universal_time() + posix_wait_time);
|
||||
}
|
||||
}
|
||||
|
||||
void timed_wait_absolute_with_pred()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
waiting = true;
|
||||
cv.timed_wait(lk, boost::posix_time::microsec_clock::universal_time() + posix_wait_time, flagIsSet);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void timed_wait_relative_without_pred()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
waiting = true;
|
||||
while (!flagIsSet())
|
||||
{
|
||||
cv.timed_wait(lk, posix_wait_time);
|
||||
}
|
||||
}
|
||||
|
||||
void timed_wait_relative_with_pred()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
waiting = true;
|
||||
cv.timed_wait(lk, posix_wait_time, flagIsSet);
|
||||
}
|
||||
|
||||
#else
|
||||
#error "Test not applicable: BOOST_THREAD_USES_DATETIME not defined for this platform as not supported"
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
|
||||
boost::chrono::milliseconds chrono_wait_time(1000);
|
||||
|
||||
template <typename F>
|
||||
void test_chrono_wait_function(F f)
|
||||
{
|
||||
flag = false;
|
||||
waiting = false;
|
||||
boost::thread t(f);
|
||||
while (!threadIsWaiting())
|
||||
{
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(1));
|
||||
}
|
||||
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
|
||||
boost::chrono::steady_clock::time_point t0 = boost::chrono::steady_clock::now();
|
||||
flag = true;
|
||||
cv.notify_one();
|
||||
lk.unlock();
|
||||
t.join();
|
||||
boost::chrono::steady_clock::time_point t1 = boost::chrono::steady_clock::now();
|
||||
|
||||
BOOST_TEST(t1 - t0 < boost::chrono::milliseconds(250));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void wait_until_system_without_pred()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
waiting = true;
|
||||
while (!flagIsSet())
|
||||
{
|
||||
cv.wait_until(lk, boost::chrono::system_clock::now() + chrono_wait_time);
|
||||
}
|
||||
}
|
||||
|
||||
void wait_until_system_with_pred()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
waiting = true;
|
||||
cv.wait_until(lk, boost::chrono::system_clock::now() + chrono_wait_time, flagIsSet);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void wait_until_steady_without_pred()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
waiting = true;
|
||||
while (!flagIsSet())
|
||||
{
|
||||
cv.wait_until(lk, boost::chrono::steady_clock::now() + chrono_wait_time);
|
||||
}
|
||||
}
|
||||
|
||||
void wait_until_steady_with_pred()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
waiting = true;
|
||||
cv.wait_until(lk, boost::chrono::steady_clock::now() + chrono_wait_time, flagIsSet);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void wait_for_without_pred()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
waiting = true;
|
||||
while (!flagIsSet())
|
||||
{
|
||||
cv.wait_for(lk, chrono_wait_time);
|
||||
}
|
||||
}
|
||||
|
||||
void wait_for_with_pred()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
waiting = true;
|
||||
cv.wait_for(lk, chrono_wait_time, flagIsSet);
|
||||
}
|
||||
|
||||
#else
|
||||
#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported"
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifdef BOOST_THREAD_USES_DATETIME
|
||||
test_posix_wait_function(timed_wait_absolute_without_pred);
|
||||
test_posix_wait_function(timed_wait_absolute_with_pred);
|
||||
test_posix_wait_function(timed_wait_relative_without_pred);
|
||||
test_posix_wait_function(timed_wait_relative_with_pred);
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
test_chrono_wait_function(wait_until_system_without_pred);
|
||||
test_chrono_wait_function(wait_until_system_with_pred);
|
||||
test_chrono_wait_function(wait_until_steady_without_pred);
|
||||
test_chrono_wait_function(wait_until_steady_with_pred);
|
||||
test_chrono_wait_function(wait_for_without_pred);
|
||||
test_chrono_wait_function(wait_for_with_pred);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -34,29 +34,38 @@ int test2 = 0;
|
||||
|
||||
int runs = 0;
|
||||
|
||||
typedef boost::chrono::steady_clock Clock;
|
||||
typedef boost::chrono::milliseconds milliseconds;
|
||||
typedef boost::chrono::nanoseconds nanoseconds;
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const milliseconds max_diff(250);
|
||||
#else
|
||||
const milliseconds max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
try {
|
||||
typedef boost::chrono::steady_clock Clock;
|
||||
typedef boost::chrono::milliseconds milliseconds;
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
assert(test2 == 0);
|
||||
test1 = 1;
|
||||
cv.notify_one();
|
||||
Clock::time_point t0 = Clock::now();
|
||||
int count=0;
|
||||
while (test2 == 0 && cv.wait_for(lk, milliseconds(250)) == boost::cv_status::no_timeout)
|
||||
count++;
|
||||
Clock::time_point t = t0 + milliseconds(250);
|
||||
while (test2 == 0 && cv.wait_for(lk, t - Clock::now()) == boost::cv_status::no_timeout) {}
|
||||
Clock::time_point t1 = Clock::now();
|
||||
if (runs == 0)
|
||||
{
|
||||
assert(t1 - t0 < milliseconds(250));
|
||||
assert(t1 - t0 < max_diff);
|
||||
assert(test2 != 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
assert(t1 - t0 - milliseconds(250) < milliseconds(count*250+5+1000));
|
||||
nanoseconds d = t1 - t0 - milliseconds(250);
|
||||
std::cout << "diff= " << d.count() << std::endl;
|
||||
std::cout << "max_diff= " << max_diff.count() << std::endl;
|
||||
assert( d < max_diff);
|
||||
assert(test2 == 0);
|
||||
}
|
||||
++runs;
|
||||
|
||||
@@ -49,30 +49,33 @@ int test2 = 0;
|
||||
|
||||
int runs = 0;
|
||||
|
||||
typedef boost::chrono::system_clock Clock;
|
||||
typedef boost::chrono::milliseconds milliseconds;
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const milliseconds max_diff(250);
|
||||
#else
|
||||
const milliseconds max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
try {
|
||||
typedef boost::chrono::system_clock Clock;
|
||||
typedef boost::chrono::milliseconds milliseconds;
|
||||
boost::unique_lock < boost::mutex > lk(mut);
|
||||
assert(test2 == 0);
|
||||
test1 = 1;
|
||||
cv.notify_one();
|
||||
Clock::time_point t0 = Clock::now();
|
||||
int count=0;
|
||||
//bool r =
|
||||
(void)cv.wait_for(lk, milliseconds(250), Pred(test2));
|
||||
count++;
|
||||
cv.wait_for(lk, milliseconds(250), Pred(test2));
|
||||
Clock::time_point t1 = Clock::now();
|
||||
if (runs == 0)
|
||||
{
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
assert(t1 - t0 < milliseconds(250+1000));
|
||||
assert(t1 - t0 < max_diff);
|
||||
assert(test2 != 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(t1 - t0 - milliseconds(250) < milliseconds(count*250+2));
|
||||
assert(t1 - t0 - milliseconds(250) < max_diff);
|
||||
assert(test2 == 0);
|
||||
}
|
||||
++runs;
|
||||
|
||||
@@ -49,6 +49,12 @@ int test2 = 0;
|
||||
|
||||
int runs = 0;
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const Clock::duration max_diff(250);
|
||||
#else
|
||||
const Clock::duration max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
try {
|
||||
@@ -58,19 +64,16 @@ void f()
|
||||
cv.notify_one();
|
||||
Clock::time_point t0 = Clock::now();
|
||||
Clock::time_point t = t0 + Clock::duration(250);
|
||||
int count=0;
|
||||
while (test2 == 0 && cv.wait_until(lk, t) == boost::cv_status::no_timeout)
|
||||
count++;
|
||||
while (test2 == 0 && cv.wait_until(lk, t) == boost::cv_status::no_timeout) {}
|
||||
Clock::time_point t1 = Clock::now();
|
||||
if (runs == 0)
|
||||
{
|
||||
assert(t1 - t0 < Clock::duration(250));
|
||||
assert(t1 - t0 < max_diff);
|
||||
assert(test2 != 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
assert(t1 - t0 - Clock::duration(250) < Clock::duration(count*250+5+1000));
|
||||
assert(t1 - t0 - Clock::duration(250) < max_diff);
|
||||
assert(test2 == 0);
|
||||
}
|
||||
++runs;
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include <iostream>
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
typedef boost::chrono::milliseconds milliseconds;
|
||||
typedef boost::chrono::nanoseconds nanoseconds;
|
||||
|
||||
struct Clock
|
||||
{
|
||||
@@ -64,6 +66,12 @@ int test2 = 0;
|
||||
|
||||
int runs = 0;
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const Clock::duration max_diff(250);
|
||||
#else
|
||||
const Clock::duration max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
try {
|
||||
@@ -74,17 +82,19 @@ void f()
|
||||
Clock::time_point t0 = Clock::now();
|
||||
Clock::time_point t = t0 + Clock::duration(250);
|
||||
bool r = cv.wait_until(lk, t, Pred(test2));
|
||||
(void)r;
|
||||
Clock::time_point t1 = Clock::now();
|
||||
if (runs == 0)
|
||||
{
|
||||
assert(t1 - t0 < Clock::duration(250));
|
||||
assert(t1 - t0 < max_diff);
|
||||
assert(test2 != 0);
|
||||
assert(r);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(t1 - t0 - Clock::duration(250) < Clock::duration(250+2));
|
||||
const nanoseconds d = t1 - t0 - milliseconds(250);
|
||||
std::cout << "diff= " << d.count() << std::endl;
|
||||
std::cout << "max_diff= " << max_diff.count() << std::endl;
|
||||
assert(d < max_diff);
|
||||
assert(test2 == 0);
|
||||
assert(!r);
|
||||
}
|
||||
|
||||
241
test/sync/conditions/condition_variable_any/lost_notif_pass.cpp
Normal file
241
test/sync/conditions/condition_variable_any/lost_notif_pass.cpp
Normal file
@@ -0,0 +1,241 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Copyright (C) 2017 Austin J. Beer
|
||||
//
|
||||
// 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/condition_variable>
|
||||
|
||||
// class condition_variable;
|
||||
|
||||
// condition_variable(const condition_variable&) = delete;
|
||||
|
||||
#include <iostream>
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <cassert>
|
||||
|
||||
// Summary of each test:
|
||||
// 1. Start the test thread and wait for it to start up.
|
||||
// The test thread waits for the flag to be set using a large timeout.
|
||||
// 2. The main thread takes the lock and then sleeps for a long time while holding
|
||||
// the lock before setting the flag and calling notify_one(). If the wait
|
||||
// function being tested is polling pthread_cond_timedwait() internally, any
|
||||
// notifications sent after pthread_cond_timedwait() times out but before it can
|
||||
// reacquire the lock may be "lost". pthread_cond_timedwait() will report that
|
||||
// it timed out and the wait function may incorrectly assume that no
|
||||
// notification was received. This test ensures that that doesn't happen.
|
||||
// 3. Measure how it takes the test thread to return. If it received the
|
||||
// notification, it will return fairly quickly. If it missed the notification,
|
||||
// the test thread won't return until the wait function being tested times out.
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
boost::condition_variable_any cv;
|
||||
boost::mutex mut;
|
||||
|
||||
bool flag;
|
||||
bool waiting;
|
||||
|
||||
bool flagIsSet()
|
||||
{
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool threadIsWaiting()
|
||||
{
|
||||
return waiting;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifdef BOOST_THREAD_USES_DATETIME
|
||||
|
||||
boost::posix_time::milliseconds posix_wait_time(1000);
|
||||
|
||||
template <typename F>
|
||||
void test_posix_wait_function(F f)
|
||||
{
|
||||
flag = false;
|
||||
waiting = false;
|
||||
boost::thread t(f);
|
||||
while (!threadIsWaiting())
|
||||
{
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(1));
|
||||
}
|
||||
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(500));
|
||||
boost::posix_time::ptime t0 = boost::posix_time::microsec_clock::universal_time();
|
||||
flag = true;
|
||||
cv.notify_one();
|
||||
lk.unlock();
|
||||
t.join();
|
||||
boost::posix_time::ptime t1 = boost::posix_time::microsec_clock::universal_time();
|
||||
|
||||
BOOST_TEST(t1 - t0 < boost::posix_time::milliseconds(250));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void timed_wait_absolute_without_pred()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
waiting = true;
|
||||
while (!flagIsSet())
|
||||
{
|
||||
cv.timed_wait(lk, boost::posix_time::microsec_clock::universal_time() + posix_wait_time);
|
||||
}
|
||||
}
|
||||
|
||||
void timed_wait_absolute_with_pred()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
waiting = true;
|
||||
cv.timed_wait(lk, boost::posix_time::microsec_clock::universal_time() + posix_wait_time, flagIsSet);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void timed_wait_relative_without_pred()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
waiting = true;
|
||||
while (!flagIsSet())
|
||||
{
|
||||
cv.timed_wait(lk, posix_wait_time);
|
||||
}
|
||||
}
|
||||
|
||||
void timed_wait_relative_with_pred()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
waiting = true;
|
||||
cv.timed_wait(lk, posix_wait_time, flagIsSet);
|
||||
}
|
||||
|
||||
#else
|
||||
#error "Test not applicable: BOOST_THREAD_USES_DATETIME not defined for this platform as not supported"
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
|
||||
boost::chrono::milliseconds chrono_wait_time(1000);
|
||||
|
||||
template <typename F>
|
||||
void test_chrono_wait_function(F f)
|
||||
{
|
||||
flag = false;
|
||||
waiting = false;
|
||||
boost::thread t(f);
|
||||
while (!threadIsWaiting())
|
||||
{
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(1));
|
||||
}
|
||||
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
|
||||
boost::chrono::steady_clock::time_point t0 = boost::chrono::steady_clock::now();
|
||||
flag = true;
|
||||
cv.notify_one();
|
||||
lk.unlock();
|
||||
t.join();
|
||||
boost::chrono::steady_clock::time_point t1 = boost::chrono::steady_clock::now();
|
||||
|
||||
BOOST_TEST(t1 - t0 < boost::chrono::milliseconds(250));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void wait_until_system_without_pred()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
waiting = true;
|
||||
while (!flagIsSet())
|
||||
{
|
||||
cv.wait_until(lk, boost::chrono::system_clock::now() + chrono_wait_time);
|
||||
}
|
||||
}
|
||||
|
||||
void wait_until_system_with_pred()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
waiting = true;
|
||||
cv.wait_until(lk, boost::chrono::system_clock::now() + chrono_wait_time, flagIsSet);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void wait_until_steady_without_pred()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
waiting = true;
|
||||
while (!flagIsSet())
|
||||
{
|
||||
cv.wait_until(lk, boost::chrono::steady_clock::now() + chrono_wait_time);
|
||||
}
|
||||
}
|
||||
|
||||
void wait_until_steady_with_pred()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
waiting = true;
|
||||
cv.wait_until(lk, boost::chrono::steady_clock::now() + chrono_wait_time, flagIsSet);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void wait_for_without_pred()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
waiting = true;
|
||||
while (!flagIsSet())
|
||||
{
|
||||
cv.wait_for(lk, chrono_wait_time);
|
||||
}
|
||||
}
|
||||
|
||||
void wait_for_with_pred()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
waiting = true;
|
||||
cv.wait_for(lk, chrono_wait_time, flagIsSet);
|
||||
}
|
||||
|
||||
#else
|
||||
#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported"
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifdef BOOST_THREAD_USES_DATETIME
|
||||
test_posix_wait_function(timed_wait_absolute_without_pred);
|
||||
test_posix_wait_function(timed_wait_absolute_with_pred);
|
||||
test_posix_wait_function(timed_wait_relative_without_pred);
|
||||
test_posix_wait_function(timed_wait_relative_with_pred);
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
test_chrono_wait_function(wait_until_system_without_pred);
|
||||
test_chrono_wait_function(wait_until_system_with_pred);
|
||||
test_chrono_wait_function(wait_until_steady_without_pred);
|
||||
test_chrono_wait_function(wait_until_steady_with_pred);
|
||||
test_chrono_wait_function(wait_for_without_pred);
|
||||
test_chrono_wait_function(wait_for_with_pred);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -36,29 +36,33 @@ int test2 = 0;
|
||||
|
||||
int runs = 0;
|
||||
|
||||
typedef boost::chrono::system_clock Clock;
|
||||
typedef boost::chrono::milliseconds milliseconds;
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const milliseconds max_diff(250);
|
||||
#else
|
||||
const milliseconds max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
typedef boost::chrono::system_clock Clock;
|
||||
typedef boost::chrono::milliseconds milliseconds;
|
||||
L1 lk(m0);
|
||||
BOOST_TEST(test2 == 0);
|
||||
test1 = 1;
|
||||
cv.notify_one();
|
||||
int count=0;
|
||||
Clock::time_point t0 = Clock::now();
|
||||
while (test2 == 0 &&
|
||||
cv.wait_for(lk, milliseconds(250)) == boost::cv_status::no_timeout)
|
||||
count++;
|
||||
Clock::time_point t = t0 + milliseconds(250);
|
||||
while (test2 == 0 && cv.wait_for(lk, t - Clock::now()) == boost::cv_status::no_timeout) {}
|
||||
Clock::time_point t1 = Clock::now();
|
||||
if (runs == 0)
|
||||
{
|
||||
BOOST_TEST(t1 - t0 < milliseconds(250));
|
||||
BOOST_TEST(t1 - t0 < max_diff);
|
||||
BOOST_TEST(test2 != 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(t1 - t0 - milliseconds(250) < milliseconds(count*250+5+1000));
|
||||
BOOST_TEST(t1 - t0 - milliseconds(250) < max_diff);
|
||||
BOOST_TEST(test2 == 0);
|
||||
}
|
||||
++runs;
|
||||
|
||||
@@ -51,26 +51,32 @@ int test2 = 0;
|
||||
|
||||
int runs = 0;
|
||||
|
||||
typedef boost::chrono::system_clock Clock;
|
||||
typedef boost::chrono::milliseconds milliseconds;
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const milliseconds max_diff(250);
|
||||
#else
|
||||
const milliseconds max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
typedef boost::chrono::system_clock Clock;
|
||||
typedef boost::chrono::milliseconds milliseconds;
|
||||
L1 lk(m0);
|
||||
BOOST_TEST(test2 == 0);
|
||||
test1 = 1;
|
||||
cv.notify_one();
|
||||
Clock::time_point t0 = Clock::now();
|
||||
//bool r =
|
||||
(void)cv.wait_for(lk, milliseconds(250), Pred(test2));
|
||||
cv.wait_for(lk, milliseconds(250), Pred(test2));
|
||||
Clock::time_point t1 = Clock::now();
|
||||
if (runs == 0)
|
||||
{
|
||||
BOOST_TEST(t1 - t0 < milliseconds(250));
|
||||
BOOST_TEST(t1 - t0 < max_diff);
|
||||
BOOST_TEST(test2 != 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_TEST(t1 - t0 - milliseconds(250) < milliseconds(250+5));
|
||||
BOOST_TEST(t1 - t0 - milliseconds(250) < max_diff);
|
||||
BOOST_TEST(test2 == 0);
|
||||
}
|
||||
++runs;
|
||||
|
||||
@@ -51,6 +51,12 @@ int test2 = 0;
|
||||
|
||||
int runs = 0;
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const Clock::duration max_diff(250);
|
||||
#else
|
||||
const Clock::duration max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
L1 lk(m0);
|
||||
@@ -59,19 +65,16 @@ void f()
|
||||
cv.notify_one();
|
||||
Clock::time_point t0 = Clock::now();
|
||||
Clock::time_point t = t0 + Clock::duration(250);
|
||||
int count=0;
|
||||
while (test2 == 0 && cv.wait_until(lk, t) == boost::cv_status::no_timeout)
|
||||
count++;
|
||||
while (test2 == 0 && cv.wait_until(lk, t) == boost::cv_status::no_timeout) {}
|
||||
Clock::time_point t1 = Clock::now();
|
||||
if (runs == 0)
|
||||
{
|
||||
BOOST_TEST(t1 - t0 < Clock::duration(250));
|
||||
BOOST_TEST(t1 - t0 < max_diff);
|
||||
BOOST_TEST(test2 != 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(t1 - t0 - Clock::duration(250) < Clock::duration(250*count+5+1000));
|
||||
BOOST_TEST(t1 - t0 - Clock::duration(250) < max_diff);
|
||||
BOOST_TEST(test2 == 0);
|
||||
}
|
||||
++runs;
|
||||
|
||||
@@ -66,6 +66,12 @@ int test2 = 0;
|
||||
|
||||
int runs = 0;
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const Clock::duration max_diff(250);
|
||||
#else
|
||||
const Clock::duration max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
L1 lk(m0);
|
||||
@@ -78,13 +84,13 @@ void f()
|
||||
Clock::time_point t1 = Clock::now();
|
||||
if (runs == 0)
|
||||
{
|
||||
BOOST_TEST(t1 - t0 < Clock::duration(250));
|
||||
BOOST_TEST(t1 - t0 < max_diff);
|
||||
BOOST_TEST(test2 != 0);
|
||||
BOOST_TEST(r);
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_TEST(t1 - t0 - Clock::duration(250) < Clock::duration(250+2));
|
||||
BOOST_TEST(t1 - t0 - Clock::duration(250) < max_diff);
|
||||
BOOST_TEST(test2 == 0);
|
||||
BOOST_TEST(!r);
|
||||
}
|
||||
|
||||
@@ -85,6 +85,12 @@ void func5(boost::promise<void> p)
|
||||
p.set_value();
|
||||
}
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
@@ -98,19 +104,19 @@ int main()
|
||||
boost::thread(func1, boost::move(p)).detach();
|
||||
#endif
|
||||
BOOST_TEST(f.valid());
|
||||
BOOST_TEST_EQ(f.wait_for(ms(300)) , boost::future_status::timeout);
|
||||
BOOST_TEST_EQ(f.wait_for(ms(250)) , boost::future_status::timeout);
|
||||
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
#else
|
||||
func1(boost::move(p));
|
||||
#endif
|
||||
BOOST_TEST(f.valid());
|
||||
BOOST_TEST_EQ(f.wait_for(ms(300)) , boost::future_status::ready);
|
||||
BOOST_TEST_EQ(f.wait_for(ms(750)) , boost::future_status::ready);
|
||||
BOOST_TEST(f.valid());
|
||||
Clock::time_point t0 = Clock::now();
|
||||
f.wait();
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(f.valid());
|
||||
BOOST_TEST(t1 - t0 < ms(50));
|
||||
BOOST_TEST(t1 - t0 < max_diff);
|
||||
}
|
||||
{
|
||||
typedef int& T;
|
||||
@@ -120,19 +126,19 @@ int main()
|
||||
boost::thread(func3, boost::move(p)).detach();
|
||||
#endif
|
||||
BOOST_TEST(f.valid());
|
||||
BOOST_TEST_EQ(f.wait_for(ms(300)) , boost::future_status::timeout);
|
||||
BOOST_TEST_EQ(f.wait_for(ms(250)) , boost::future_status::timeout);
|
||||
BOOST_TEST(f.valid());
|
||||
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
#else
|
||||
func3(boost::move(p));
|
||||
#endif
|
||||
BOOST_TEST_EQ(f.wait_for(ms(300)) , boost::future_status::ready);
|
||||
BOOST_TEST_EQ(f.wait_for(ms(750)) , boost::future_status::ready);
|
||||
BOOST_TEST(f.valid());
|
||||
Clock::time_point t0 = Clock::now();
|
||||
f.wait();
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(f.valid());
|
||||
BOOST_TEST(t1 - t0 < ms(50));
|
||||
BOOST_TEST(t1 - t0 < max_diff);
|
||||
}
|
||||
{
|
||||
typedef void T;
|
||||
@@ -142,19 +148,19 @@ int main()
|
||||
boost::thread(func5, boost::move(p)).detach();
|
||||
#endif
|
||||
BOOST_TEST(f.valid());
|
||||
BOOST_TEST_EQ(f.wait_for(ms(300)) , boost::future_status::timeout);
|
||||
BOOST_TEST_EQ(f.wait_for(ms(250)) , boost::future_status::timeout);
|
||||
BOOST_TEST(f.valid());
|
||||
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
#else
|
||||
func5(boost::move(p));
|
||||
#endif
|
||||
BOOST_TEST_EQ(f.wait_for(ms(300)) , boost::future_status::ready);
|
||||
BOOST_TEST_EQ(f.wait_for(ms(750)) , boost::future_status::ready);
|
||||
BOOST_TEST(f.valid());
|
||||
Clock::time_point t0 = Clock::now();
|
||||
f.wait();
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(f.valid());
|
||||
BOOST_TEST(t1 - t0 < ms(50));
|
||||
BOOST_TEST(t1 - t0 < max_diff);
|
||||
}
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
|
||||
@@ -86,6 +86,12 @@ void func5(boost::promise<void> p)
|
||||
p.set_value();
|
||||
}
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
@@ -99,19 +105,19 @@ int main()
|
||||
boost::thread(func1, boost::move(p)).detach();
|
||||
#endif
|
||||
BOOST_TEST(f.valid());
|
||||
BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(300)) , boost::future_status::timeout);
|
||||
BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(250)) , boost::future_status::timeout);
|
||||
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
#else
|
||||
func1(boost::move(p));
|
||||
#endif
|
||||
BOOST_TEST(f.valid());
|
||||
BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(300)) , boost::future_status::ready);
|
||||
BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(750)) , boost::future_status::ready);
|
||||
BOOST_TEST(f.valid());
|
||||
Clock::time_point t0 = Clock::now();
|
||||
f.wait();
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(f.valid());
|
||||
BOOST_TEST(t1 - t0 < ms(50));
|
||||
BOOST_TEST(t1 - t0 < max_diff);
|
||||
}
|
||||
{
|
||||
typedef int& T;
|
||||
@@ -121,19 +127,19 @@ int main()
|
||||
boost::thread(func3, boost::move(p)).detach();
|
||||
#endif
|
||||
BOOST_TEST(f.valid());
|
||||
BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(300)) , boost::future_status::timeout);
|
||||
BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(250)) , boost::future_status::timeout);
|
||||
BOOST_TEST(f.valid());
|
||||
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
#else
|
||||
func3(boost::move(p));
|
||||
#endif
|
||||
BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(300)) , boost::future_status::ready);
|
||||
BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(750)) , boost::future_status::ready);
|
||||
BOOST_TEST(f.valid());
|
||||
Clock::time_point t0 = Clock::now();
|
||||
f.wait();
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(f.valid());
|
||||
BOOST_TEST(t1 - t0 < ms(50));
|
||||
BOOST_TEST(t1 - t0 < max_diff);
|
||||
}
|
||||
{
|
||||
typedef void T;
|
||||
@@ -143,19 +149,19 @@ int main()
|
||||
boost::thread(func5, boost::move(p)).detach();
|
||||
#endif
|
||||
BOOST_TEST(f.valid());
|
||||
BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(300)) , boost::future_status::timeout);
|
||||
BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(250)) , boost::future_status::timeout);
|
||||
BOOST_TEST(f.valid());
|
||||
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
#else
|
||||
func5(boost::move(p));
|
||||
#endif
|
||||
BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(300)) , boost::future_status::ready);
|
||||
BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(750)) , boost::future_status::ready);
|
||||
BOOST_TEST(f.valid());
|
||||
Clock::time_point t0 = Clock::now();
|
||||
f.wait();
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(f.valid());
|
||||
BOOST_TEST(t1 - t0 < ms(50));
|
||||
BOOST_TEST(t1 - t0 < max_diff);
|
||||
}
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
|
||||
@@ -85,6 +85,12 @@ void func5(boost::promise<void> p)
|
||||
p.set_value();
|
||||
}
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
@@ -98,19 +104,19 @@ int main()
|
||||
boost::thread(func1, boost::move(p)).detach();
|
||||
#endif
|
||||
BOOST_TEST(f.valid());
|
||||
BOOST_TEST_EQ(f.wait_for(ms(300)) , boost::future_status::timeout);
|
||||
BOOST_TEST_EQ(f.wait_for(ms(250)) , boost::future_status::timeout);
|
||||
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
#else
|
||||
func1(boost::move(p));
|
||||
#endif
|
||||
BOOST_TEST(f.valid());
|
||||
BOOST_TEST_EQ(f.wait_for(ms(300)) , boost::future_status::ready);
|
||||
BOOST_TEST_EQ(f.wait_for(ms(750)) , boost::future_status::ready);
|
||||
BOOST_TEST(f.valid());
|
||||
Clock::time_point t0 = Clock::now();
|
||||
f.wait();
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(f.valid());
|
||||
BOOST_TEST(t1 - t0 < ms(50));
|
||||
BOOST_TEST(t1 - t0 < max_diff);
|
||||
}
|
||||
{
|
||||
typedef int& T;
|
||||
@@ -120,19 +126,19 @@ int main()
|
||||
boost::thread(func3, boost::move(p)).detach();
|
||||
#endif
|
||||
BOOST_TEST(f.valid());
|
||||
BOOST_TEST_EQ(f.wait_for(ms(300)) , boost::future_status::timeout);
|
||||
BOOST_TEST_EQ(f.wait_for(ms(250)) , boost::future_status::timeout);
|
||||
BOOST_TEST(f.valid());
|
||||
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
#else
|
||||
func3(boost::move(p));
|
||||
#endif
|
||||
BOOST_TEST_EQ(f.wait_for(ms(300)) , boost::future_status::ready);
|
||||
BOOST_TEST_EQ(f.wait_for(ms(750)) , boost::future_status::ready);
|
||||
BOOST_TEST(f.valid());
|
||||
Clock::time_point t0 = Clock::now();
|
||||
f.wait();
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(f.valid());
|
||||
BOOST_TEST(t1 - t0 < ms(50));
|
||||
BOOST_TEST(t1 - t0 < max_diff);
|
||||
}
|
||||
{
|
||||
typedef void T;
|
||||
@@ -142,19 +148,19 @@ int main()
|
||||
boost::thread(func5, boost::move(p)).detach();
|
||||
#endif
|
||||
BOOST_TEST(f.valid());
|
||||
BOOST_TEST_EQ(f.wait_for(ms(300)) , boost::future_status::timeout);
|
||||
BOOST_TEST_EQ(f.wait_for(ms(250)) , boost::future_status::timeout);
|
||||
BOOST_TEST(f.valid());
|
||||
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
#else
|
||||
func5(boost::move(p));
|
||||
#endif
|
||||
BOOST_TEST_EQ(f.wait_for(ms(300)) , boost::future_status::ready);
|
||||
BOOST_TEST_EQ(f.wait_for(ms(750)) , boost::future_status::ready);
|
||||
BOOST_TEST(f.valid());
|
||||
Clock::time_point t0 = Clock::now();
|
||||
f.wait();
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(f.valid());
|
||||
BOOST_TEST(t1 - t0 < ms(50));
|
||||
BOOST_TEST(t1 - t0 < max_diff);
|
||||
}
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
|
||||
@@ -86,6 +86,12 @@ void func5(boost::promise<void> p)
|
||||
p.set_value();
|
||||
}
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
@@ -99,19 +105,19 @@ int main()
|
||||
boost::thread(func1, boost::move(p)).detach();
|
||||
#endif
|
||||
BOOST_TEST(f.valid());
|
||||
BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(300)) , boost::future_status::timeout);
|
||||
BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(250)) , boost::future_status::timeout);
|
||||
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
#else
|
||||
func1(boost::move(p));
|
||||
#endif
|
||||
BOOST_TEST(f.valid());
|
||||
BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(300)) , boost::future_status::ready);
|
||||
BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(750)) , boost::future_status::ready);
|
||||
BOOST_TEST(f.valid());
|
||||
Clock::time_point t0 = Clock::now();
|
||||
f.wait();
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(f.valid());
|
||||
BOOST_TEST(t1 - t0 < ms(50));
|
||||
BOOST_TEST(t1 - t0 < max_diff);
|
||||
}
|
||||
{
|
||||
typedef int& T;
|
||||
@@ -121,19 +127,19 @@ int main()
|
||||
boost::thread(func3, boost::move(p)).detach();
|
||||
#endif
|
||||
BOOST_TEST(f.valid());
|
||||
BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(300)) , boost::future_status::timeout);
|
||||
BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(250)) , boost::future_status::timeout);
|
||||
BOOST_TEST(f.valid());
|
||||
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
#else
|
||||
func3(boost::move(p));
|
||||
#endif
|
||||
BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(300)) , boost::future_status::ready);
|
||||
BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(750)) , boost::future_status::ready);
|
||||
BOOST_TEST(f.valid());
|
||||
Clock::time_point t0 = Clock::now();
|
||||
f.wait();
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(f.valid());
|
||||
BOOST_TEST(t1 - t0 < ms(50));
|
||||
BOOST_TEST(t1 - t0 < max_diff);
|
||||
}
|
||||
{
|
||||
typedef void T;
|
||||
@@ -143,19 +149,19 @@ int main()
|
||||
boost::thread(func5, boost::move(p)).detach();
|
||||
#endif
|
||||
BOOST_TEST(f.valid());
|
||||
BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(300)) , boost::future_status::timeout);
|
||||
BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(250)) , boost::future_status::timeout);
|
||||
BOOST_TEST(f.valid());
|
||||
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
#else
|
||||
func5(boost::move(p));
|
||||
#endif
|
||||
BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(300)) , boost::future_status::ready);
|
||||
BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(750)) , boost::future_status::ready);
|
||||
BOOST_TEST(f.valid());
|
||||
Clock::time_point t0 = Clock::now();
|
||||
f.wait();
|
||||
Clock::time_point t1 = Clock::now();
|
||||
BOOST_TEST(f.valid());
|
||||
BOOST_TEST(t1 - t0 < ms(50));
|
||||
BOOST_TEST(t1 - t0 < max_diff);
|
||||
}
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
|
||||
@@ -32,6 +32,12 @@ typedef boost::chrono::nanoseconds ns;
|
||||
#endif
|
||||
boost::mutex m;
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
@@ -43,7 +49,7 @@ void f()
|
||||
t1 = Clock::now();
|
||||
}
|
||||
ns d = t1 - t0 - ms(250);
|
||||
BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
//time_point t1;
|
||||
@@ -53,7 +59,7 @@ void f()
|
||||
//t1 = Clock::now();
|
||||
}
|
||||
//ns d = t1 - t0 - ms(250);
|
||||
//BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
//BOOST_TEST(d < max_diff);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,12 @@ typedef boost::chrono::nanoseconds ns;
|
||||
|
||||
boost::mutex m;
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
@@ -43,8 +49,7 @@ void f()
|
||||
t1 = Clock::now();
|
||||
}
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
//time_point t1;
|
||||
@@ -53,8 +58,7 @@ void f()
|
||||
//t1 = Clock::now();
|
||||
}
|
||||
//ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
//BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
//BOOST_TEST(d < max_diff);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,12 @@ boost::mutex m;
|
||||
|
||||
#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ! defined BOOST_THREAD_NO_MAKE_LOCK_GUARD
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
@@ -48,7 +54,7 @@ void f()
|
||||
t1 = Clock::now();
|
||||
}
|
||||
ns d = t1 - t0 - ms(250);
|
||||
BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
//time_point t1;
|
||||
@@ -58,7 +64,7 @@ void f()
|
||||
//t1 = Clock::now();
|
||||
}
|
||||
//ns d = t1 - t0 - ms(250);
|
||||
//BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
//BOOST_TEST(d < max_diff);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -37,6 +37,12 @@ boost::mutex m;
|
||||
|
||||
#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ! defined BOOST_THREAD_NO_MAKE_LOCK_GUARD && defined BOOST_THREAD_USES_CHRONO
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
time_point t0 = Clock::now();
|
||||
@@ -46,8 +52,7 @@ void f()
|
||||
t1 = Clock::now();
|
||||
}
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -25,6 +25,12 @@ typedef boost::chrono::nanoseconds ns;
|
||||
|
||||
boost::mutex m;
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
@@ -36,8 +42,7 @@ void f()
|
||||
t1 = Clock::now();
|
||||
}
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
//time_point t1;
|
||||
@@ -47,8 +52,7 @@ void f()
|
||||
//t1 = Clock::now();
|
||||
}
|
||||
//ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
//BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
//BOOST_TEST(d < max_diff);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,12 @@ boost::mutex m;
|
||||
|
||||
#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ! defined BOOST_THREAD_NO_MAKE_NESTED_STRICT_LOCK && defined BOOST_THREAD_USES_CHRONO
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
time_point t0 = Clock::now();
|
||||
@@ -39,8 +45,7 @@ void f()
|
||||
t1 = Clock::now();
|
||||
}
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -33,16 +33,20 @@ typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f1()
|
||||
{
|
||||
time_point t0 = Clock::now();
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
boost::shared_lock<boost::shared_mutex> lk(m, ms(300)+ms(1000));
|
||||
boost::shared_lock<boost::shared_mutex> lk(m, ms(750));
|
||||
BOOST_TEST(lk.owns_lock() == true);
|
||||
time_point t1 = Clock::now();
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(5000000)+ms(1000)); // within 5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
}
|
||||
|
||||
void f2()
|
||||
@@ -52,8 +56,7 @@ void f2()
|
||||
BOOST_TEST(lk.owns_lock() == false);
|
||||
time_point t1 = Clock::now();
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(5000000)+ms(1000)); // within 5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
}
|
||||
|
||||
int main()
|
||||
@@ -68,8 +71,7 @@ int main()
|
||||
{
|
||||
m.lock();
|
||||
boost::thread t(f2);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
boost::this_thread::sleep_for(ms(300)+ms(1000));
|
||||
boost::this_thread::sleep_for(ms(750));
|
||||
m.unlock();
|
||||
t.join();
|
||||
}
|
||||
|
||||
@@ -35,6 +35,12 @@ typedef boost::chrono::nanoseconds ns;
|
||||
#else
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
@@ -45,8 +51,7 @@ void f()
|
||||
t1 = Clock::now();
|
||||
}
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(2500000)+ms(2000)); // within 2.5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
//time_point t1;
|
||||
@@ -55,8 +60,7 @@ void f()
|
||||
//t1 = Clock::now();
|
||||
}
|
||||
//ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
//BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
//BOOST_TEST(d < max_diff);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -32,16 +32,20 @@ typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f1()
|
||||
{
|
||||
time_point t0 = Clock::now();
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
boost::shared_lock<boost::shared_mutex> lk(m, Clock::now() + ms(300)+ms(1000));
|
||||
boost::shared_lock<boost::shared_mutex> lk(m, Clock::now() + ms(750));
|
||||
BOOST_TEST(lk.owns_lock() == true);
|
||||
time_point t1 = Clock::now();
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(50000000)+ms(1000)); // within 50ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
}
|
||||
|
||||
void f2()
|
||||
@@ -51,8 +55,7 @@ void f2()
|
||||
BOOST_TEST(lk.owns_lock() == false);
|
||||
time_point t1 = Clock::now();
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(5000000)+ms(1000)); // within 5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
}
|
||||
|
||||
int main()
|
||||
@@ -67,7 +70,7 @@ int main()
|
||||
{
|
||||
m.lock();
|
||||
boost::thread t(f2);
|
||||
boost::this_thread::sleep_for(ms(300)+ms(1000));
|
||||
boost::this_thread::sleep_for(ms(750));
|
||||
m.unlock();
|
||||
t.join();
|
||||
}
|
||||
|
||||
@@ -35,6 +35,12 @@ typedef boost::chrono::nanoseconds ns;
|
||||
#else
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
@@ -58,8 +64,7 @@ void f()
|
||||
}
|
||||
time_point t1 = Clock::now();
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(50000000)+ms(1000)); // within 50ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
#else
|
||||
// time_point t0 = Clock::now();
|
||||
// {
|
||||
@@ -81,8 +86,7 @@ void f()
|
||||
}
|
||||
//time_point t1 = Clock::now();
|
||||
//ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
//BOOST_TEST(d < ns(50000000)+ms(1000)); // within 50ms
|
||||
//BOOST_TEST(d < max_diff);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,12 @@ typedef boost::chrono::nanoseconds ns;
|
||||
#else
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
@@ -44,8 +50,7 @@ void f()
|
||||
time_point t1 = Clock::now();
|
||||
BOOST_TEST(lk.owns_lock() == true);
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
try
|
||||
{
|
||||
lk.lock();
|
||||
@@ -73,8 +78,7 @@ void f()
|
||||
//time_point t1 = Clock::now();
|
||||
BOOST_TEST(lk.owns_lock() == true);
|
||||
//ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
//BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
//BOOST_TEST(d < max_diff);
|
||||
try
|
||||
{
|
||||
lk.lock();
|
||||
|
||||
@@ -34,6 +34,12 @@ typedef boost::chrono::nanoseconds ns;
|
||||
|
||||
boost::shared_mutex m;
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
@@ -45,7 +51,7 @@ void f()
|
||||
t1 = Clock::now();
|
||||
}
|
||||
ns d = t1 - t0 - ms(250);
|
||||
BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
//time_point t1;
|
||||
@@ -55,7 +61,7 @@ void f()
|
||||
//t1 = Clock::now();
|
||||
}
|
||||
//ns d = t1 - t0 - ms(250);
|
||||
//BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
//BOOST_TEST(d < max_diff);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <boost/thread/shared_mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <iostream>
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
typedef boost::chrono::high_resolution_clock Clock;
|
||||
@@ -34,6 +35,12 @@ typedef boost::chrono::nanoseconds ns;
|
||||
|
||||
boost::shared_mutex m;
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
@@ -44,8 +51,8 @@ void f()
|
||||
t1 = Clock::now();
|
||||
}
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
std::cout << "diff= " << d.count() << std::endl;
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
//time_point t1;
|
||||
@@ -54,8 +61,7 @@ void f()
|
||||
//t1 = Clock::now();
|
||||
}
|
||||
//ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
//BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
//BOOST_TEST(d < max_diff);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,12 @@ typedef boost::chrono::nanoseconds ns;
|
||||
|
||||
boost::mutex m;
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
@@ -34,8 +40,7 @@ void f()
|
||||
t1 = Clock::now();
|
||||
}
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
//time_point t1;
|
||||
@@ -44,8 +49,7 @@ void f()
|
||||
//t1 = Clock::now();
|
||||
}
|
||||
//ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
//BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
//BOOST_TEST(d < max_diff);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,12 @@ boost::mutex m;
|
||||
|
||||
#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ! defined BOOST_THREAD_NO_MAKE_STRICT_LOCK && defined BOOST_THREAD_USES_CHRONO
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
time_point t0 = Clock::now();
|
||||
@@ -37,8 +43,7 @@ void f()
|
||||
t1 = Clock::now();
|
||||
}
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -37,16 +37,20 @@ typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f1()
|
||||
{
|
||||
time_point t0 = Clock::now();
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
boost::unique_lock<boost::timed_mutex> lk(m, ms(300)+ms(1000));
|
||||
boost::unique_lock<boost::timed_mutex> lk(m, ms(750));
|
||||
BOOST_TEST(lk.owns_lock() == true);
|
||||
time_point t1 = Clock::now();
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(5000000)+ms(1000)); // within 5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
}
|
||||
|
||||
void f2()
|
||||
@@ -56,8 +60,7 @@ void f2()
|
||||
BOOST_TEST(lk.owns_lock() == false);
|
||||
time_point t1 = Clock::now();
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(5000000)+ms(1000)); // within 5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
}
|
||||
|
||||
int main()
|
||||
@@ -72,7 +75,7 @@ int main()
|
||||
{
|
||||
m.lock();
|
||||
boost::thread t(f2);
|
||||
boost::this_thread::sleep_for(ms(300)+ms(1000));
|
||||
boost::this_thread::sleep_for(ms(750));
|
||||
m.unlock();
|
||||
t.join();
|
||||
}
|
||||
|
||||
@@ -30,6 +30,12 @@ typedef boost::chrono::nanoseconds ns;
|
||||
#else
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
@@ -46,8 +52,7 @@ void f()
|
||||
t1 = Clock::now();
|
||||
}
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
//time_point t1;
|
||||
@@ -62,8 +67,7 @@ void f()
|
||||
//t1 = Clock::now();
|
||||
}
|
||||
//ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
//BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
//BOOST_TEST(d < max_diff);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,12 @@ typedef boost::chrono::nanoseconds ns;
|
||||
#else
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
@@ -41,8 +47,7 @@ void f()
|
||||
BOOST_TEST(lk.owns_lock() == false);
|
||||
time_point t1 = Clock::now();
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(50000000)+ms(1000)); // within 50ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
}
|
||||
{
|
||||
time_point t0 = Clock::now();
|
||||
@@ -55,8 +60,7 @@ void f()
|
||||
BOOST_TEST(lk.owns_lock() == false);
|
||||
time_point t1 = Clock::now();
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(50000000)+ms(1000)); // within 50ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
}
|
||||
{
|
||||
time_point t0 = Clock::now();
|
||||
@@ -69,8 +73,7 @@ void f()
|
||||
BOOST_TEST(lk.owns_lock() == false);
|
||||
time_point t1 = Clock::now();
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(50000000)+ms(1000)); // within 50ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
}
|
||||
{
|
||||
time_point t0 = Clock::now();
|
||||
@@ -86,8 +89,7 @@ void f()
|
||||
}
|
||||
time_point t1 = Clock::now();
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(50000000)+ms(1000)); // within 50ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
}
|
||||
#else
|
||||
// time_point t0 = Clock::now();
|
||||
@@ -115,8 +117,7 @@ void f()
|
||||
}
|
||||
//time_point t1 = Clock::now();
|
||||
//ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
//BOOST_TEST(d < ns(50000000)+ms(1000)); // within 50ms
|
||||
//BOOST_TEST(d < max_diff);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,12 @@ typedef boost::chrono::nanoseconds ns;
|
||||
#else
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
@@ -42,8 +48,7 @@ void f()
|
||||
t1 = Clock::now();
|
||||
}
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
//time_point t1;
|
||||
@@ -52,8 +57,7 @@ void f()
|
||||
//t1 = Clock::now();
|
||||
}
|
||||
//ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
//BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
//BOOST_TEST(d < max_diff);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
boost::mutex m;
|
||||
@@ -36,6 +37,12 @@ typedef boost::chrono::nanoseconds ns;
|
||||
#else
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
@@ -46,8 +53,9 @@ void f()
|
||||
t1 = Clock::now();
|
||||
}
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
std::cout << "diff= " << d.count() << std::endl;
|
||||
std::cout << "max_diff= " << max_diff.count() << std::endl;
|
||||
BOOST_TEST(d < max_diff);
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
//time_point t1;
|
||||
@@ -56,8 +64,7 @@ void f()
|
||||
//t1 = Clock::now();
|
||||
}
|
||||
//ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
//BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
//BOOST_TEST(d < max_diff);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -36,16 +36,20 @@ typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f1()
|
||||
{
|
||||
time_point t0 = Clock::now();
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
boost::unique_lock<boost::timed_mutex> lk(m, Clock::now() + ms(300)+ms(1000));
|
||||
boost::unique_lock<boost::timed_mutex> lk(m, Clock::now() + ms(750));
|
||||
BOOST_TEST(lk.owns_lock() == true);
|
||||
time_point t1 = Clock::now();
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
ns d = t1 - t0 - ms(250);
|
||||
BOOST_TEST(d < ns(50000000)+ms(1000)); // within 50ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
}
|
||||
|
||||
void f2()
|
||||
@@ -55,8 +59,7 @@ void f2()
|
||||
BOOST_TEST(lk.owns_lock() == false);
|
||||
time_point t1 = Clock::now();
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(5000000)+ms(1000)); // within 5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
}
|
||||
|
||||
int main()
|
||||
@@ -71,7 +74,7 @@ int main()
|
||||
{
|
||||
m.lock();
|
||||
boost::thread t(f2);
|
||||
boost::this_thread::sleep_for(ms(350));
|
||||
boost::this_thread::sleep_for(ms(750));
|
||||
m.unlock();
|
||||
t.join();
|
||||
}
|
||||
|
||||
@@ -36,6 +36,12 @@ typedef boost::chrono::nanoseconds ns;
|
||||
#else
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
@@ -60,8 +66,9 @@ void f()
|
||||
time_point t1 = Clock::now();
|
||||
//m.unlock();
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(50000000)+ms(1000)); // within 50ms
|
||||
std::cout << "diff= " << d.count() << std::endl;
|
||||
std::cout << "max_diff= " << max_diff.count() << std::endl;
|
||||
BOOST_TEST(d < max_diff);
|
||||
#else
|
||||
// time_point t0 = Clock::now();
|
||||
// {
|
||||
@@ -83,8 +90,7 @@ void f()
|
||||
}
|
||||
//time_point t1 = Clock::now();
|
||||
//ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
//BOOST_TEST(d < ns(50000000)+ms(1000)); // within 50ms
|
||||
//BOOST_TEST(d < max_diff);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,12 @@ typedef boost::chrono::nanoseconds ns;
|
||||
#else
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
@@ -44,8 +50,7 @@ void f()
|
||||
time_point t1 = Clock::now();
|
||||
BOOST_TEST(lk.owns_lock() == true);
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
try
|
||||
{
|
||||
lk.lock();
|
||||
@@ -73,8 +78,7 @@ void f()
|
||||
//time_point t1 = Clock::now();
|
||||
BOOST_TEST(lk.owns_lock() == true);
|
||||
//ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
//BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
//BOOST_TEST(d < max_diff);
|
||||
try
|
||||
{
|
||||
lk.lock();
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
int main()
|
||||
{
|
||||
boost::shared_mutex m;
|
||||
m.lock();
|
||||
m.lock_upgrade();
|
||||
boost::upgrade_lock<boost::shared_mutex> lk(m, boost::adopt_lock);
|
||||
BOOST_TEST(lk.mutex() == &m);
|
||||
BOOST_TEST(lk.owns_lock() == true);
|
||||
|
||||
@@ -35,16 +35,20 @@ typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f1()
|
||||
{
|
||||
time_point t0 = Clock::now();
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
boost::upgrade_lock<boost::shared_mutex> lk(m, ms(300)+ms(1000));
|
||||
boost::upgrade_lock<boost::shared_mutex> lk(m, ms(750));
|
||||
BOOST_TEST(lk.owns_lock() == true);
|
||||
time_point t1 = Clock::now();
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(5000000)+ms(1000)); // within 5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
}
|
||||
|
||||
void f2()
|
||||
@@ -54,8 +58,7 @@ void f2()
|
||||
BOOST_TEST(lk.owns_lock() == false);
|
||||
time_point t1 = Clock::now();
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(5000000)+ms(1000)); // within 5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
}
|
||||
|
||||
int main()
|
||||
@@ -70,7 +73,7 @@ int main()
|
||||
{
|
||||
m.lock();
|
||||
boost::thread t(f2);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
boost::this_thread::sleep_for(ms(750));
|
||||
m.unlock();
|
||||
t.join();
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <boost/thread/shared_mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <iostream>
|
||||
|
||||
boost::shared_mutex m;
|
||||
|
||||
@@ -35,6 +36,12 @@ typedef boost::chrono::nanoseconds ns;
|
||||
#else
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
@@ -45,8 +52,9 @@ void f()
|
||||
t1 = Clock::now();
|
||||
}
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
std::cout << "diff= " << d.count() << std::endl;
|
||||
std::cout << "max_diff= " << max_diff.count() << std::endl;
|
||||
BOOST_TEST(d < max_diff);
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
//time_point t1;
|
||||
@@ -55,8 +63,7 @@ void f()
|
||||
//t1 = Clock::now();
|
||||
}
|
||||
//ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
//BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
//BOOST_TEST(d < max_diff);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -34,16 +34,20 @@ typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f1()
|
||||
{
|
||||
time_point t0 = Clock::now();
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
boost::upgrade_lock<boost::shared_mutex> lk(m, Clock::now() + ms(300)+ms(1000));
|
||||
boost::upgrade_lock<boost::shared_mutex> lk(m, Clock::now() + ms(750));
|
||||
BOOST_TEST(lk.owns_lock() == true);
|
||||
time_point t1 = Clock::now();
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(50000000)+ms(1000)); // within 50ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
}
|
||||
|
||||
void f2()
|
||||
@@ -53,8 +57,7 @@ void f2()
|
||||
BOOST_TEST(lk.owns_lock() == false);
|
||||
time_point t1 = Clock::now();
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(5000000)+ms(1000)); // within 5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
}
|
||||
|
||||
int main()
|
||||
@@ -69,7 +72,7 @@ int main()
|
||||
{
|
||||
m.lock();
|
||||
boost::thread t(f2);
|
||||
boost::this_thread::sleep_for(ms(350));
|
||||
boost::this_thread::sleep_for(ms(750));
|
||||
m.unlock();
|
||||
t.join();
|
||||
}
|
||||
|
||||
@@ -35,6 +35,12 @@ typedef boost::chrono::nanoseconds ns;
|
||||
#else
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
@@ -59,8 +65,7 @@ void f()
|
||||
time_point t1 = Clock::now();
|
||||
//m.unlock();
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(50000000)+ms(1000)); // within 50ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
#else
|
||||
// time_point t0 = Clock::now();
|
||||
// {
|
||||
@@ -82,8 +87,7 @@ void f()
|
||||
}
|
||||
//time_point t1 = Clock::now();
|
||||
//ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
//BOOST_TEST(d < ns(50000000)+ms(1000)); // within 50ms
|
||||
//BOOST_TEST(d < max_diff);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,12 @@ typedef boost::chrono::nanoseconds ns;
|
||||
#else
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
@@ -44,8 +50,7 @@ void f()
|
||||
time_point t1 = Clock::now();
|
||||
BOOST_TEST(lk.owns_lock() == true);
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
try
|
||||
{
|
||||
lk.lock();
|
||||
@@ -73,8 +78,7 @@ void f()
|
||||
//time_point t1 = Clock::now();
|
||||
BOOST_TEST(lk.owns_lock() == true);
|
||||
//ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
//BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
//BOOST_TEST(d < max_diff);
|
||||
try
|
||||
{
|
||||
lk.lock();
|
||||
|
||||
@@ -34,6 +34,12 @@ typedef boost::chrono::nanoseconds ns;
|
||||
#else
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
@@ -42,16 +48,14 @@ void f()
|
||||
time_point t1 = Clock::now();
|
||||
m.unlock();
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
m.lock();
|
||||
//time_point t1 = Clock::now();
|
||||
m.unlock();
|
||||
//ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
//BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
//BOOST_TEST(d < max_diff);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,12 @@ typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
@@ -45,8 +51,7 @@ void f()
|
||||
time_point t1 = Clock::now();
|
||||
m.unlock();
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(50000000)+ms(1000)); // within 50ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
//BOOST_TEST(!m.try_lock());
|
||||
@@ -57,8 +62,7 @@ void f()
|
||||
//time_point t1 = Clock::now();
|
||||
m.unlock();
|
||||
//ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
//BOOST_TEST(d < ns(50000000)+ms(1000)); // within 50ms
|
||||
//BOOST_TEST(d < max_diff);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -35,6 +35,12 @@ typedef boost::chrono::nanoseconds ns;
|
||||
#else
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(50);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
@@ -45,8 +51,7 @@ void f()
|
||||
m.unlock();
|
||||
m.unlock();
|
||||
ns d = t1 - t0 ;
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(2500000)); // within 2.5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
m.lock();
|
||||
@@ -55,8 +60,7 @@ void f()
|
||||
m.unlock();
|
||||
m.unlock();
|
||||
//ns d = t1 - t0 ;
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
//BOOST_TEST(d < ns(2500000)); // within 2.5ms
|
||||
//BOOST_TEST(d < max_diff);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -34,18 +34,22 @@ typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(50);
|
||||
#endif
|
||||
|
||||
void f1()
|
||||
{
|
||||
time_point t0 = Clock::now();
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(m.try_lock_for(ms(100)) == true);
|
||||
BOOST_TEST(m.try_lock_for(ms(250)) == true);
|
||||
time_point t1 = Clock::now();
|
||||
BOOST_TEST(m.try_lock());
|
||||
m.unlock();
|
||||
m.unlock();
|
||||
ns d = t1 - t0 ;
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(5000000)); // within 5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -35,6 +35,12 @@ typedef boost::chrono::nanoseconds ns;
|
||||
#else
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(50);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
@@ -45,8 +51,7 @@ void f()
|
||||
m.unlock();
|
||||
m.unlock();
|
||||
ns d = t1 - t0;
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(50000000)); // within 50ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
#else
|
||||
BOOST_TEST(m.try_lock());
|
||||
BOOST_TEST(m.try_lock());
|
||||
|
||||
@@ -33,14 +33,20 @@ typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(50);
|
||||
#endif
|
||||
|
||||
void f1()
|
||||
{
|
||||
time_point t0 = Clock::now();
|
||||
BOOST_TEST(m.try_lock_until(Clock::now() + ms(300) ) == true);
|
||||
BOOST_TEST(m.try_lock_until(Clock::now() + ms(250)) == true);
|
||||
time_point t1 = Clock::now();
|
||||
m.unlock();
|
||||
ns d = t1 - t0 ;
|
||||
BOOST_TEST(d < ns(5000000)); // within 5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -34,6 +34,12 @@ typedef boost::chrono::nanoseconds ns;
|
||||
#else
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
@@ -44,8 +50,7 @@ void f()
|
||||
m.unlock();
|
||||
m.unlock();
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
m.lock();
|
||||
@@ -54,8 +59,7 @@ void f()
|
||||
m.unlock();
|
||||
m.unlock();
|
||||
//ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
//BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
//BOOST_TEST(d < max_diff);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <boost/thread/recursive_mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
boost::recursive_mutex m;
|
||||
|
||||
@@ -34,6 +34,12 @@ typedef boost::chrono::nanoseconds ns;
|
||||
#else
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
@@ -48,8 +54,9 @@ void f()
|
||||
m.unlock();
|
||||
m.unlock();
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(50000000)+ms(1000)); // within 50ms
|
||||
std::cout << "diff= " << d.count() << std::endl;
|
||||
std::cout << "max_diff= " << max_diff.count() << std::endl;
|
||||
BOOST_TEST(d < max_diff);
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
//BOOST_TEST(!m.try_lock());
|
||||
@@ -62,8 +69,7 @@ void f()
|
||||
m.unlock();
|
||||
m.unlock();
|
||||
//ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
//BOOST_TEST(d < ns(50000000)+ms(1000)); // within 50ms
|
||||
//BOOST_TEST(d < max_diff);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -21,8 +21,7 @@
|
||||
#include <boost/thread/recursive_mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
|
||||
#include <iostream>
|
||||
|
||||
boost::recursive_timed_mutex m;
|
||||
|
||||
@@ -35,6 +34,12 @@ typedef boost::chrono::nanoseconds ns;
|
||||
#else
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
@@ -45,8 +50,9 @@ void f()
|
||||
m.unlock();
|
||||
m.unlock();
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
std::cout << "diff= " << d.count() << std::endl;
|
||||
std::cout << "max_diff= " << max_diff.count() << std::endl;
|
||||
BOOST_TEST(d < max_diff);
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
m.lock();
|
||||
@@ -55,8 +61,7 @@ void f()
|
||||
m.unlock();
|
||||
m.unlock();
|
||||
//ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
//BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
//BOOST_TEST(d < max_diff);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -34,18 +34,22 @@ typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f1()
|
||||
{
|
||||
time_point t0 = Clock::now();
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(m.try_lock_for(ms(300)+ms(1000)) == true);
|
||||
BOOST_TEST(m.try_lock_for(ms(750)) == true);
|
||||
time_point t1 = Clock::now();
|
||||
BOOST_TEST(m.try_lock());
|
||||
m.unlock();
|
||||
m.unlock();
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(5000000)+ms(1000)); // within 5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
}
|
||||
|
||||
void f2()
|
||||
@@ -54,8 +58,7 @@ void f2()
|
||||
BOOST_TEST(m.try_lock_for(ms(250)) == false);
|
||||
time_point t1 = Clock::now();
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(5000000)+ms(1000)); // within 5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
}
|
||||
|
||||
int main()
|
||||
@@ -70,7 +73,7 @@ int main()
|
||||
{
|
||||
m.lock();
|
||||
boost::thread t(f2);
|
||||
boost::this_thread::sleep_for(ms(400));
|
||||
boost::this_thread::sleep_for(ms(750));
|
||||
m.unlock();
|
||||
t.join();
|
||||
}
|
||||
|
||||
@@ -35,6 +35,12 @@ typedef boost::chrono::nanoseconds ns;
|
||||
#else
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
@@ -49,8 +55,7 @@ void f()
|
||||
m.unlock();
|
||||
m.unlock();
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(50000000)+ms(1000)); // within 50ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
//BOOST_TEST(!m.try_lock());
|
||||
@@ -63,8 +68,7 @@ void f()
|
||||
m.unlock();
|
||||
m.unlock();
|
||||
//ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
//BOOST_TEST(d < ns(50000000)+ms(1000)); // within 50ms
|
||||
//BOOST_TEST(d < max_diff);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -33,15 +33,20 @@ typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f1()
|
||||
{
|
||||
time_point t0 = Clock::now();
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(m.try_lock_until(Clock::now() + ms(300) + ms(1000)) == true);
|
||||
BOOST_TEST(m.try_lock_until(Clock::now() + ms(750)) == true);
|
||||
time_point t1 = Clock::now();
|
||||
m.unlock();
|
||||
ns d = t1 - t0 - ms(250);
|
||||
BOOST_TEST(d < ns(5000000)+ms(1000)); // within 5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
}
|
||||
|
||||
void f2()
|
||||
@@ -50,8 +55,7 @@ void f2()
|
||||
BOOST_TEST(m.try_lock_until(Clock::now() + ms(250)) == false);
|
||||
time_point t1 = Clock::now();
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(5000000)+ms(1000)); // within 5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
}
|
||||
|
||||
int main()
|
||||
@@ -66,7 +70,7 @@ int main()
|
||||
{
|
||||
m.lock();
|
||||
boost::thread t(f2);
|
||||
boost::this_thread::sleep_for(ms(300));
|
||||
boost::this_thread::sleep_for(ms(750));
|
||||
m.unlock();
|
||||
t.join();
|
||||
}
|
||||
|
||||
@@ -32,6 +32,13 @@ typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
#else
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_PLATFORM_WIN32
|
||||
const ms max_diff(250);
|
||||
#else
|
||||
const ms max_diff(75);
|
||||
#endif
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
@@ -40,16 +47,14 @@ void f()
|
||||
time_point t1 = Clock::now();
|
||||
m.unlock();
|
||||
ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
BOOST_TEST(d < max_diff);
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
m.lock();
|
||||
//time_point t1 = Clock::now();
|
||||
m.unlock();
|
||||
//ns d = t1 - t0 - ms(250);
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
//BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
//BOOST_TEST(d < max_diff);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user