mirror of
https://github.com/boostorg/thread.git
synced 2026-02-03 09:42:16 +00:00
Compare commits
249 Commits
pr/fix-gcc
...
pr/fix-det
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
534f5af9e6 | ||
|
|
aaca72e34b | ||
|
|
f4b239bab1 | ||
|
|
bf7e79c709 | ||
|
|
8c1d232b8c | ||
|
|
92a5bc4300 | ||
|
|
5b209c2e83 | ||
|
|
33ad8b1834 | ||
|
|
8fb92dfb52 | ||
|
|
c550979eff | ||
|
|
15f2d7a21c | ||
|
|
371fb42709 | ||
|
|
f7581a3662 | ||
|
|
e54f7e3960 | ||
|
|
d1284b02ad | ||
|
|
c5e756d196 | ||
|
|
ee607c86d4 | ||
|
|
68eef9240f | ||
|
|
de7608f067 | ||
|
|
743f2a0348 | ||
|
|
d8d549cf3e | ||
|
|
fc08c1fe28 | ||
|
|
dce24d5b43 | ||
|
|
b45ae62791 | ||
|
|
b0485bafdd | ||
|
|
3b52a8950f | ||
|
|
e60f66e023 | ||
|
|
2a68582676 | ||
|
|
b7ebda0f15 | ||
|
|
7b2289a1c5 | ||
|
|
25b915308a | ||
|
|
079871ffac | ||
|
|
4d62627668 | ||
|
|
2b88759f43 | ||
|
|
d60968b61c | ||
|
|
5aad4ac056 | ||
|
|
2ef70e02a5 | ||
|
|
f525a18239 | ||
|
|
5c2dd21508 | ||
|
|
6d9aaff58a | ||
|
|
db72b0477d | ||
|
|
1f08b38461 | ||
|
|
8cffb15e1e | ||
|
|
3f1590bce7 | ||
|
|
37e5c6513c | ||
|
|
7585187d1c | ||
|
|
8764a5b3dd | ||
|
|
9f9feca70c | ||
|
|
1874018c12 | ||
|
|
d78a0ca53f | ||
|
|
d1ef6369d9 | ||
|
|
040481760c | ||
|
|
e848363029 | ||
|
|
8ce9826d98 | ||
|
|
5fa7ae14b9 | ||
|
|
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%
|
||||
|
||||
@@ -38,6 +38,8 @@ import path ;
|
||||
import configure ;
|
||||
import threadapi-feature ;
|
||||
|
||||
exe has_atomic_flag_lockfree : ../build/has_atomic_flag_lockfree_test.cpp ;
|
||||
|
||||
project boost/thread
|
||||
: source-location ../src
|
||||
: requirements <threading>multi
|
||||
@@ -141,8 +143,6 @@ project boost/thread
|
||||
<library>/boost/system//boost_system
|
||||
;
|
||||
|
||||
exe has_atomic_flag_lockfree : ../build/has_atomic_flag_lockfree_test.cpp ;
|
||||
|
||||
rule tag ( name : type ? : property-set )
|
||||
{
|
||||
local result = $(name) ;
|
||||
@@ -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
|
||||
|
||||
175
circle.yml
Normal file
175
circle.yml
Normal file
@@ -0,0 +1,175 @@
|
||||
# Copyright 2018 Tom Hughes
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
|
||||
|
||||
build_steps: &build_steps
|
||||
steps:
|
||||
- run:
|
||||
name: Setup
|
||||
command: |
|
||||
PLATFORM=`uname`
|
||||
if [ "${PLATFORM}" == "Linux" ]; then
|
||||
sudo apt-get install -y software-properties-common apt-transport-https
|
||||
|
||||
# https://github.com/ilikenwf/apt-fast
|
||||
sudo add-apt-repository -y ppa:apt-fast/stable
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install apt-fast
|
||||
|
||||
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add -
|
||||
echo "deb https://apt.llvm.org/trusty/ llvm-toolchain-trusty-4.0 main" | sudo tee -a /etc/apt/sources.list
|
||||
echo "deb https://apt.llvm.org/trusty/ llvm-toolchain-trusty-5.0 main" | sudo tee -a /etc/apt/sources.list
|
||||
echo "deb https://apt.llvm.org/trusty/ llvm-toolchain-trusty-6.0 main" | sudo tee -a /etc/apt/sources.list
|
||||
sudo apt-fast update
|
||||
sudo apt-fast install -y $COMPILER
|
||||
fi
|
||||
- checkout
|
||||
- run:
|
||||
name: Install
|
||||
command: |
|
||||
BOOST_BRANCH=develop && [ "$CIRCLE_BRANCH" == "master" ] && BOOST_BRANCH=master || true
|
||||
cd ..
|
||||
git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
cd boost-root
|
||||
git submodule update --init tools/build
|
||||
git submodule update --init libs/config
|
||||
git submodule update --init tools/boostdep
|
||||
mkdir -p libs/thread
|
||||
cp -r $HOME/project/* libs/thread
|
||||
python tools/boostdep/depinst/depinst.py thread
|
||||
./bootstrap.sh
|
||||
./b2 headers
|
||||
- run:
|
||||
name: Build
|
||||
command: |
|
||||
echo "using $TOOLSET : : $COMPILER : <cxxflags>-std=$CXXSTD <cxxflags>$DEFINES ;" > ~/user-config.jam
|
||||
cd ../boost-root
|
||||
./b2 -j8 libs/thread/test toolset=$TOOLSET
|
||||
|
||||
mac_build: &mac_build
|
||||
macos:
|
||||
xcode: "9.2.0"
|
||||
<<: *build_steps
|
||||
|
||||
linux_build: &linux_build
|
||||
docker:
|
||||
- image: circleci/buildpack-deps:trusty
|
||||
<<: *build_steps
|
||||
|
||||
|
||||
version: 2
|
||||
jobs:
|
||||
linux-g++-c++11:
|
||||
<<: *linux_build
|
||||
environment:
|
||||
- TOOLSET: "gcc"
|
||||
- COMPILER: "g++"
|
||||
- CXXSTD: "c++11"
|
||||
|
||||
linux-g++-7-c++98:
|
||||
<<: *linux_build
|
||||
environment:
|
||||
- TOOLSET: "gcc"
|
||||
- COMPILER: "g++-7"
|
||||
- CXXSTD: "c++98"
|
||||
|
||||
linux-g++-7-c++11:
|
||||
<<: *linux_build
|
||||
environment:
|
||||
- TOOLSET: "gcc"
|
||||
- COMPILER: "g++-7"
|
||||
- CXXSTD: "c++11"
|
||||
|
||||
linux-g++-7-c++14:
|
||||
<<: *linux_build
|
||||
environment:
|
||||
- TOOLSET: "gcc"
|
||||
- COMPILER: "g++-7"
|
||||
- CXXSTD: "c++14"
|
||||
|
||||
linux-g++-7-c++1z:
|
||||
<<: *linux_build
|
||||
environment:
|
||||
- TOOLSET: "gcc"
|
||||
- COMPILER: "g++-7"
|
||||
- CXXSTD: "c++1z"
|
||||
|
||||
linux-clang++-4.0-c++98:
|
||||
<<: *linux_build
|
||||
environment:
|
||||
- TOOLSET: "clang"
|
||||
- COMPILER: "clang++-4.0"
|
||||
- CXXSTD: "c++98"
|
||||
|
||||
linux-clang++-4.0-c++11:
|
||||
<<: *linux_build
|
||||
environment:
|
||||
- TOOLSET: "clang"
|
||||
- COMPILER: "clang++-4.0"
|
||||
- CXXSTD: "c++11"
|
||||
|
||||
linux-clang++-4.0-c++14:
|
||||
<<: *linux_build
|
||||
environment:
|
||||
- TOOLSET: "clang"
|
||||
- COMPILER: "clang++-4.0"
|
||||
- CXXSTD: "c++14"
|
||||
|
||||
linux-clang++-4.0-c++1z:
|
||||
<<: *linux_build
|
||||
environment:
|
||||
- TOOLSET: "clang"
|
||||
- COMPILER: "clang++-4.0"
|
||||
- CXXSTD: "c++1z"
|
||||
|
||||
mac-clang++-c++98:
|
||||
<<: *mac_build
|
||||
environment:
|
||||
- TOOLSET: "clang"
|
||||
- COMPILER: "clang++"
|
||||
- CXXSTD: "c++98"
|
||||
- DEFINES: "-DBOOST_THREAD_TEST_TIME_MS=100"
|
||||
|
||||
mac-clang++-c++11:
|
||||
<<: *mac_build
|
||||
environment:
|
||||
- TOOLSET: "clang"
|
||||
- COMPILER: "clang++"
|
||||
- CXXSTD: "c++11"
|
||||
- DEFINES: "-DBOOST_THREAD_TEST_TIME_MS=100"
|
||||
|
||||
mac-clang++-c++14:
|
||||
<<: *mac_build
|
||||
environment:
|
||||
- TOOLSET: "clang"
|
||||
- COMPILER: "clang++"
|
||||
- CXXSTD: "c++14"
|
||||
- DEFINES: "-DBOOST_THREAD_TEST_TIME_MS=100"
|
||||
|
||||
mac-clang++-c++1z:
|
||||
<<: *mac_build
|
||||
environment:
|
||||
- TOOLSET: "clang"
|
||||
- COMPILER: "clang++"
|
||||
- CXXSTD: "c++1z"
|
||||
- DEFINES: "-DBOOST_THREAD_TEST_TIME_MS=100"
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
continous:
|
||||
jobs:
|
||||
- linux-g++-c++11
|
||||
- linux-g++-7-c++98
|
||||
- linux-g++-7-c++11
|
||||
- linux-g++-7-c++14
|
||||
- linux-g++-7-c++1z
|
||||
- linux-clang++-4.0-c++98
|
||||
- linux-clang++-4.0-c++11
|
||||
- linux-clang++-4.0-c++14
|
||||
- linux-clang++-4.0-c++1z
|
||||
- mac-clang++-c++98
|
||||
- mac-clang++-c++11
|
||||
- mac-clang++-c++14
|
||||
- mac-clang++-c++1z
|
||||
|
||||
@@ -1526,7 +1526,7 @@ A thread pool with up to a fixed number of threads.
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Destroys the thread pool.]]
|
||||
[[Effects:] [Interrupts and joins all the threads and then destroys the threads.]]
|
||||
|
||||
[[Synchronization:] [The completion of all the closures happen before the completion of the executor destructor.]]
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[/
|
||||
(C) Copyright 2007-11 Anthony Williams.
|
||||
(C) Copyright 2011-17 Vicente J. Botet Escriba.
|
||||
(C) Copyright 2011-18 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).
|
||||
@@ -8,6 +8,27 @@
|
||||
|
||||
[section:changes History]
|
||||
|
||||
[heading Version 4.8.1 - boost 1.67]
|
||||
|
||||
[*Know Bugs:]
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/3926 #3926] thread_specific_ptr + dlopen library causes a SIGSEGV.
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10964 #10964] future<future<T>>::unwrap().then() Deadlocks
|
||||
|
||||
|
||||
Please take a look at [@https://svn.boost.org/trac/boost/query?status=assigned&status=new&status=reopened&component=thread&type=!Feature+Requests&col=id&col=summary&order=id thread Know Bugs] to see the current state.
|
||||
|
||||
Please take a look at [@http://www.boost.org/development/tests/master/developer/thread.html thread master regression test] to see the last regression test snapshot.
|
||||
|
||||
[*Fixed Bugs:]
|
||||
|
||||
|
||||
* [@https://github.com/boostorg/thread/issues/162 #162] fix as much time-related issues as possible and improve the QOI
|
||||
* [@https://github.com/boostorg/thread/issues/193 #193] future_then unit test contains two different implementations of do_continuation function
|
||||
* [@https://github.com/boostorg/thread/issues/209 #209] Legal problem with `win32/thread_primitives.hpp`
|
||||
|
||||
|
||||
[heading Version 4.8.0 - boost 1.66]
|
||||
|
||||
[*Know Bugs:]
|
||||
@@ -22,14 +43,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)
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/thread/detail/platform.hpp>
|
||||
#include <boost/thread/detail/thread_safety.hpp>
|
||||
|
||||
//#define BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
|
||||
//#define BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS
|
||||
// ATTRIBUTE_MAY_ALIAS
|
||||
|
||||
@@ -30,6 +30,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 +124,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 +413,34 @@
|
||||
# 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
|
||||
#elif defined(__ANDROID__)
|
||||
#define BOOST_THREAD_HAS_MONO_CLOCK
|
||||
#if defined(__ANDROID_API__) && __ANDROID_API__ >= 21
|
||||
#define BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
|
||||
#endif
|
||||
#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)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// 2013/09 Vicente J. Botet Escriba
|
||||
// 2013,2018 Vicente J. Botet Escriba
|
||||
// Adapt to boost from CCIA C++11 implementation
|
||||
// Make use of Boost.Move
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/csbl/memory/shared_ptr.hpp>
|
||||
#include <boost/type_traits/decay.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
@@ -72,12 +73,16 @@ namespace boost
|
||||
|
||||
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
template<typename F>
|
||||
explicit nullary_function(F& f):
|
||||
explicit nullary_function(F& f
|
||||
, typename disable_if<is_same<typename decay<F>::type, nullary_function>, int* >::type=0
|
||||
):
|
||||
impl(new impl_type<F>(f))
|
||||
{}
|
||||
#endif
|
||||
template<typename F>
|
||||
nullary_function(BOOST_THREAD_RV_REF(F) f):
|
||||
nullary_function(BOOST_THREAD_RV_REF(F) f
|
||||
, typename disable_if<is_same<typename decay<F>::type, nullary_function>, int* >::type=0
|
||||
):
|
||||
impl(new impl_type<typename decay<F>::type>(thread_detail::decay_copy(boost::forward<F>(f))))
|
||||
{}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -626,7 +594,7 @@ namespace thread_detail {
|
||||
#endif
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
inline BOOST_SYMBOL_VISIBLE void sleep(xtime const& abs_time)
|
||||
inline BOOST_SYMBOL_VISIBLE void sleep(::boost::xtime const& abs_time)
|
||||
{
|
||||
sleep(system_time(abs_time));
|
||||
}
|
||||
@@ -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"));
|
||||
@@ -847,6 +811,7 @@ namespace thread_detail {
|
||||
};
|
||||
|
||||
void BOOST_THREAD_DECL add_thread_exit_function(thread_exit_function_base*);
|
||||
//#ifndef BOOST_NO_EXCEPTIONS
|
||||
struct shared_state_base;
|
||||
#if defined(BOOST_THREAD_PLATFORM_WIN32)
|
||||
inline void make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
|
||||
@@ -860,6 +825,7 @@ namespace thread_detail {
|
||||
#else
|
||||
void BOOST_THREAD_DECL make_ready_at_thread_exit(shared_ptr<shared_state_base> as);
|
||||
#endif
|
||||
//#endif
|
||||
}
|
||||
|
||||
namespace this_thread
|
||||
|
||||
151
include/boost/thread/detail/thread_safety.hpp
Normal file
151
include/boost/thread/detail/thread_safety.hpp
Normal file
@@ -0,0 +1,151 @@
|
||||
#ifndef BOOST_THREAD_DETAIL_THREAD_SAFETY_HPP
|
||||
#define BOOST_THREAD_DETAIL_THREAD_SAFETY_HPP
|
||||
|
||||
// See https://clang.llvm.org/docs/ThreadSafetyAnalysis.html
|
||||
|
||||
// Un-comment to enable Thread Safety Analysis
|
||||
//#define BOOST_THREAD_ENABLE_THREAD_SAFETY_ANALYSIS
|
||||
|
||||
// Enable thread safety attributes only with clang.
|
||||
// The attributes can be safely erased when compiling with other compilers.
|
||||
#if defined (BOOST_THREAD_ENABLE_THREAD_SAFETY_ANALYSIS) && defined(__clang__) && (!defined(SWIG))
|
||||
#define BOOST_THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
|
||||
#else
|
||||
#define BOOST_THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op
|
||||
#endif
|
||||
|
||||
#define BOOST_THREAD_CAPABILITY(x) \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(capability(x))
|
||||
|
||||
#define BOOST_THREAD_SCOPED_CAPABILITY \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
|
||||
|
||||
#define BOOST_THREAD_GUARDED_BY(x) \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
|
||||
|
||||
#define BOOST_THREAD_PT_GUARDED_BY(x) \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
|
||||
|
||||
#define BOOST_THREAD_ACQUIRED_BEFORE(...) \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__))
|
||||
|
||||
#define BOOST_THREAD_ACQUIRED_AFTER(...) \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))
|
||||
|
||||
#define BOOST_THREAD_REQUIRES(...) \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__))
|
||||
|
||||
#define BOOST_THREAD_REQUIRES_SHARED(...) \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__))
|
||||
|
||||
#define BOOST_THREAD_ACQUIRE(...) \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__))
|
||||
|
||||
#define BOOST_THREAD_ACQUIRE_SHARED(...) \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__))
|
||||
|
||||
#define BOOST_THREAD_RELEASE(...) \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__))
|
||||
|
||||
#define BOOST_THREAD_RELEASE_SHARED(...) \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__))
|
||||
|
||||
#define BOOST_THREAD_TRY_ACQUIRE(...) \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__))
|
||||
|
||||
#define BOOST_THREAD_TRY_ACQUIRE_SHARED(...) \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__))
|
||||
|
||||
#define BOOST_THREAD_EXCLUDES(...) \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
|
||||
|
||||
#define BOOST_THREAD_ASSERT_CAPABILITY(x) \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x))
|
||||
|
||||
#define BOOST_THREAD_ASSERT_SHARED_CAPABILITY(x) \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x))
|
||||
|
||||
#define BOOST_THREAD_RETURN_CAPABILITY(x) \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
|
||||
|
||||
#define BOOST_THREAD_NO_THREAD_SAFETY_ANALYSIS \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
|
||||
|
||||
#if defined(__clang__) && (!defined(SWIG)) && defined(__FreeBSD__)
|
||||
#if __has_attribute(no_thread_safety_analysis)
|
||||
#define BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis))
|
||||
#else
|
||||
#define BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
|
||||
#endif
|
||||
#else
|
||||
#define BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
|
||||
#endif
|
||||
|
||||
#ifdef USE_LOCK_STYLE_THREAD_SAFETY_ATTRIBUTES
|
||||
// The original version of thread safety analysis the following attribute
|
||||
// definitions. These use a lock-based terminology. They are still in use
|
||||
// by existing thread safety code, and will continue to be supported.
|
||||
|
||||
// Deprecated.
|
||||
#define BOOST_THREAD_PT_GUARDED_VAR \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_var)
|
||||
|
||||
// Deprecated.
|
||||
#define BOOST_THREAD_GUARDED_VAR \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(guarded_var)
|
||||
|
||||
// Replaced by REQUIRES
|
||||
#define BOOST_THREAD_EXCLUSIVE_LOCKS_REQUIRED(...) \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__))
|
||||
|
||||
// Replaced by REQUIRES_SHARED
|
||||
#define BOOST_THREAD_SHARED_LOCKS_REQUIRED(...) \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(__VA_ARGS__))
|
||||
|
||||
// Replaced by CAPABILITY
|
||||
#define BOOST_THREAD_LOCKABLE \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(lockable)
|
||||
|
||||
// Replaced by SCOPED_CAPABILITY
|
||||
#define BOOST_THREAD_SCOPED_LOCKABLE \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
|
||||
|
||||
// Replaced by ACQUIRE
|
||||
#define BOOST_THREAD_EXCLUSIVE_LOCK_FUNCTION(...) \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__))
|
||||
|
||||
// Replaced by ACQUIRE_SHARED
|
||||
#define BOOST_THREAD_SHARED_LOCK_FUNCTION(...) \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__))
|
||||
|
||||
// Replaced by RELEASE and RELEASE_SHARED
|
||||
#define BOOST_THREAD_UNLOCK_FUNCTION(...) \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__))
|
||||
|
||||
// Replaced by TRY_ACQUIRE
|
||||
#define BOOST_THREAD_EXCLUSIVE_TRYLOCK_FUNCTION(...) \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(__VA_ARGS__))
|
||||
|
||||
// Replaced by TRY_ACQUIRE_SHARED
|
||||
#define BOOST_THREAD_SHARED_TRYLOCK_FUNCTION(...) \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(__VA_ARGS__))
|
||||
|
||||
// Replaced by ASSERT_CAPABILITY
|
||||
#define BOOST_THREAD_ASSERT_EXCLUSIVE_LOCK(...) \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(assert_exclusive_lock(__VA_ARGS__))
|
||||
|
||||
// Replaced by ASSERT_SHARED_CAPABILITY
|
||||
#define BOOST_THREAD_ASSERT_SHARED_LOCK(...) \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_lock(__VA_ARGS__))
|
||||
|
||||
// Replaced by EXCLUDE_CAPABILITY.
|
||||
#define BOOST_THREAD_LOCKS_EXCLUDED(...) \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
|
||||
|
||||
// Replaced by RETURN_CAPABILITY
|
||||
#define BOOST_THREAD_LOCK_RETURNED(x) \
|
||||
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
|
||||
|
||||
#endif // USE_LOCK_STYLE_THREAD_SAFETY_ATTRIBUTES
|
||||
|
||||
#endif // BOOST_THREAD_DETAIL_THREAD_SAFETY_HPP
|
||||
@@ -231,13 +231,36 @@ namespace executors
|
||||
// signal to all the worker threads that there will be no more submissions.
|
||||
close();
|
||||
// joins all the threads before destroying the thread pool resources (e.g. the queue).
|
||||
join();
|
||||
interrupt_and_join();
|
||||
}
|
||||
|
||||
/**
|
||||
* \b Effects: join all the threads.
|
||||
*/
|
||||
void join()
|
||||
{
|
||||
for (unsigned i = 0; i < threads.size(); ++i)
|
||||
{
|
||||
//threads[i].interrupt();
|
||||
threads[i].join();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \b Effects: interrupt all the threads.
|
||||
*/
|
||||
void interrupt()
|
||||
{
|
||||
for (unsigned i = 0; i < threads.size(); ++i)
|
||||
{
|
||||
threads[i].interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \b Effects: interrupt and join all the threads.
|
||||
*/
|
||||
void interrupt_and_join()
|
||||
{
|
||||
for (unsigned i = 0; i < threads.size(); ++i)
|
||||
{
|
||||
|
||||
@@ -15,7 +15,16 @@
|
||||
|
||||
//#define BOOST_THREAD_CONTINUATION_SYNC
|
||||
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
#ifdef BOOST_NO_EXCEPTIONS
|
||||
namespace boost
|
||||
{
|
||||
namespace detail {
|
||||
struct shared_state_base {
|
||||
void notify_deferred() {}
|
||||
};
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
@@ -159,7 +168,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 +182,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 +277,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 +298,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 +392,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 +411,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 +429,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 +442,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 +586,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 +770,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 +848,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 +939,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 +1044,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 +1070,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 +1093,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 +1122,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 +1482,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 +2272,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 +2563,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 +3189,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 +3531,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 +3621,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 +3642,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 +3859,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 +3918,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 +4147,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 +4163,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 +4182,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 +4212,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 +4268,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 +4990,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 +5014,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());
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace boost
|
||||
{
|
||||
|
||||
template <typename Mutex>
|
||||
class lock_guard
|
||||
class BOOST_THREAD_SCOPED_CAPABILITY lock_guard
|
||||
{
|
||||
private:
|
||||
Mutex& m;
|
||||
@@ -32,13 +32,13 @@ namespace boost
|
||||
typedef Mutex mutex_type;
|
||||
BOOST_THREAD_NO_COPYABLE( lock_guard )
|
||||
|
||||
explicit lock_guard(Mutex& m_) :
|
||||
explicit lock_guard(Mutex& m_) BOOST_THREAD_ACQUIRE(m_) :
|
||||
m(m_)
|
||||
{
|
||||
m.lock();
|
||||
}
|
||||
|
||||
lock_guard(Mutex& m_, adopt_lock_t) :
|
||||
lock_guard(Mutex& m_, adopt_lock_t) BOOST_THREAD_REQUIRES(m_) :
|
||||
m(m_)
|
||||
{
|
||||
#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
|
||||
@@ -62,7 +62,7 @@ namespace boost
|
||||
}
|
||||
|
||||
#endif
|
||||
~lock_guard()
|
||||
~lock_guard() BOOST_THREAD_RELEASE()
|
||||
{
|
||||
m.unlock();
|
||||
}
|
||||
|
||||
@@ -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,18 +218,38 @@ 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)
|
||||
bool timed_wait(lock_type& m,::boost::xtime const& abs_time)
|
||||
{
|
||||
return timed_wait(m,system_time(abs_time));
|
||||
}
|
||||
@@ -224,22 +257,59 @@ 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>
|
||||
bool timed_wait(lock_type& m,xtime const& abs_time, predicate_type pred)
|
||||
bool timed_wait(lock_type& m,::boost::xtime const& abs_time, predicate_type pred)
|
||||
{
|
||||
return timed_wait(m,system_time(abs_time),pred);
|
||||
}
|
||||
@@ -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,25 +95,40 @@ 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(
|
||||
unique_lock<mutex>& m,
|
||||
xtime const& abs_time)
|
||||
::boost::xtime const& abs_time)
|
||||
{
|
||||
return timed_wait(m,system_time(abs_time));
|
||||
}
|
||||
@@ -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,18 +169,32 @@ 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>
|
||||
bool timed_wait(
|
||||
unique_lock<mutex>& m,
|
||||
xtime const& abs_time,predicate_type pred)
|
||||
::boost::xtime const& abs_time,predicate_type pred)
|
||||
{
|
||||
return timed_wait(m,system_time(abs_time),pred);
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -43,53 +39,8 @@
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace posix {
|
||||
#ifdef BOOST_THREAD_HAS_EINTR_BUG
|
||||
BOOST_FORCEINLINE int pthread_mutex_destroy(pthread_mutex_t* m)
|
||||
{
|
||||
int ret;
|
||||
do
|
||||
{
|
||||
ret = ::pthread_mutex_destroy(m);
|
||||
} while (ret == EINTR);
|
||||
return ret;
|
||||
}
|
||||
BOOST_FORCEINLINE int pthread_mutex_lock(pthread_mutex_t* m)
|
||||
{
|
||||
int ret;
|
||||
do
|
||||
{
|
||||
ret = ::pthread_mutex_lock(m);
|
||||
} while (ret == EINTR);
|
||||
return ret;
|
||||
}
|
||||
BOOST_FORCEINLINE int pthread_mutex_unlock(pthread_mutex_t* m)
|
||||
{
|
||||
int ret;
|
||||
do
|
||||
{
|
||||
ret = ::pthread_mutex_unlock(m);
|
||||
} while (ret == EINTR);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
BOOST_FORCEINLINE int pthread_mutex_destroy(pthread_mutex_t* m)
|
||||
{
|
||||
return ::pthread_mutex_destroy(m);
|
||||
}
|
||||
BOOST_FORCEINLINE int pthread_mutex_lock(pthread_mutex_t* m)
|
||||
{
|
||||
return ::pthread_mutex_lock(m);
|
||||
}
|
||||
BOOST_FORCEINLINE int pthread_mutex_unlock(pthread_mutex_t* m)
|
||||
{
|
||||
return ::pthread_mutex_unlock(m);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
class mutex
|
||||
class BOOST_THREAD_CAPABILITY("mutex") mutex
|
||||
{
|
||||
private:
|
||||
pthread_mutex_t m;
|
||||
@@ -111,7 +62,7 @@ namespace boost
|
||||
BOOST_ASSERT(!res);
|
||||
}
|
||||
|
||||
void lock()
|
||||
void lock() BOOST_THREAD_ACQUIRE()
|
||||
{
|
||||
int res = posix::pthread_mutex_lock(&m);
|
||||
if (res)
|
||||
@@ -120,7 +71,7 @@ namespace boost
|
||||
}
|
||||
}
|
||||
|
||||
void unlock()
|
||||
void unlock() BOOST_THREAD_RELEASE()
|
||||
{
|
||||
int res = posix::pthread_mutex_unlock(&m);
|
||||
(void)res;
|
||||
@@ -131,12 +82,12 @@ namespace boost
|
||||
// }
|
||||
}
|
||||
|
||||
bool try_lock()
|
||||
bool try_lock() BOOST_THREAD_TRY_ACQUIRE(true)
|
||||
{
|
||||
int res;
|
||||
do
|
||||
{
|
||||
res = pthread_mutex_trylock(&m);
|
||||
res = posix::pthread_mutex_trylock(&m);
|
||||
} while (res == EINTR);
|
||||
if (res==EBUSY)
|
||||
{
|
||||
@@ -165,7 +116,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 +129,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 +142,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 +151,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);
|
||||
@@ -234,7 +206,7 @@ namespace boost
|
||||
int res;
|
||||
do
|
||||
{
|
||||
res = pthread_mutex_trylock(&m);
|
||||
res = posix::pthread_mutex_trylock(&m);
|
||||
} while (res == EINTR);
|
||||
if (res==EBUSY)
|
||||
{
|
||||
@@ -246,9 +218,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;
|
||||
}
|
||||
@@ -260,7 +232,7 @@ namespace boost
|
||||
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
|
||||
while(is_locked)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
|
||||
BOOST_VERIFY(!posix::pthread_cond_wait(&cond,&m));
|
||||
}
|
||||
is_locked=true;
|
||||
}
|
||||
@@ -269,7 +241,7 @@ namespace boost
|
||||
{
|
||||
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
|
||||
is_locked=false;
|
||||
BOOST_VERIFY(!pthread_cond_signal(&cond));
|
||||
BOOST_VERIFY(!posix::pthread_cond_signal(&cond));
|
||||
}
|
||||
|
||||
bool try_lock()
|
||||
@@ -284,18 +256,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 +281,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 +306,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 +338,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
|
||||
@@ -13,6 +13,75 @@
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace posix {
|
||||
#ifdef BOOST_THREAD_HAS_EINTR_BUG
|
||||
BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
|
||||
int pthread_mutex_destroy(pthread_mutex_t* m)
|
||||
{
|
||||
int ret;
|
||||
do
|
||||
{
|
||||
ret = ::pthread_mutex_destroy(m);
|
||||
} while (ret == EINTR);
|
||||
return ret;
|
||||
}
|
||||
BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
|
||||
int pthread_mutex_lock(pthread_mutex_t* m)
|
||||
{
|
||||
int ret;
|
||||
do
|
||||
{
|
||||
ret = ::pthread_mutex_lock(m);
|
||||
} while (ret == EINTR);
|
||||
return ret;
|
||||
}
|
||||
BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
|
||||
int pthread_mutex_unlock(pthread_mutex_t* m)
|
||||
{
|
||||
int ret;
|
||||
do
|
||||
{
|
||||
ret = ::pthread_mutex_unlock(m);
|
||||
} while (ret == EINTR);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
|
||||
int pthread_mutex_destroy(pthread_mutex_t* m)
|
||||
{
|
||||
return ::pthread_mutex_destroy(m);
|
||||
}
|
||||
BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
|
||||
int pthread_mutex_lock(pthread_mutex_t* m)
|
||||
{
|
||||
return ::pthread_mutex_lock(m);
|
||||
}
|
||||
BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
|
||||
int pthread_mutex_unlock(pthread_mutex_t* m)
|
||||
{
|
||||
return ::pthread_mutex_unlock(m);
|
||||
}
|
||||
|
||||
#endif
|
||||
BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
|
||||
int pthread_mutex_trylock(pthread_mutex_t* m)
|
||||
{
|
||||
return ::pthread_mutex_trylock(m);
|
||||
}
|
||||
|
||||
BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
|
||||
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
|
||||
{
|
||||
return ::pthread_cond_wait(cond, mutex);
|
||||
}
|
||||
BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
|
||||
int pthread_cond_signal(pthread_cond_t *cond)
|
||||
{
|
||||
return ::pthread_cond_signal(cond);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
namespace pthread
|
||||
{
|
||||
class pthread_mutex_scoped_lock
|
||||
@@ -23,11 +92,11 @@ namespace boost
|
||||
explicit pthread_mutex_scoped_lock(pthread_mutex_t* m_) BOOST_NOEXCEPT:
|
||||
m(m_),locked(true)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_lock(m));
|
||||
BOOST_VERIFY(!posix::pthread_mutex_lock(m));
|
||||
}
|
||||
void unlock() BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_unlock(m));
|
||||
BOOST_VERIFY(!posix::pthread_mutex_unlock(m));
|
||||
locked=false;
|
||||
}
|
||||
void unlock_if_locked() BOOST_NOEXCEPT
|
||||
@@ -54,11 +123,11 @@ namespace boost
|
||||
explicit pthread_mutex_scoped_unlock(pthread_mutex_t* m_) BOOST_NOEXCEPT:
|
||||
m(m_)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_unlock(m));
|
||||
BOOST_VERIFY(!posix::pthread_mutex_unlock(m));
|
||||
}
|
||||
~pthread_mutex_scoped_unlock() BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_lock(m));
|
||||
BOOST_VERIFY(!posix::pthread_mutex_lock(m));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
@@ -110,17 +105,17 @@ namespace boost
|
||||
#ifdef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
|
||||
void lock()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_lock(&m));
|
||||
BOOST_VERIFY(!posix::pthread_mutex_lock(&m));
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_unlock(&m));
|
||||
BOOST_VERIFY(!posix::pthread_mutex_unlock(&m));
|
||||
}
|
||||
|
||||
bool try_lock() BOOST_NOEXCEPT
|
||||
{
|
||||
int const res=pthread_mutex_trylock(&m);
|
||||
int const res=posix::pthread_mutex_trylock(&m);
|
||||
BOOST_ASSERT(!res || res==EBUSY);
|
||||
return !res;
|
||||
}
|
||||
@@ -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,31 +241,53 @@ 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
|
||||
|
||||
#ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
|
||||
void lock()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_lock(&m));
|
||||
BOOST_VERIFY(!posix::pthread_mutex_lock(&m));
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_unlock(&m));
|
||||
BOOST_VERIFY(!posix::pthread_mutex_unlock(&m));
|
||||
}
|
||||
|
||||
bool try_lock()
|
||||
{
|
||||
int const res=pthread_mutex_trylock(&m);
|
||||
int const res=posix::pthread_mutex_trylock(&m);
|
||||
BOOST_ASSERT(!res || res==EBUSY);
|
||||
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
|
||||
@@ -12,10 +12,12 @@
|
||||
#include <boost/thread/lock_types.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/pthread/condition_variable_fwd.hpp>
|
||||
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
|
||||
|
||||
#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
|
||||
@@ -55,7 +57,7 @@ namespace boost
|
||||
#else
|
||||
std::size_t page_size = ::sysconf( _SC_PAGESIZE);
|
||||
#endif
|
||||
#ifdef PTHREAD_STACK_MIN
|
||||
#if PTHREAD_STACK_MIN > 0
|
||||
if (size<PTHREAD_STACK_MIN) size=PTHREAD_STACK_MIN;
|
||||
#endif
|
||||
size = ((size+page_size-1)/page_size)*page_size;
|
||||
@@ -111,8 +113,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;
|
||||
@@ -131,9 +131,10 @@ namespace boost
|
||||
> notify_list_t;
|
||||
notify_list_t notify;
|
||||
|
||||
//#ifndef BOOST_NO_EXCEPTIONS
|
||||
typedef std::vector<shared_ptr<shared_state_base> > async_states_t;
|
||||
async_states_t async_states_;
|
||||
|
||||
//#endif
|
||||
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
// These data must be at the end so that the access to the other fields doesn't change
|
||||
// when BOOST_THREAD_PROVIDES_INTERRUPTIONS is defined.
|
||||
@@ -149,8 +150,10 @@ namespace boost
|
||||
cond_mutex(0),
|
||||
current_cond(0),
|
||||
//#endif
|
||||
notify(),
|
||||
async_states_()
|
||||
notify()
|
||||
//#ifndef BOOST_NO_EXCEPTIONS
|
||||
, async_states_()
|
||||
//#endif
|
||||
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
, interrupt_enabled(true)
|
||||
, interrupt_requested(false)
|
||||
@@ -166,11 +169,12 @@ namespace boost
|
||||
notify.push_back(std::pair<condition_variable*, mutex*>(cv, m));
|
||||
}
|
||||
|
||||
//#ifndef BOOST_NO_EXCEPTIONS
|
||||
void make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
|
||||
{
|
||||
async_states_.push_back(as);
|
||||
}
|
||||
|
||||
//#endif
|
||||
};
|
||||
|
||||
BOOST_THREAD_DECL thread_data_base* get_current_thread_data();
|
||||
@@ -206,11 +210,11 @@ namespace boost
|
||||
check_for_interruption();
|
||||
thread_info->cond_mutex=cond_mutex;
|
||||
thread_info->current_cond=cond;
|
||||
BOOST_VERIFY(!pthread_mutex_lock(m));
|
||||
BOOST_VERIFY(!posix::pthread_mutex_lock(m));
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_lock(m));
|
||||
BOOST_VERIFY(!posix::pthread_mutex_lock(m));
|
||||
}
|
||||
}
|
||||
void unlock_if_locked()
|
||||
@@ -218,14 +222,14 @@ namespace boost
|
||||
if ( ! done) {
|
||||
if (set)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_unlock(m));
|
||||
BOOST_VERIFY(!posix::pthread_mutex_unlock(m));
|
||||
lock_guard<mutex> guard(thread_info->data_mutex);
|
||||
thread_info->cond_mutex=NULL;
|
||||
thread_info->current_cond=NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_unlock(m));
|
||||
BOOST_VERIFY(!posix::pthread_mutex_unlock(m));
|
||||
}
|
||||
done = true;
|
||||
}
|
||||
@@ -241,49 +245,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 +262,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::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)
|
||||
{
|
||||
long const current_thread_id=boost::detail::winapi::GetCurrentThreadId();
|
||||
template <class Rep, class Period>
|
||||
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
|
||||
{
|
||||
long const current_thread_id=boost::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)
|
||||
{
|
||||
long const current_thread_id=boost::detail::winapi::GetCurrentThreadId();
|
||||
}
|
||||
template <class Clock, class Duration>
|
||||
bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
long const current_thread_id=boost::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>
|
||||
|
||||
@@ -112,8 +113,10 @@ namespace boost
|
||||
> notify_list_t;
|
||||
notify_list_t notify;
|
||||
|
||||
//#ifndef BOOST_NO_EXCEPTIONS
|
||||
typedef std::vector<shared_ptr<shared_state_base> > async_states_t;
|
||||
async_states_t async_states_;
|
||||
//#endif
|
||||
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
// These data must be at the end so that the access to the other fields doesn't change
|
||||
// when BOOST_THREAD_PROVIDES_INTERRUPTIONS is defined
|
||||
@@ -128,8 +131,10 @@ namespace boost
|
||||
thread_exit_callbacks(0),
|
||||
id(0),
|
||||
tss_data(),
|
||||
notify(),
|
||||
async_states_()
|
||||
notify()
|
||||
//#ifndef BOOST_NO_EXCEPTIONS
|
||||
, async_states_()
|
||||
//#endif
|
||||
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
, interruption_handle(create_anonymous_event(detail::win32::manual_reset_event,detail::win32::event_initially_reset))
|
||||
, interruption_enabled(true)
|
||||
@@ -153,7 +158,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;
|
||||
@@ -165,155 +170,121 @@ namespace boost
|
||||
notify.push_back(std::pair<condition_variable*, mutex*>(cv, m));
|
||||
}
|
||||
|
||||
//#ifndef BOOST_NO_EXCEPTIONS
|
||||
void make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
|
||||
{
|
||||
async_states_.push_back(as);
|
||||
}
|
||||
|
||||
//#endif
|
||||
};
|
||||
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 (BOOST_WINAPI_WINAPI_CC *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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,17 +57,17 @@ struct xtime
|
||||
|
||||
};
|
||||
|
||||
inline xtime get_xtime(boost::system_time const& abs_time)
|
||||
inline ::boost::xtime get_xtime(boost::system_time const& abs_time)
|
||||
{
|
||||
xtime res;
|
||||
::boost::xtime res;
|
||||
boost::posix_time::time_duration const time_since_epoch=abs_time-boost::posix_time::from_time_t(0);
|
||||
|
||||
res.sec=static_cast<xtime::xtime_sec_t>(time_since_epoch.total_seconds());
|
||||
res.nsec=static_cast<xtime::xtime_nsec_t>(time_since_epoch.fractional_seconds()*(1000000000/time_since_epoch.ticks_per_second()));
|
||||
res.sec=static_cast< ::boost::xtime::xtime_sec_t>(time_since_epoch.total_seconds());
|
||||
res.nsec=static_cast< ::boost::xtime::xtime_nsec_t>(time_since_epoch.fractional_seconds()*(1000000000/time_since_epoch.ticks_per_second()));
|
||||
return res;
|
||||
}
|
||||
|
||||
inline int xtime_get(struct xtime* xtp, int clock_type)
|
||||
inline int xtime_get(struct ::boost::xtime* xtp, int clock_type)
|
||||
{
|
||||
if (clock_type == TIME_UTC_)
|
||||
{
|
||||
@@ -78,7 +78,7 @@ inline int xtime_get(struct xtime* xtp, int clock_type)
|
||||
}
|
||||
|
||||
|
||||
inline int xtime_cmp(const xtime& xt1, const xtime& xt2)
|
||||
inline int xtime_cmp(const ::boost::xtime& xt1, const ::boost::xtime& xt2)
|
||||
{
|
||||
if (xt1.sec == xt2.sec)
|
||||
return (int)(xt1.nsec - xt2.nsec);
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
|
||||
#include <boost/thread/futures/future_error_code.hpp>
|
||||
#include <string>
|
||||
|
||||
@@ -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>
|
||||
@@ -49,11 +53,13 @@ namespace boost
|
||||
i->second->unlock();
|
||||
i->first->notify_all();
|
||||
}
|
||||
//#ifndef BOOST_NO_EXCEPTIONS
|
||||
for (async_states_t::iterator i = async_states_.begin(), e = async_states_.end();
|
||||
i != e; ++i)
|
||||
{
|
||||
(*i)->notify_deferred();
|
||||
}
|
||||
//#endif
|
||||
}
|
||||
|
||||
struct thread_exit_callback_node
|
||||
@@ -209,8 +215,10 @@ namespace boost
|
||||
~externally_launched_thread() {
|
||||
BOOST_ASSERT(notify.empty());
|
||||
notify.clear();
|
||||
//#ifndef BOOST_NO_EXCEPTIONS
|
||||
BOOST_ASSERT(async_states_.empty());
|
||||
async_states_.clear();
|
||||
//#endif
|
||||
}
|
||||
void run()
|
||||
{}
|
||||
@@ -350,7 +358,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 +369,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 +441,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)
|
||||
@@ -532,16 +470,15 @@ namespace boost
|
||||
# elif defined(BOOST_HAS_PTHREAD_YIELD)
|
||||
BOOST_VERIFY(!pthread_yield());
|
||||
//# elif defined BOOST_THREAD_USES_DATETIME
|
||||
// xtime xt;
|
||||
// ::boost::xtime xt;
|
||||
// xtime_get(&xt, TIME_UTC_);
|
||||
// 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 +493,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
|
||||
@@ -828,6 +777,8 @@ namespace boost
|
||||
current_thread_data->notify_all_at_thread_exit(&cond, lk.release());
|
||||
}
|
||||
}
|
||||
|
||||
//#ifndef BOOST_NO_EXCEPTIONS
|
||||
namespace detail {
|
||||
|
||||
void BOOST_THREAD_DECL make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
|
||||
@@ -839,7 +790,7 @@ namespace detail {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
@@ -54,11 +54,13 @@ namespace boost
|
||||
i->second->unlock();
|
||||
i->first->notify_all();
|
||||
}
|
||||
//#ifndef BOOST_NO_EXCEPTIONS
|
||||
for (async_states_t::iterator i = async_states_.begin(), e = async_states_.end();
|
||||
i != e; ++i)
|
||||
{
|
||||
(*i)->notify_deferred();
|
||||
}
|
||||
//#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,8 +372,10 @@ namespace boost
|
||||
~externally_launched_thread() {
|
||||
BOOST_ASSERT(notify.empty());
|
||||
notify.clear();
|
||||
//#ifndef BOOST_NO_EXCEPTIONS
|
||||
BOOST_ASSERT(async_states_.empty());
|
||||
async_states_.clear();
|
||||
//#endif
|
||||
}
|
||||
|
||||
void run()
|
||||
@@ -439,7 +443,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 +453,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 +496,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
|
||||
@@ -524,12 +522,12 @@ namespace boost
|
||||
GetLogicalProcessorInformation(NULL, &size);
|
||||
if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
|
||||
return 0;
|
||||
const size_t Elements = size / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
|
||||
|
||||
std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> buffer(size);
|
||||
std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> buffer(Elements);
|
||||
if (GetLogicalProcessorInformation(&buffer.front(), &size) == FALSE)
|
||||
return 0;
|
||||
|
||||
const size_t Elements = size / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
|
||||
|
||||
for (size_t i = 0; i < Elements; ++i) {
|
||||
if (buffer[i].Relationship == RelationProcessorCore)
|
||||
@@ -561,62 +559,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 +609,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 +635,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 +661,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 +685,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 +697,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 +727,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 +753,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 +782,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 +805,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 +816,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 +828,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
|
||||
|
||||
|
||||
156
src/win32/thread_primitives.cpp
Normal file
156
src/win32/thread_primitives.cpp
Normal file
@@ -0,0 +1,156 @@
|
||||
// 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)
|
||||
{
|
||||
// GetProcAddress returns a pointer to some function. It can return
|
||||
// pointers to different functions, so it has to return something that is
|
||||
// suitable to store any pointer to function. Microsoft chose FARPROC,
|
||||
// which is int (WINAPI *)() on 32-bit Windows. The user is supposed to
|
||||
// know the signature of the function he requests and perform a cast
|
||||
// (which is a nop on this platform). The result is a pointer to function
|
||||
// with the required signature, which is bitwise equal to what
|
||||
// GetProcAddress returned.
|
||||
// However, gcc >= 8 warns about that.
|
||||
#if defined(BOOST_GCC) && BOOST_GCC >= 80000
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-function-type"
|
||||
#endif
|
||||
boost::detail::win32::detail::gettickcount64_t p =
|
||||
(boost::detail::win32::detail::gettickcount64_t)boost::winapi::get_proc_address(hKernel32, "GetTickCount64");
|
||||
#if defined(BOOST_GCC) && BOOST_GCC >= 80000
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
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)
|
||||
|
||||
@@ -208,6 +208,36 @@ rule thread-compile-fail ( sources : reqs * : name )
|
||||
;
|
||||
}
|
||||
|
||||
rule clang-thread-safety ( properties * )
|
||||
{
|
||||
if <toolset>clang in $(properties)
|
||||
{
|
||||
return <cxxflags>-Werror=thread-safety <define>BOOST_THREAD_ENABLE_THREAD_SAFETY_ANALYSIS ;
|
||||
}
|
||||
else
|
||||
{
|
||||
return <build>no ;
|
||||
}
|
||||
}
|
||||
|
||||
rule thread-safety-compile ( sources : reqs * : name )
|
||||
{
|
||||
return
|
||||
[ compile $(sources)
|
||||
: $(reqs) <conditional>@clang-thread-safety
|
||||
: $(name) ]
|
||||
;
|
||||
}
|
||||
|
||||
rule thread-safety-compile-fail ( sources : reqs * : name )
|
||||
{
|
||||
return
|
||||
[ compile-fail $(sources)
|
||||
: $(reqs) <conditional>@clang-thread-safety
|
||||
: $(name) ]
|
||||
;
|
||||
}
|
||||
|
||||
rule thread-compile ( sources : reqs * : name )
|
||||
{
|
||||
return
|
||||
@@ -325,6 +355,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 +365,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 ]
|
||||
;
|
||||
@@ -459,6 +491,10 @@ rule thread-compile ( sources : reqs * : name )
|
||||
:
|
||||
[ thread-compile-fail ./sync/mutual_exclusion/locks/lock_guard/copy_assign_fail.cpp : : lock_guard__cons__copy_assign_f ]
|
||||
[ thread-compile-fail ./sync/mutual_exclusion/locks/lock_guard/copy_ctor_fail.cpp : : lock_guard__cons__copy_ctor_f ]
|
||||
[ thread-safety-compile ./sync/mutual_exclusion/locks/lock_guard/lock_guard_compile_pass.cpp : : lock_guard__lock_compile_p ]
|
||||
[ thread-safety-compile-fail ./sync/mutual_exclusion/locks/lock_guard/lock_guard_compile_fail.cpp : : lock_guard__lock_compile_f ]
|
||||
[ thread-safety-compile ./sync/mutual_exclusion/locks/lock_guard/lock_guard_adopt_lock_compile_pass.cpp : : lock_guard__adopt_lock_compile_p ]
|
||||
[ thread-safety-compile-fail ./sync/mutual_exclusion/locks/lock_guard/lock_guard_adopt_lock_compile_fail.cpp : : lock_guard__adopt_lock_compile_f ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/lock_guard/adopt_lock_pass.cpp : lock_guard__cons__adopt_lock_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/lock_guard/default_pass.cpp : lock_guard__cons__default_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/locks/lock_guard/types_pass.cpp : lock_guard__types_p ]
|
||||
@@ -613,6 +649,12 @@ rule thread-compile ( sources : reqs * : name )
|
||||
:
|
||||
[ thread-compile-fail ./sync/mutual_exclusion/mutex/assign_fail.cpp : : mutex__assign_f ]
|
||||
[ thread-compile-fail ./sync/mutual_exclusion/mutex/copy_fail.cpp : : mutex__copy_f ]
|
||||
[ thread-safety-compile ./sync/mutual_exclusion/mutex/lock_compile_pass.cpp : : mutex__lock_compile_p ]
|
||||
[ thread-safety-compile-fail ./sync/mutual_exclusion/mutex/lock_compile_fail.cpp : : mutex__lock_compile_f ]
|
||||
# https://bugs.llvm.org/show_bug.cgi?id=32954
|
||||
# http://clang-developers.42468.n3.nabble.com/thread-safety-warnings-specifically-try-acquire-capability-td4059337.html
|
||||
#[ thread-safety-compile ./sync/mutual_exclusion/mutex/try_lock_compile_pass.cpp : : mutex__try_lock_compile_p ]
|
||||
[ thread-safety-compile-fail ./sync/mutual_exclusion/mutex/try_lock_compile_fail.cpp : : mutex__try_lock_compile_f ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/mutex/default_pass.cpp : mutex__default_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/mutex/lock_pass.cpp : mutex__lock_p ]
|
||||
[ thread-run2-noit-pthread ./sync/mutual_exclusion/mutex/native_handle_pass.cpp : mutex__native_handle_p ]
|
||||
@@ -968,9 +1010,45 @@ rule thread-compile ( sources : reqs * : name )
|
||||
#[ thread-run test_11818.cpp ]
|
||||
#[ thread-run test_11796.cpp ]
|
||||
#[ thread-run test_12293.cpp ]
|
||||
[ thread-run test_12949.cpp ]
|
||||
#[ thread-run test_12949.cpp ]
|
||||
#[ thread-run test_13480b.cpp ]
|
||||
[ thread-run test_13561.cpp ]
|
||||
|
||||
;
|
||||
|
||||
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 boost::report_errors();
|
||||
}
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <cassert>
|
||||
#include "../../../timming.hpp"
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
|
||||
@@ -34,29 +35,36 @@ int test2 = 0;
|
||||
|
||||
int runs = 0;
|
||||
|
||||
typedef boost::chrono::steady_clock Clock;
|
||||
typedef boost::chrono::milliseconds milliseconds;
|
||||
typedef boost::chrono::nanoseconds nanoseconds;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
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;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include "../../../timming.hpp"
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
|
||||
@@ -49,30 +50,31 @@ int test2 = 0;
|
||||
|
||||
int runs = 0;
|
||||
|
||||
typedef boost::chrono::system_clock Clock;
|
||||
typedef boost::chrono::milliseconds milliseconds;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
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;
|
||||
|
||||
@@ -23,9 +23,11 @@
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include "../../../timming.hpp"
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
struct Clock
|
||||
{
|
||||
typedef boost::chrono::milliseconds duration;
|
||||
@@ -44,11 +46,14 @@ struct Clock
|
||||
boost::condition_variable cv;
|
||||
boost::mutex mut;
|
||||
|
||||
|
||||
int test1 = 0;
|
||||
int test2 = 0;
|
||||
|
||||
int runs = 0;
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
void f()
|
||||
{
|
||||
try {
|
||||
@@ -58,19 +63,18 @@ 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));
|
||||
ns d = t1 - t0;
|
||||
BOOST_THREAD_TEST_IT(d, ns(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));
|
||||
ns d = t1 - t0 - Clock::duration(250);
|
||||
BOOST_THREAD_TEST_IT(d, ns(max_diff));
|
||||
assert(test2 == 0);
|
||||
}
|
||||
++runs;
|
||||
|
||||
@@ -23,9 +23,13 @@
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include "../../../timming.hpp"
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
|
||||
typedef boost::chrono::milliseconds milliseconds;
|
||||
typedef boost::chrono::nanoseconds nanoseconds;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
struct Clock
|
||||
{
|
||||
typedef boost::chrono::milliseconds duration;
|
||||
@@ -64,6 +68,8 @@ int test2 = 0;
|
||||
|
||||
int runs = 0;
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
void f()
|
||||
{
|
||||
try {
|
||||
@@ -74,17 +80,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 boost::report_errors();
|
||||
}
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "../../../timming.hpp"
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
|
||||
@@ -36,29 +37,33 @@ int test2 = 0;
|
||||
|
||||
int runs = 0;
|
||||
|
||||
typedef boost::chrono::system_clock Clock;
|
||||
typedef boost::chrono::milliseconds milliseconds;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
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));
|
||||
ns d = t1 - t0;
|
||||
BOOST_THREAD_TEST_IT(d, ns(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));
|
||||
ns d = t1 - t0 - ms(250);
|
||||
BOOST_THREAD_TEST_IT(d, ns(max_diff));
|
||||
BOOST_TEST(test2 == 0);
|
||||
}
|
||||
++runs;
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "../../../timming.hpp"
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
|
||||
@@ -51,27 +52,33 @@ int test2 = 0;
|
||||
|
||||
int runs = 0;
|
||||
|
||||
typedef boost::chrono::system_clock Clock;
|
||||
typedef boost::chrono::milliseconds milliseconds;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
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(test2 != 0);
|
||||
ns d = t1 - t0 ;
|
||||
BOOST_THREAD_TEST_IT(d, ns(max_diff));
|
||||
BOOST_TEST(test2 != 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_TEST(t1 - t0 - milliseconds(250) < milliseconds(250+5));
|
||||
BOOST_TEST(test2 == 0);
|
||||
ns d = t1 - t0 - ms(250);
|
||||
BOOST_THREAD_TEST_IT(d, ns(max_diff));
|
||||
BOOST_TEST(test2 == 0);
|
||||
}
|
||||
++runs;
|
||||
}
|
||||
|
||||
@@ -21,9 +21,11 @@
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "../../../timming.hpp"
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
struct Clock
|
||||
{
|
||||
typedef boost::chrono::milliseconds duration;
|
||||
@@ -51,6 +53,8 @@ int test2 = 0;
|
||||
|
||||
int runs = 0;
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
void f()
|
||||
{
|
||||
L1 lk(m0);
|
||||
@@ -59,20 +63,19 @@ 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(test2 != 0);
|
||||
ns d = t1 - t0;
|
||||
BOOST_THREAD_TEST_IT(d, ns(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(test2 == 0);
|
||||
ns d = t1 - t0 - ms(250);
|
||||
BOOST_THREAD_TEST_IT(d, ns(max_diff));
|
||||
BOOST_TEST(test2 == 0);
|
||||
}
|
||||
++runs;
|
||||
}
|
||||
|
||||
@@ -21,9 +21,13 @@
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "../../../timming.hpp"
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
|
||||
struct Clock
|
||||
{
|
||||
typedef boost::chrono::milliseconds duration;
|
||||
@@ -66,6 +70,8 @@ int test2 = 0;
|
||||
|
||||
int runs = 0;
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
void f()
|
||||
{
|
||||
L1 lk(m0);
|
||||
@@ -78,13 +84,15 @@ void f()
|
||||
Clock::time_point t1 = Clock::now();
|
||||
if (runs == 0)
|
||||
{
|
||||
BOOST_TEST(t1 - t0 < Clock::duration(250));
|
||||
ns d = t1 - t0;
|
||||
BOOST_THREAD_TEST_IT(d, ns(max_diff));
|
||||
BOOST_TEST(test2 != 0);
|
||||
BOOST_TEST(r);
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_TEST(t1 - t0 - Clock::duration(250) < Clock::duration(250+2));
|
||||
ns d = t1 - t0 - ms(250);
|
||||
BOOST_THREAD_TEST_IT(d, ns(max_diff));
|
||||
BOOST_TEST(test2 == 0);
|
||||
BOOST_TEST(!r);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
//#define BOOST_THREAD_USES_LOG
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
#include <boost/thread/detail/log.hpp>
|
||||
#include "../../../timming.hpp"
|
||||
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
@@ -37,6 +38,7 @@
|
||||
#endif
|
||||
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
|
||||
namespace boost
|
||||
{
|
||||
@@ -85,6 +87,8 @@ void func5(boost::promise<void> p)
|
||||
p.set_value();
|
||||
}
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
int main()
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
@@ -98,19 +102,20 @@ 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));
|
||||
ns d = t1 - t0;
|
||||
BOOST_THREAD_TEST_IT(d, ns(max_diff));
|
||||
}
|
||||
{
|
||||
typedef int& T;
|
||||
@@ -120,19 +125,20 @@ 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));
|
||||
ns d = t1 - t0;
|
||||
BOOST_THREAD_TEST_IT(d, ns(max_diff));
|
||||
}
|
||||
{
|
||||
typedef void T;
|
||||
@@ -142,19 +148,20 @@ 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));
|
||||
ns d = t1 - t0;
|
||||
BOOST_THREAD_TEST_IT(d, ns(max_diff));
|
||||
}
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/chrono/chrono_io.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "../../../timming.hpp"
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
|
||||
@@ -38,6 +39,7 @@
|
||||
#endif
|
||||
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
|
||||
namespace boost
|
||||
{
|
||||
@@ -86,6 +88,8 @@ void func5(boost::promise<void> p)
|
||||
p.set_value();
|
||||
}
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
int main()
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
@@ -99,19 +103,20 @@ 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));
|
||||
ns d = t1 - t0;
|
||||
BOOST_THREAD_TEST_IT(d, ns(max_diff));
|
||||
}
|
||||
{
|
||||
typedef int& T;
|
||||
@@ -121,19 +126,20 @@ 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));
|
||||
ns d = t1 - t0;
|
||||
BOOST_THREAD_TEST_IT(d, ns(max_diff));
|
||||
}
|
||||
{
|
||||
typedef void T;
|
||||
@@ -143,19 +149,20 @@ 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));
|
||||
ns d = t1 - t0;
|
||||
BOOST_THREAD_TEST_IT(d, ns(max_diff));
|
||||
}
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
|
||||
@@ -59,6 +59,7 @@ int main()
|
||||
BOOST_TEST(!p0.valid());
|
||||
BOOST_TEST(!p.valid());
|
||||
}
|
||||
return boost::report_errors();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/chrono/chrono_io.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "../../../timming.hpp"
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
|
||||
@@ -37,6 +38,7 @@
|
||||
#endif
|
||||
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
|
||||
namespace boost
|
||||
{
|
||||
@@ -85,6 +87,8 @@ void func5(boost::promise<void> p)
|
||||
p.set_value();
|
||||
}
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
int main()
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
@@ -98,19 +102,20 @@ 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));
|
||||
ns d = t1 - t0;
|
||||
BOOST_THREAD_TEST_IT(d, ns(max_diff));
|
||||
}
|
||||
{
|
||||
typedef int& T;
|
||||
@@ -120,19 +125,20 @@ 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));
|
||||
ns d = t1 - t0;
|
||||
BOOST_THREAD_TEST_IT(d, ns(max_diff));
|
||||
}
|
||||
{
|
||||
typedef void T;
|
||||
@@ -142,19 +148,20 @@ 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));
|
||||
ns d = t1 - t0;
|
||||
BOOST_THREAD_TEST_IT(d, ns(max_diff));
|
||||
}
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/chrono/chrono_io.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "../../../timming.hpp"
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
|
||||
@@ -38,6 +39,7 @@
|
||||
#endif
|
||||
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
|
||||
namespace boost
|
||||
{
|
||||
@@ -86,6 +88,8 @@ void func5(boost::promise<void> p)
|
||||
p.set_value();
|
||||
}
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
int main()
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
@@ -99,19 +103,20 @@ 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));
|
||||
ns d = t1 - t0;
|
||||
BOOST_THREAD_TEST_IT(d, ns(max_diff));
|
||||
}
|
||||
{
|
||||
typedef int& T;
|
||||
@@ -121,19 +126,20 @@ 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));
|
||||
ns d = t1 - t0;
|
||||
BOOST_THREAD_TEST_IT(d, ns(max_diff));
|
||||
}
|
||||
{
|
||||
typedef void T;
|
||||
@@ -143,19 +149,20 @@ 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));
|
||||
ns d = t1 - t0;
|
||||
BOOST_THREAD_TEST_IT(d, ns(max_diff));
|
||||
}
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
|
||||
@@ -205,7 +205,6 @@ int main()
|
||||
BOOST_TEST(all.valid());
|
||||
BOOST_TEST(! all.is_ready());
|
||||
pt1();
|
||||
BOOST_TEST(! all.is_ready());
|
||||
pt2();
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(300));
|
||||
BOOST_TEST(all.is_ready());
|
||||
|
||||
@@ -169,7 +169,6 @@ int main()
|
||||
BOOST_TEST(all.valid());
|
||||
BOOST_TEST(! all.is_ready());
|
||||
pt1();
|
||||
BOOST_TEST(! all.is_ready());
|
||||
pt2();
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(300));
|
||||
BOOST_TEST(all.is_ready());
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "../../../../timming.hpp"
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
typedef boost::chrono::high_resolution_clock Clock;
|
||||
@@ -29,21 +30,22 @@ typedef Clock::time_point time_point;
|
||||
typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
time_point t0;
|
||||
time_point t1;
|
||||
#endif
|
||||
boost::mutex m;
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
void f()
|
||||
{
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
time_point t0 = Clock::now();
|
||||
time_point t1;
|
||||
t0 = Clock::now();
|
||||
{
|
||||
m.lock();
|
||||
boost::lock_guard<boost::mutex> lg(m, boost::adopt_lock);
|
||||
t1 = Clock::now();
|
||||
}
|
||||
ns d = t1 - t0 - ms(250);
|
||||
BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
//time_point t1;
|
||||
@@ -53,7 +55,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
|
||||
}
|
||||
|
||||
@@ -62,11 +64,22 @@ int main()
|
||||
m.lock();
|
||||
boost::thread t(f);
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
time_point t2 = Clock::now();
|
||||
boost::this_thread::sleep_for(ms(250));
|
||||
time_point t3 = Clock::now();
|
||||
#endif
|
||||
m.unlock();
|
||||
t.join();
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
ns sleep_time = t3 - t2;
|
||||
ns d_ns = t1 - t0 - sleep_time;
|
||||
ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns);
|
||||
// BOOST_TEST_GE(d_ms.count(), 0);
|
||||
BOOST_THREAD_TEST_IT(d_ms, max_diff);
|
||||
BOOST_THREAD_TEST_IT(d_ns, ns(max_diff));
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "../../../../timming.hpp"
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
typedef boost::chrono::high_resolution_clock Clock;
|
||||
@@ -29,22 +30,22 @@ typedef Clock::time_point time_point;
|
||||
typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
time_point t0;
|
||||
time_point t1;
|
||||
#endif
|
||||
|
||||
boost::mutex m;
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
void f()
|
||||
{
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
time_point t0 = Clock::now();
|
||||
time_point t1;
|
||||
t0 = Clock::now();
|
||||
{
|
||||
boost::lock_guard<boost::mutex> lg(m);
|
||||
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
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
//time_point t1;
|
||||
@@ -53,8 +54,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
|
||||
}
|
||||
|
||||
@@ -63,10 +63,21 @@ int main()
|
||||
m.lock();
|
||||
boost::thread t(f);
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
time_point t2 = Clock::now();
|
||||
boost::this_thread::sleep_for(ms(250));
|
||||
time_point t3 = Clock::now();
|
||||
#endif
|
||||
m.unlock();
|
||||
t.join();
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
ns sleep_time = t3 - t2;
|
||||
ns d_ns = t1 - t0 - sleep_time;
|
||||
ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns);
|
||||
// BOOST_TEST_GE(d_ms.count(), 0);
|
||||
BOOST_THREAD_TEST_IT(d_ms, max_diff);
|
||||
BOOST_THREAD_TEST_IT(d_ns, ns(max_diff));
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright (C) 2018 Tom Hughes
|
||||
//
|
||||
// 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/lock_guard.hpp>
|
||||
|
||||
// template <class Mutex> class lock_guard;
|
||||
|
||||
// lock_guard(Mutex& m_, adopt_lock_t)
|
||||
|
||||
#include <boost/thread/lock_guard.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
boost::mutex m;
|
||||
|
||||
void fail()
|
||||
{
|
||||
boost::lock_guard<boost::mutex> lk(m, boost::adopt_lock);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright (C) 2018 Tom Hughes
|
||||
//
|
||||
// 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/lock_guard.hpp>
|
||||
|
||||
// template <class Mutex> class lock_guard;
|
||||
|
||||
// lock_guard(Mutex& m_, adopt_lock_t)
|
||||
|
||||
#include <boost/thread/lock_guard.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
boost::mutex m;
|
||||
|
||||
void pass()
|
||||
{
|
||||
m.lock();
|
||||
boost::lock_guard<boost::mutex> lk(m, boost::adopt_lock);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright (C) 2018 Tom Hughes
|
||||
//
|
||||
// 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/lock_guard.hpp>
|
||||
|
||||
// template <class Mutex> class lock_guard;
|
||||
|
||||
// lock_guard(Mutex& m_)
|
||||
|
||||
#include <boost/thread/lock_guard.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
boost::mutex m;
|
||||
|
||||
void fail()
|
||||
{
|
||||
boost::lock_guard<boost::mutex> lk0(m);
|
||||
boost::lock_guard<boost::mutex> lk1(m);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// Copyright (C) 2018 Tom Hughes
|
||||
//
|
||||
// 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/lock_guard.hpp>
|
||||
|
||||
// template <class Mutex> class lock_guard;
|
||||
|
||||
// lock_guard(Mutex& m_)
|
||||
|
||||
#include <boost/thread/lock_guard.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
boost::mutex m;
|
||||
|
||||
void pass()
|
||||
{
|
||||
{
|
||||
boost::lock_guard<boost::mutex> lk0(m);
|
||||
}
|
||||
boost::lock_guard<boost::mutex> lk1(m);
|
||||
}
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "../../../../timming.hpp"
|
||||
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
@@ -31,24 +32,25 @@ typedef Clock::time_point time_point;
|
||||
typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
time_point t0;
|
||||
time_point t1;
|
||||
#endif
|
||||
boost::mutex m;
|
||||
|
||||
#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ! defined BOOST_THREAD_NO_MAKE_LOCK_GUARD
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
void f()
|
||||
{
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
time_point t0 = Clock::now();
|
||||
time_point t1;
|
||||
t0 = Clock::now();
|
||||
{
|
||||
m.lock();
|
||||
auto&& lg = boost::make_lock_guard(m, boost::adopt_lock); (void)lg;
|
||||
|
||||
t1 = Clock::now();
|
||||
}
|
||||
ns d = t1 - t0 - ms(250);
|
||||
BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
//time_point t1;
|
||||
@@ -58,7 +60,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
|
||||
@@ -69,10 +71,22 @@ int main()
|
||||
m.lock();
|
||||
boost::thread t(f);
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
time_point t2 = Clock::now();
|
||||
boost::this_thread::sleep_for(ms(250));
|
||||
time_point t3 = Clock::now();
|
||||
#endif
|
||||
m.unlock();
|
||||
t.join();
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
ns sleep_time = t3 - t2;
|
||||
ns d_ns = t1 - t0 - sleep_time;
|
||||
ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns);
|
||||
// BOOST_TEST_GE(d_ms.count(), 0);
|
||||
BOOST_THREAD_TEST_IT(d_ms, max_diff);
|
||||
BOOST_THREAD_TEST_IT(d_ns, ns(max_diff));
|
||||
#endif
|
||||
|
||||
#endif
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <boost/thread/thread.hpp>
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "../../../../timming.hpp"
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
typedef boost::chrono::high_resolution_clock Clock;
|
||||
@@ -31,36 +32,45 @@ typedef Clock::time_point time_point;
|
||||
typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
time_point t0;
|
||||
time_point t1;
|
||||
#endif
|
||||
|
||||
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
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
void f()
|
||||
{
|
||||
time_point t0 = Clock::now();
|
||||
time_point t1;
|
||||
t0 = Clock::now();
|
||||
{
|
||||
const auto&& lg = boost::make_lock_guard(m); (void)lg;
|
||||
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
|
||||
}
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ! defined BOOST_THREAD_NO_MAKE_LOCK_GUARD
|
||||
#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
|
||||
{
|
||||
m.lock();
|
||||
boost::thread t(f);
|
||||
time_point t2 = Clock::now();
|
||||
boost::this_thread::sleep_for(ms(250));
|
||||
time_point t3 = Clock::now();
|
||||
m.unlock();
|
||||
t.join();
|
||||
|
||||
ns sleep_time = t3 - t2;
|
||||
ns d_ns = t1 - t0 - sleep_time;
|
||||
ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns);
|
||||
// BOOST_TEST_GE(d_ms.count(), 0);
|
||||
BOOST_THREAD_TEST_IT(d_ms, max_diff);
|
||||
BOOST_THREAD_TEST_IT(d_ns, ns(max_diff));
|
||||
}
|
||||
#endif
|
||||
return boost::report_errors();
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "../../../../timming.hpp"
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
typedef boost::chrono::high_resolution_clock Clock;
|
||||
@@ -21,23 +22,23 @@ typedef Clock::time_point time_point;
|
||||
typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
time_point t0;
|
||||
time_point t1;
|
||||
#endif
|
||||
|
||||
boost::mutex m;
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
void f()
|
||||
{
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
time_point t0 = Clock::now();
|
||||
time_point t1;
|
||||
t0 = Clock::now();
|
||||
boost::unique_lock<boost::mutex> lg(m);
|
||||
{
|
||||
boost::nested_strict_lock<boost::unique_lock<boost::mutex> > nlg(lg);
|
||||
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
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
//time_point t1;
|
||||
@@ -47,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);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -58,10 +58,21 @@ int main()
|
||||
m.lock();
|
||||
boost::thread t(f);
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
time_point t2 = Clock::now();
|
||||
boost::this_thread::sleep_for(ms(250));
|
||||
time_point t3 = Clock::now();
|
||||
#endif
|
||||
m.unlock();
|
||||
t.join();
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
ns sleep_time = t3 - t2;
|
||||
ns d_ns = t1 - t0 - sleep_time;
|
||||
ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns);
|
||||
// BOOST_TEST_GE(d_ms.count(), 0);
|
||||
BOOST_THREAD_TEST_IT(d_ms, max_diff);
|
||||
BOOST_THREAD_TEST_IT(d_ns, ns(max_diff));
|
||||
#endif
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <boost/thread/thread.hpp>
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "../../../../timming.hpp"
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
typedef boost::chrono::high_resolution_clock Clock;
|
||||
@@ -23,37 +24,46 @@ typedef Clock::time_point time_point;
|
||||
typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
time_point t0;
|
||||
time_point t1;
|
||||
#endif
|
||||
|
||||
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
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
void f()
|
||||
{
|
||||
time_point t0 = Clock::now();
|
||||
time_point t1;
|
||||
t0 = Clock::now();
|
||||
boost::unique_lock<boost::mutex> lg(m);
|
||||
{
|
||||
const auto&& nlg = boost::make_nested_strict_lock(lg); (void)nlg;
|
||||
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
|
||||
}
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ! defined BOOST_THREAD_NO_MAKE_NESTED_STRICT_LOCK
|
||||
#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
|
||||
{
|
||||
m.lock();
|
||||
boost::thread t(f);
|
||||
time_point t2 = Clock::now();
|
||||
boost::this_thread::sleep_for(ms(250));
|
||||
time_point t3 = Clock::now();
|
||||
m.unlock();
|
||||
t.join();
|
||||
|
||||
ns sleep_time = t3 - t2;
|
||||
ns d_ns = t1 - t0 - sleep_time;
|
||||
ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns);
|
||||
// BOOST_TEST_GE(d_ms.count(), 0);
|
||||
BOOST_THREAD_TEST_IT(d_ms, max_diff);
|
||||
BOOST_THREAD_TEST_IT(d_ns, ns(max_diff));
|
||||
}
|
||||
#endif
|
||||
return boost::report_errors();
|
||||
|
||||
@@ -24,36 +24,36 @@
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <boost/chrono/chrono_io.hpp>
|
||||
#include "../../../../../timming.hpp"
|
||||
|
||||
boost::shared_mutex m;
|
||||
|
||||
typedef boost::chrono::steady_clock Clock;
|
||||
typedef boost::chrono::high_resolution_clock Clock;
|
||||
typedef Clock::time_point time_point;
|
||||
typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
time_point t0;
|
||||
time_point t1;
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
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));
|
||||
t0 = Clock::now();
|
||||
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
|
||||
t1 = Clock::now();
|
||||
}
|
||||
|
||||
void f2()
|
||||
{
|
||||
time_point t0 = Clock::now();
|
||||
t0 = Clock::now();
|
||||
boost::shared_lock<boost::shared_mutex> lk(m, ms(250));
|
||||
BOOST_TEST(lk.owns_lock() == false);
|
||||
time_point t1 = Clock::now();
|
||||
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_THREAD_TEST_IT(d, ns(max_diff));
|
||||
}
|
||||
|
||||
int main()
|
||||
@@ -61,15 +61,23 @@ int main()
|
||||
{
|
||||
m.lock();
|
||||
boost::thread t(f1);
|
||||
time_point t2 = Clock::now();
|
||||
boost::this_thread::sleep_for(ms(250));
|
||||
time_point t3 = Clock::now();
|
||||
m.unlock();
|
||||
t.join();
|
||||
|
||||
ns sleep_time = t3 - t2;
|
||||
ns d_ns = t1 - t0 - sleep_time;
|
||||
ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns);
|
||||
// BOOST_TEST_GE(d_ms.count(), 0);
|
||||
BOOST_THREAD_TEST_IT(d_ms, max_diff);
|
||||
BOOST_THREAD_TEST_IT(d_ns, ns(max_diff));
|
||||
}
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -18,35 +18,35 @@
|
||||
|
||||
// explicit shared_lock(Mutex& m);
|
||||
|
||||
|
||||
#include <boost/thread/lock_types.hpp>
|
||||
#include <boost/thread/shared_mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "../../../../../timming.hpp"
|
||||
|
||||
boost::shared_mutex m;
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
typedef boost::chrono::system_clock Clock;
|
||||
typedef boost::chrono::high_resolution_clock Clock;
|
||||
typedef Clock::time_point time_point;
|
||||
typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
time_point t0;
|
||||
time_point t1;
|
||||
#else
|
||||
#endif
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
time_point t0 = Clock::now();
|
||||
time_point t1;
|
||||
t0 = Clock::now();
|
||||
{
|
||||
boost::shared_lock<boost::shared_mutex> ul(m);
|
||||
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
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
//time_point t1;
|
||||
@@ -55,8 +55,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
|
||||
}
|
||||
|
||||
@@ -65,12 +64,23 @@ int main()
|
||||
m.lock();
|
||||
boost::thread t(f);
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
time_point t2 = Clock::now();
|
||||
boost::this_thread::sleep_for(ms(250));
|
||||
time_point t3 = Clock::now();
|
||||
#else
|
||||
#endif
|
||||
m.unlock();
|
||||
t.join();
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
ns sleep_time = t3 - t2;
|
||||
ns d_ns = t1 - t0 - sleep_time;
|
||||
ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns);
|
||||
// BOOST_TEST_GE(d_ms.count(), 0);
|
||||
BOOST_THREAD_TEST_IT(d_ms, max_diff);
|
||||
BOOST_THREAD_TEST_IT(d_ns, ns(max_diff));
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
|
||||
@@ -23,36 +23,36 @@
|
||||
#include <boost/thread/shared_mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "../../../../../timming.hpp"
|
||||
|
||||
boost::shared_mutex m;
|
||||
|
||||
typedef boost::chrono::steady_clock Clock;
|
||||
typedef boost::chrono::high_resolution_clock Clock;
|
||||
typedef Clock::time_point time_point;
|
||||
typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
time_point t0;
|
||||
time_point t1;
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
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));
|
||||
t0 = Clock::now();
|
||||
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
|
||||
t1 = Clock::now();
|
||||
}
|
||||
|
||||
void f2()
|
||||
{
|
||||
time_point t0 = Clock::now();
|
||||
t0 = Clock::now();
|
||||
boost::shared_lock<boost::shared_mutex> lk(m, Clock::now() + ms(250));
|
||||
BOOST_TEST(lk.owns_lock() == false);
|
||||
time_point t1 = Clock::now();
|
||||
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_THREAD_TEST_IT(d, ns(max_diff));
|
||||
}
|
||||
|
||||
int main()
|
||||
@@ -60,14 +60,23 @@ int main()
|
||||
{
|
||||
m.lock();
|
||||
boost::thread t(f1);
|
||||
time_point t2 = Clock::now();
|
||||
boost::this_thread::sleep_for(ms(250));
|
||||
time_point t3 = Clock::now();
|
||||
m.unlock();
|
||||
t.join();
|
||||
|
||||
ns sleep_time = t3 - t2;
|
||||
ns d_ns = t1 - t0 - sleep_time;
|
||||
ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns);
|
||||
// BOOST_TEST_GE(d_ms.count(), 0);
|
||||
BOOST_THREAD_TEST_IT(d_ms, max_diff);
|
||||
BOOST_THREAD_TEST_IT(d_ns, ns(max_diff));
|
||||
}
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -18,27 +18,31 @@
|
||||
|
||||
// shared_lock(mutex_type& m, try_to_lock_t);
|
||||
|
||||
|
||||
#include <boost/thread/lock_types.hpp>
|
||||
#include <boost/thread/shared_mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "../../../../../timming.hpp"
|
||||
|
||||
boost::shared_mutex m;
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
typedef boost::chrono::system_clock Clock;
|
||||
typedef boost::chrono::high_resolution_clock Clock;
|
||||
typedef Clock::time_point time_point;
|
||||
typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
time_point t0;
|
||||
time_point t1;
|
||||
#else
|
||||
#endif
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
time_point t0 = Clock::now();
|
||||
t0 = Clock::now();
|
||||
{
|
||||
boost::shared_lock<boost::shared_mutex> lk(m, boost::try_to_lock);
|
||||
BOOST_TEST(lk.owns_lock() == false);
|
||||
@@ -54,12 +58,11 @@ void f()
|
||||
for (;;)
|
||||
{
|
||||
boost::shared_lock<boost::shared_mutex> lk(m, boost::try_to_lock);
|
||||
if (lk.owns_lock()) break;
|
||||
if (lk.owns_lock()) {
|
||||
t1 = Clock::now();
|
||||
break;
|
||||
}
|
||||
}
|
||||
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
|
||||
#else
|
||||
// time_point t0 = Clock::now();
|
||||
// {
|
||||
@@ -81,8 +84,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
|
||||
}
|
||||
|
||||
@@ -91,12 +93,23 @@ int main()
|
||||
m.lock();
|
||||
boost::thread t(f);
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
time_point t2 = Clock::now();
|
||||
boost::this_thread::sleep_for(ms(250));
|
||||
time_point t3 = Clock::now();
|
||||
#else
|
||||
#endif
|
||||
m.unlock();
|
||||
t.join();
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
ns sleep_time = t3 - t2;
|
||||
ns d_ns = t1 - t0 - sleep_time;
|
||||
ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns);
|
||||
// BOOST_TEST_GE(d_ms.count(), 0);
|
||||
BOOST_THREAD_TEST_IT(d_ms, max_diff);
|
||||
BOOST_THREAD_TEST_IT(d_ns, ns(max_diff));
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
|
||||
@@ -23,29 +23,31 @@
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <iostream>
|
||||
#include "../../../../../timming.hpp"
|
||||
|
||||
boost::shared_mutex m;
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
typedef boost::chrono::system_clock Clock;
|
||||
typedef boost::chrono::high_resolution_clock Clock;
|
||||
typedef Clock::time_point time_point;
|
||||
typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
time_point t0;
|
||||
time_point t1;
|
||||
#else
|
||||
#endif
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
boost::shared_lock < boost::shared_mutex > lk(m, boost::defer_lock);
|
||||
time_point t0 = Clock::now();
|
||||
t0 = Clock::now();
|
||||
lk.lock();
|
||||
time_point t1 = Clock::now();
|
||||
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
|
||||
try
|
||||
{
|
||||
lk.lock();
|
||||
@@ -73,8 +75,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();
|
||||
@@ -103,12 +104,23 @@ int main()
|
||||
m.lock();
|
||||
boost::thread t(f);
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
time_point t2 = Clock::now();
|
||||
boost::this_thread::sleep_for(ms(250));
|
||||
time_point t3 = Clock::now();
|
||||
#else
|
||||
#endif
|
||||
m.unlock();
|
||||
t.join();
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
ns sleep_time = t3 - t2;
|
||||
ns d_ns = t1 - t0 - sleep_time;
|
||||
ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns);
|
||||
// BOOST_TEST_GE(d_ms.count(), 0);
|
||||
BOOST_THREAD_TEST_IT(d_ms, max_diff);
|
||||
BOOST_THREAD_TEST_IT(d_ns, ns(max_diff));
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <boost/thread/shared_mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "../../../../timming.hpp"
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
typedef boost::chrono::high_resolution_clock Clock;
|
||||
@@ -29,23 +30,24 @@ typedef Clock::time_point time_point;
|
||||
typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
time_point t0;
|
||||
time_point t1;
|
||||
#else
|
||||
#endif
|
||||
|
||||
boost::shared_mutex m;
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
time_point t0 = Clock::now();
|
||||
time_point t1;
|
||||
t0 = Clock::now();
|
||||
{
|
||||
m.lock_shared();
|
||||
boost::shared_lock_guard<boost::shared_mutex> lg(m, boost::adopt_lock);
|
||||
t1 = Clock::now();
|
||||
}
|
||||
ns d = t1 - t0 - ms(250);
|
||||
BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
//time_point t1;
|
||||
@@ -55,7 +57,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
|
||||
}
|
||||
|
||||
@@ -64,12 +66,23 @@ int main()
|
||||
m.lock();
|
||||
boost::thread t(f);
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
time_point t2 = Clock::now();
|
||||
boost::this_thread::sleep_for(ms(250));
|
||||
time_point t3 = Clock::now();
|
||||
#else
|
||||
#endif
|
||||
m.unlock();
|
||||
t.join();
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
ns sleep_time = t3 - t2;
|
||||
ns d_ns = t1 - t0 - sleep_time;
|
||||
ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns);
|
||||
// BOOST_TEST_GE(d_ms.count(), 0);
|
||||
BOOST_THREAD_TEST_IT(d_ms, max_diff);
|
||||
BOOST_THREAD_TEST_IT(d_ns, ns(max_diff));
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include <boost/thread/shared_mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <iostream>
|
||||
#include "../../../../timming.hpp"
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
typedef boost::chrono::high_resolution_clock Clock;
|
||||
@@ -29,23 +31,23 @@ typedef Clock::time_point time_point;
|
||||
typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
time_point t0;
|
||||
time_point t1;
|
||||
#else
|
||||
#endif
|
||||
|
||||
boost::shared_mutex m;
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
time_point t0 = Clock::now();
|
||||
time_point t1;
|
||||
t0 = Clock::now();
|
||||
{
|
||||
boost::shared_lock_guard<boost::shared_mutex> lg(m);
|
||||
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
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
//time_point t1;
|
||||
@@ -54,8 +56,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
|
||||
}
|
||||
|
||||
@@ -64,11 +65,22 @@ int main()
|
||||
m.lock();
|
||||
boost::thread t(f);
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
time_point t2 = Clock::now();
|
||||
boost::this_thread::sleep_for(ms(250));
|
||||
time_point t3 = Clock::now();
|
||||
#else
|
||||
#endif
|
||||
m.unlock();
|
||||
t.join();
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
ns sleep_time = t3 - t2;
|
||||
ns d_ns = t1 - t0 - sleep_time;
|
||||
ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns);
|
||||
// BOOST_TEST_GE(d_ms.count(), 0);
|
||||
BOOST_THREAD_TEST_IT(d_ms, max_diff);
|
||||
BOOST_THREAD_TEST_IT(d_ns, ns(max_diff));
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "../../../../timming.hpp"
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
typedef boost::chrono::high_resolution_clock Clock;
|
||||
@@ -20,22 +21,22 @@ typedef Clock::time_point time_point;
|
||||
typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
time_point t0;
|
||||
time_point t1;
|
||||
#endif
|
||||
|
||||
boost::mutex m;
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
void f()
|
||||
{
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
time_point t0 = Clock::now();
|
||||
time_point t1;
|
||||
t0 = Clock::now();
|
||||
{
|
||||
boost::strict_lock<boost::mutex> lg(m);
|
||||
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
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
//time_point t1;
|
||||
@@ -44,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
|
||||
}
|
||||
|
||||
@@ -54,10 +54,21 @@ int main()
|
||||
m.lock();
|
||||
boost::thread t(f);
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
time_point t2 = Clock::now();
|
||||
boost::this_thread::sleep_for(ms(250));
|
||||
time_point t3 = Clock::now();
|
||||
#endif
|
||||
m.unlock();
|
||||
t.join();
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
ns sleep_time = t3 - t2;
|
||||
ns d_ns = t1 - t0 - sleep_time;
|
||||
ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns);
|
||||
// BOOST_TEST_GE(d_ms.count(), 0);
|
||||
BOOST_THREAD_TEST_IT(d_ms, max_diff);
|
||||
BOOST_THREAD_TEST_IT(d_ns, ns(max_diff));
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <boost/thread/thread.hpp>
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "../../../../timming.hpp"
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
typedef boost::chrono::high_resolution_clock Clock;
|
||||
@@ -22,36 +23,47 @@ typedef Clock::time_point time_point;
|
||||
typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
time_point t0;
|
||||
time_point t1;
|
||||
#endif
|
||||
|
||||
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
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
void f()
|
||||
{
|
||||
time_point t0 = Clock::now();
|
||||
time_point t1;
|
||||
t0 = Clock::now();
|
||||
{
|
||||
const auto&& lg = boost::make_strict_lock(m); (void)lg;
|
||||
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_THREAD_TEST_IT(d, ns(max_diff));
|
||||
}
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ! defined BOOST_THREAD_NO_MAKE_STRICT_LOCK
|
||||
#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
|
||||
{
|
||||
m.lock();
|
||||
boost::thread t(f);
|
||||
time_point t2 = Clock::now();
|
||||
boost::this_thread::sleep_for(ms(250));
|
||||
time_point t3 = Clock::now();
|
||||
m.unlock();
|
||||
t.join();
|
||||
|
||||
ns sleep_time = t3 - t2;
|
||||
ns d_ns = t1 - t0 - sleep_time;
|
||||
ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns);
|
||||
// BOOST_TEST_GE(d_ms.count(), 0);
|
||||
BOOST_THREAD_TEST_IT(d_ms, max_diff);
|
||||
BOOST_THREAD_TEST_IT(d_ns, ns(max_diff));
|
||||
}
|
||||
#endif
|
||||
return boost::report_errors();
|
||||
|
||||
@@ -26,38 +26,38 @@
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <boost/chrono/chrono_io.hpp>
|
||||
#include "../../../../../timming.hpp"
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
|
||||
boost::timed_mutex m;
|
||||
|
||||
typedef boost::chrono::steady_clock Clock;
|
||||
typedef boost::chrono::high_resolution_clock Clock;
|
||||
typedef Clock::time_point time_point;
|
||||
typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
time_point t0;
|
||||
time_point t1;
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
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));
|
||||
t0 = Clock::now();
|
||||
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
|
||||
t1 = Clock::now();
|
||||
}
|
||||
|
||||
void f2()
|
||||
{
|
||||
time_point t0 = Clock::now();
|
||||
t0 = Clock::now();
|
||||
boost::unique_lock<boost::timed_mutex> lk(m, ms(250));
|
||||
BOOST_TEST(lk.owns_lock() == false);
|
||||
time_point t1 = Clock::now();
|
||||
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_THREAD_TEST_IT(d, ns(max_diff));
|
||||
}
|
||||
|
||||
int main()
|
||||
@@ -65,14 +65,23 @@ int main()
|
||||
{
|
||||
m.lock();
|
||||
boost::thread t(f1);
|
||||
time_point t2 = Clock::now();
|
||||
boost::this_thread::sleep_for(ms(250));
|
||||
time_point t3 = Clock::now();
|
||||
m.unlock();
|
||||
t.join();
|
||||
|
||||
ns sleep_time = t3 - t2;
|
||||
ns d_ns = t1 - t0 - sleep_time;
|
||||
ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns);
|
||||
// BOOST_TEST_GE(d_ms.count(), 0);
|
||||
BOOST_THREAD_TEST_IT(d_ms, max_diff);
|
||||
BOOST_THREAD_TEST_IT(d_ns, ns(max_diff));
|
||||
}
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "../../../../../timming.hpp"
|
||||
|
||||
//#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
|
||||
@@ -22,19 +23,22 @@ boost::mutex m;
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
|
||||
typedef boost::chrono::system_clock Clock;
|
||||
typedef boost::chrono::high_resolution_clock Clock;
|
||||
typedef Clock::time_point time_point;
|
||||
typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
time_point t0;
|
||||
time_point t1;
|
||||
#else
|
||||
#endif
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
time_point t0 = Clock::now();
|
||||
time_point t1;
|
||||
t0 = Clock::now();
|
||||
{
|
||||
#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS)
|
||||
auto
|
||||
@@ -45,9 +49,6 @@ void f()
|
||||
_ = boost::make_unique_lock(m); (void)_;
|
||||
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
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
//time_point t1;
|
||||
@@ -62,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
|
||||
}
|
||||
|
||||
@@ -72,12 +72,23 @@ int main()
|
||||
m.lock();
|
||||
boost::thread t(f);
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
time_point t2 = Clock::now();
|
||||
boost::this_thread::sleep_for(ms(250));
|
||||
time_point t3 = Clock::now();
|
||||
#else
|
||||
#endif
|
||||
m.unlock();
|
||||
t.join();
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
ns sleep_time = t3 - t2;
|
||||
ns d_ns = t1 - t0 - sleep_time;
|
||||
ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns);
|
||||
// BOOST_TEST_GE(d_ms.count(), 0);
|
||||
BOOST_THREAD_TEST_IT(d_ms, max_diff);
|
||||
BOOST_THREAD_TEST_IT(d_ns, ns(max_diff));
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
//#else
|
||||
|
||||
@@ -15,23 +15,28 @@
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "../../../../../timming.hpp"
|
||||
|
||||
boost::mutex m;
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
typedef boost::chrono::system_clock Clock;
|
||||
typedef boost::chrono::high_resolution_clock Clock;
|
||||
typedef Clock::time_point time_point;
|
||||
typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
time_point t0;
|
||||
time_point t1;
|
||||
#else
|
||||
#endif
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
{
|
||||
time_point t0 = Clock::now();
|
||||
t0 = Clock::now();
|
||||
#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS)
|
||||
auto
|
||||
#else
|
||||
@@ -39,13 +44,12 @@ void f()
|
||||
#endif
|
||||
lk = boost::make_unique_lock(m, boost::try_to_lock);
|
||||
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
|
||||
t1 = Clock::now();
|
||||
ns d = t1 - t0;
|
||||
BOOST_THREAD_TEST_IT(d, ns(max_diff));
|
||||
}
|
||||
{
|
||||
time_point t0 = Clock::now();
|
||||
t0 = Clock::now();
|
||||
#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS)
|
||||
auto
|
||||
#else
|
||||
@@ -53,13 +57,12 @@ void f()
|
||||
#endif
|
||||
lk = boost::make_unique_lock(m, boost::try_to_lock);
|
||||
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
|
||||
t1 = Clock::now();
|
||||
ns d = t1 - t0;
|
||||
BOOST_THREAD_TEST_IT(d, ns(max_diff));
|
||||
}
|
||||
{
|
||||
time_point t0 = Clock::now();
|
||||
t0 = Clock::now();
|
||||
#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS)
|
||||
auto
|
||||
#else
|
||||
@@ -67,13 +70,12 @@ void f()
|
||||
#endif
|
||||
lk = boost::make_unique_lock(m, boost::try_to_lock);
|
||||
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
|
||||
t1 = Clock::now();
|
||||
ns d = t1 - t0;
|
||||
BOOST_THREAD_TEST_IT(d, ns(max_diff));
|
||||
}
|
||||
{
|
||||
time_point t0 = Clock::now();
|
||||
t0 = Clock::now();
|
||||
for (;;)
|
||||
{
|
||||
#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS)
|
||||
@@ -82,12 +84,11 @@ void f()
|
||||
boost::unique_lock<boost::mutex>
|
||||
#endif
|
||||
lk = boost::make_unique_lock(m, boost::try_to_lock);
|
||||
if (lk.owns_lock()) break;
|
||||
if (lk.owns_lock()) {
|
||||
t1 = Clock::now();
|
||||
break;
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
#else
|
||||
// time_point t0 = Clock::now();
|
||||
@@ -115,8 +116,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
|
||||
}
|
||||
|
||||
@@ -125,11 +125,22 @@ int main()
|
||||
m.lock();
|
||||
boost::thread t(f);
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
time_point t2 = Clock::now();
|
||||
boost::this_thread::sleep_for(ms(250));
|
||||
time_point t3 = Clock::now();
|
||||
#else
|
||||
#endif
|
||||
m.unlock();
|
||||
t.join();
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
ns sleep_time = t3 - t2;
|
||||
ns d_ns = t1 - t0 - sleep_time;
|
||||
ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns);
|
||||
// BOOST_TEST_GE(d_ms.count(), 0);
|
||||
BOOST_THREAD_TEST_IT(d_ms, max_diff);
|
||||
BOOST_THREAD_TEST_IT(d_ns, ns(max_diff));
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "../../../../../timming.hpp"
|
||||
|
||||
#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && ! defined BOOST_THREAD_NO_MAKE_UNIQUE_LOCKS && ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
|
||||
@@ -24,26 +25,26 @@ boost::mutex m3;
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
|
||||
typedef boost::chrono::system_clock Clock;
|
||||
typedef boost::chrono::high_resolution_clock Clock;
|
||||
typedef Clock::time_point time_point;
|
||||
typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
time_point t0;
|
||||
time_point t1;
|
||||
#else
|
||||
#endif
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
time_point t0 = Clock::now();
|
||||
time_point t1;
|
||||
t0 = Clock::now();
|
||||
{
|
||||
auto&& _ = boost::make_unique_locks(m1,m2,m3); (void)_;
|
||||
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
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
//time_point t1;
|
||||
@@ -52,8 +53,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
|
||||
}
|
||||
|
||||
@@ -64,7 +64,9 @@ int main()
|
||||
m3.lock();
|
||||
boost::thread t(f);
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
time_point t2 = Clock::now();
|
||||
boost::this_thread::sleep_for(ms(250));
|
||||
time_point t3 = Clock::now();
|
||||
#else
|
||||
#endif
|
||||
m1.unlock();
|
||||
@@ -72,6 +74,15 @@ int main()
|
||||
m3.unlock();
|
||||
t.join();
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
ns sleep_time = t3 - t2;
|
||||
ns d_ns = t1 - t0 - sleep_time;
|
||||
ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns);
|
||||
// BOOST_TEST_GE(d_ms.count(), 0);
|
||||
BOOST_THREAD_TEST_IT(d_ms, max_diff);
|
||||
BOOST_THREAD_TEST_IT(d_ns, ns(max_diff));
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -23,31 +23,33 @@
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <iostream>
|
||||
#include "../../../../../timming.hpp"
|
||||
|
||||
|
||||
boost::mutex m;
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
typedef boost::chrono::system_clock Clock;
|
||||
typedef boost::chrono::high_resolution_clock Clock;
|
||||
typedef Clock::time_point time_point;
|
||||
typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
time_point t0;
|
||||
time_point t1;
|
||||
#else
|
||||
#endif
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
time_point t0 = Clock::now();
|
||||
time_point t1;
|
||||
t0 = Clock::now();
|
||||
{
|
||||
boost::unique_lock<boost::mutex> ul(m);
|
||||
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
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
//time_point t1;
|
||||
@@ -56,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
|
||||
}
|
||||
|
||||
@@ -66,12 +67,23 @@ int main()
|
||||
m.lock();
|
||||
boost::thread t(f);
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
time_point t2 = Clock::now();
|
||||
boost::this_thread::sleep_for(ms(250));
|
||||
time_point t3 = Clock::now();
|
||||
#else
|
||||
#endif
|
||||
m.unlock();
|
||||
t.join();
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
ns sleep_time = t3 - t2;
|
||||
ns d_ns = t1 - t0 - sleep_time;
|
||||
ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns);
|
||||
// BOOST_TEST_GE(d_ms.count(), 0);
|
||||
BOOST_THREAD_TEST_IT(d_ms, max_diff);
|
||||
BOOST_THREAD_TEST_IT(d_ns, ns(max_diff));
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
|
||||
@@ -25,38 +25,38 @@
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "../../../../../timming.hpp"
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
|
||||
boost::timed_mutex m;
|
||||
|
||||
typedef boost::chrono::steady_clock Clock;
|
||||
typedef boost::chrono::high_resolution_clock Clock;
|
||||
typedef Clock::time_point time_point;
|
||||
typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
time_point t0;
|
||||
time_point t1;
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
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));
|
||||
t0 = Clock::now();
|
||||
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
|
||||
t1 = Clock::now();
|
||||
}
|
||||
|
||||
void f2()
|
||||
{
|
||||
time_point t0 = Clock::now();
|
||||
t0 = Clock::now();
|
||||
boost::unique_lock<boost::timed_mutex> lk(m, Clock::now() + ms(250));
|
||||
BOOST_TEST(lk.owns_lock() == false);
|
||||
time_point t1 = Clock::now();
|
||||
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()
|
||||
@@ -64,14 +64,23 @@ int main()
|
||||
{
|
||||
m.lock();
|
||||
boost::thread t(f1);
|
||||
time_point t2 = Clock::now();
|
||||
boost::this_thread::sleep_for(ms(250));
|
||||
time_point t3 = Clock::now();
|
||||
m.unlock();
|
||||
t.join();
|
||||
|
||||
ns sleep_time = t3 - t2;
|
||||
ns d_ns = t1 - t0 - sleep_time;
|
||||
ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns);
|
||||
// BOOST_TEST_GE(d_ms.count(), 0);
|
||||
BOOST_THREAD_TEST_IT(d_ms, max_diff);
|
||||
BOOST_THREAD_TEST_IT(d_ns, ns(max_diff));
|
||||
}
|
||||
{
|
||||
m.lock();
|
||||
boost::thread t(f2);
|
||||
boost::this_thread::sleep_for(ms(350));
|
||||
boost::this_thread::sleep_for(ms(750));
|
||||
m.unlock();
|
||||
t.join();
|
||||
}
|
||||
|
||||
@@ -23,23 +23,28 @@
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "../../../../../timming.hpp"
|
||||
|
||||
|
||||
boost::mutex m;
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
typedef boost::chrono::system_clock Clock;
|
||||
typedef boost::chrono::high_resolution_clock Clock;
|
||||
typedef Clock::time_point time_point;
|
||||
typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
time_point t0;
|
||||
time_point t1;
|
||||
#else
|
||||
#endif
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
time_point t0 = Clock::now();
|
||||
t0 = Clock::now();
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(m, boost::try_to_lock);
|
||||
BOOST_TEST(lk.owns_lock() == false);
|
||||
@@ -55,13 +60,12 @@ void f()
|
||||
for (;;)
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(m, boost::try_to_lock);
|
||||
if (lk.owns_lock()) break;
|
||||
if (lk.owns_lock()) {
|
||||
t1 = Clock::now();
|
||||
break;
|
||||
}
|
||||
}
|
||||
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
|
||||
#else
|
||||
// time_point t0 = Clock::now();
|
||||
// {
|
||||
@@ -83,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
|
||||
}
|
||||
|
||||
@@ -93,12 +96,25 @@ int main()
|
||||
m.lock();
|
||||
boost::thread t(f);
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
time_point t2 = Clock::now();
|
||||
boost::this_thread::sleep_for(ms(250));
|
||||
time_point t3 = Clock::now();
|
||||
#else
|
||||
#endif
|
||||
m.unlock();
|
||||
t.join();
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
ns sleep_time = t3 - t2;
|
||||
ns d_ns = t1 - t0 - sleep_time;
|
||||
ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns);
|
||||
std::cout << "d_ns: " << d_ns.count() << std::endl;
|
||||
std::cout << "d_ms: " << d_ms.count() << std::endl;
|
||||
// BOOST_TEST_GE(d_ms.count(), 0);
|
||||
BOOST_THREAD_TEST_IT(d_ms, max_diff);
|
||||
BOOST_THREAD_TEST_IT(d_ns, ns(max_diff));
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
|
||||
@@ -23,29 +23,31 @@
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <iostream>
|
||||
#include "../../../../../timming.hpp"
|
||||
|
||||
boost::mutex m;
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
typedef boost::chrono::system_clock Clock;
|
||||
typedef boost::chrono::high_resolution_clock Clock;
|
||||
typedef Clock::time_point time_point;
|
||||
typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
time_point t0;
|
||||
time_point t1;
|
||||
#else
|
||||
#endif
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
boost::unique_lock < boost::mutex > lk(m, boost::defer_lock);
|
||||
time_point t0 = Clock::now();
|
||||
t0 = Clock::now();
|
||||
lk.lock();
|
||||
time_point t1 = Clock::now();
|
||||
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
|
||||
try
|
||||
{
|
||||
lk.lock();
|
||||
@@ -73,8 +75,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();
|
||||
@@ -103,12 +104,23 @@ int main()
|
||||
m.lock();
|
||||
boost::thread t(f);
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
time_point t2 = Clock::now();
|
||||
boost::this_thread::sleep_for(ms(250));
|
||||
time_point t3 = Clock::now();
|
||||
#else
|
||||
#endif
|
||||
m.unlock();
|
||||
t.join();
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
ns sleep_time = t3 - t2;
|
||||
ns d_ns = t1 - t0 - sleep_time;
|
||||
ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns);
|
||||
// BOOST_TEST_GE(d_ms.count(), 0);
|
||||
BOOST_THREAD_TEST_IT(d_ms, max_diff);
|
||||
BOOST_THREAD_TEST_IT(d_ns, ns(max_diff));
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -26,36 +26,36 @@
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <boost/chrono/chrono_io.hpp>
|
||||
#include "../../../../../timming.hpp"
|
||||
|
||||
boost::shared_mutex m;
|
||||
|
||||
typedef boost::chrono::steady_clock Clock;
|
||||
typedef boost::chrono::high_resolution_clock Clock;
|
||||
typedef Clock::time_point time_point;
|
||||
typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
time_point t0;
|
||||
time_point t1;
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
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));
|
||||
t0 = Clock::now();
|
||||
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
|
||||
t1 = Clock::now();
|
||||
}
|
||||
|
||||
void f2()
|
||||
{
|
||||
time_point t0 = Clock::now();
|
||||
t0 = Clock::now();
|
||||
boost::upgrade_lock<boost::shared_mutex> lk(m, ms(250));
|
||||
BOOST_TEST(lk.owns_lock() == false);
|
||||
time_point t1 = Clock::now();
|
||||
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_THREAD_TEST_IT(d, ns(max_diff));
|
||||
}
|
||||
|
||||
int main()
|
||||
@@ -63,14 +63,23 @@ int main()
|
||||
{
|
||||
m.lock();
|
||||
boost::thread t(f1);
|
||||
time_point t2 = Clock::now();
|
||||
boost::this_thread::sleep_for(ms(250));
|
||||
time_point t3 = Clock::now();
|
||||
m.unlock();
|
||||
t.join();
|
||||
|
||||
ns sleep_time = t3 - t2;
|
||||
ns d_ns = t1 - t0 - sleep_time;
|
||||
ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns);
|
||||
// BOOST_TEST_GE(d_ms.count(), 0);
|
||||
BOOST_THREAD_TEST_IT(d_ms, max_diff);
|
||||
BOOST_THREAD_TEST_IT(d_ns, ns(max_diff));
|
||||
}
|
||||
{
|
||||
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,30 +23,32 @@
|
||||
#include <boost/thread/shared_mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <iostream>
|
||||
#include "../../../../../timming.hpp"
|
||||
|
||||
boost::shared_mutex m;
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
typedef boost::chrono::system_clock Clock;
|
||||
typedef boost::chrono::high_resolution_clock Clock;
|
||||
typedef Clock::time_point time_point;
|
||||
typedef Clock::duration duration;
|
||||
typedef boost::chrono::milliseconds ms;
|
||||
typedef boost::chrono::nanoseconds ns;
|
||||
time_point t0;
|
||||
time_point t1;
|
||||
#else
|
||||
#endif
|
||||
|
||||
const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
|
||||
|
||||
void f()
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
time_point t0 = Clock::now();
|
||||
time_point t1;
|
||||
t0 = Clock::now();
|
||||
{
|
||||
boost::upgrade_lock<boost::shared_mutex> ul(m);
|
||||
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
|
||||
#else
|
||||
//time_point t0 = Clock::now();
|
||||
//time_point t1;
|
||||
@@ -55,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
|
||||
}
|
||||
|
||||
@@ -65,12 +66,23 @@ int main()
|
||||
m.lock();
|
||||
boost::thread t(f);
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
time_point t2 = Clock::now();
|
||||
boost::this_thread::sleep_for(ms(250));
|
||||
time_point t3 = Clock::now();
|
||||
#else
|
||||
#endif
|
||||
m.unlock();
|
||||
t.join();
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
ns sleep_time = t3 - t2;
|
||||
ns d_ns = t1 - t0 - sleep_time;
|
||||
ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns);
|
||||
// BOOST_TEST_GE(d_ms.count(), 0);
|
||||
BOOST_THREAD_TEST_IT(d_ms, max_diff);
|
||||
BOOST_THREAD_TEST_IT(d_ns, ns(max_diff));
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user