mirror of
https://github.com/boostorg/thread.git
synced 2026-02-03 09:42:16 +00:00
Compare commits
422 Commits
pdimov-pat
...
feature/up
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
49ece352b3 | ||
|
|
116e8f6eb8 | ||
|
|
66892e5ddd | ||
|
|
42a48f4b03 | ||
|
|
f33abfd621 | ||
|
|
0277d357ae | ||
|
|
e18ae7b173 | ||
|
|
119009f2d1 | ||
|
|
9eee38db94 | ||
|
|
3e59ecec49 | ||
|
|
b1842da010 | ||
|
|
b0da8e291b | ||
|
|
1d436f9030 | ||
|
|
8ebd61c280 | ||
|
|
c13beec81c | ||
|
|
9b0e0714f0 | ||
|
|
a2492a49af | ||
|
|
25ea5c83ed | ||
|
|
1623ca9e05 | ||
|
|
b1d20a5ce7 | ||
|
|
5f9a247e0b | ||
|
|
9efc377980 | ||
|
|
5589c69547 | ||
|
|
74fb0a2609 | ||
|
|
1eb8efbad7 | ||
|
|
76ce71930f | ||
|
|
2e0bae88f7 | ||
|
|
5507e47ac2 | ||
|
|
2492e7a48c | ||
|
|
0ee9ad87eb | ||
|
|
47fd6b85e3 | ||
|
|
042ce47e77 | ||
|
|
65dcf92e48 | ||
|
|
3071b9e8b5 | ||
|
|
8190a50838 | ||
|
|
23539a88c0 | ||
|
|
6168f43db8 | ||
|
|
a05c37a997 | ||
|
|
34e354be4c | ||
|
|
ccf70ce0aa | ||
|
|
86b7ceb05a | ||
|
|
a645ef761d | ||
|
|
9a20debf11 | ||
|
|
2502b2741b | ||
|
|
5c6180fa4f | ||
|
|
c6863c4b27 | ||
|
|
48a4a06f86 | ||
|
|
a0b255768e | ||
|
|
e5eef80c28 | ||
|
|
ff38aad946 | ||
|
|
7966756ac4 | ||
|
|
8aac9047ab | ||
|
|
f90bdfd2a5 | ||
|
|
7b8fe78ccf | ||
|
|
d49236480f | ||
|
|
ea54f2ec4d | ||
|
|
2553ce4fa0 | ||
|
|
d4c2cef0a2 | ||
|
|
ba02b3af42 | ||
|
|
5d20f5b342 | ||
|
|
52b742d001 | ||
|
|
e16786f173 | ||
|
|
9342fe3f25 | ||
|
|
085c9c6ca8 | ||
|
|
7ba2f2cf5b | ||
|
|
800d0ca597 | ||
|
|
81d4e5a824 | ||
|
|
c97b504925 | ||
|
|
758d087662 | ||
|
|
f5133ab829 | ||
|
|
c46da73e3a | ||
|
|
e942774b90 | ||
|
|
c90ed87527 | ||
|
|
970dcb8afd | ||
|
|
8d0f077ab2 | ||
|
|
dfe6cc3c49 | ||
|
|
330a0a15e6 | ||
|
|
f60dfdfad9 | ||
|
|
ccb1b99e3f | ||
|
|
aa444afc5c | ||
|
|
f1d464d0d5 | ||
|
|
57161ddbb6 | ||
|
|
9a7d21444f | ||
|
|
1b2bc4e451 | ||
|
|
e1b5f9d786 | ||
|
|
8b5cd5f02a | ||
|
|
5b2ffe7104 | ||
|
|
5af180ba36 | ||
|
|
340cc5ab61 | ||
|
|
9a3b8bb4b0 | ||
|
|
79f955e229 | ||
|
|
1da2a57124 | ||
|
|
54871e21a1 | ||
|
|
00efec75d9 | ||
|
|
c66c4b1c76 | ||
|
|
6c70eccb01 | ||
|
|
fbf8d58ad7 | ||
|
|
46a94dd8ba | ||
|
|
76c7b25d4b | ||
|
|
eb297ce86c | ||
|
|
cc31d32b3f | ||
|
|
7f258e5da3 | ||
|
|
c3897bea65 | ||
|
|
502876f0e9 | ||
|
|
e1e4cbf4be | ||
|
|
d2679fec89 | ||
|
|
ba5632e33a | ||
|
|
9a3b7ff859 | ||
|
|
a35ffa3a83 | ||
|
|
1a8229160e | ||
|
|
acda67baf4 | ||
|
|
f6609a42dc | ||
|
|
534f5af9e6 | ||
|
|
2be8908dcd | ||
|
|
aaca72e34b | ||
|
|
24404dcae4 | ||
|
|
f4b239bab1 | ||
|
|
bf7e79c709 | ||
|
|
526e2d6554 | ||
|
|
8c1d232b8c | ||
|
|
92a5bc4300 | ||
|
|
0389f58f23 | ||
|
|
5b209c2e83 | ||
|
|
33ad8b1834 | ||
|
|
8fb92dfb52 | ||
|
|
c550979eff | ||
|
|
15f2d7a21c | ||
|
|
371fb42709 | ||
|
|
f7581a3662 | ||
|
|
e54f7e3960 | ||
|
|
d1284b02ad | ||
|
|
c5e756d196 | ||
|
|
ee607c86d4 | ||
|
|
68eef9240f | ||
|
|
de7608f067 | ||
|
|
743f2a0348 | ||
|
|
d8d549cf3e | ||
|
|
fc08c1fe28 | ||
|
|
dce24d5b43 | ||
|
|
b45ae62791 | ||
|
|
b0485bafdd | ||
|
|
3b52a8950f | ||
|
|
e60f66e023 | ||
|
|
2a68582676 | ||
|
|
b7ebda0f15 | ||
|
|
7b2289a1c5 | ||
|
|
377bb87ad5 | ||
|
|
180ca01c97 | ||
|
|
a6dede8199 | ||
|
|
25b915308a | ||
|
|
079871ffac | ||
|
|
4d62627668 | ||
|
|
2b88759f43 | ||
|
|
d60968b61c | ||
|
|
5aad4ac056 | ||
|
|
2ef70e02a5 | ||
|
|
f525a18239 | ||
|
|
5c2dd21508 | ||
|
|
6d9aaff58a | ||
|
|
db72b0477d | ||
|
|
1f08b38461 | ||
|
|
8cffb15e1e | ||
|
|
3f1590bce7 | ||
|
|
37e5c6513c | ||
|
|
7585187d1c | ||
|
|
8764a5b3dd | ||
|
|
9f9feca70c | ||
|
|
d268106bf8 | ||
|
|
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 | ||
|
|
b86f9eda93 | ||
|
|
4d26e4a07f | ||
|
|
f329ba3540 | ||
|
|
adbd9c8d4c | ||
|
|
b12858610a | ||
|
|
3ebd3b6bce | ||
|
|
f247ef75cd | ||
|
|
f67e6d4417 | ||
|
|
517f1efc56 | ||
|
|
db160fa8c5 | ||
|
|
983fb2e686 | ||
|
|
f794d5a9d1 | ||
|
|
e3f586836a | ||
|
|
82e2c82e95 | ||
|
|
3479524845 | ||
|
|
178e0661ab | ||
|
|
b94c36f960 | ||
|
|
9f7e37c892 | ||
|
|
e7d6055ed3 | ||
|
|
75d5ebbea5 | ||
|
|
9969ec8504 | ||
|
|
995033cf20 | ||
|
|
d5da7a4dda | ||
|
|
659d309206 | ||
|
|
847dcbf237 | ||
|
|
35d25851ce | ||
|
|
5ffca91e60 | ||
|
|
51e6e654e3 | ||
|
|
71bc9c855d | ||
|
|
f3492f8da0 | ||
|
|
3c25ad09ce | ||
|
|
a2e037bb54 | ||
|
|
a4a21b1c12 | ||
|
|
e9ce83b399 | ||
|
|
c2b207faa4 | ||
|
|
c3a007e88b | ||
|
|
68abb96818 | ||
|
|
29c3b48da0 | ||
|
|
9c1c372067 | ||
|
|
13713f3b9c | ||
|
|
776d42f6cb | ||
|
|
b20ea9ebb1 | ||
|
|
46c1ae6f96 | ||
|
|
f02f23eff5 | ||
|
|
fb0317ec7d | ||
|
|
417a2d8a46 | ||
|
|
ce7f2b09cc | ||
|
|
e6226a95ba | ||
|
|
aa221d02b5 | ||
|
|
5a7d8eca6f | ||
|
|
de4ee72554 | ||
|
|
ad5ea75ddd | ||
|
|
dd1b5282b2 | ||
|
|
45321f0570 | ||
|
|
4e83359537 | ||
|
|
961a0689f3 | ||
|
|
bafc9f43a5 | ||
|
|
ab3da91e67 | ||
|
|
6ee1c88869 | ||
|
|
b98d022d40 | ||
|
|
f2d6d99d54 | ||
|
|
aeb54ddbe5 | ||
|
|
2fb41edf1a | ||
|
|
4d385bedd3 | ||
|
|
03a2ea4612 | ||
|
|
c290fc5f98 | ||
|
|
23861b9608 | ||
|
|
24fd5953c9 | ||
|
|
8f51d9c4a7 | ||
|
|
5dcc5f6d26 | ||
|
|
70a4ce8eb3 | ||
|
|
8207b88e97 | ||
|
|
de7e354a8e | ||
|
|
981e993d40 | ||
|
|
bad686d620 | ||
|
|
2f1b1c4d44 | ||
|
|
d8f24d9183 | ||
|
|
0fa843532e | ||
|
|
7b49f3f354 | ||
|
|
e6f876e830 | ||
|
|
285d35f43f | ||
|
|
a18dfa1fea | ||
|
|
f5ccff5b6e | ||
|
|
4329e5be07 | ||
|
|
962ef813b4 | ||
|
|
1c51b5d9b8 | ||
|
|
a9706f0745 | ||
|
|
8e718893e5 | ||
|
|
f56bc930bc | ||
|
|
f1dec7935f | ||
|
|
732f8c7458 | ||
|
|
dd66147e07 | ||
|
|
aebbcda3fe | ||
|
|
5b4d230d4a | ||
|
|
48a2a960da | ||
|
|
728c8f9507 | ||
|
|
d0db967e3b | ||
|
|
6b174a3419 | ||
|
|
d40e0faceb | ||
|
|
0a71259442 | ||
|
|
aa2fea2250 | ||
|
|
a759fc693d | ||
|
|
9813c81ef3 | ||
|
|
65989edb97 | ||
|
|
1c85a84474 | ||
|
|
c86ef1721c | ||
|
|
e2b9ce78c2 | ||
|
|
576231942d | ||
|
|
9b4c86dbd4 | ||
|
|
82eed2ca6d | ||
|
|
56016e8348 | ||
|
|
b6b6a6944a | ||
|
|
dfb64a5af5 | ||
|
|
711bcae5d7 | ||
|
|
ed9ce65eb8 | ||
|
|
d7010f9924 | ||
|
|
b64aad9869 | ||
|
|
739f8eeb81 | ||
|
|
eead731177 | ||
|
|
c689b6205c | ||
|
|
03431ae64f | ||
|
|
c33b4bafbb | ||
|
|
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 |
465
.travis.yml
465
.travis.yml
@@ -4,13 +4,7 @@
|
||||
|
||||
language: cpp
|
||||
|
||||
sudo: false
|
||||
|
||||
python: "2.7"
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
os: linux
|
||||
|
||||
branches:
|
||||
only:
|
||||
@@ -28,120 +22,89 @@ matrix:
|
||||
- env: BOGUS_JOB=true
|
||||
|
||||
include:
|
||||
# - os: linux
|
||||
# compiler: g++-4.7
|
||||
# env: TOOLSET=gcc COMPILER=g++-4.7 CXXSTD=c++11
|
||||
# addons:
|
||||
# apt:
|
||||
# packages:
|
||||
# - g++-4.7
|
||||
# sources:
|
||||
# - ubuntu-toolchain-r-test
|
||||
#
|
||||
# - os: linux
|
||||
# compiler: g++-4.8
|
||||
# env: TOOLSET=gcc COMPILER=g++-4.8 CXXSTD=c++11
|
||||
# addons:
|
||||
# apt:
|
||||
# packages:
|
||||
# - g++-4.8
|
||||
# sources:
|
||||
# - ubuntu-toolchain-r-test
|
||||
#
|
||||
# - os: linux
|
||||
# compiler: g++-4.9
|
||||
# env: TOOLSET=gcc COMPILER=g++-4.9 CXXSTD=c++11
|
||||
# addons:
|
||||
# apt:
|
||||
# packages:
|
||||
# - g++-4.9
|
||||
# sources:
|
||||
# - ubuntu-toolchain-r-test
|
||||
#
|
||||
# - os: linux
|
||||
# compiler: g++-5
|
||||
# env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++98
|
||||
# addons:
|
||||
# apt:
|
||||
# packages:
|
||||
# - g++-5
|
||||
# sources:
|
||||
# - ubuntu-toolchain-r-test
|
||||
#
|
||||
# - os: linux
|
||||
# compiler: g++-5
|
||||
# env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++11
|
||||
# addons:
|
||||
# apt:
|
||||
# packages:
|
||||
# - g++-5
|
||||
# sources:
|
||||
# - ubuntu-toolchain-r-test
|
||||
#
|
||||
# - os: linux
|
||||
# compiler: g++-5
|
||||
# env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++14
|
||||
# addons:
|
||||
# apt:
|
||||
# packages:
|
||||
# - g++-5
|
||||
# sources:
|
||||
# - ubuntu-toolchain-r-test
|
||||
#
|
||||
# - os: linux
|
||||
# compiler: g++-5
|
||||
# env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++1z
|
||||
# addons:
|
||||
# apt:
|
||||
# packages:
|
||||
# - g++-5
|
||||
# sources:
|
||||
# - ubuntu-toolchain-r-test
|
||||
#
|
||||
# - os: linux
|
||||
# compiler: g++-6
|
||||
# env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++98
|
||||
# addons:
|
||||
# apt:
|
||||
# packages:
|
||||
# - g++-6
|
||||
# sources:
|
||||
# - ubuntu-toolchain-r-test
|
||||
#
|
||||
# - os: linux
|
||||
# compiler: g++-6
|
||||
# env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++11
|
||||
# addons:
|
||||
# apt:
|
||||
# packages:
|
||||
# - g++-6
|
||||
# sources:
|
||||
# - ubuntu-toolchain-r-test
|
||||
#
|
||||
# - os: linux
|
||||
# compiler: g++-6
|
||||
# env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++14
|
||||
# addons:
|
||||
# apt:
|
||||
# packages:
|
||||
# - g++-6
|
||||
# sources:
|
||||
# - ubuntu-toolchain-r-test
|
||||
#
|
||||
# - os: linux
|
||||
# compiler: g++-6
|
||||
# env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++1z
|
||||
# addons:
|
||||
# apt:
|
||||
# packages:
|
||||
# - g++-6
|
||||
# sources:
|
||||
# - ubuntu-toolchain-r-test
|
||||
- os: linux
|
||||
compiler: g++-4.4
|
||||
env: TOOLSET=gcc CXXSTD=98,0x HEADERS_ONLY=1
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-4.4
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-4.6
|
||||
env: TOOLSET=gcc CXXSTD=98,0x HEADERS_ONLY=1
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-4.6
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-4.7
|
||||
env: TOOLSET=gcc CXXSTD=03,11 HEADERS_ONLY=1
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-4.7
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-4.8
|
||||
env: TOOLSET=gcc CXXSTD=03,11 HEADERS_ONLY=1
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-4.8
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-4.9
|
||||
env: TOOLSET=gcc CXXSTD=03,11 HEADERS_ONLY=1
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-4.9
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-5
|
||||
env: TOOLSET=gcc CXXSTD=03
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-5
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-5
|
||||
env: TOOLSET=gcc CXXSTD=11
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-5
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-6
|
||||
env: TOOLSET=gcc CXXSTD=14,1z HEADERS_ONLY=1
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-6
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
dist: trusty
|
||||
compiler: g++-7
|
||||
env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=c++98
|
||||
env: TOOLSET=gcc CXXSTD=14,17 HEADERS_ONLY=1
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
@@ -150,215 +113,199 @@ matrix:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
dist: trusty
|
||||
compiler: g++-7
|
||||
env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=c++11
|
||||
compiler: g++-8
|
||||
env: TOOLSET=gcc CXXSTD=14,17 HEADERS_ONLY=1
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-7
|
||||
- g++-8
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-9
|
||||
env: TOOLSET=gcc CXXSTD=14
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-9
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-9
|
||||
env: TOOLSET=gcc CXXSTD=17
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-9
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
dist: trusty
|
||||
compiler: g++-7
|
||||
env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=c++14
|
||||
compiler: clang++-3.5
|
||||
env: TOOLSET=clang CXXSTD=03,11 HEADERS_ONLY=1
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-7
|
||||
- clang-3.5
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
dist: trusty
|
||||
compiler: g++-7
|
||||
env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=c++1z
|
||||
compiler: clang++-3.6
|
||||
env: TOOLSET=clang CXXSTD=03,11,14 HEADERS_ONLY=1
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-7
|
||||
- clang-3.6
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.7
|
||||
env: TOOLSET=clang CXXSTD=03,11,14 HEADERS_ONLY=1
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.7
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.8
|
||||
env: TOOLSET=clang CXXSTD=03,11,14 HEADERS_ONLY=1
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.8
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.9
|
||||
env: TOOLSET=clang CXXSTD=03,11,14,1z HEADERS_ONLY=1
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.9
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
# - os: linux
|
||||
# compiler: clang++-3.5
|
||||
# env: TOOLSET=clang COMPILER=clang++-3.5 CXXSTD=c++11
|
||||
# addons:
|
||||
# apt:
|
||||
# packages:
|
||||
# - clang-3.5
|
||||
# sources:
|
||||
# - ubuntu-toolchain-r-test
|
||||
# - llvm-toolchain-precise-3.5#
|
||||
#
|
||||
# - os: linux
|
||||
# compiler: clang++-3.6
|
||||
# env: TOOLSET=clang COMPILER=clang++-3.6 CXXSTD=c++11
|
||||
# addons:
|
||||
# apt:
|
||||
# packages:
|
||||
# - clang-3.6
|
||||
# sources:
|
||||
# - ubuntu-toolchain-r-test
|
||||
# - llvm-toolchain-precise-3.6
|
||||
#
|
||||
# - os: linux
|
||||
# compiler: clang++-3.7
|
||||
# env: TOOLSET=clang COMPILER=clang++-3.7 CXXSTD=c++11
|
||||
# addons:
|
||||
# apt:
|
||||
# packages:
|
||||
# - clang-3.7
|
||||
# sources:
|
||||
# - ubuntu-toolchain-r-test
|
||||
# - llvm-toolchain-precise-3.7
|
||||
#
|
||||
# - os: linux
|
||||
# compiler: clang++-3.8
|
||||
# env: TOOLSET=clang COMPILER=clang++-3.8 CXXSTD=c++11
|
||||
# addons:
|
||||
# apt:
|
||||
# packages:
|
||||
# - clang-3.8
|
||||
# sources:
|
||||
# - ubuntu-toolchain-r-test
|
||||
# - llvm-toolchain-precise-3.8
|
||||
#
|
||||
# - os: linux
|
||||
# compiler: clang++-3.8
|
||||
# env: TOOLSET=clang COMPILER=clang++-3.8 CXXSTD=c++14
|
||||
# addons:
|
||||
# apt:
|
||||
# packages:
|
||||
# - clang-3.8
|
||||
# sources:
|
||||
# - ubuntu-toolchain-r-test
|
||||
# - llvm-toolchain-precise-3.8
|
||||
#
|
||||
# - os: linux
|
||||
# compiler: clang++-3.8
|
||||
# env: TOOLSET=clang COMPILER=clang++-3.8 CXXSTD=c++1z
|
||||
# addons:
|
||||
# apt:
|
||||
# packages:
|
||||
# - clang-3.8
|
||||
# sources:
|
||||
# - ubuntu-toolchain-r-test
|
||||
# - llvm-toolchain-precise-3.8
|
||||
#
|
||||
# - os: linux
|
||||
# compiler: clang++-3.9
|
||||
# env: TOOLSET=clang COMPILER=clang++-3.9 CXXSTD=c++11
|
||||
# addons:
|
||||
# apt:
|
||||
# packages:
|
||||
# - clang-3.9
|
||||
# sources:
|
||||
# - ubuntu-toolchain-r-test
|
||||
# - llvm-toolchain-precise-3.9
|
||||
#
|
||||
# - os: linux
|
||||
# compiler: clang++-3.9
|
||||
# env: TOOLSET=clang COMPILER=clang++-3.9 CXXSTD=c++14
|
||||
# addons:
|
||||
# apt:
|
||||
# packages:
|
||||
# - clang-3.9
|
||||
# sources:
|
||||
# - ubuntu-toolchain-r-test
|
||||
# - llvm-toolchain-precise-3.9
|
||||
#
|
||||
# - os: linux
|
||||
# compiler: clang++-3.9
|
||||
# env: TOOLSET=clang COMPILER=clang++-3.9 CXXSTD=c++1z
|
||||
# addons:
|
||||
# apt:
|
||||
# packages:
|
||||
# - clang-3.9
|
||||
# sources:
|
||||
# - ubuntu-toolchain-r-test
|
||||
# - llvm-toolchain-precise-3.9
|
||||
#
|
||||
- os: linux
|
||||
compiler: clang++-4.0
|
||||
env: TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=c++98
|
||||
env: TOOLSET=clang CXXSTD=03,11,14,1z HEADERS_ONLY=1
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-4.0
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-4.0
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-4.0
|
||||
env: TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=c++11
|
||||
compiler: clang++-5.0
|
||||
env: TOOLSET=clang CXXSTD=03,11,14,1z HEADERS_ONLY=1
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-4.0
|
||||
- clang-5.0
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-4.0
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-4.0
|
||||
env: TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=c++14
|
||||
compiler: clang++-6.0
|
||||
env: TOOLSET=clang CXXSTD=14,17 HEADERS_ONLY=1
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-4.0
|
||||
- clang-6.0
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-4.0
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-4.0
|
||||
env: TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=c++1z
|
||||
compiler: clang++-7
|
||||
env: TOOLSET=clang CXXSTD=14,17,2a HEADERS_ONLY=1
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-4.0
|
||||
- clang-7
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-4.0
|
||||
- llvm-toolchain-xenial-7
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-8
|
||||
env: TOOLSET=clang CXXSTD=14,17,2a HEADERS_ONLY=1
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-8
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-xenial-8
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-9
|
||||
env: TOOLSET=clang CXXSTD=14
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-9
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main'
|
||||
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-9
|
||||
env: TOOLSET=clang CXXSTD=17
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-9
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main'
|
||||
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
|
||||
|
||||
- os: osx
|
||||
compiler: clang++
|
||||
env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++98
|
||||
env: TOOLSET=clang CXXSTD=98
|
||||
|
||||
# - os: osx
|
||||
# compiler: clang++
|
||||
# env: TOOLSET=clang CXXSTD=11
|
||||
|
||||
# - os: osx
|
||||
# compiler: clang++
|
||||
# env: TOOLSET=clang CXXSTD=14
|
||||
|
||||
- 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++1z
|
||||
env: TOOLSET=clang CXXSTD=1z
|
||||
|
||||
install:
|
||||
- BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true
|
||||
- GIT_FETCH_JOBS=8
|
||||
- BOOST_BRANCH=develop
|
||||
- if [ "$TRAVIS_BRANCH" = "master" ]; then BOOST_BRANCH=master; fi
|
||||
- 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
|
||||
- git submodule init tools/build
|
||||
- git submodule init libs/config
|
||||
- git submodule init tools/boostdep
|
||||
- git submodule update --jobs $GIT_FETCH_JOBS
|
||||
- mkdir -p libs/thread
|
||||
- cp -r $TRAVIS_BUILD_DIR/* libs/thread
|
||||
- python tools/boostdep/depinst/depinst.py thread
|
||||
- python tools/boostdep/depinst/depinst.py --git_args "--jobs $GIT_FETCH_JOBS" thread
|
||||
- ./bootstrap.sh
|
||||
- ./b2 headers
|
||||
|
||||
script:
|
||||
- |-
|
||||
echo "using $TOOLSET : : $COMPILER : <cxxflags>-std=$CXXSTD ;" > ~/user-config.jam
|
||||
- ./b2 -j3 libs/thread/test toolset=$TOOLSET
|
||||
echo "using $TOOLSET : : $TRAVIS_COMPILER ;" > ~/user-config.jam
|
||||
- ./b2 -j3 -l60 libs/thread/test${HEADERS_ONLY:+//test_self_contained_headers} toolset=$TOOLSET cxxstd=$CXXSTD
|
||||
|
||||
notifications:
|
||||
email:
|
||||
|
||||
71
appveyor.yml
71
appveyor.yml
@@ -1,4 +1,5 @@
|
||||
# Copyright 2016, 2017 Peter Dimov
|
||||
# Copyright 2016-2018 Peter Dimov
|
||||
# Copyright 2018 Vicente Botet
|
||||
# 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)
|
||||
|
||||
@@ -12,30 +13,72 @@ branches:
|
||||
- develop
|
||||
- /feature\/.*/
|
||||
|
||||
image: Visual Studio 2015
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
||||
TOOLSET: msvc-12.0
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
TOOLSET: msvc-14.0
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
TOOLSET: msvc-14.1
|
||||
|
||||
- TOOLSET: msvc-12.0
|
||||
VARIANT: release
|
||||
|
||||
- TOOLSET: msvc-14.0
|
||||
ADDRMD: 32
|
||||
VARIANT: debug
|
||||
|
||||
- TOOLSET: msvc-14.1
|
||||
ADDRMD: 64
|
||||
VARIANT: release
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
|
||||
- TOOLSET: msvc-14.2
|
||||
CXXSTD: 17
|
||||
ADDRMD: 64
|
||||
VARIANT: debug
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
|
||||
- ADDPATH: C:\cygwin\bin;
|
||||
TOOLSET: gcc
|
||||
VARIANT: release
|
||||
|
||||
- ADDPATH: C:\mingw\bin;
|
||||
TOOLSET: gcc
|
||||
VARIANT: debug
|
||||
|
||||
# The following configurations fail with
|
||||
# ./boost/thread/detail/invoke.hpp:101:43: internal compiler error: in gimplify_expr, at gimplify.c:12039
|
||||
# https://sourceforge.net/p/mingw-w64/bugs/694/
|
||||
#
|
||||
# - ADDPATH: C:\cygwin64\bin;
|
||||
# TOOLSET: gcc
|
||||
# VARIANT: debug
|
||||
# - ADDPATH: C:\mingw-w64\x86_64-6.3.0-posix-seh-rt_v5-rev1\mingw64\bin;
|
||||
# TOOLSET: gcc
|
||||
# VARIANT: debug
|
||||
# - ADDPATH: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin;
|
||||
# TOOLSET: gcc
|
||||
# VARIANT: debug,release
|
||||
|
||||
install:
|
||||
- set GIT_FETCH_JOBS=8
|
||||
- set BOOST_BRANCH=develop
|
||||
- if "%APPVEYOR_REPO_BRANCH%" == "master" set BOOST_BRANCH=master
|
||||
- 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
|
||||
- xcopy /s /e /q %APPVEYOR_BUILD_FOLDER% libs\thread\
|
||||
- python tools/boostdep/depinst/depinst.py thread
|
||||
- git submodule init tools/build
|
||||
- git submodule init libs/config
|
||||
- git submodule init tools/boostdep
|
||||
- git submodule update --jobs %GIT_FETCH_JOBS%
|
||||
- xcopy /s /e /q %APPVEYOR_BUILD_FOLDER% libs\thread
|
||||
- python tools/boostdep/depinst/depinst.py --git_args "--jobs %GIT_FETCH_JOBS%" thread
|
||||
- cmd /c bootstrap
|
||||
- b2 headers
|
||||
- b2 -d0 headers
|
||||
|
||||
build: off
|
||||
|
||||
test_script:
|
||||
- b2 libs/mp11/test toolset=%TOOLSET%
|
||||
- PATH=%ADDPATH%%PATH%
|
||||
- if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD%
|
||||
- if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD%
|
||||
- if not "%VARIANT%" == "" set VARIANT=variant=%VARIANT%
|
||||
- b2 -j2 --abbreviate-paths libs/thread/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% %VARIANT%
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
# PTW32_INCLUDE and PTW32_LIB respectively. You can specify these
|
||||
# paths in site-config.jam, user-config.jam or in the environment.
|
||||
# A new feature is provided to request a specific API:
|
||||
# <threadapi>win32 and <threadapi)pthread.
|
||||
# <threadapi>win32 and <threadapi>pthread.
|
||||
#
|
||||
# The naming of the resulting libraries is mostly the same for the
|
||||
# variant native to the build platform, i.e.
|
||||
@@ -33,10 +33,12 @@
|
||||
#########################################################################
|
||||
|
||||
import os ;
|
||||
import feature ;
|
||||
import indirect ;
|
||||
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
|
||||
@@ -52,7 +54,6 @@ project boost/thread
|
||||
#<define>BOOST_SYSTEM_NO_DEPRECATED
|
||||
#<define>BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS
|
||||
|
||||
<library>/boost/system//boost_system
|
||||
#-pedantic -ansi -std=gnu++0x -Wextra -fpermissive
|
||||
<warnings>all
|
||||
<toolset>gcc:<cxxflags>-Wextra
|
||||
@@ -138,21 +139,8 @@ project boost/thread
|
||||
#<define>BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
|
||||
#<define>BOOST_SYSTEM_NO_DEPRECATED
|
||||
#<define>BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS
|
||||
<library>/boost/system//boost_system
|
||||
;
|
||||
|
||||
local rule default_threadapi ( )
|
||||
{
|
||||
local api = pthread ;
|
||||
if [ os.name ] = "NT" { api = win32 ; }
|
||||
return $(api) ;
|
||||
}
|
||||
|
||||
feature.feature threadapi : pthread win32 : propagated ;
|
||||
feature.set-default threadapi : [ default_threadapi ] ;
|
||||
|
||||
exe has_atomic_flag_lockfree : ../build/has_atomic_flag_lockfree_test.cpp ;
|
||||
|
||||
rule tag ( name : type ? : property-set )
|
||||
{
|
||||
local result = $(name) ;
|
||||
@@ -162,7 +150,7 @@ rule tag ( name : type ? : property-set )
|
||||
local api = [ $(property-set).get <threadapi> ] ;
|
||||
|
||||
# non native api gets additional tag
|
||||
if $(api) != [ default_threadapi ] {
|
||||
if $(api) != [ threadapi-feature.get-default $(property-set) ] {
|
||||
result = $(result)_$(api) ;
|
||||
}
|
||||
}
|
||||
@@ -248,6 +236,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)
|
||||
#{
|
||||
@@ -282,6 +274,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 ;
|
||||
}
|
||||
@@ -294,6 +290,7 @@ alias thread_sources
|
||||
win32/thread.cpp
|
||||
win32/tss_dll.cpp
|
||||
win32/tss_pe.cpp
|
||||
win32/thread_primitives.cpp
|
||||
future.cpp
|
||||
: ## requirements ##
|
||||
<threadapi>win32
|
||||
|
||||
177
circle.yml
Normal file
177
circle.yml
Normal file
@@ -0,0 +1,177 @@
|
||||
# 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>$CXXFLAGS <cxxflags>$DEFINES ;" > ~/user-config.jam
|
||||
cd ../boost-root
|
||||
./b2 -d2 -j8 -l60 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"
|
||||
- CXXFLAGS: "-Wno-unusable-partial-specialization"
|
||||
- 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"
|
||||
- CXXFLAGS: "-Wno-unusable-partial-specialization"
|
||||
- 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[/
|
||||
/ Copyright (c) 2014-2015 Vicente J. Botet Escriba
|
||||
/ Copyright (c) 2014-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)
|
||||
@@ -481,7 +481,7 @@ If invoked closure throws an exception the executor will call std::terminate, as
|
||||
[/////////////////////////]
|
||||
[section:work Class `work`]
|
||||
|
||||
#include <boost/thread/work.hpp>
|
||||
#include <boost/thread/executors/work.hpp>
|
||||
namespace boost {
|
||||
typedef 'implementation_defined' work;
|
||||
}
|
||||
@@ -499,7 +499,7 @@ If invoked closure throws an exception the executor will call std::terminate, as
|
||||
|
||||
Executor abstract base class.
|
||||
|
||||
#include <boost/thread/executor.hpp>
|
||||
#include <boost/thread/executors/executor.hpp>
|
||||
namespace boost {
|
||||
class executor
|
||||
{
|
||||
@@ -564,7 +564,7 @@ Executor abstract base class.
|
||||
|
||||
Polymorphic adaptor of a model of Executor to an executor.
|
||||
|
||||
#include <boost/thread/executor.hpp>
|
||||
#include <boost/thread/executors/executor.hpp>
|
||||
namespace boost {
|
||||
template <typename Executor>
|
||||
class executor_adaptor : public executor
|
||||
@@ -643,7 +643,7 @@ Polymorphic adaptor of a model of Executor to an executor.
|
||||
|
||||
Executor abstract base class.
|
||||
|
||||
#include <boost/thread/generic_executor_ref.hpp>
|
||||
#include <boost/thread/executors/generic_executor_ref.hpp>
|
||||
namespace boost {
|
||||
class generic_executor_ref
|
||||
{
|
||||
@@ -1333,7 +1333,7 @@ Executor providing time related functions.
|
||||
|
||||
A serial executor ensuring that there are no two work units that executes concurrently.
|
||||
|
||||
#include <boost/thread/serial_executor.hpp>
|
||||
#include <boost/thread/executors/serial_executor.hpp>
|
||||
namespace boost {
|
||||
template <class Executor>
|
||||
class serial_executor
|
||||
@@ -1404,83 +1404,6 @@ A serial executor ensuring that there are no two work units that executes concur
|
||||
]
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
||||
|
||||
[//////////////////////////////////////////////////////////]
|
||||
[section:generic_serial_executor Class `generic_serial_executor`]
|
||||
|
||||
A serial executor ensuring that there are no two work units that executes concurrently.
|
||||
|
||||
#include <boost/thread/generic_serial_executor.hpp>
|
||||
namespace boost {
|
||||
class generic_serial_executor
|
||||
{
|
||||
public:
|
||||
generic_serial_executor(generic_serial_executor const&) = delete;
|
||||
generic_serial_executor& operator=(generic_serial_executor const&) = delete;
|
||||
|
||||
template <class Executor>
|
||||
generic_serial_executor(Executor& ex);
|
||||
|
||||
generic_executor_ref& underlying_executor() noexcept;
|
||||
|
||||
void close();
|
||||
bool closed();
|
||||
|
||||
template <typename Closure>
|
||||
void submit(Closure&& closure);
|
||||
|
||||
bool try_executing_one();
|
||||
template <typename Pred>
|
||||
bool reschedule_until(Pred const& pred);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
[/////////////////////////////////////]
|
||||
[section:constructor Constructor `generic_serial_executor(Executor&)`]
|
||||
|
||||
template <class Executor>
|
||||
generic_serial_executor(Executor& ex);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Constructs a serial_executor. ]]
|
||||
|
||||
[[Throws:] [Nothing. ]]
|
||||
|
||||
]
|
||||
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:destructor Destructor `~serial_executor()`]
|
||||
|
||||
~generic_serial_executor();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Destroys the serial_executor.]]
|
||||
|
||||
[[Synchronization:] [The completion of all the closures happen before the completion of the executor destructor.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:underlying_executor Function member `underlying_executor()`]
|
||||
|
||||
Executor& underlying_executor() noexcept;
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Return:] [The underlying executor instance. ]]
|
||||
|
||||
]
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
||||
@@ -1491,7 +1414,7 @@ A serial executor ensuring that there are no two work units that executes concur
|
||||
|
||||
A serial executor ensuring that there are no two work units that executes concurrently.
|
||||
|
||||
#include <boost/thread/inline_executor.hpp>
|
||||
#include <boost/thread/executors/inline_executor.hpp>
|
||||
namespace boost {
|
||||
class inline_executor
|
||||
{
|
||||
@@ -1603,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.]]
|
||||
|
||||
@@ -1675,7 +1598,7 @@ A thread_executor with a threads for each task.
|
||||
|
||||
A user scheduled executor.
|
||||
|
||||
#include <boost/thread/loop_executor.hpp>
|
||||
#include <boost/thread/executors/loop_executor.hpp>
|
||||
namespace boost {
|
||||
class loop_executor
|
||||
{
|
||||
|
||||
@@ -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,57 @@
|
||||
|
||||
[section:changes History]
|
||||
|
||||
[heading Version 4.9.0 - boost 1.70]
|
||||
|
||||
[*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/pull/268] Add self contained header tests and fix discovered bugs
|
||||
|
||||
* Improvements support for cygwin platform using the pthread interface.
|
||||
* [@https://github.com/boostorg/thread/pull/263] Fix compilation of timed functions on Cygwin
|
||||
$ [@https://github.com/boostorg/thread/pull/262] Fix MinGW warnings about violation of the strict aliasing rules
|
||||
|
||||
* [@https://github.com/boostorg/thread/pull/260] Fix "interruption_point" defined twice.
|
||||
|
||||
* [@https://github.com/boostorg/thread/pull/249] Simplify TSS cleanup routines. Fixes #236
|
||||
|
||||
[*New Experimental Features:]
|
||||
|
||||
* Since BOOST_THREAD_VERSION 5, BOOST_THREAD_USES_EXECUTOR is defined by default.
|
||||
* [@https://github.com/boostorg/thread/pull/266] Remove linking with Boost.System
|
||||
|
||||
[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,10 +73,33 @@ 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]
|
||||
|
||||
[*Fixed Bugs:]
|
||||
|
||||
* [@https://github.com/boostorg/thread/issues/130 #130] windows: Bug in boost::condition_variable on Windows
|
||||
|
||||
|
||||
@@ -10,37 +10,37 @@
|
||||
|
||||
|
||||
[table Default Values for Configurable Features
|
||||
[[Feature] [Anti-Feature] [V2] [V3] [V4] ]
|
||||
[[USES_CHRONO] [DONT_USE_CHRONO] [YES/NO] [YES/NO] [YES/NO] ]
|
||||
[[PROVIDES_INTERRUPTIONS] [DONT_PROVIDE_INTERRUPTIONS] [YES] [YES] [YES] ]
|
||||
[[THROW_IF_PRECONDITION_NOT_SATISFIED] [-] [NO] [NO] [NO] ]
|
||||
[[Feature] [Anti-Feature] [V2] [V3] [V4] [V5] ]
|
||||
[[USES_CHRONO] [DONT_USE_CHRONO] [YES/NO] [YES/NO] [YES/NO] [YES/NO] ]
|
||||
[[PROVIDES_INTERRUPTIONS] [DONT_PROVIDE_INTERRUPTIONS] [YES] [YES] [YES] [YES] ]
|
||||
[[THROW_IF_PRECONDITION_NOT_SATISFIED] [-] [NO] [NO] [NO] [NO] ]
|
||||
|
||||
|
||||
|
||||
[[PROVIDES_PROMISE_LAZY] [DONT_PROVIDE_PROMISE_LAZY] [YES] [NO] [NO] ]
|
||||
[[PROVIDES_PROMISE_LAZY] [DONT_PROVIDE_PROMISE_LAZY] [YES] [NO] [NO] [NO] ]
|
||||
|
||||
[[PROVIDES_BASIC_THREAD_ID] [DONT_PROVIDE_BASIC_THREAD_ID] [NO] [YES] [YES] ]
|
||||
[[PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN] [DONT_PROVIDE_GENERIC_SHARED_MUTEX_ON_WIN] [NO] [YES] [YES] ]
|
||||
[[PROVIDES_BASIC_THREAD_ID] [DONT_PROVIDE_BASIC_THREAD_ID] [NO] [YES] [YES] [YES] ]
|
||||
[[PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN] [DONT_PROVIDE_GENERIC_SHARED_MUTEX_ON_WIN] [NO] [YES] [YES] [YES] ]
|
||||
|
||||
[[PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION] [DONT_PROVIDE_SHARED_MUTEX_UPWARDS_CONVERSION] [NO] [YES] [YES] ]
|
||||
[[PROVIDES_EXECUTORS] [-] [NO] [NO] [NO] ]
|
||||
[[PROVIDES_EXPLICIT_LOCK_CONVERSION] [DONT_PROVIDE_EXPLICIT_LOCK_CONVERSION] [NO] [YES] [YES] ]
|
||||
[[PROVIDES_FUTURE] [DONT_PROVIDE_FUTURE] [NO] [YES] [YES] ]
|
||||
[[PROVIDES_FUTURE_CTOR_ALLOCATORS] [DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS] [NO] [YES] [YES] ]
|
||||
[[PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE] [DONT_PROVIDE_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE] [NO] [YES] [YES] ]
|
||||
[[PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE] [DONT_PROVIDE_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE] [NO] [YES] [YES] ]
|
||||
[[PROVIDES_ONCE_CXX11] [DONT_PROVIDE_ONCE_CXX11] [NO] [YES] [YES] ]
|
||||
[[USES_MOVE] [DONT_USE_MOVE] [NO] [YES] [YES] ]
|
||||
[[PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION] [DONT_PROVIDE_SHARED_MUTEX_UPWARDS_CONVERSION] [NO] [YES] [YES] [YES] ]
|
||||
[[PROVIDES_EXECUTORS] [-] [NO] [NO] [NO] [YES] ]
|
||||
[[PROVIDES_EXPLICIT_LOCK_CONVERSION] [DONT_PROVIDE_EXPLICIT_LOCK_CONVERSION] [NO] [YES] [YES] [YES] ]
|
||||
[[PROVIDES_FUTURE] [DONT_PROVIDE_FUTURE] [NO] [YES] [YES] [YES] ]
|
||||
[[PROVIDES_FUTURE_CTOR_ALLOCATORS] [DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS] [NO] [YES] [YES] [YES] ]
|
||||
[[PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE] [DONT_PROVIDE_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE] [NO] [YES] [YES] [YES] ]
|
||||
[[PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE] [DONT_PROVIDE_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE] [NO] [YES] [YES] [YES] ]
|
||||
[[PROVIDES_ONCE_CXX11] [DONT_PROVIDE_ONCE_CXX11] [NO] [YES] [YES] [YES] ]
|
||||
[[USES_MOVE] [DONT_USE_MOVE] [NO] [YES] [YES] [YES] ]
|
||||
|
||||
[[USES_DATETIME] [DONT_USE_DATETIME] [YES/NO] [YES/NO] [YES/NO] ]
|
||||
[[PROVIDES_THREAD_EQ] [DONT_PROVIDE_THREAD_EQ] [YES] [YES] [NO] ]
|
||||
[[PROVIDES_CONDITION] [DONT_PROVIDE_CONDITION] [YES] [YES] [NO] ]
|
||||
[[PROVIDES_NESTED_LOCKS] [DONT_PROVIDE_NESTED_LOCKS] [YES] [YES] [NO] ]
|
||||
[[PROVIDES_SIGNATURE_PACKAGED_TASK] [DONT_PROVIDE_SIGNATURE_PACKAGED_TASK] [NO] [NO] [YES] ]
|
||||
[[PROVIDES_FUTURE_INVALID_AFTER_GET] [DONT_PROVIDE_FUTURE_INVALID_AFTER_GET] [NO] [NO] [YES] ]
|
||||
[/ [[PROVIDES_FUTURE_CONTINUATION] [DONT_PROVIDE_FUTURE_CONTINUATION] [NO] [NO] [YES] ] ]
|
||||
[[USES_DATETIME] [DONT_USE_DATETIME] [YES/NO] [YES/NO] [YES/NO] [YES/NO] ]
|
||||
[[PROVIDES_THREAD_EQ] [DONT_PROVIDE_THREAD_EQ] [YES] [YES] [NO] [NO] ]
|
||||
[[PROVIDES_CONDITION] [DONT_PROVIDE_CONDITION] [YES] [YES] [NO] [NO] ]
|
||||
[[PROVIDES_NESTED_LOCKS] [DONT_PROVIDE_NESTED_LOCKS] [YES] [YES] [NO] [NO] ]
|
||||
[[PROVIDES_SIGNATURE_PACKAGED_TASK] [DONT_PROVIDE_SIGNATURE_PACKAGED_TASK] [NO] [NO] [YES] [YES] ]
|
||||
[[PROVIDES_FUTURE_INVALID_AFTER_GET] [DONT_PROVIDE_FUTURE_INVALID_AFTER_GET] [NO] [NO] [YES] [YES] ]
|
||||
[/ [[PROVIDES_FUTURE_CONTINUATION] [DONT_PROVIDE_FUTURE_CONTINUATION] [NO] [NO] [YES] [YES] ] ]
|
||||
|
||||
[[PROVIDES_VARIADIC_THREAD] [DONT_PROVIDE_VARIADIC_THREAD] [NO] [NO] [C++11] ]
|
||||
[[PROVIDES_VARIADIC_THREAD] [DONT_PROVIDE_VARIADIC_THREAD] [NO] [NO] [C++11] [C++11] ]
|
||||
|
||||
]
|
||||
|
||||
@@ -179,9 +179,9 @@ When `BOOST_THREAD_VERSION>=3` define `BOOST_THREAD_DONT_PROVIDE_GENERIC_SHARED_
|
||||
[section:shared_upwards Shared Locking Upwards Conversion]
|
||||
|
||||
Boost.Threads includes in version 3 the Shared Locking Upwards Conversion as defined in [@http://home.roadrunner.com/~hinnant/bloomington/shared_mutex.html Shared Locking].
|
||||
These conversions need to be used carefully to avoid deadlock or livelock. The user need to define explicitly `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION` to get these upwards conversions.
|
||||
These conversions need to be used carefully to avoid deadlock or livelock. The user need to define explicitly `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS` to get these upwards conversions.
|
||||
|
||||
When `BOOST_THREAD_VERSION==2` define `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION ` if you want these features.
|
||||
When `BOOST_THREAD_VERSION==2` define `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS ` if you want these features.
|
||||
When `BOOST_THREAD_VERSION>=3` define `BOOST_THREAD_DONT_PROVIDE_SHARED_MUTEX_UPWARDS_CONVERSION ` if you don't want these features.
|
||||
|
||||
[endsect]
|
||||
@@ -303,7 +303,7 @@ When `BOOST_THREAD_VERSION>=4` define `BOOST_THREAD_DONT_PROVIDE_SIGNATURE_PACKA
|
||||
|
||||
[section:thread_const-var thread constructor with variadic rvalue parameters]
|
||||
|
||||
C++11 thread constructor accep a variable number of rvalue argumentshas. When `BOOST_THREAD_PROVIDES_VARIADIC_THREAD ` is defined Boost.Thread provides this C++ feature if the following are not defined
|
||||
C++11 thread constructor accept a variable number of rvalue arguments has. When `BOOST_THREAD_PROVIDES_VARIADIC_THREAD ` is defined Boost.Thread provides this C++ feature if the following are not defined
|
||||
|
||||
* BOOST_NO_SFINAE_EXPR
|
||||
* BOOST_NO_CXX11_VARIADIC_TEMPLATES
|
||||
@@ -352,7 +352,7 @@ The user can request the version 3 by defining `BOOST_THREAD_VERSION` to 3. In t
|
||||
* Breaking change `BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION `
|
||||
* Conformity & Breaking change `BOOST_THREAD_PROVIDES_FUTURE`
|
||||
* Uniformity `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN`
|
||||
* Extension `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION`
|
||||
* Extension `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS`
|
||||
* Conformity `BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS`
|
||||
* Conformity & Breaking change BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE
|
||||
* Conformity & Breaking change BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE
|
||||
|
||||
@@ -1507,6 +1507,13 @@ executor, then the parent is filled by immediately calling `.wait()`, and the po
|
||||
|
||||
template<typename F>
|
||||
void set_wait_callback(F f); // EXTENSION
|
||||
|
||||
void set_value_deferred(see below); // EXTENSION
|
||||
void set_exception_deferred(exception_ptr p); // EXTENSION
|
||||
template <typename E>
|
||||
void set_exception_deferred(E e); // EXTENSION
|
||||
void notify_deferred(); // EXTENSION
|
||||
|
||||
};
|
||||
|
||||
[///////////////////////////////////////////////]
|
||||
@@ -1683,9 +1690,10 @@ Stores the value r in the shared state without making that state ready immediate
|
||||
Schedules that state to be made ready when the current thread exits, after all objects of thread storage duration
|
||||
associated with the current thread have been destroyed.]]
|
||||
|
||||
[[Postconditions:] [the result associated with `*this` is set as deferred]]
|
||||
|
||||
[[Throws:] [
|
||||
- __promise_already_satisfied__ if the result associated with `*this` is already ['ready].
|
||||
- __promise_already_satisfied__ if the result associated with `*this` is already ['ready] or deferred.
|
||||
|
||||
- __broken_promise__ if `*this` has no shared state.
|
||||
|
||||
@@ -1711,11 +1719,11 @@ Stores the exception pointer p in the shared state without making that state rea
|
||||
Schedules that state to be made ready when the current thread exits, after all objects of thread storage duration
|
||||
associated with the current thread have been destroyed.]]
|
||||
|
||||
[[Postconditions:] [All futures waiting on the shared state are ['ready] and __unique_future_has_exception__ or
|
||||
__shared_future_has_exception__ for those futures shall return `true`.]]
|
||||
[[Postconditions:] [the result associated with `*this` is set as deferred]]
|
||||
|
||||
|
||||
[[Throws:] [
|
||||
- __promise_already_satisfied__ if the result associated with `*this` is already ['ready].
|
||||
- __promise_already_satisfied__ if the result associated with `*this` is already ['ready] or deferred.
|
||||
|
||||
- __broken_promise__ if `*this` has no shared state.
|
||||
|
||||
@@ -1745,6 +1753,82 @@ or __shared_future__ associated with this result, and the result is not ['ready]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[///////////////////////////////////////////////]
|
||||
[section:set_value Member Function `set_value_deferred()` EXTENSION]
|
||||
|
||||
void set_value_deferred(R&& r);
|
||||
void set_value_deferred(const R& r);
|
||||
void promise<R&>:: set_value_deferred(R& r);
|
||||
void promise<void>:: set_value_deferred();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [
|
||||
- If BOOST_THREAD_PROVIDES_PROMISE_LAZY is defined and if `*this` was not associated with a result, allocate storage for a new shared state and associate it with `*this`.
|
||||
|
||||
- Stores the value `r` in the shared state without making that state ready immediately. Threads blocked waiting for the asynchronous result are not woken. They will be woken only when `notify_deferred` is called.
|
||||
]]
|
||||
|
||||
[[Postconditions:] [the result associated with `*this` is set as deferred]]
|
||||
|
||||
[[Throws:] [
|
||||
- __promise_already_satisfied__ if the result associated with `*this` is already ['ready] or deferred.
|
||||
|
||||
- __broken_promise__ if `*this` has no shared state.
|
||||
|
||||
- `std::bad_alloc` if the memory required for storage of the result cannot be allocated.
|
||||
|
||||
- Any exception thrown by the copy or move-constructor of `R`.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[///////////////////////////////////////////////////////]
|
||||
[section:set_exception Member Function `set_exception_deferred()` EXTENSION]
|
||||
|
||||
void set_exception_deferred(boost::exception_ptr e);
|
||||
template <typename E>
|
||||
void set_exception_deferred(E e); // EXTENSION
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [
|
||||
- If BOOST_THREAD_PROVIDES_PROMISE_LAZY is defined and if `*this` was not associated with a result, allocate storage for a new shared state and associate it with `*this`.
|
||||
|
||||
- Store the exception `e` in the shared state associated with `*this`without making that state ready immediately. Threads blocked waiting for the asynchronous result are not woken. They will be woken only when `notify_deferred` is called.]]
|
||||
|
||||
[[Postconditions:] [the result associated with `*this` is set as deferred]]
|
||||
|
||||
|
||||
[[Throws:] [
|
||||
- __promise_already_satisfied__ if the result associated with `*this` is already ['ready] or deferred.
|
||||
|
||||
- __broken_promise__ if `*this` has no shared state.
|
||||
|
||||
- `std::bad_alloc` if the memory required for storage of the result cannot be allocated.
|
||||
]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[///////////////////////////////////////////////]
|
||||
[section:set_value Member Function `notify_deferred()` EXTENSION]
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [
|
||||
Any threads blocked waiting for the asynchronous result are woken.
|
||||
]]
|
||||
|
||||
[[Postconditions:] [All futures waiting on the shared state are ['ready] and __unique_future_has_value__ or
|
||||
__shared_future_has_value__ for those futures shall return `true`.]]
|
||||
|
||||
[[Postconditions:] [the result associated with `*this` is ready.]]
|
||||
|
||||
]
|
||||
[endsect]
|
||||
|
||||
|
||||
[endsect]
|
||||
[////////////////////////////////////////////////////]
|
||||
|
||||
0
doc/futures.qbk
Executable file → Normal file
0
doc/futures.qbk
Executable file → Normal file
@@ -542,7 +542,7 @@ requirements and the following expressions are well-formed and have the specifie
|
||||
* `m.__unlock_upgrade_and_lock_shared();`
|
||||
|
||||
|
||||
If `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION is defined the following expressions are also required:
|
||||
If `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS is defined the following expressions are also required:
|
||||
|
||||
* `m.__try_unlock_shared_and_lock();`
|
||||
* `m.__try_unlock_shared_and_lock_for(rel_time);`
|
||||
@@ -678,7 +678,7 @@ If the conversion is not successful, the shared ownership of m is retained.]]
|
||||
|
||||
[[Throws:] [Nothing]]
|
||||
|
||||
[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION` and `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
|
||||
[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS` and `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
|
||||
|
||||
]
|
||||
[endsect]
|
||||
@@ -704,7 +704,7 @@ If the conversion is not successful, the shared ownership of the mutex is retain
|
||||
|
||||
[[Throws:] [Nothing]]
|
||||
|
||||
[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION` and `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
|
||||
[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS` and `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
|
||||
|
||||
]
|
||||
[endsect]
|
||||
@@ -730,7 +730,7 @@ If the conversion is not successful, the shared ownership of the mutex is retain
|
||||
|
||||
[[Throws:] [Nothing]]
|
||||
|
||||
[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION` and `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
|
||||
[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS` and `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
|
||||
|
||||
]
|
||||
[endsect]
|
||||
@@ -770,7 +770,7 @@ If the conversion is not successful, the shared ownership of the mutex is retain
|
||||
|
||||
[[Throws:] [Nothing]]
|
||||
|
||||
[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION` and `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
|
||||
[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS` and `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
|
||||
|
||||
]
|
||||
[endsect]
|
||||
@@ -797,7 +797,7 @@ If the conversion is not successful, the shared ownership of m is retained.]]
|
||||
|
||||
[[Throws:] [Nothing]]
|
||||
|
||||
[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION` and `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
|
||||
[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS` and `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
|
||||
|
||||
|
||||
]
|
||||
@@ -823,7 +823,7 @@ If the conversion is not successful, the shared ownership of the mutex is retain
|
||||
|
||||
[[Throws:] [Nothing]]
|
||||
|
||||
[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION` and `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
|
||||
[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS` and `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
|
||||
|
||||
]
|
||||
[endsect]
|
||||
@@ -1268,7 +1268,7 @@ The following classes are models of `StrictLock`:
|
||||
unique_lock(Lockable& m_,defer_lock_t) noexcept;
|
||||
unique_lock(Lockable& m_,try_to_lock_t);
|
||||
|
||||
#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION
|
||||
#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
|
||||
unique_lock(shared_lock<mutex_type>&& sl, try_to_lock_t); // C++14
|
||||
template <class Clock, class Duration>
|
||||
unique_lock(shared_lock<mutex_type>&& sl,
|
||||
@@ -1426,7 +1426,7 @@ Else `sl.__owns_lock()` returns `true`, and in this case if `sl.mutex()->try_unl
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION` and `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
|
||||
[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS` and `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
|
||||
|
||||
]
|
||||
|
||||
@@ -1451,7 +1451,7 @@ Else `sl.__owns_lock_shared_ref__()` returns `true`, and in this case if `sl.mut
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION` and `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
|
||||
[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS` and `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
|
||||
|
||||
]
|
||||
|
||||
@@ -1478,7 +1478,7 @@ Else `sl.owns_lock()` returns `true`, and in this case if `sl.mutex()-> __try_un
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION` and `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
|
||||
[[Notes:] [Available only if `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS` and `BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN` is defined on Windows platform]]
|
||||
|
||||
]
|
||||
|
||||
@@ -1899,7 +1899,7 @@ __owns_lock_shared_ref__ returns `false`.]]
|
||||
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
|
||||
void unlock();
|
||||
|
||||
#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION
|
||||
#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
|
||||
// Conversion from shared locking
|
||||
upgrade_lock(shared_lock<mutex_type>&& sl, try_to_lock_t);
|
||||
template <class Clock, class Duration>
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
|
||||
struct once_flag
|
||||
{
|
||||
constexprr once_flag() noexcept;
|
||||
constexpr once_flag() noexcept;
|
||||
once_flag(const once_flag&) = delete;
|
||||
once_flag& operator=(const once_flag&) = delete;
|
||||
};
|
||||
|
||||
@@ -12,6 +12,10 @@
|
||||
#include <boost/thread/lock_types.hpp>
|
||||
#include <iostream>
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(disable: 4355) // 'this' : used in base member initializer list
|
||||
#endif
|
||||
|
||||
using namespace boost;
|
||||
|
||||
class BankAccount
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(disable: 4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
int p1_ex()
|
||||
{
|
||||
BOOST_THREAD_LOG << "P1" << BOOST_THREAD_END_LOG;
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
#include <iostream>
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(disable: 4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
int p1()
|
||||
{
|
||||
BOOST_THREAD_LOG << "P1" << BOOST_THREAD_END_LOG;
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(disable: 4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
int p1()
|
||||
{
|
||||
BOOST_THREAD_LOG << "P1" << BOOST_THREAD_END_LOG;
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
#include <string>
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(disable: 4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
int p1()
|
||||
{
|
||||
BOOST_THREAD_LOG
|
||||
|
||||
@@ -20,8 +20,11 @@
|
||||
#include <iostream>
|
||||
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION \
|
||||
&& ! defined BOOST_NO_CXX11_LAMBDAS && ! (defined BOOST_MSVC && _MSC_VER < 1700)
|
||||
&& ! defined BOOST_NO_CXX11_LAMBDAS && ! (defined BOOST_MSVC && _MSC_VER < 1800) // works since msvc-12.0
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(disable: 4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
@@ -68,6 +71,8 @@ int main()
|
||||
}
|
||||
#else
|
||||
|
||||
//#warning "This test is not supported in this configuration, either because Bosst.Thread has been configured to don't support continuations, the compiler doesn't provides lambdas or because they are buggy as for MSV versions < msvc-12.0"
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
|
||||
@@ -37,7 +37,7 @@ struct accumulate_block
|
||||
template<typename Iterator,typename T>
|
||||
T parallel_accumulate(Iterator first,Iterator last,T init)
|
||||
{
|
||||
unsigned long const length=std::distance(first,last);
|
||||
unsigned long const length=static_cast<unsigned long>(std::distance(first,last));
|
||||
|
||||
if(!length)
|
||||
return init;
|
||||
|
||||
@@ -8,8 +8,7 @@
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
#define BOOST_THREAD_VERSION 5
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
|
||||
#include <boost/thread/caller_context.hpp>
|
||||
|
||||
@@ -20,6 +20,7 @@ struct func
|
||||
int& i;
|
||||
|
||||
func(int& i_):i(i_){}
|
||||
func(func const& other):i(other.i){}
|
||||
|
||||
void operator()()
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_VERSION 5
|
||||
//#define BOOST_THREAD_USES_LOG
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
@@ -15,9 +15,14 @@
|
||||
|
||||
#include <boost/thread/detail/log.hpp>
|
||||
#include <boost/thread/executors/basic_thread_pool.hpp>
|
||||
#include <boost/thread/thread_only.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <string>
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(disable: 4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
void p1()
|
||||
{
|
||||
BOOST_THREAD_LOG
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_VERSION 5
|
||||
//#define BOOST_THREAD_USES_LOG
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
@@ -17,6 +17,10 @@
|
||||
#include <boost/thread/thread_only.hpp>
|
||||
#include <string>
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(disable: 4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
void p1()
|
||||
{
|
||||
BOOST_THREAD_LOG
|
||||
|
||||
@@ -148,7 +148,7 @@ namespace detail
|
||||
template <class Q, class T,
|
||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
#if defined __GNUC__ && ! defined __clang__
|
||||
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 7) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
bool Copyable = is_copy_constructible<T>::value,
|
||||
bool Movable = true
|
||||
#else
|
||||
|
||||
@@ -140,7 +140,7 @@ namespace detail
|
||||
template <class T, class ST,
|
||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
#if defined __GNUC__ && ! defined __clang__
|
||||
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 7) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
bool Copyable = is_copy_constructible<T>::value,
|
||||
bool Movable = true
|
||||
#else
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Vicente J. Botet Escriba 2013-2014. Distributed under the Boost
|
||||
// (C) Copyright Vicente J. Botet Escriba 2013-2017. 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)
|
||||
//
|
||||
@@ -11,15 +11,15 @@
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/bind/bind.hpp>
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
|
||||
|
||||
#include <boost/chrono/duration.hpp>
|
||||
#include <boost/chrono/time_point.hpp>
|
||||
#include <boost/chrono/system_clocks.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
@@ -40,10 +40,6 @@ namespace detail
|
||||
typedef typename Queue::size_type size_type;
|
||||
typedef queue_op_status op_status;
|
||||
|
||||
typedef typename chrono::steady_clock clock;
|
||||
typedef typename clock::duration duration;
|
||||
typedef typename clock::time_point time_point;
|
||||
|
||||
// Constructors/Assignment/Destructors
|
||||
BOOST_THREAD_NO_COPYABLE(sync_deque_base)
|
||||
inline sync_deque_base();
|
||||
@@ -67,7 +63,7 @@ namespace detail
|
||||
|
||||
protected:
|
||||
mutable mutex mtx_;
|
||||
condition_variable not_empty_;
|
||||
condition_variable cond_;
|
||||
underlying_queue_type data_;
|
||||
bool closed_;
|
||||
|
||||
@@ -90,17 +86,19 @@ 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 wait_until_not_empty_or_closed(unique_lock<mutex>& lk);
|
||||
inline queue_op_status wait_until_not_empty_until(unique_lock<mutex>& lk, time_point const&);
|
||||
inline bool not_empty_or_closed(unique_lock<mutex>& ) const;
|
||||
|
||||
inline void notify_not_empty_if_needed(unique_lock<mutex>& )
|
||||
inline bool wait_until_not_empty_or_closed(unique_lock<mutex>& lk);
|
||||
template <class WClock, class Duration>
|
||||
queue_op_status wait_until_not_empty_or_closed_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&tp);
|
||||
|
||||
inline void notify_elem_added(unique_lock<mutex>& )
|
||||
{
|
||||
not_empty_.notify_one();
|
||||
cond_.notify_all();
|
||||
}
|
||||
inline void notify_not_empty_if_needed(lock_guard<mutex>& )
|
||||
inline void notify_elem_added(lock_guard<mutex>& )
|
||||
{
|
||||
not_empty_.notify_one();
|
||||
cond_.notify_all();
|
||||
}
|
||||
|
||||
};
|
||||
@@ -124,7 +122,7 @@ namespace detail
|
||||
lock_guard<mutex> lk(mtx_);
|
||||
closed_ = true;
|
||||
}
|
||||
not_empty_.notify_all();
|
||||
cond_.notify_all();
|
||||
}
|
||||
|
||||
template <class ValueType, class Queue>
|
||||
@@ -181,39 +179,29 @@ 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;
|
||||
cond_.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>
|
||||
queue_op_status sync_deque_base<ValueType, Queue>::wait_until_not_empty_until(unique_lock<mutex>& lk, time_point const&tp)
|
||||
template <class WClock, class Duration>
|
||||
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 (! cond_.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;
|
||||
}
|
||||
|
||||
|
||||
} // detail
|
||||
} // concurrent
|
||||
} // boost
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Vicente J. Botet Escriba 2013-2014. Distributed under the Boost
|
||||
// (C) Copyright Vicente J. Botet Escriba 2013-2017. 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)
|
||||
//
|
||||
@@ -11,15 +11,15 @@
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/bind/bind.hpp>
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
|
||||
|
||||
#include <boost/chrono/duration.hpp>
|
||||
#include <boost/chrono/time_point.hpp>
|
||||
#include <boost/chrono/system_clocks.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
@@ -40,10 +40,6 @@ namespace detail
|
||||
typedef typename Queue::size_type size_type;
|
||||
typedef queue_op_status op_status;
|
||||
|
||||
typedef typename chrono::steady_clock clock;
|
||||
typedef typename clock::duration duration;
|
||||
typedef typename clock::time_point time_point;
|
||||
|
||||
// Constructors/Assignment/Destructors
|
||||
BOOST_THREAD_NO_COPYABLE(sync_queue_base)
|
||||
inline sync_queue_base();
|
||||
@@ -67,7 +63,7 @@ namespace detail
|
||||
|
||||
protected:
|
||||
mutable mutex mtx_;
|
||||
condition_variable not_empty_;
|
||||
condition_variable cond_;
|
||||
underlying_queue_type data_;
|
||||
bool closed_;
|
||||
|
||||
@@ -90,17 +86,19 @@ 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 wait_until_not_empty_or_closed(unique_lock<mutex>& lk);
|
||||
inline queue_op_status wait_until_not_empty_until(unique_lock<mutex>& lk, time_point const&);
|
||||
inline bool not_empty_or_closed(unique_lock<mutex>& ) const;
|
||||
|
||||
inline void notify_not_empty_if_needed(unique_lock<mutex>& )
|
||||
inline bool wait_until_not_empty_or_closed(unique_lock<mutex>& lk);
|
||||
template <class WClock, class Duration>
|
||||
queue_op_status wait_until_not_empty_or_closed_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&tp);
|
||||
|
||||
inline void notify_elem_added(unique_lock<mutex>& )
|
||||
{
|
||||
not_empty_.notify_one();
|
||||
cond_.notify_all();
|
||||
}
|
||||
inline void notify_not_empty_if_needed(lock_guard<mutex>& )
|
||||
inline void notify_elem_added(lock_guard<mutex>& )
|
||||
{
|
||||
not_empty_.notify_one();
|
||||
cond_.notify_all();
|
||||
}
|
||||
|
||||
};
|
||||
@@ -124,7 +122,7 @@ namespace detail
|
||||
lock_guard<mutex> lk(mtx_);
|
||||
closed_ = true;
|
||||
}
|
||||
not_empty_.notify_all();
|
||||
cond_.notify_all();
|
||||
}
|
||||
|
||||
template <class ValueType, class Queue>
|
||||
@@ -181,39 +179,29 @@ 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;
|
||||
cond_.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>
|
||||
queue_op_status sync_queue_base<ValueType, Queue>::wait_until_not_empty_until(unique_lock<mutex>& lk, time_point const&tp)
|
||||
template <class WClock, class Duration>
|
||||
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 (! cond_.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;
|
||||
}
|
||||
|
||||
|
||||
} // detail
|
||||
} // concurrent
|
||||
} // boost
|
||||
|
||||
@@ -148,7 +148,7 @@ namespace detail
|
||||
template <class Q, class T,
|
||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
#if defined __GNUC__ && ! defined __clang__
|
||||
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 7) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
bool Copyable = is_copy_constructible<T>::value,
|
||||
bool Movable = true
|
||||
#else
|
||||
|
||||
2
include/boost/thread/concurrent_queues/queue_base.hpp
Executable file → Normal file
2
include/boost/thread/concurrent_queues/queue_base.hpp
Executable file → Normal file
@@ -140,7 +140,7 @@ namespace detail
|
||||
template <class T, class ST,
|
||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
#if defined __GNUC__ && ! defined __clang__
|
||||
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 7) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
bool Copyable = is_copy_constructible<T>::value,
|
||||
bool Movable = true
|
||||
#else
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <exception>
|
||||
#include <boost/core/scoped_enum.hpp>
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
|
||||
@@ -25,7 +27,7 @@ namespace concurrent
|
||||
{ success = 0, empty, full, closed, busy, timeout, not_ready }
|
||||
BOOST_SCOPED_ENUM_DECLARE_END(queue_op_status)
|
||||
|
||||
struct sync_queue_is_closed : std::exception
|
||||
struct BOOST_SYMBOL_VISIBLE sync_queue_is_closed : std::exception
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
@@ -655,7 +655,7 @@ namespace concurrent
|
||||
queue_op_status sync_bounded_queue<ValueType>::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
|
||||
{
|
||||
unique_lock<mutex> lk(mtx_);
|
||||
return try_push_back(boost::move(elem), lk);
|
||||
return wait_push_back(boost::move(elem), lk);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -92,13 +92,13 @@ namespace concurrent
|
||||
inline void push_back(const value_type& elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
super::data_.push_back(elem);
|
||||
super::notify_not_empty_if_needed(lk);
|
||||
super::notify_elem_added(lk);
|
||||
}
|
||||
|
||||
inline void push_back(BOOST_THREAD_RV_REF(value_type) elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
super::data_.push_back(boost::move(elem));
|
||||
super::notify_not_empty_if_needed(lk);
|
||||
super::notify_elem_added(lk);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -122,7 +122,7 @@ namespace concurrent
|
||||
// {
|
||||
// data_.push(boost::move(*cur));;
|
||||
// }
|
||||
// notify_not_empty_if_needed(lk);
|
||||
// notify_elem_added(lk);
|
||||
// }
|
||||
// catch (...)
|
||||
// {
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (C) 2014 Ian Forbed
|
||||
// Copyright (C) 2014 Vicente J. Botet Escriba
|
||||
// Copyright (C) 2014-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)
|
||||
@@ -82,7 +82,7 @@ namespace detail {
|
||||
return boost::move(result);
|
||||
}
|
||||
|
||||
Type const& top()
|
||||
Type const& top() const
|
||||
{
|
||||
return _elements.front();
|
||||
}
|
||||
@@ -130,8 +130,10 @@ namespace concurrent
|
||||
|
||||
void pull(ValueType&);
|
||||
|
||||
queue_op_status pull_until(const clock::time_point&, ValueType&);
|
||||
queue_op_status pull_for(const clock::duration&, ValueType&);
|
||||
template <class WClock, class Duration>
|
||||
queue_op_status pull_until(const chrono::time_point<WClock,Duration>&, ValueType&);
|
||||
template <class Rep, class Period>
|
||||
queue_op_status pull_for(const chrono::duration<Rep,Period>&, ValueType&);
|
||||
|
||||
queue_op_status try_pull(ValueType& elem);
|
||||
queue_op_status wait_pull(ValueType& elem);
|
||||
@@ -172,14 +174,14 @@ namespace concurrent
|
||||
{
|
||||
super::throw_if_closed(lk);
|
||||
super::data_.push(elem);
|
||||
super::notify_not_empty_if_needed(lk);
|
||||
super::notify_elem_added(lk);
|
||||
}
|
||||
template <class T, class Container,class Cmp>
|
||||
void sync_priority_queue<T,Container,Cmp>::push(lock_guard<mutex>& lk, const T& elem)
|
||||
{
|
||||
super::throw_if_closed(lk);
|
||||
super::data_.push(elem);
|
||||
super::notify_not_empty_if_needed(lk);
|
||||
super::notify_elem_added(lk);
|
||||
}
|
||||
template <class T, class Container,class Cmp>
|
||||
void sync_priority_queue<T,Container,Cmp>::push(const T& elem)
|
||||
@@ -194,14 +196,14 @@ namespace concurrent
|
||||
{
|
||||
super::throw_if_closed(lk);
|
||||
super::data_.push(boost::move(elem));
|
||||
super::notify_not_empty_if_needed(lk);
|
||||
super::notify_elem_added(lk);
|
||||
}
|
||||
template <class T, class Container,class Cmp>
|
||||
void sync_priority_queue<T,Container,Cmp>::push(lock_guard<mutex>& lk, BOOST_THREAD_RV_REF(T) elem)
|
||||
{
|
||||
super::throw_if_closed(lk);
|
||||
super::data_.push(boost::move(elem));
|
||||
super::notify_not_empty_if_needed(lk);
|
||||
super::notify_elem_added(lk);
|
||||
}
|
||||
template <class T, class Container,class Cmp>
|
||||
void sync_priority_queue<T,Container,Cmp>::push(BOOST_THREAD_RV_REF(T) elem)
|
||||
@@ -247,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);
|
||||
}
|
||||
|
||||
@@ -267,28 +270,30 @@ 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);
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
template <class T, class Cont,class Cmp>
|
||||
template <class WClock, class Duration>
|
||||
queue_op_status
|
||||
sync_priority_queue<T,Cont,Cmp>::pull_until(const clock::time_point& tp, T& elem)
|
||||
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;
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
template <class T, class Cont,class Cmp>
|
||||
template <class Rep, class Period>
|
||||
queue_op_status
|
||||
sync_priority_queue<T,Cont,Cmp>::pull_for(const clock::duration& dura, T& elem)
|
||||
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);
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
@@ -330,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;
|
||||
@@ -348,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);
|
||||
@@ -94,13 +92,13 @@ namespace concurrent
|
||||
inline void push(const value_type& elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
super::data_.push_back(elem);
|
||||
super::notify_not_empty_if_needed(lk);
|
||||
super::notify_elem_added(lk);
|
||||
}
|
||||
|
||||
inline void push(BOOST_THREAD_RV_REF(value_type) elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
super::data_.push_back(boost::move(elem));
|
||||
super::notify_not_empty_if_needed(lk);
|
||||
super::notify_elem_added(lk);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -124,7 +122,7 @@ namespace concurrent
|
||||
// {
|
||||
// data_.push(boost::move(*cur));;
|
||||
// }
|
||||
// notify_not_empty_if_needed(lk);
|
||||
// notify_elem_added(lk);
|
||||
// }
|
||||
// catch (...)
|
||||
// {
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (C) 2014 Ian Forbed
|
||||
// Copyright (C) 2014 Vicente J. Botet Escriba
|
||||
// Copyright (C) 2014-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)
|
||||
@@ -16,6 +16,8 @@
|
||||
#include <boost/chrono/system_clocks.hpp>
|
||||
#include <boost/chrono/chrono_io.hpp>
|
||||
|
||||
#include <algorithm> // std::min
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
@@ -24,12 +26,13 @@ namespace concurrent
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <class T, class Clock = chrono::steady_clock>
|
||||
// fixme: shouldn't the timepoint be configurable
|
||||
template <class T, class Clock = chrono::steady_clock, class TimePoint=typename Clock::time_point>
|
||||
struct scheduled_type
|
||||
{
|
||||
typedef T value_type;
|
||||
typedef Clock clock;
|
||||
typedef typename clock::time_point time_point;
|
||||
typedef TimePoint time_point;
|
||||
T data;
|
||||
time_point time;
|
||||
|
||||
@@ -52,24 +55,58 @@ namespace detail
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool time_not_reached() const
|
||||
{
|
||||
return time > clock::now();
|
||||
}
|
||||
|
||||
bool operator <(const scheduled_type<T> other) const
|
||||
bool operator <(const scheduled_type & other) const
|
||||
{
|
||||
return this->time > other.time;
|
||||
}
|
||||
}; //end struct
|
||||
|
||||
template <class Duration>
|
||||
chrono::time_point<chrono::steady_clock,Duration>
|
||||
limit_timepoint(chrono::time_point<chrono::steady_clock,Duration> const& tp)
|
||||
{
|
||||
// Clock == chrono::steady_clock
|
||||
return tp;
|
||||
}
|
||||
|
||||
template <class Clock, class Duration>
|
||||
chrono::time_point<Clock,Duration>
|
||||
limit_timepoint(chrono::time_point<Clock,Duration> const& tp)
|
||||
{
|
||||
// Clock != chrono::steady_clock
|
||||
// The system time may jump while wait_until() is waiting. To compensate for this and time out near
|
||||
// the correct time, we limit how long wait_until() can wait before going around the loop again.
|
||||
const chrono::time_point<Clock,Duration> tpmax(chrono::time_point_cast<Duration>(Clock::now() + chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
|
||||
return (std::min)(tp, tpmax);
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
chrono::steady_clock::time_point
|
||||
convert_to_steady_clock_timepoint(chrono::time_point<chrono::steady_clock,Duration> const& tp)
|
||||
{
|
||||
// Clock == chrono::steady_clock
|
||||
return chrono::time_point_cast<chrono::steady_clock::duration>(tp);
|
||||
}
|
||||
|
||||
template <class Clock, class Duration>
|
||||
chrono::steady_clock::time_point
|
||||
convert_to_steady_clock_timepoint(chrono::time_point<Clock,Duration> const& tp)
|
||||
{
|
||||
// Clock != chrono::steady_clock
|
||||
// The system time may jump while wait_until() is waiting. To compensate for this and time out near
|
||||
// the correct time, we limit how long wait_until() can wait before going around the loop again.
|
||||
const chrono::steady_clock::duration dura(chrono::duration_cast<chrono::steady_clock::duration>(tp - Clock::now()));
|
||||
const chrono::steady_clock::duration duramax(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
return chrono::steady_clock::now() + (std::min)(dura, duramax);
|
||||
}
|
||||
|
||||
} //end detail namespace
|
||||
|
||||
template <class T, class Clock = chrono::steady_clock>
|
||||
template <class T, class Clock = chrono::steady_clock, class TimePoint=typename Clock::time_point>
|
||||
class sync_timed_queue
|
||||
: private sync_priority_queue<detail::scheduled_type<T, Clock> >
|
||||
: private sync_priority_queue<detail::scheduled_type<T, Clock, TimePoint> >
|
||||
{
|
||||
typedef detail::scheduled_type<T, Clock> stype;
|
||||
typedef detail::scheduled_type<T, Clock, TimePoint> stype;
|
||||
typedef sync_priority_queue<stype> super;
|
||||
public:
|
||||
typedef T value_type;
|
||||
@@ -122,6 +159,14 @@ 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>&);
|
||||
queue_op_status wait_to_pull_until(unique_lock<mutex>&, TimePoint const& tp);
|
||||
template <class Rep, class Period>
|
||||
queue_op_status wait_to_pull_for(unique_lock<mutex>& lk, chrono::duration<Rep,Period> const& dura);
|
||||
|
||||
T pull(unique_lock<mutex>&);
|
||||
T pull(lock_guard<mutex>&);
|
||||
|
||||
@@ -133,15 +178,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 Duration>
|
||||
queue_op_status pull_when_time_reached_until(unique_lock<mutex>&, chrono::time_point<clock,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));
|
||||
@@ -149,309 +185,274 @@ namespace detail
|
||||
}; //end class
|
||||
|
||||
|
||||
template <class T, class Clock>
|
||||
template <class T, class Clock, class TimePoint>
|
||||
template <class Duration>
|
||||
void sync_timed_queue<T, Clock>::push(const T& elem, chrono::time_point<clock,Duration> const& tp)
|
||||
void sync_timed_queue<T, Clock, TimePoint>::push(const T& elem, chrono::time_point<clock,Duration> const& tp)
|
||||
{
|
||||
super::push(stype(elem,tp));
|
||||
}
|
||||
|
||||
template <class T, class Clock>
|
||||
template <class T, class Clock, class TimePoint>
|
||||
template <class Rep, class Period>
|
||||
void sync_timed_queue<T, Clock>::push(const T& elem, chrono::duration<Rep,Period> const& dura)
|
||||
void sync_timed_queue<T, Clock, TimePoint>::push(const T& elem, chrono::duration<Rep,Period> const& dura)
|
||||
{
|
||||
push(elem, clock::now() + dura);
|
||||
}
|
||||
|
||||
template <class T, class Clock>
|
||||
template <class T, class Clock, class TimePoint>
|
||||
template <class Duration>
|
||||
void sync_timed_queue<T, Clock>::push(BOOST_THREAD_RV_REF(T) elem, chrono::time_point<clock,Duration> const& tp)
|
||||
void sync_timed_queue<T, Clock, TimePoint>::push(BOOST_THREAD_RV_REF(T) elem, chrono::time_point<clock,Duration> const& tp)
|
||||
{
|
||||
super::push(stype(boost::move(elem),tp));
|
||||
}
|
||||
|
||||
template <class T, class Clock>
|
||||
template <class T, class Clock, class TimePoint>
|
||||
template <class Rep, class Period>
|
||||
void sync_timed_queue<T, Clock>::push(BOOST_THREAD_RV_REF(T) elem, chrono::duration<Rep,Period> const& dura)
|
||||
void sync_timed_queue<T, Clock, TimePoint>::push(BOOST_THREAD_RV_REF(T) elem, chrono::duration<Rep,Period> const& dura)
|
||||
{
|
||||
push(boost::move(elem), clock::now() + dura);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class T, class Clock>
|
||||
template <class T, class Clock, class TimePoint>
|
||||
template <class Duration>
|
||||
queue_op_status sync_timed_queue<T, Clock>::try_push(const T& elem, chrono::time_point<clock,Duration> const& tp)
|
||||
queue_op_status sync_timed_queue<T, Clock, TimePoint>::try_push(const T& elem, chrono::time_point<clock,Duration> const& tp)
|
||||
{
|
||||
return super::try_push(stype(elem,tp));
|
||||
}
|
||||
|
||||
template <class T, class Clock>
|
||||
template <class T, class Clock, class TimePoint>
|
||||
template <class Rep, class Period>
|
||||
queue_op_status sync_timed_queue<T, Clock>::try_push(const T& elem, chrono::duration<Rep,Period> const& dura)
|
||||
queue_op_status sync_timed_queue<T, Clock, TimePoint>::try_push(const T& elem, chrono::duration<Rep,Period> const& dura)
|
||||
{
|
||||
return try_push(elem,clock::now() + dura);
|
||||
}
|
||||
|
||||
template <class T, class Clock>
|
||||
template <class T, class Clock, class TimePoint>
|
||||
template <class Duration>
|
||||
queue_op_status sync_timed_queue<T, Clock>::try_push(BOOST_THREAD_RV_REF(T) elem, chrono::time_point<clock,Duration> const& tp)
|
||||
queue_op_status sync_timed_queue<T, Clock, TimePoint>::try_push(BOOST_THREAD_RV_REF(T) elem, chrono::time_point<clock,Duration> const& tp)
|
||||
{
|
||||
return super::try_push(stype(boost::move(elem), tp));
|
||||
}
|
||||
|
||||
template <class T, class Clock>
|
||||
template <class T, class Clock, class TimePoint>
|
||||
template <class Rep, class Period>
|
||||
queue_op_status sync_timed_queue<T, Clock>::try_push(BOOST_THREAD_RV_REF(T) elem, chrono::duration<Rep,Period> const& dura)
|
||||
queue_op_status sync_timed_queue<T, Clock, TimePoint>::try_push(BOOST_THREAD_RV_REF(T) elem, chrono::duration<Rep,Period> const& dura)
|
||||
{
|
||||
return try_push(boost::move(elem), clock::now() + dura);
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
template <class T, class Clock>
|
||||
bool sync_timed_queue<T, Clock>::time_not_reached(unique_lock<mutex>&)
|
||||
template <class T, class Clock, class TimePoint>
|
||||
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>
|
||||
bool sync_timed_queue<T, Clock>::time_not_reached(lock_guard<mutex>&)
|
||||
template <class T, class Clock, class TimePoint>
|
||||
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>
|
||||
bool sync_timed_queue<T, Clock>::wait_until_not_empty_time_reached_or_closed(unique_lock<mutex>& lk)
|
||||
template <class T, class Clock, class TimePoint>
|
||||
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);
|
||||
if (not_empty_and_time_reached(lk)) return false; // success
|
||||
if (super::closed(lk)) return true; // closed
|
||||
|
||||
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 tpmin(detail::limit_timepoint(super::data_.top().time));
|
||||
super::cond_.wait_until(lk, tpmin);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class Clock, class TimePoint>
|
||||
queue_op_status sync_timed_queue<T, Clock, TimePoint>::wait_to_pull_until(unique_lock<mutex>& lk, TimePoint const& tp)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
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;
|
||||
|
||||
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((std::min)(tp, detail::limit_timepoint(super::data_.top().time)));
|
||||
super::cond_.wait_until(lk, tpmin);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class Clock, class TimePoint>
|
||||
template <class Rep, class Period>
|
||||
queue_op_status sync_timed_queue<T, Clock, TimePoint>::wait_to_pull_for(unique_lock<mutex>& lk, chrono::duration<Rep,Period> const& dura)
|
||||
{
|
||||
const chrono::steady_clock::time_point tp(chrono::steady_clock::now() + chrono::duration_cast<chrono::steady_clock::duration>(dura));
|
||||
for (;;)
|
||||
{
|
||||
if (not_empty_and_time_reached(lk)) return queue_op_status::success;
|
||||
if (super::closed(lk)) return queue_op_status::closed;
|
||||
if (chrono::steady_clock::now() >= tp) return super::empty(lk) ? queue_op_status::timeout : queue_op_status::not_ready;
|
||||
|
||||
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 (chrono::steady_clock::now() >= tp) return super::empty(lk) ? queue_op_status::timeout : queue_op_status::not_ready;
|
||||
|
||||
const chrono::steady_clock::time_point tpmin((std::min)(tp, detail::convert_to_steady_clock_timepoint(super::data_.top().time)));
|
||||
super::cond_.wait_until(lk, tpmin);
|
||||
}
|
||||
//return false;
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
template <class T, class Clock>
|
||||
T sync_timed_queue<T, Clock>::pull_when_time_reached(unique_lock<mutex>& lk)
|
||||
template <class T, class Clock, class TimePoint>
|
||||
T sync_timed_queue<T, Clock, TimePoint>::pull(unique_lock<mutex>&)
|
||||
{
|
||||
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);
|
||||
}
|
||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
return boost::move(super::data_.pull().data);
|
||||
#else
|
||||
return super::data_.pull().data;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T, class Clock, class TimePoint>
|
||||
T sync_timed_queue<T, Clock, TimePoint>::pull(lock_guard<mutex>&)
|
||||
{
|
||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
return boost::move(super::data_.pull().data);
|
||||
#else
|
||||
return super::data_.pull().data;
|
||||
#endif
|
||||
}
|
||||
template <class T, class Clock, class TimePoint>
|
||||
T sync_timed_queue<T, Clock, TimePoint>::pull()
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
const bool has_been_closed = wait_to_pull(lk);
|
||||
if (has_been_closed) super::throw_if_closed(lk);
|
||||
return pull(lk);
|
||||
}
|
||||
|
||||
template <class T, class Clock>
|
||||
template <class Duration>
|
||||
queue_op_status
|
||||
sync_timed_queue<T, Clock>::pull_when_time_reached_until(unique_lock<mutex>& lk, chrono::time_point<clock,Duration> const& tp, T& elem)
|
||||
///////////////////////////
|
||||
template <class T, class Clock, class TimePoint>
|
||||
void sync_timed_queue<T, Clock, TimePoint>::pull(unique_lock<mutex>&, T& elem)
|
||||
{
|
||||
chrono::time_point<clock,Duration> tpmin = (tp < super::data_.top().time) ? tp : super::data_.top().time;
|
||||
while (time_not_reached(lk))
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
elem = boost::move(super::data_.pull().data);
|
||||
#else
|
||||
elem = super::data_.pull().data;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T, class Clock, class TimePoint>
|
||||
void sync_timed_queue<T, Clock, TimePoint>::pull(lock_guard<mutex>&, T& elem)
|
||||
{
|
||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
elem = boost::move(super::data_.pull().data);
|
||||
#else
|
||||
elem = super::data_.pull().data;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T, class Clock, class TimePoint>
|
||||
void sync_timed_queue<T, Clock, TimePoint>::pull(T& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
const bool has_been_closed = wait_to_pull(lk);
|
||||
if (has_been_closed) super::throw_if_closed(lk);
|
||||
pull(lk, elem);
|
||||
return queue_op_status::success;
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
template <class T, class Clock>
|
||||
bool sync_timed_queue<T, Clock>::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>
|
||||
bool sync_timed_queue<T, Clock>::empty_or_time_not_reached(lock_guard<mutex>& lk)
|
||||
{
|
||||
if ( super::empty(lk) ) return true;
|
||||
if ( time_not_reached(lk) ) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
template <class T, class Clock>
|
||||
T sync_timed_queue<T, Clock>::pull(unique_lock<mutex>&)
|
||||
{
|
||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
return boost::move(super::data_.pull().data);
|
||||
#else
|
||||
return super::data_.pull().data;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T, class Clock>
|
||||
T sync_timed_queue<T, Clock>::pull(lock_guard<mutex>&)
|
||||
{
|
||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
return boost::move(super::data_.pull().data);
|
||||
#else
|
||||
return super::data_.pull().data;
|
||||
#endif
|
||||
}
|
||||
template <class T, class Clock>
|
||||
T sync_timed_queue<T, Clock>::pull()
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
super::wait_until_not_empty(lk);
|
||||
return pull_when_time_reached(lk);
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
template <class T, class Clock>
|
||||
void sync_timed_queue<T, Clock>::pull(unique_lock<mutex>&, T& elem)
|
||||
{
|
||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
elem = boost::move(super::data_.pull().data);
|
||||
#else
|
||||
elem = super::data_.pull().data;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T, class Clock>
|
||||
void sync_timed_queue<T, Clock>::pull(lock_guard<mutex>&, T& elem)
|
||||
{
|
||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
elem = boost::move(super::data_.pull().data);
|
||||
#else
|
||||
elem = super::data_.pull().data;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T, class Clock>
|
||||
void sync_timed_queue<T, Clock>::pull(T& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
super::wait_until_not_empty(lk);
|
||||
elem = pull_when_time_reached(lk);
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
template <class T, class Clock>
|
||||
template <class T, class Clock, class TimePoint>
|
||||
template <class Duration>
|
||||
queue_op_status
|
||||
sync_timed_queue<T, Clock>::pull_until(chrono::time_point<clock,Duration> const& tp, T& elem)
|
||||
sync_timed_queue<T, Clock, TimePoint>::pull_until(chrono::time_point<clock,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, chrono::time_point_cast<typename time_point::duration>(tp));
|
||||
if (rc == queue_op_status::success) pull(lk, elem);
|
||||
return rc;
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
template <class T, class Clock>
|
||||
template <class T, class Clock, class TimePoint>
|
||||
template <class Rep, class Period>
|
||||
queue_op_status
|
||||
sync_timed_queue<T, Clock>::pull_for(chrono::duration<Rep,Period> const& dura, T& elem)
|
||||
sync_timed_queue<T, Clock, TimePoint>::pull_for(chrono::duration<Rep,Period> const& dura, T& elem)
|
||||
{
|
||||
return pull_until(clock::now() + dura, elem);
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
const queue_op_status rc = wait_to_pull_for(lk, dura);
|
||||
if (rc == queue_op_status::success) pull(lk, elem);
|
||||
return rc;
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
template <class T, class Clock>
|
||||
queue_op_status sync_timed_queue<T, Clock>::try_pull(unique_lock<mutex>& lk, T& elem)
|
||||
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>
|
||||
queue_op_status sync_timed_queue<T, Clock>::try_pull(lock_guard<mutex>& lk, T& elem)
|
||||
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>
|
||||
queue_op_status sync_timed_queue<T, Clock>::try_pull(T& elem)
|
||||
template <class T, class Clock, class TimePoint>
|
||||
queue_op_status sync_timed_queue<T, Clock, TimePoint>::try_pull(T& elem)
|
||||
{
|
||||
lock_guard<mutex> lk(super::mtx_);
|
||||
return try_pull(lk, elem);
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
template <class T, class Clock>
|
||||
queue_op_status sync_timed_queue<T, Clock>::wait_pull(unique_lock<mutex>& lk, T& 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 = 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;
|
||||
}
|
||||
|
||||
template <class T, class Clock>
|
||||
queue_op_status sync_timed_queue<T, Clock>::wait_pull(T& elem)
|
||||
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>
|
||||
// queue_op_status sync_timed_queue<T, Clock>::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>
|
||||
// queue_op_status sync_timed_queue<T, Clock>::wait_pull(T& elem)
|
||||
// {
|
||||
// unique_lock<mutex> lk(super::mtx_);
|
||||
// return wait_pull(lk, elem);
|
||||
// }
|
||||
|
||||
///////////////////////////
|
||||
template <class T, class Clock>
|
||||
queue_op_status sync_timed_queue<T, Clock>::nonblocking_pull(T& elem)
|
||||
template <class T, class Clock, class TimePoint>
|
||||
queue_op_status sync_timed_queue<T, Clock, TimePoint>::nonblocking_pull(T& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_, try_to_lock);
|
||||
if (! lk.owns_lock()) return queue_op_status::busy;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
//
|
||||
// 2013/10 Vicente J. Botet Escriba
|
||||
// Creation.
|
||||
|
||||
#if 0
|
||||
#ifndef BOOST_CSBL_QUEUE_HPP
|
||||
#define BOOST_CSBL_QUEUE_HPP
|
||||
|
||||
@@ -43,3 +43,4 @@ namespace boost
|
||||
}
|
||||
}
|
||||
#endif // header
|
||||
#endif
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -24,8 +24,39 @@
|
||||
|
||||
#define BOOST_THREAD_DETAIL_USE_ATTRIBUTE_MAY_ALIAS
|
||||
#endif
|
||||
#if defined(BOOST_MAY_ALIAS)
|
||||
#define BOOST_THREAD_ATTRIBUTE_MAY_ALIAS BOOST_MAY_ALIAS
|
||||
#else
|
||||
#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(BOOST_THREAD_PLATFORM_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) \
|
||||
@@ -93,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
|
||||
@@ -307,10 +338,18 @@
|
||||
|
||||
#if BOOST_THREAD_VERSION>=5
|
||||
//#define BOOST_THREAD_FUTURE_BLOCKING
|
||||
|
||||
#if ! defined BOOST_THREAD_PROVIDES_EXECUTORS \
|
||||
&& ! defined BOOST_THREAD_DONT_PROVIDE_EXECUTORS
|
||||
#define BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
#endif
|
||||
|
||||
#else
|
||||
//#define BOOST_THREAD_FUTURE_BLOCKING
|
||||
#define BOOST_THREAD_ASYNC_FUTURE_WAITS
|
||||
#endif
|
||||
|
||||
|
||||
// INTERRUPTIONS
|
||||
#if ! defined BOOST_THREAD_PROVIDES_INTERRUPTIONS \
|
||||
&& ! defined BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS
|
||||
@@ -382,9 +421,37 @@
|
||||
# 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
|
||||
#if defined(BOOST_THREAD_DYN_DLL) && ! defined(BOOST_THREAD_DYN_LINK)
|
||||
# define BOOST_THREAD_DYN_LINK
|
||||
#endif
|
||||
|
||||
@@ -403,7 +470,8 @@
|
||||
#else //Use default
|
||||
# if defined(BOOST_THREAD_PLATFORM_WIN32)
|
||||
# if defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN) \
|
||||
|| defined(__MINGW32__) || defined(MINGW32) || defined(BOOST_MINGW32)
|
||||
|| defined(__MINGW32__) || defined(MINGW32) || defined(BOOST_MINGW32) \
|
||||
|| (defined(_MSC_VER) && defined(__clang__))
|
||||
//For compilers supporting auto-tss cleanup
|
||||
//with Boost.Threads lib, use Boost.Threads lib
|
||||
# define BOOST_THREAD_USE_LIB
|
||||
@@ -443,7 +511,7 @@
|
||||
// Tell the autolink to link dynamically, this will get undef'ed by auto_link.hpp
|
||||
// once it's done with it:
|
||||
//
|
||||
#if defined(BOOST_THREAD_USE_DLL)
|
||||
#if defined(BOOST_THREAD_USE_DLL) & ! defined(BOOST_DYN_LINK)
|
||||
# define BOOST_DYN_LINK
|
||||
#endif
|
||||
//
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/core/enable_if.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/type_traits/is_base_of.hpp>
|
||||
#include <boost/type_traits/is_pointer.hpp>
|
||||
#include <boost/type_traits/is_member_function_pointer.hpp>
|
||||
@@ -531,13 +530,13 @@ namespace boost
|
||||
// f(t1, t2, ..., tN) in all other cases.
|
||||
|
||||
template <class Ret, class Fp, class ...Args>
|
||||
inline Ret do_invoke(mpl::false_, BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args)
|
||||
inline Ret do_invoke(boost::false_type, BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args)
|
||||
{
|
||||
return boost::forward<Fp>(f)(boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class Ret, class Fp, class ...Args>
|
||||
inline Ret do_invoke(mpl::true_, BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args)
|
||||
inline Ret do_invoke(boost::true_type, BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args)
|
||||
{
|
||||
return f(boost::forward<Args>(args)...);
|
||||
}
|
||||
@@ -1360,12 +1359,12 @@ namespace boost
|
||||
// f(t1, t2, ..., tN) in all other cases.
|
||||
|
||||
template <class Ret, class Fp>
|
||||
inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f)
|
||||
inline Ret do_invoke(boost::false_type, BOOST_THREAD_FWD_REF(Fp) f)
|
||||
{
|
||||
return boost::forward<Fp>(f)();
|
||||
}
|
||||
template <class Ret, class Fp>
|
||||
inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f)
|
||||
inline Ret do_invoke(boost::true_type, BOOST_THREAD_FWD_REF(Fp) f)
|
||||
{
|
||||
return f();
|
||||
}
|
||||
@@ -1382,12 +1381,12 @@ namespace boost
|
||||
}
|
||||
|
||||
template <class Ret, class Fp, class A1>
|
||||
inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
|
||||
inline Ret do_invoke(boost::false_type, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
|
||||
{
|
||||
return boost::forward<Fp>(f)(boost::forward<A1>(a1));
|
||||
}
|
||||
template <class Ret, class Fp, class A1>
|
||||
inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
|
||||
inline Ret do_invoke(boost::true_type, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
|
||||
{
|
||||
return f(boost::forward<A1>(a1));
|
||||
}
|
||||
@@ -1404,12 +1403,12 @@ namespace boost
|
||||
}
|
||||
|
||||
template <class Ret, class Fp, class A1, class A2>
|
||||
inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
|
||||
inline Ret do_invoke(boost::false_type, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
|
||||
{
|
||||
return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
|
||||
}
|
||||
template <class Ret, class Fp, class A1, class A2>
|
||||
inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
|
||||
inline Ret do_invoke(boost::true_type, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
|
||||
{
|
||||
return f(boost::forward<A1>(a1), boost::forward<A2>(a2));
|
||||
}
|
||||
@@ -1426,12 +1425,12 @@ namespace boost
|
||||
}
|
||||
|
||||
template <class Ret, class Fp, class A1, class A2, class A3>
|
||||
inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
|
||||
inline Ret do_invoke(boost::false_type, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
|
||||
{
|
||||
return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
|
||||
}
|
||||
template <class Ret, class Fp, class A1, class A2, class A3>
|
||||
inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
|
||||
inline Ret do_invoke(boost::true_type, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
|
||||
{
|
||||
return f(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
|
||||
}
|
||||
@@ -1449,12 +1448,12 @@ namespace boost
|
||||
|
||||
|
||||
template <class Ret, class Fp, class A1>
|
||||
inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1)
|
||||
inline Ret do_invoke(boost::false_type, BOOST_THREAD_FWD_REF(Fp) f, A1 a1)
|
||||
{
|
||||
return boost::forward<Fp>(f)(a1);
|
||||
}
|
||||
template <class Ret, class Fp, class A1>
|
||||
inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1)
|
||||
inline Ret do_invoke(boost::true_type, BOOST_THREAD_FWD_REF(Fp) f, A1 a1)
|
||||
{
|
||||
return f(a1);
|
||||
}
|
||||
@@ -1471,12 +1470,12 @@ namespace boost
|
||||
}
|
||||
|
||||
template <class Ret, class Fp, class A1, class A2>
|
||||
inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2)
|
||||
inline Ret do_invoke(boost::false_type, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2)
|
||||
{
|
||||
return boost::forward<Fp>(f)(a1, a2);
|
||||
}
|
||||
template <class Ret, class Fp, class A1, class A2>
|
||||
inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2)
|
||||
inline Ret do_invoke(boost::true_type, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2)
|
||||
{
|
||||
return f(a1, a2);
|
||||
}
|
||||
@@ -1493,12 +1492,12 @@ namespace boost
|
||||
}
|
||||
|
||||
template <class Ret, class Fp, class A1, class A2, class A3>
|
||||
inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2, A3 a3)
|
||||
inline Ret do_invoke(boost::false_type, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2, A3 a3)
|
||||
{
|
||||
return boost::forward<Fp>(f)(a1, a2, a3);
|
||||
}
|
||||
template <class Ret, class Fp, class A1, class A2, class A3>
|
||||
inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2, A3 a3)
|
||||
inline Ret do_invoke(boost::true_type, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2, A3 a3)
|
||||
{
|
||||
return f(a1, a2, a3);
|
||||
}
|
||||
|
||||
@@ -72,7 +72,13 @@ namespace boost
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#define BOOST_THREAD_LOG \
|
||||
__pragma(warning(suppress:4127)) /* conditional expression is constant */ \
|
||||
if (true) {} else boost::thread_detail::dummy_stream
|
||||
#else
|
||||
#define BOOST_THREAD_LOG if (true) {} else boost::thread_detail::dummy_stream
|
||||
#endif
|
||||
#define BOOST_THREAD_END_LOG boost::thread_detail::dummy_stream
|
||||
|
||||
#endif
|
||||
@@ -80,4 +86,13 @@ namespace boost
|
||||
#define BOOST_THREAD_TRACE BOOST_THREAD_LOG << BOOST_THREAD_END_LOG
|
||||
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#define BOOST_DETAIL_THREAD_LOG \
|
||||
__pragma(warning(suppress:4127)) /* conditional expression is constant */ \
|
||||
if (false) {} else std::cout << std::endl << __FILE__ << "[" << __LINE__ << "]"
|
||||
#else
|
||||
#define BOOST_DETAIL_THREAD_LOG \
|
||||
if (false) {} else std::cout << std::endl << __FILE__ << "[" << __LINE__ << "]"
|
||||
#endif
|
||||
|
||||
#endif // header
|
||||
|
||||
@@ -18,9 +18,7 @@
|
||||
#include <boost/type_traits/remove_extent.hpp>
|
||||
#include <boost/type_traits/is_array.hpp>
|
||||
#include <boost/type_traits/is_function.hpp>
|
||||
#include <boost/type_traits/remove_cv.hpp>
|
||||
#include <boost/type_traits/add_pointer.hpp>
|
||||
#include <boost/type_traits/decay.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/thread/detail/delete.hpp>
|
||||
@@ -352,12 +350,19 @@ namespace boost
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
template <class T>
|
||||
typename decay<T>::type
|
||||
decay_copy(T&& t)
|
||||
{
|
||||
return boost::forward<T>(t);
|
||||
}
|
||||
template <class T>
|
||||
typename decay<T>::type
|
||||
decay_copy(T&& t)
|
||||
{
|
||||
return boost::forward<T>(t);
|
||||
}
|
||||
typedef void (*void_fct_ptr)();
|
||||
|
||||
// inline void_fct_ptr
|
||||
// decay_copy(void (&t)())
|
||||
// {
|
||||
// return &t;
|
||||
// }
|
||||
#else
|
||||
template <class T>
|
||||
typename decay<T>::type
|
||||
|
||||
@@ -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/winapi/time.hpp>
|
||||
#include <boost/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::winapi::FILETIME_ ft;
|
||||
boost::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::winapi::LARGE_INTEGER_ freq;
|
||||
if ( !boost::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::winapi::LARGE_INTEGER_ pcount;
|
||||
unsigned times=0;
|
||||
while ( ! boost::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
|
||||
@@ -18,6 +18,9 @@
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
#include <boost/thread/xtime.hpp>
|
||||
#endif
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
#include <boost/thread/interruption.hpp>
|
||||
#endif
|
||||
#include <boost/thread/detail/thread_heap_alloc.hpp>
|
||||
#include <boost/thread/detail/make_tuple_indices.hpp>
|
||||
#include <boost/thread/detail/invoke.hpp>
|
||||
@@ -27,7 +30,7 @@
|
||||
#include <algorithm>
|
||||
#include <boost/core/ref.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/bind/bind.hpp>
|
||||
#include <stdlib.h>
|
||||
#include <memory>
|
||||
#include <boost/core/enable_if.hpp>
|
||||
@@ -36,6 +39,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 +159,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 +458,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,19 +585,13 @@ 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
|
||||
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
void BOOST_THREAD_DECL interruption_point();
|
||||
bool BOOST_THREAD_DECL interruption_enabled() BOOST_NOEXCEPT;
|
||||
bool BOOST_THREAD_DECL interruption_requested() BOOST_NOEXCEPT;
|
||||
#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));
|
||||
}
|
||||
@@ -672,10 +637,6 @@ namespace thread_detail {
|
||||
#endif
|
||||
{}
|
||||
|
||||
id(const id& other) BOOST_NOEXCEPT :
|
||||
thread_data(other.thread_data)
|
||||
{}
|
||||
|
||||
bool operator==(const id& y) const BOOST_NOEXCEPT
|
||||
{
|
||||
return thread_data==y.thread_data;
|
||||
@@ -745,7 +706,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 +729,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 +738,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 +804,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 +818,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
|
||||
|
||||
160
include/boost/thread/detail/thread_safety.hpp
Normal file
160
include/boost/thread/detail/thread_safety.hpp
Normal file
@@ -0,0 +1,160 @@
|
||||
#ifndef BOOST_THREAD_DETAIL_THREAD_SAFETY_HPP
|
||||
#define BOOST_THREAD_DETAIL_THREAD_SAFETY_HPP
|
||||
|
||||
#if defined(__GNUC__) && !defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
//
|
||||
// This is horrible, but it seems to be the only we can shut up the
|
||||
// "anonymous variadic macros were introduced in C99 [-Wvariadic-macros]"
|
||||
// warning that get spewed out otherwise in non-C++11 mode.
|
||||
//
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
// 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
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
#if defined(BOOST_THREAD_WIN32)
|
||||
|
||||
namespace boost
|
||||
{
|
||||
@@ -58,7 +58,7 @@ namespace boost
|
||||
//it to be linked into the Boost.Threads library.
|
||||
}
|
||||
|
||||
#endif //defined(BOOST_HAS_WINTHREADS)
|
||||
#endif //defined(BOOST_THREAD_WIN32)
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace boost
|
||||
{
|
||||
}
|
||||
|
||||
~thread_exception() throw()
|
||||
~thread_exception() BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ namespace boost
|
||||
{
|
||||
}
|
||||
|
||||
~lock_error() throw()
|
||||
~lock_error() BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
};
|
||||
@@ -141,7 +141,7 @@ namespace boost
|
||||
}
|
||||
|
||||
|
||||
~thread_resource_error() throw()
|
||||
~thread_resource_error() BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
};
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#define BOOST_THREAD_EXECUTORS_BASIC_THREAD_POOL_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
|
||||
|
||||
#include <boost/thread/detail/delete.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
@@ -231,13 +233,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)
|
||||
{
|
||||
@@ -324,3 +349,4 @@ using executors::basic_thread_pool;
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#define BOOST_THREAD_EXECUTORS_EXECUTOR_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
|
||||
|
||||
#include <boost/thread/detail/delete.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
@@ -146,3 +147,4 @@ namespace boost
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#define BOOST_THREAD_EXECUTORS_EXECUTOR_ADAPTOR_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
|
||||
|
||||
#include <boost/thread/executors/executor.hpp>
|
||||
|
||||
@@ -134,3 +135,4 @@ using executors::executor_adaptor;
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#define BOOST_THREAD_EXECUTORS_GENERIC_EXECUTOR_REF_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
|
||||
|
||||
#include <boost/thread/detail/delete.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
@@ -211,3 +212,4 @@ namespace boost
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -10,9 +10,16 @@
|
||||
#define BOOST_THREAD_INLINE_EXECUTOR_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
|
||||
|
||||
#include <exception> // std::terminate
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/thread/detail/delete.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/executors/work.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/lock_guard.hpp>
|
||||
#include <boost/thread/concurrent_queues/queue_op_status.hpp> // sync_queue_is_closed
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
@@ -169,3 +176,4 @@ using executors::inline_executor;
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
#define BOOST_THREAD_EXECUTORS_LOOP_EXECUTOR_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
|
||||
|
||||
#include <boost/thread/detail/delete.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/concurrent_queues/sync_queue.hpp>
|
||||
@@ -205,5 +208,6 @@ using executors::loop_executor;
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
#ifndef BOOST_THREAD_EXECUTORS_SCHEDULED_THREAD_POOL_HPP
|
||||
#define BOOST_THREAD_EXECUTORS_SCHEDULED_THREAD_POOL_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
|
||||
|
||||
#include <boost/thread/executors/detail/scheduled_executor_base.hpp>
|
||||
|
||||
namespace boost
|
||||
@@ -46,4 +49,5 @@ using executors::scheduled_thread_pool;
|
||||
|
||||
} //end boost
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#define BOOST_THREAD_EXECUTORS_SCHEDULER_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
|
||||
#include <boost/thread/executors/detail/scheduled_executor_base.hpp>
|
||||
|
||||
#include <boost/chrono/time_point.hpp>
|
||||
@@ -16,6 +17,11 @@
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4355) // 'this' : used in base member initializer list
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace executors
|
||||
@@ -267,6 +273,11 @@ namespace boost
|
||||
using executors::scheduler;
|
||||
}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -8,27 +8,34 @@
|
||||
#ifndef BOOST_THREAD_EXECUTORS_SCHEDULING_ADAPTOR_HPP
|
||||
#define BOOST_THREAD_EXECUTORS_SCHEDULING_ADAPTOR_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
|
||||
#include <boost/thread/executors/detail/scheduled_executor_base.hpp>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4355) // 'this' : used in base member initializer list
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace executors
|
||||
{
|
||||
|
||||
template <typename Executor>
|
||||
class scheduling_adpator : public detail::scheduled_executor_base<>
|
||||
class scheduling_adaptor : public detail::scheduled_executor_base<>
|
||||
{
|
||||
private:
|
||||
Executor& _exec;
|
||||
thread _scheduler;
|
||||
public:
|
||||
|
||||
scheduling_adpator(Executor& ex)
|
||||
scheduling_adaptor(Executor& ex)
|
||||
: super(),
|
||||
_exec(ex),
|
||||
_scheduler(&super::loop, this) {}
|
||||
|
||||
~scheduling_adpator()
|
||||
~scheduling_adaptor()
|
||||
{
|
||||
this->close();
|
||||
_scheduler.interrupt();
|
||||
@@ -46,7 +53,13 @@ namespace executors
|
||||
|
||||
} //end executors
|
||||
|
||||
using executors::scheduling_adpator;
|
||||
using executors::scheduling_adaptor;
|
||||
|
||||
} //end boost
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
#define BOOST_THREAD_SERIAL_EXECUTOR_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
|
||||
|
||||
#include <exception>
|
||||
#include <boost/thread/detail/delete.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/concurrent_queues/sync_queue.hpp>
|
||||
@@ -20,6 +23,11 @@
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4355) // 'this' : used in base member initializer list
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace executors
|
||||
@@ -211,6 +219,11 @@ namespace executors
|
||||
using executors::serial_executor;
|
||||
}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -10,13 +10,19 @@
|
||||
#define BOOST_THREAD_SERIAL_EXECUTOR_CONT_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
|
||||
|
||||
#include <exception> // std::terminate
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/thread/detail/delete.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/concurrent_queues/sync_queue.hpp>
|
||||
#include <boost/thread/executors/work.hpp>
|
||||
#include <boost/thread/executors/generic_executor_ref.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/thread/scoped_thread.hpp>
|
||||
#include <boost/thread/lock_guard.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
@@ -32,7 +38,7 @@ namespace executors
|
||||
private:
|
||||
|
||||
generic_executor_ref ex_;
|
||||
future<void> fut_; // protected by mtx_
|
||||
BOOST_THREAD_FUTURE<void> fut_; // protected by mtx_
|
||||
bool closed_; // protected by mtx_
|
||||
mutex mtx_;
|
||||
|
||||
@@ -44,7 +50,7 @@ namespace executors
|
||||
};
|
||||
continuation(BOOST_THREAD_RV_REF(work) tsk)
|
||||
: task(boost::move(tsk)) {}
|
||||
void operator()(future<void> f)
|
||||
void operator()(BOOST_THREAD_FUTURE<void> f)
|
||||
{
|
||||
try {
|
||||
task();
|
||||
@@ -168,3 +174,4 @@ using executors::serial_executor_cont;
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -10,10 +10,15 @@
|
||||
#define BOOST_THREAD_THREAD_EXECUTOR_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
|
||||
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/thread/detail/delete.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/executors/work.hpp>
|
||||
#include <boost/thread/executors/executor.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/lock_guard.hpp>
|
||||
#include <boost/thread/thread_only.hpp>
|
||||
#include <boost/thread/scoped_thread.hpp>
|
||||
#include <boost/thread/csbl/vector.hpp>
|
||||
@@ -155,3 +160,4 @@ using executors::thread_executor;
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#define BOOST_THREAD_EXECUTORS_WORK_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
|
||||
|
||||
#include <boost/thread/detail/nullary_function.hpp>
|
||||
#include <boost/thread/csbl/functional.hpp>
|
||||
|
||||
@@ -26,5 +28,5 @@ namespace boost
|
||||
}
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif
|
||||
#endif // BOOST_THREAD_EXECUTORS_WORK_HPP
|
||||
|
||||
8
include/boost/thread/experimental/parallel/v2/task_region.hpp
Executable file → Normal file
8
include/boost/thread/experimental/parallel/v2/task_region.hpp
Executable file → Normal file
@@ -10,6 +10,9 @@
|
||||
// See http://www.boost.org/libs/thread for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <exception>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/thread/future.hpp>
|
||||
@@ -18,6 +21,7 @@
|
||||
#endif
|
||||
#include <boost/thread/experimental/exception_list.hpp>
|
||||
#include <boost/thread/experimental/parallel/v2/inline_namespace.hpp>
|
||||
#include <boost/thread/csbl/vector.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
@@ -126,7 +130,7 @@ BOOST_THREAD_INLINE_NAMESPACE(v2)
|
||||
|
||||
for (group_type::iterator it = group.begin(); it != group.end(); ++it)
|
||||
{
|
||||
future<void>& f = *it;
|
||||
BOOST_THREAD_FUTURE<void>& f = *it;
|
||||
if (f.has_exception())
|
||||
{
|
||||
try
|
||||
@@ -191,7 +195,7 @@ protected:
|
||||
Executor* ex;
|
||||
#endif
|
||||
exception_list exs;
|
||||
typedef csbl::vector<future<void> > group_type;
|
||||
typedef csbl::vector<BOOST_THREAD_FUTURE<void> > group_type;
|
||||
group_type group;
|
||||
|
||||
public:
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class mutex;
|
||||
|
||||
/**
|
||||
* externally_locked cloaks an object of type T, and actually provides full
|
||||
|
||||
@@ -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>
|
||||
@@ -45,7 +54,7 @@
|
||||
#endif
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/bind/bind.hpp>
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
#include <boost/chrono/system_clocks.hpp>
|
||||
#endif
|
||||
@@ -109,6 +118,7 @@ namespace boost
|
||||
namespace executors {
|
||||
class executor;
|
||||
}
|
||||
using executors::executor;
|
||||
#endif
|
||||
typedef shared_ptr<executor> executor_ptr_type;
|
||||
|
||||
@@ -159,7 +169,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 +183,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 +278,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 +299,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 +393,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 +412,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 +430,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 +443,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;
|
||||
}
|
||||
@@ -421,7 +462,7 @@ namespace boost
|
||||
mark_exceptional_finish_internal(boost::current_exception(), lock);
|
||||
}
|
||||
|
||||
void set_exception_at_thread_exit(exception_ptr e)
|
||||
void set_exception_deferred(exception_ptr e)
|
||||
{
|
||||
unique_lock<boost::mutex> lk(this->mutex);
|
||||
if (has_value(lk))
|
||||
@@ -430,6 +471,17 @@ namespace boost
|
||||
}
|
||||
exception=e;
|
||||
this->is_constructed = true;
|
||||
}
|
||||
void set_exception_at_thread_exit(exception_ptr e)
|
||||
{
|
||||
set_exception_deferred(e);
|
||||
// unique_lock<boost::mutex> lk(this->mutex);
|
||||
// if (has_value(lk))
|
||||
// {
|
||||
// throw_exception(promise_already_satisfied());
|
||||
// }
|
||||
// exception=e;
|
||||
// this->is_constructed = true;
|
||||
detail::make_ready_at_thread_exit(shared_from_this());
|
||||
}
|
||||
|
||||
@@ -535,10 +587,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)
|
||||
{
|
||||
@@ -617,8 +667,7 @@ namespace boost
|
||||
boost::unique_lock<boost::mutex> lk(this->mutex);
|
||||
return this->get_sh(lk);
|
||||
}
|
||||
|
||||
void set_value_at_thread_exit(source_reference_type result_)
|
||||
void set_value_deferred(source_reference_type result_)
|
||||
{
|
||||
unique_lock<boost::mutex> lk(this->mutex);
|
||||
if (this->has_value(lk))
|
||||
@@ -632,13 +681,14 @@ namespace boost
|
||||
#endif
|
||||
|
||||
this->is_constructed = true;
|
||||
detail::make_ready_at_thread_exit(shared_from_this());
|
||||
}
|
||||
void set_value_at_thread_exit(rvalue_source_type result_)
|
||||
void set_value_deferred(rvalue_source_type result_)
|
||||
{
|
||||
unique_lock<boost::mutex> lk(this->mutex);
|
||||
if (this->has_value(lk))
|
||||
{
|
||||
throw_exception(promise_already_satisfied());
|
||||
}
|
||||
|
||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
|
||||
@@ -654,6 +704,46 @@ namespace boost
|
||||
#endif
|
||||
#endif
|
||||
this->is_constructed = true;
|
||||
}
|
||||
|
||||
void set_value_at_thread_exit(source_reference_type result_)
|
||||
{
|
||||
set_value_deferred(result_);
|
||||
// unique_lock<boost::mutex> lk(this->mutex);
|
||||
// if (this->has_value(lk))
|
||||
// {
|
||||
// throw_exception(promise_already_satisfied());
|
||||
// }
|
||||
//#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
|
||||
// result = result_;
|
||||
//#else
|
||||
// result.reset(new T(result_));
|
||||
//#endif
|
||||
//
|
||||
// this->is_constructed = true;
|
||||
detail::make_ready_at_thread_exit(shared_from_this());
|
||||
}
|
||||
void set_value_at_thread_exit(rvalue_source_type result_)
|
||||
{
|
||||
set_value_deferred(boost::move(result_));
|
||||
// unique_lock<boost::mutex> lk(this->mutex);
|
||||
// if (this->has_value(lk))
|
||||
// throw_exception(promise_already_satisfied());
|
||||
//
|
||||
//#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
//#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
|
||||
// result = boost::move(result_);
|
||||
//#else
|
||||
// result.reset(new T(boost::move(result_)));
|
||||
//#endif
|
||||
//#else
|
||||
//#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
|
||||
// result = boost::move(result_);
|
||||
//#else
|
||||
// result.reset(new T(static_cast<rvalue_source_type>(result_)));
|
||||
//#endif
|
||||
//#endif
|
||||
// this->is_constructed = true;
|
||||
detail::make_ready_at_thread_exit(shared_from_this());
|
||||
}
|
||||
|
||||
@@ -681,9 +771,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)
|
||||
{
|
||||
@@ -719,13 +808,25 @@ namespace boost
|
||||
return get_sh(lock);
|
||||
}
|
||||
|
||||
void set_value_at_thread_exit(T& result_)
|
||||
void set_value_deferred(T& result_)
|
||||
{
|
||||
unique_lock<boost::mutex> lk(this->mutex);
|
||||
if (this->has_value(lk))
|
||||
{
|
||||
throw_exception(promise_already_satisfied());
|
||||
}
|
||||
result= &result_;
|
||||
this->is_constructed = true;
|
||||
}
|
||||
|
||||
void set_value_at_thread_exit(T& result_)
|
||||
{
|
||||
set_value_deferred(result_);
|
||||
// unique_lock<boost::mutex> lk(this->mutex);
|
||||
// if (this->has_value(lk))
|
||||
// throw_exception(promise_already_satisfied());
|
||||
// result= &result_;
|
||||
// this->is_constructed = true;
|
||||
detail::make_ready_at_thread_exit(shared_from_this());
|
||||
}
|
||||
|
||||
@@ -748,6 +849,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);
|
||||
@@ -779,7 +883,7 @@ namespace boost
|
||||
this->get_sh(lock);
|
||||
}
|
||||
|
||||
void set_value_at_thread_exit()
|
||||
void set_value_deferred()
|
||||
{
|
||||
unique_lock<boost::mutex> lk(this->mutex);
|
||||
if (this->has_value(lk))
|
||||
@@ -787,6 +891,16 @@ namespace boost
|
||||
throw_exception(promise_already_satisfied());
|
||||
}
|
||||
this->is_constructed = true;
|
||||
}
|
||||
void set_value_at_thread_exit()
|
||||
{
|
||||
set_value_deferred();
|
||||
// unique_lock<boost::mutex> lk(this->mutex);
|
||||
// if (this->has_value(lk))
|
||||
// {
|
||||
// throw_exception(promise_already_satisfied());
|
||||
// }
|
||||
// this->is_constructed = true;
|
||||
detail::make_ready_at_thread_exit(shared_from_this());
|
||||
}
|
||||
private:
|
||||
@@ -826,10 +940,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
|
||||
}
|
||||
|
||||
@@ -934,10 +1045,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))
|
||||
{
|
||||
@@ -962,10 +1071,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))
|
||||
{
|
||||
@@ -987,10 +1094,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))
|
||||
{
|
||||
@@ -1018,7 +1123,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_;
|
||||
@@ -1379,7 +1483,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
|
||||
@@ -2165,13 +2273,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
|
||||
}
|
||||
|
||||
@@ -2263,7 +2371,8 @@ namespace boost
|
||||
|
||||
#if defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
template <class TR>
|
||||
typename boost::enable_if_c<is_copy_constructible<TR>::value && is_same<R, TR>::value, void>::type set_value(TR const & r)
|
||||
typename boost::enable_if_c<is_copy_constructible<TR>::value && is_same<R, TR>::value, void>::type
|
||||
set_value(TR const & r)
|
||||
{
|
||||
lazy_init();
|
||||
boost::unique_lock<boost::mutex> lock(future_->mutex);
|
||||
@@ -2301,6 +2410,44 @@ namespace boost
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
template <class TR>
|
||||
typename boost::enable_if_c<is_copy_constructible<TR>::value && is_same<R, TR>::value, void>::type
|
||||
set_value_deferred(TR const & r)
|
||||
{
|
||||
lazy_init();
|
||||
if (future_.get()==0)
|
||||
{
|
||||
boost::throw_exception(promise_moved());
|
||||
}
|
||||
future_->set_value_deferred(r);
|
||||
}
|
||||
#else
|
||||
void set_value_deferred(source_reference_type r)
|
||||
{
|
||||
lazy_init();
|
||||
if (future_.get()==0)
|
||||
{
|
||||
boost::throw_exception(promise_moved());
|
||||
}
|
||||
future_->set_value_deferred(r);
|
||||
}
|
||||
#endif
|
||||
|
||||
void set_value_deferred(rvalue_source_type r)
|
||||
{
|
||||
lazy_init();
|
||||
if (future_.get()==0)
|
||||
{
|
||||
boost::throw_exception(promise_moved());
|
||||
}
|
||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
future_->set_value_deferred(boost::move(r));
|
||||
#else
|
||||
future_->set_value_deferred(static_cast<rvalue_source_type>(r));
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template <class ...Args>
|
||||
void emplace(BOOST_THREAD_FWD_REF(Args) ...args)
|
||||
@@ -2331,6 +2478,21 @@ namespace boost
|
||||
{
|
||||
set_exception(boost::copy_exception(ex));
|
||||
}
|
||||
void set_exception_deferred(boost::exception_ptr p)
|
||||
{
|
||||
lazy_init();
|
||||
if (future_.get()==0)
|
||||
{
|
||||
boost::throw_exception(promise_moved());
|
||||
}
|
||||
future_->set_exception_deferred(p);
|
||||
}
|
||||
template <typename E>
|
||||
void set_exception_deferred(E ex)
|
||||
{
|
||||
set_exception_deferred(boost::copy_exception(ex));
|
||||
}
|
||||
|
||||
// setting the result with deferred notification
|
||||
#if defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
template <class TR>
|
||||
@@ -2380,6 +2542,14 @@ namespace boost
|
||||
lazy_init();
|
||||
future_->set_wait_callback(f,this);
|
||||
}
|
||||
void notify_deferred()
|
||||
{
|
||||
if (future_.get()==0)
|
||||
{
|
||||
boost::throw_exception(promise_moved());
|
||||
}
|
||||
future_->notify_deferred();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -2394,13 +2564,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
|
||||
}
|
||||
|
||||
@@ -2488,7 +2658,15 @@ namespace boost
|
||||
}
|
||||
future_->mark_finished_with_result_internal(r, lock);
|
||||
}
|
||||
|
||||
void set_value_deferred(R& r)
|
||||
{
|
||||
lazy_init();
|
||||
if (future_.get()==0)
|
||||
{
|
||||
boost::throw_exception(promise_already_satisfied());
|
||||
}
|
||||
future_->set_value_deferred(r);
|
||||
}
|
||||
void set_exception(boost::exception_ptr p)
|
||||
{
|
||||
lazy_init();
|
||||
@@ -2504,7 +2682,20 @@ namespace boost
|
||||
{
|
||||
set_exception(boost::copy_exception(ex));
|
||||
}
|
||||
|
||||
void set_exception_deferred(boost::exception_ptr p)
|
||||
{
|
||||
lazy_init();
|
||||
if (future_.get()==0)
|
||||
{
|
||||
boost::throw_exception(promise_moved());
|
||||
}
|
||||
future_->set_exception_deferred(p);
|
||||
}
|
||||
template <typename E>
|
||||
void set_exception_deferred(E ex)
|
||||
{
|
||||
set_exception_deferred(boost::copy_exception(ex));
|
||||
}
|
||||
// setting the result with deferred notification
|
||||
void set_value_at_thread_exit(R& r)
|
||||
{
|
||||
@@ -2535,6 +2726,14 @@ namespace boost
|
||||
lazy_init();
|
||||
future_->set_wait_callback(f,this);
|
||||
}
|
||||
void notify_deferred()
|
||||
{
|
||||
if (future_.get()==0)
|
||||
{
|
||||
boost::throw_exception(promise_moved());
|
||||
}
|
||||
future_->notify_deferred();
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
@@ -2644,6 +2843,15 @@ namespace boost
|
||||
}
|
||||
future_->mark_finished_with_result_internal(lock);
|
||||
}
|
||||
void set_value_deferred()
|
||||
{
|
||||
lazy_init();
|
||||
if (future_.get()==0)
|
||||
{
|
||||
boost::throw_exception(promise_moved());
|
||||
}
|
||||
future_->set_value_deferred();
|
||||
}
|
||||
|
||||
void set_exception(boost::exception_ptr p)
|
||||
{
|
||||
@@ -2660,7 +2868,20 @@ namespace boost
|
||||
{
|
||||
set_exception(boost::copy_exception(ex));
|
||||
}
|
||||
|
||||
void set_exception_deferred(boost::exception_ptr p)
|
||||
{
|
||||
lazy_init();
|
||||
if (future_.get()==0)
|
||||
{
|
||||
boost::throw_exception(promise_moved());
|
||||
}
|
||||
future_->set_exception_deferred(p);
|
||||
}
|
||||
template <typename E>
|
||||
void set_exception_deferred(E ex)
|
||||
{
|
||||
set_exception_deferred(boost::copy_exception(ex));
|
||||
}
|
||||
// setting the result with deferred notification
|
||||
void set_value_at_thread_exit()
|
||||
{
|
||||
@@ -2691,7 +2912,14 @@ namespace boost
|
||||
lazy_init();
|
||||
future_->set_wait_callback(f,this);
|
||||
}
|
||||
|
||||
void notify_deferred()
|
||||
{
|
||||
if (future_.get()==0)
|
||||
{
|
||||
boost::throw_exception(promise_moved());
|
||||
}
|
||||
future_->notify_deferred();
|
||||
}
|
||||
};
|
||||
}
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
|
||||
@@ -2962,7 +3190,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)
|
||||
@@ -3304,7 +3532,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)
|
||||
@@ -3394,7 +3622,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)())
|
||||
{
|
||||
@@ -3415,7 +3643,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>
|
||||
@@ -3632,7 +3860,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>
|
||||
@@ -3691,7 +3919,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)
|
||||
|
||||
@@ -3920,7 +4148,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>
|
||||
@@ -3936,7 +4164,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(
|
||||
@@ -3955,7 +4183,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>
|
||||
@@ -3985,7 +4213,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>
|
||||
@@ -4041,7 +4269,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>
|
||||
@@ -4763,6 +4991,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());
|
||||
@@ -4783,6 +5015,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());
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <boost/thread/futures/is_future_type.hpp>
|
||||
#include <boost/thread/lock_algorithms.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
|
||||
#include <boost/core/enable_if.hpp>
|
||||
#include <boost/next_prior.hpp>
|
||||
|
||||
22
include/boost/thread/interruption.hpp
Normal file
22
include/boost/thread/interruption.hpp
Normal file
@@ -0,0 +1,22 @@
|
||||
// (C) Copyright 2013 Vicente J. Botet Escriba
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
|
||||
#ifndef BOOST_THREAD_INTERRUPTION_HPP
|
||||
#define BOOST_THREAD_INTERRUPTION_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace this_thread
|
||||
{
|
||||
void BOOST_THREAD_DECL interruption_point();
|
||||
bool BOOST_THREAD_DECL interruption_enabled() BOOST_NOEXCEPT;
|
||||
bool BOOST_THREAD_DECL interruption_requested() BOOST_NOEXCEPT;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // header
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -11,7 +11,12 @@
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/type_traits/integral_constant.hpp>
|
||||
#ifdef BOOST_NO_CXX11_SFINAE_EXPR
|
||||
#include <boost/type_traits/is_class.hpp>
|
||||
#else
|
||||
#include <boost/type_traits/declval.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
@@ -33,6 +38,7 @@ namespace boost
|
||||
#ifndef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES
|
||||
namespace detail
|
||||
{
|
||||
#ifdef BOOST_NO_CXX11_SFINAE_EXPR
|
||||
#define BOOST_THREAD_DEFINE_HAS_MEMBER_CALLED(member_name) \
|
||||
template<typename T, bool=boost::is_class<T>::value> \
|
||||
struct has_member_called_##member_name \
|
||||
@@ -142,6 +148,31 @@ namespace boost
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool,value=sizeof(has_member_try_lock<T>::has_member(&T::try_lock))==sizeof(true_type));
|
||||
};
|
||||
#else
|
||||
template<typename T,typename Enabled=void>
|
||||
struct has_member_lock : false_type {};
|
||||
|
||||
template<typename T>
|
||||
struct has_member_lock<T,
|
||||
decltype(void(boost::declval<T&>().lock()))
|
||||
> : true_type {};
|
||||
|
||||
template<typename T,typename Enabled=void>
|
||||
struct has_member_unlock : false_type {};
|
||||
|
||||
template<typename T>
|
||||
struct has_member_unlock<T,
|
||||
decltype(void(boost::declval<T&>().unlock()))
|
||||
> : true_type {};
|
||||
|
||||
template<typename T,typename Enabled=bool>
|
||||
struct has_member_try_lock : false_type {};
|
||||
|
||||
template<typename T>
|
||||
struct has_member_try_lock<T,
|
||||
decltype(bool(boost::declval<T&>().try_lock()))
|
||||
> : true_type {};
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,12 @@
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4702) // unreachable code
|
||||
#endif
|
||||
|
||||
#include <boost/thread/detail/platform.hpp>
|
||||
#if defined(BOOST_THREAD_PLATFORM_WIN32)
|
||||
#include <boost/thread/win32/once.hpp>
|
||||
@@ -41,4 +47,8 @@ inline void call_once(Function func,once_flag& flag)
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -30,6 +30,9 @@ namespace boost
|
||||
};
|
||||
//]
|
||||
|
||||
// A proper name for basic_poly_lockable, consistent with naming scheme of other polymorphic wrappers
|
||||
typedef basic_poly_lockable poly_basic_lockable;
|
||||
|
||||
//[poly_lockable
|
||||
class poly_lockable : public basic_poly_lockable
|
||||
{
|
||||
@@ -51,18 +54,20 @@ namespace boost
|
||||
template <typename Clock, typename Duration>
|
||||
bool try_lock_until(chrono::time_point<Clock, Duration> const & abs_time)
|
||||
{
|
||||
return try_lock_until(time_point_cast<Clock::time_point>(abs_time));
|
||||
return try_lock_until(chrono::time_point_cast<Clock::time_point>(abs_time));
|
||||
}
|
||||
|
||||
virtual bool try_lock_for(chrono::nanoseconds const & relative_time)=0;
|
||||
template <typename Rep, typename Period>
|
||||
bool try_lock_for(chrono::duration<Rep, Period> const & rel_time)
|
||||
{
|
||||
return try_lock_for(duration_cast<Clock::duration>(rel_time));
|
||||
return try_lock_for(chrono::duration_cast<chrono::nanoseconds>(rel_time));
|
||||
}
|
||||
|
||||
};
|
||||
//]
|
||||
|
||||
// A proper name for timed_poly_lockable, consistent with naming scheme of other polymorphic wrappers
|
||||
typedef timed_poly_lockable poly_timed_lockable;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -33,20 +33,22 @@ namespace boost
|
||||
template <typename Clock, typename Duration>
|
||||
bool try_lock_shared_until(chrono::time_point<Clock, Duration> const & abs_time)
|
||||
{
|
||||
return try_lock_shared_until(time_point_cast<Clock::time_point>(abs_time));
|
||||
return try_lock_shared_until(chrono::time_point_cast<Clock::time_point>(abs_time));
|
||||
}
|
||||
|
||||
virtual bool try_lock_shared_for(chrono::nanoseconds const & relative_time)=0;
|
||||
template <typename Rep, typename Period>
|
||||
bool try_lock_shared_for(chrono::duration<Rep, Period> const & rel_time)
|
||||
{
|
||||
return try_lock_shared_for(duration_cast<Clock::duration>(rel_time));
|
||||
return try_lock_shared_for(chrono::duration_cast<chrono::nanoseconds>(rel_time));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//]
|
||||
|
||||
// A proper name for shared_poly_lockable, consistent with naming scheme of other polymorphic wrappers
|
||||
typedef shared_poly_lockable poly_shared_lockable;
|
||||
|
||||
//[upgrade_poly_lockable
|
||||
class upgrade_poly_lockable: public shared_poly_lockable
|
||||
{
|
||||
@@ -62,14 +64,14 @@ namespace boost
|
||||
template <typename Clock, typename Duration>
|
||||
bool try_lock_upgrade_until(chrono::time_point<Clock, Duration> const & abs_time)
|
||||
{
|
||||
return try_lock_upgrade_until(time_point_cast<Clock::time_point>(abs_time));
|
||||
return try_lock_upgrade_until(chrono::time_point_cast<Clock::time_point>(abs_time));
|
||||
}
|
||||
|
||||
virtual bool try_lock_upgrade_for(chrono::nanoseconds const & relative_time)=0;
|
||||
template <typename Rep, typename Period>
|
||||
bool try_lock_upgrade_for(chrono::duration<Rep, Period> const & rel_time)
|
||||
{
|
||||
return try_lock_upgrade_for(duration_cast<Clock::duration>(rel_time));
|
||||
return try_lock_upgrade_for(chrono::duration_cast<chrono::nanoseconds>(rel_time));
|
||||
}
|
||||
|
||||
virtual bool try_unlock_shared_and_lock() = 0;
|
||||
@@ -79,14 +81,14 @@ namespace boost
|
||||
template <typename Clock, typename Duration>
|
||||
bool try_unlock_shared_and_lock_until(chrono::time_point<Clock, Duration> const & abs_time)
|
||||
{
|
||||
return try_unlock_shared_and_lock_until(time_point_cast<Clock::time_point>(abs_time));
|
||||
return try_unlock_shared_and_lock_until(chrono::time_point_cast<Clock::time_point>(abs_time));
|
||||
}
|
||||
|
||||
virtual bool try_unlock_shared_and_lock_for(chrono::nanoseconds const & relative_time)=0;
|
||||
template <typename Rep, typename Period>
|
||||
bool try_unlock_shared_and_lock_for(chrono::duration<Rep, Period> const & rel_time)
|
||||
{
|
||||
return try_unlock_shared_and_lock_for(duration_cast<Clock::duration>(rel_time));
|
||||
return try_unlock_shared_and_lock_for(chrono::duration_cast<chrono::nanoseconds>(rel_time));
|
||||
}
|
||||
|
||||
virtual void unlock_and_lock_shared() = 0;
|
||||
@@ -97,14 +99,14 @@ namespace boost
|
||||
template <typename Clock, typename Duration>
|
||||
bool try_unlock_shared_and_lock_upgrade_until(chrono::time_point<Clock, Duration> const & abs_time)
|
||||
{
|
||||
return try_unlock_shared_and_lock_upgrade_until(time_point_cast<Clock::time_point>(abs_time));
|
||||
return try_unlock_shared_and_lock_upgrade_until(chrono::time_point_cast<Clock::time_point>(abs_time));
|
||||
}
|
||||
|
||||
virtual bool try_unlock_shared_and_lock_upgrade_for(chrono::nanoseconds const & relative_time)=0;
|
||||
template <typename Rep, typename Period>
|
||||
bool try_unlock_shared_and_lock_upgrade_for(chrono::duration<Rep, Period> const & rel_time)
|
||||
{
|
||||
return try_unlock_shared_and_lock_upgrade_for(duration_cast<Clock::duration>(rel_time));
|
||||
return try_unlock_shared_and_lock_upgrade_for(chrono::duration_cast<chrono::nanoseconds>(rel_time));
|
||||
}
|
||||
|
||||
virtual void unlock_and_lock_upgrade() = 0;
|
||||
@@ -116,20 +118,22 @@ namespace boost
|
||||
template <typename Clock, typename Duration>
|
||||
bool try_unlock_upgrade_and_lock_until(chrono::time_point<Clock, Duration> const & abs_time)
|
||||
{
|
||||
return try_unlock_upgrade_and_lock_until(time_point_cast<Clock::time_point>(abs_time));
|
||||
return try_unlock_upgrade_and_lock_until(chrono::time_point_cast<Clock::time_point>(abs_time));
|
||||
}
|
||||
|
||||
virtual bool try_unlock_upgrade_and_lock_for(chrono::nanoseconds const & relative_time)=0;
|
||||
template <typename Rep, typename Period>
|
||||
bool try_unlock_upgrade_and_lock_for(chrono::duration<Rep, Period> const & rel_time)
|
||||
{
|
||||
return try_unlock_upgrade_and_lock_for(duration_cast<Clock::duration>(rel_time));
|
||||
return try_unlock_upgrade_and_lock_for(chrono::duration_cast<chrono::nanoseconds>(rel_time));
|
||||
}
|
||||
|
||||
virtual void unlock_upgrade_and_lock_shared() = 0;
|
||||
|
||||
};
|
||||
//]
|
||||
//]
|
||||
|
||||
// A proper name for upgrade_poly_lockable, consistent with naming scheme of other polymorphic wrappers
|
||||
typedef upgrade_poly_lockable poly_upgrade_lockable;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
namespace boost
|
||||
{
|
||||
|
||||
//[shared_lockable_adapter
|
||||
//[poly_shared_lockable_adapter
|
||||
template <typename Mutex, typename Base=poly_shared_lockable>
|
||||
class poly_shared_lockable_adapter: public poly_timed_lockable_adapter<Mutex, Base>
|
||||
{
|
||||
@@ -54,9 +54,9 @@ namespace boost
|
||||
|
||||
//]
|
||||
|
||||
//[upgrade_lockable_adapter
|
||||
//[poly_upgrade_lockable_adapter
|
||||
template <typename Mutex, typename Base=poly_shared_lockable>
|
||||
class upgrade_lockable_adapter: public shared_lockable_adapter<Mutex, Base>
|
||||
class poly_upgrade_lockable_adapter: public poly_shared_lockable_adapter<Mutex, Base>
|
||||
{
|
||||
public:
|
||||
typedef Mutex mutex_type;
|
||||
@@ -102,7 +102,6 @@ namespace boost
|
||||
{
|
||||
return this->mtx().try_unlock_shared_and_lock_until(abs_time);
|
||||
}
|
||||
template <typename Rep, typename Period>
|
||||
bool try_unlock_shared_and_lock_for(chrono::nanoseconds const & rel_time)
|
||||
{
|
||||
return this->mtx().try_unlock_shared_and_lock_for(rel_time);
|
||||
|
||||
@@ -6,9 +6,12 @@
|
||||
// (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/interruption.hpp>
|
||||
#include <boost/thread/pthread/thread_data.hpp>
|
||||
#endif
|
||||
#include <boost/thread/pthread/condition_variable_fwd.hpp>
|
||||
@@ -18,17 +21,12 @@
|
||||
#endif
|
||||
#include <boost/thread/detail/delete.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
namespace this_thread
|
||||
{
|
||||
void BOOST_THREAD_DECL interruption_point();
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace thread_cv_detail
|
||||
{
|
||||
template<typename MutexType>
|
||||
@@ -78,26 +76,35 @@ namespace boost
|
||||
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
|
||||
pthread_mutex_t* the_mutex = &internal_mutex;
|
||||
guard.activate(m);
|
||||
res = pthread_cond_wait(&cond,the_mutex);
|
||||
check_for_interruption.check();
|
||||
res = posix::pthread_cond_wait(&cond,the_mutex);
|
||||
check_for_interruption.unlock_if_locked();
|
||||
guard.deactivate();
|
||||
#else
|
||||
pthread_mutex_t* the_mutex = m.mutex()->native_handle();
|
||||
res = pthread_cond_wait(&cond,the_mutex);
|
||||
res = posix::pthread_cond_wait(&cond,the_mutex);
|
||||
#endif
|
||||
}
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
this_thread::interruption_point();
|
||||
#endif
|
||||
if(res && res != EINTR)
|
||||
if(res)
|
||||
{
|
||||
boost::throw_exception(condition_error(res, "boost::condition_variable::wait failed in pthread_cond_wait"));
|
||||
}
|
||||
}
|
||||
|
||||
// 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 +119,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);
|
||||
check_for_interruption.check();
|
||||
cond_res=posix::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=posix::pthread_cond_timedwait(&cond,the_mutex,&timeout.getTs());
|
||||
#endif
|
||||
}
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
@@ -139,7 +146,7 @@ namespace boost
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
|
||||
#endif
|
||||
BOOST_VERIFY(!pthread_cond_signal(&cond));
|
||||
BOOST_VERIFY(!posix::pthread_cond_signal(&cond));
|
||||
}
|
||||
|
||||
inline void condition_variable::notify_all() BOOST_NOEXCEPT
|
||||
@@ -147,7 +154,7 @@ namespace boost
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
|
||||
#endif
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&cond));
|
||||
BOOST_VERIFY(!posix::pthread_cond_broadcast(&cond));
|
||||
}
|
||||
|
||||
class condition_variable_any
|
||||
@@ -159,22 +166,22 @@ namespace boost
|
||||
BOOST_THREAD_NO_COPYABLE(condition_variable_any)
|
||||
condition_variable_any()
|
||||
{
|
||||
int const res=pthread_mutex_init(&internal_mutex,NULL);
|
||||
int const res=posix::pthread_mutex_init(&internal_mutex);
|
||||
if(res)
|
||||
{
|
||||
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 = posix::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_VERIFY(!posix::pthread_mutex_destroy(&internal_mutex));
|
||||
boost::throw_exception(thread_resource_error(res2, "boost::condition_variable_any::condition_variable_any() failed in pthread_cond_init"));
|
||||
}
|
||||
}
|
||||
~condition_variable_any()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
|
||||
BOOST_VERIFY(!pthread_cond_destroy(&cond));
|
||||
BOOST_VERIFY(!posix::pthread_mutex_destroy(&internal_mutex));
|
||||
BOOST_VERIFY(!posix::pthread_cond_destroy(&cond));
|
||||
}
|
||||
|
||||
template<typename lock_type>
|
||||
@@ -189,8 +196,8 @@ namespace boost
|
||||
boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
|
||||
#endif
|
||||
guard.activate(m);
|
||||
res=pthread_cond_wait(&cond,&internal_mutex);
|
||||
check_for_interruption.check();
|
||||
res=posix::pthread_cond_wait(&cond,&internal_mutex);
|
||||
check_for_interruption.unlock_if_locked();
|
||||
guard.deactivate();
|
||||
}
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
@@ -205,18 +212,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 +251,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 +311,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 +365,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 +385,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 +410,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,27 +431,36 @@ 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
|
||||
|
||||
void notify_one() BOOST_NOEXCEPT
|
||||
{
|
||||
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
|
||||
BOOST_VERIFY(!pthread_cond_signal(&cond));
|
||||
BOOST_VERIFY(!posix::pthread_cond_signal(&cond));
|
||||
}
|
||||
|
||||
void notify_all() BOOST_NOEXCEPT
|
||||
{
|
||||
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&cond));
|
||||
BOOST_VERIFY(!posix::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,8 +471,8 @@ 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);
|
||||
check_for_interruption.check();
|
||||
res=posix::pthread_cond_timedwait(&cond,&internal_mutex,&timeout.getTs());
|
||||
check_for_interruption.unlock_if_locked();
|
||||
guard.deactivate();
|
||||
}
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
@@ -437,7 +489,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)
|
||||
@@ -87,36 +58,29 @@ namespace boost
|
||||
// above) and must be initialized (etc) in case some
|
||||
// compilation units provide interruptions and others
|
||||
// don't.
|
||||
res=pthread_mutex_init(&internal_mutex,NULL);
|
||||
res=posix::pthread_mutex_init(&internal_mutex);
|
||||
if(res)
|
||||
{
|
||||
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 = posix::pthread_cond_init(&cond);
|
||||
if (res)
|
||||
{
|
||||
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
// ditto
|
||||
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
|
||||
BOOST_VERIFY(!posix::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()
|
||||
{
|
||||
int ret;
|
||||
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
// ditto
|
||||
do {
|
||||
ret = pthread_mutex_destroy(&internal_mutex);
|
||||
} while (ret == EINTR);
|
||||
BOOST_ASSERT(!ret);
|
||||
BOOST_VERIFY(!posix::pthread_mutex_destroy(&internal_mutex));
|
||||
//#endif
|
||||
do {
|
||||
ret = pthread_cond_destroy(&cond);
|
||||
} while (ret == EINTR);
|
||||
BOOST_ASSERT(!ret);
|
||||
BOOST_VERIFY(!posix::pthread_cond_destroy(&cond));
|
||||
}
|
||||
|
||||
void wait(unique_lock<mutex>& m);
|
||||
@@ -124,25 +88,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 +133,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 +162,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 +201,7 @@ namespace boost
|
||||
{
|
||||
while (!pred())
|
||||
{
|
||||
wait(m); // or do_wait(m,detail::timeout::sentinel());
|
||||
wait(m);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -202,26 +209,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 +252,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 +297,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 +318,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 +331,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,80 +16,27 @@
|
||||
#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>
|
||||
|
||||
#ifndef BOOST_THREAD_HAS_NO_EINTR_BUG
|
||||
#define BOOST_THREAD_HAS_EINTR_BUG
|
||||
#endif
|
||||
|
||||
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;
|
||||
@@ -98,7 +45,7 @@ namespace boost
|
||||
|
||||
mutex()
|
||||
{
|
||||
int const res=pthread_mutex_init(&m,NULL);
|
||||
int const res=posix::pthread_mutex_init(&m);
|
||||
if(res)
|
||||
{
|
||||
boost::throw_exception(thread_resource_error(res, "boost:: mutex constructor failed in pthread_mutex_init"));
|
||||
@@ -106,12 +53,10 @@ namespace boost
|
||||
}
|
||||
~mutex()
|
||||
{
|
||||
int const res = posix::pthread_mutex_destroy(&m);
|
||||
boost::ignore_unused(res);
|
||||
BOOST_ASSERT(!res);
|
||||
BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
|
||||
}
|
||||
|
||||
void lock()
|
||||
void lock() BOOST_THREAD_ACQUIRE()
|
||||
{
|
||||
int res = posix::pthread_mutex_lock(&m);
|
||||
if (res)
|
||||
@@ -120,24 +65,14 @@ namespace boost
|
||||
}
|
||||
}
|
||||
|
||||
void unlock()
|
||||
void unlock() BOOST_THREAD_RELEASE()
|
||||
{
|
||||
int res = posix::pthread_mutex_unlock(&m);
|
||||
(void)res;
|
||||
BOOST_ASSERT(res == 0);
|
||||
// if (res)
|
||||
// {
|
||||
// boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock"));
|
||||
// }
|
||||
BOOST_VERIFY(!posix::pthread_mutex_unlock(&m));
|
||||
}
|
||||
|
||||
bool try_lock()
|
||||
bool try_lock() BOOST_THREAD_TRY_ACQUIRE(true)
|
||||
{
|
||||
int res;
|
||||
do
|
||||
{
|
||||
res = pthread_mutex_trylock(&m);
|
||||
} while (res == EINTR);
|
||||
int res = posix::pthread_mutex_trylock(&m);
|
||||
if (res==EBUSY)
|
||||
{
|
||||
return false;
|
||||
@@ -165,7 +100,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
|
||||
@@ -173,17 +108,16 @@ namespace boost
|
||||
BOOST_THREAD_NO_COPYABLE(timed_mutex)
|
||||
timed_mutex()
|
||||
{
|
||||
int const res=pthread_mutex_init(&m,NULL);
|
||||
int const res=posix::pthread_mutex_init(&m);
|
||||
if(res)
|
||||
{
|
||||
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=posix::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"));
|
||||
}
|
||||
is_locked=false;
|
||||
@@ -192,8 +126,8 @@ namespace boost
|
||||
~timed_mutex()
|
||||
{
|
||||
BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
|
||||
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||
BOOST_VERIFY(!pthread_cond_destroy(&cond));
|
||||
#ifndef BOOST_THREAD_USES_PTHREAD_TIMEDLOCK
|
||||
BOOST_VERIFY(!posix::pthread_cond_destroy(&cond));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -201,14 +135,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);
|
||||
@@ -220,22 +176,12 @@ namespace boost
|
||||
|
||||
void unlock()
|
||||
{
|
||||
int res = posix::pthread_mutex_unlock(&m);
|
||||
(void)res;
|
||||
BOOST_ASSERT(res == 0);
|
||||
// if (res)
|
||||
// {
|
||||
// boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock"));
|
||||
// }
|
||||
BOOST_VERIFY(!posix::pthread_mutex_unlock(&m));
|
||||
}
|
||||
|
||||
bool try_lock()
|
||||
{
|
||||
int res;
|
||||
do
|
||||
{
|
||||
res = pthread_mutex_trylock(&m);
|
||||
} while (res == EINTR);
|
||||
int res = posix::pthread_mutex_trylock(&m);
|
||||
if (res==EBUSY)
|
||||
{
|
||||
return false;
|
||||
@@ -246,9 +192,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 +206,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 +215,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 +230,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=posix::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 +255,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 +280,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 +312,6 @@ namespace boost
|
||||
typedef scoped_timed_lock scoped_lock;
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
@@ -14,11 +14,12 @@
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/detail/invoke.hpp>
|
||||
|
||||
#include <boost/thread/pthread/pthread_helpers.hpp>
|
||||
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
|
||||
#include <boost/thread/detail/delete.hpp>
|
||||
#include <boost/core/no_exceptions_support.hpp>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/bind/bind.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
@@ -149,18 +150,18 @@ namespace boost
|
||||
BOOST_CATCH (...)
|
||||
{
|
||||
flag.epoch=uninitialized_flag;
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
flag.epoch=--thread_detail::once_global_epoch;
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
}
|
||||
else
|
||||
{
|
||||
while(flag.epoch==being_initialized)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
|
||||
BOOST_VERIFY(!posix::pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -194,18 +195,18 @@ namespace boost
|
||||
BOOST_CATCH (...)
|
||||
{
|
||||
flag.epoch=uninitialized_flag;
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
flag.epoch=--thread_detail::once_global_epoch;
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
}
|
||||
else
|
||||
{
|
||||
while(flag.epoch==being_initialized)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
|
||||
BOOST_VERIFY(!posix::pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -238,18 +239,18 @@ namespace boost
|
||||
BOOST_CATCH (...)
|
||||
{
|
||||
flag.epoch=uninitialized_flag;
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
flag.epoch=--thread_detail::once_global_epoch;
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
}
|
||||
else
|
||||
{
|
||||
while(flag.epoch==being_initialized)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
|
||||
BOOST_VERIFY(!posix::pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -281,18 +282,18 @@ namespace boost
|
||||
BOOST_CATCH (...)
|
||||
{
|
||||
flag.epoch=uninitialized_flag;
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
flag.epoch=--thread_detail::once_global_epoch;
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
}
|
||||
else
|
||||
{
|
||||
while(flag.epoch==being_initialized)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
|
||||
BOOST_VERIFY(!posix::pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -325,18 +326,18 @@ namespace boost
|
||||
BOOST_CATCH (...)
|
||||
{
|
||||
flag.epoch=uninitialized_flag;
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
flag.epoch=--thread_detail::once_global_epoch;
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
}
|
||||
else
|
||||
{
|
||||
while(flag.epoch==being_initialized)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
|
||||
BOOST_VERIFY(!posix::pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -369,18 +370,18 @@ namespace boost
|
||||
BOOST_CATCH (...)
|
||||
{
|
||||
flag.epoch=uninitialized_flag;
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
flag.epoch=--thread_detail::once_global_epoch;
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
}
|
||||
else
|
||||
{
|
||||
while(flag.epoch==being_initialized)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
|
||||
BOOST_VERIFY(!posix::pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -416,18 +417,18 @@ namespace boost
|
||||
BOOST_CATCH (...)
|
||||
{
|
||||
flag.epoch=uninitialized_flag;
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
flag.epoch=--thread_detail::once_global_epoch;
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
}
|
||||
else
|
||||
{
|
||||
while(flag.epoch==being_initialized)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
|
||||
BOOST_VERIFY(!posix::pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -463,18 +464,18 @@ namespace boost
|
||||
BOOST_CATCH (...)
|
||||
{
|
||||
flag.epoch=uninitialized_flag;
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
flag.epoch=--thread_detail::once_global_epoch;
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
}
|
||||
else
|
||||
{
|
||||
while(flag.epoch==being_initialized)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
|
||||
BOOST_VERIFY(!posix::pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -512,18 +513,18 @@ namespace boost
|
||||
BOOST_CATCH (...)
|
||||
{
|
||||
flag.epoch=uninitialized_flag;
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
flag.epoch=--thread_detail::once_global_epoch;
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
|
||||
}
|
||||
else
|
||||
{
|
||||
while(flag.epoch==being_initialized)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
|
||||
BOOST_VERIFY(!posix::pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/detail/invoke.hpp>
|
||||
#include <boost/core/no_exceptions_support.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/bind/bind.hpp>
|
||||
#include <boost/atomic.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
187
include/boost/thread/pthread/pthread_helpers.hpp
Normal file
187
include/boost/thread/pthread/pthread_helpers.hpp
Normal file
@@ -0,0 +1,187 @@
|
||||
#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 <boost/throw_exception.hpp>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
#ifndef BOOST_THREAD_HAS_NO_EINTR_BUG
|
||||
#define BOOST_THREAD_HAS_EINTR_BUG
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace posix
|
||||
{
|
||||
BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
|
||||
int pthread_mutex_init(pthread_mutex_t* m, const pthread_mutexattr_t* attr = NULL)
|
||||
{
|
||||
return ::pthread_mutex_init(m, attr);
|
||||
}
|
||||
|
||||
BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
|
||||
int pthread_cond_init(pthread_cond_t* c)
|
||||
{
|
||||
#ifdef BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
|
||||
pthread_condattr_t attr;
|
||||
int res = pthread_condattr_init(&attr);
|
||||
if (res)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
BOOST_VERIFY(!pthread_condattr_setclock(&attr, CLOCK_MONOTONIC));
|
||||
res = ::pthread_cond_init(c, &attr);
|
||||
BOOST_VERIFY(!pthread_condattr_destroy(&attr));
|
||||
return res;
|
||||
#else
|
||||
return ::pthread_cond_init(c, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
#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_cond_destroy(pthread_cond_t* c)
|
||||
{
|
||||
int ret;
|
||||
do
|
||||
{
|
||||
ret = ::pthread_cond_destroy(c);
|
||||
} 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_trylock(pthread_mutex_t* m)
|
||||
{
|
||||
int ret;
|
||||
do
|
||||
{
|
||||
ret = ::pthread_mutex_trylock(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;
|
||||
}
|
||||
|
||||
BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
|
||||
int pthread_cond_wait(pthread_cond_t* c, pthread_mutex_t* m)
|
||||
{
|
||||
int ret;
|
||||
do
|
||||
{
|
||||
ret = ::pthread_cond_wait(c, m);
|
||||
} while (ret == EINTR);
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
|
||||
int pthread_cond_timedwait(pthread_cond_t* c, pthread_mutex_t* m, const struct timespec* t)
|
||||
{
|
||||
int ret;
|
||||
do
|
||||
{
|
||||
ret = ::pthread_cond_timedwait(c, m, t);
|
||||
} 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_cond_destroy(pthread_cond_t* c)
|
||||
{
|
||||
return ::pthread_cond_destroy(c);
|
||||
}
|
||||
|
||||
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_trylock(pthread_mutex_t* m)
|
||||
{
|
||||
return ::pthread_mutex_trylock(m);
|
||||
}
|
||||
|
||||
BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
|
||||
int pthread_mutex_unlock(pthread_mutex_t* m)
|
||||
{
|
||||
return ::pthread_mutex_unlock(m);
|
||||
}
|
||||
|
||||
BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
|
||||
int pthread_cond_wait(pthread_cond_t* c, pthread_mutex_t* m)
|
||||
{
|
||||
return ::pthread_cond_wait(c, m);
|
||||
}
|
||||
|
||||
BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
|
||||
int pthread_cond_timedwait(pthread_cond_t* c, pthread_mutex_t* m, const struct timespec* t)
|
||||
{
|
||||
return ::pthread_cond_timedwait(c, m, t);
|
||||
}
|
||||
#endif
|
||||
|
||||
BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
|
||||
int pthread_cond_signal(pthread_cond_t* c)
|
||||
{
|
||||
return ::pthread_cond_signal(c);
|
||||
}
|
||||
|
||||
BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
|
||||
int pthread_cond_broadcast(pthread_cond_t* c)
|
||||
{
|
||||
return ::pthread_cond_broadcast(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <pthread.h>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/thread/pthread/pthread_helpers.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
@@ -23,14 +24,14 @@ 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 check() BOOST_NOEXCEPT
|
||||
void unlock_if_locked() BOOST_NOEXCEPT
|
||||
{
|
||||
if(locked)
|
||||
{
|
||||
@@ -54,11 +55,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
|
||||
|
||||
@@ -76,7 +71,7 @@ namespace boost
|
||||
boost::throw_exception(thread_resource_error(set_attr_res, "boost:: recursive_mutex constructor failed in pthread_mutexattr_settype"));
|
||||
}
|
||||
|
||||
int const res=pthread_mutex_init(&m,&attr);
|
||||
int const res=posix::pthread_mutex_init(&m,&attr);
|
||||
if(res)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
|
||||
@@ -84,15 +79,15 @@ namespace boost
|
||||
}
|
||||
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
|
||||
#else
|
||||
int const res=pthread_mutex_init(&m,NULL);
|
||||
int const res=posix::pthread_mutex_init(&m);
|
||||
if(res)
|
||||
{
|
||||
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=posix::pthread_cond_init(&cond);
|
||||
if(res2)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_destroy(&m));
|
||||
BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
|
||||
boost::throw_exception(thread_resource_error(res2, "boost:: recursive_mutex constructor failed in pthread_cond_init"));
|
||||
}
|
||||
is_locked=false;
|
||||
@@ -101,26 +96,26 @@ namespace boost
|
||||
}
|
||||
~recursive_mutex()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_destroy(&m));
|
||||
BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
|
||||
#ifndef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
|
||||
BOOST_VERIFY(!pthread_cond_destroy(&cond));
|
||||
BOOST_VERIFY(!posix::pthread_cond_destroy(&cond));
|
||||
#endif
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
@@ -143,7 +138,7 @@ namespace boost
|
||||
|
||||
while(is_locked)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
|
||||
BOOST_VERIFY(!posix::pthread_cond_wait(&cond,&m));
|
||||
}
|
||||
is_locked=true;
|
||||
++count;
|
||||
@@ -157,7 +152,7 @@ namespace boost
|
||||
{
|
||||
is_locked=false;
|
||||
}
|
||||
BOOST_VERIFY(!pthread_cond_signal(&cond));
|
||||
BOOST_VERIFY(!posix::pthread_cond_signal(&cond));
|
||||
}
|
||||
|
||||
bool try_lock()
|
||||
@@ -211,7 +206,7 @@ namespace boost
|
||||
boost::throw_exception(thread_resource_error(set_attr_res, "boost:: recursive_timed_mutex constructor failed in pthread_mutexattr_settype"));
|
||||
}
|
||||
|
||||
int const res=pthread_mutex_init(&m,&attr);
|
||||
int const res=posix::pthread_mutex_init(&m,&attr);
|
||||
if(res)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
|
||||
@@ -219,15 +214,15 @@ namespace boost
|
||||
}
|
||||
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
|
||||
#else
|
||||
int const res=pthread_mutex_init(&m,NULL);
|
||||
int const res=posix::pthread_mutex_init(&m);
|
||||
if(res)
|
||||
{
|
||||
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=posix::pthread_cond_init(&cond);
|
||||
if(res2)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_destroy(&m));
|
||||
BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
|
||||
boost::throw_exception(thread_resource_error(res2, "boost:: recursive_timed_mutex constructor failed in pthread_cond_init"));
|
||||
}
|
||||
is_locked=false;
|
||||
@@ -236,9 +231,9 @@ namespace boost
|
||||
}
|
||||
~recursive_timed_mutex()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_destroy(&m));
|
||||
BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
|
||||
#ifndef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
|
||||
BOOST_VERIFY(!pthread_cond_destroy(&cond));
|
||||
BOOST_VERIFY(!posix::pthread_cond_destroy(&cond));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -289,7 +306,7 @@ namespace boost
|
||||
|
||||
while(is_locked)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
|
||||
BOOST_VERIFY(!posix::pthread_cond_wait(&cond,&m));
|
||||
}
|
||||
is_locked=true;
|
||||
++count;
|
||||
@@ -303,7 +320,7 @@ namespace boost
|
||||
{
|
||||
is_locked=false;
|
||||
}
|
||||
BOOST_VERIFY(!pthread_cond_signal(&cond));
|
||||
BOOST_VERIFY(!posix::pthread_cond_signal(&cond));
|
||||
}
|
||||
|
||||
bool try_lock() BOOST_NOEXCEPT
|
||||
@@ -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=posix::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/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_helpers.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
|
||||
@@ -92,12 +94,15 @@ namespace boost
|
||||
struct thread_exit_callback_node;
|
||||
struct tss_data_node
|
||||
{
|
||||
boost::shared_ptr<boost::detail::tss_cleanup_function> func;
|
||||
typedef void(*cleanup_func_t)(void*);
|
||||
typedef void(*cleanup_caller_t)(cleanup_func_t, void*);
|
||||
|
||||
cleanup_caller_t caller;
|
||||
cleanup_func_t func;
|
||||
void* value;
|
||||
|
||||
tss_data_node(boost::shared_ptr<boost::detail::tss_cleanup_function> func_,
|
||||
void* value_):
|
||||
func(func_),value(value_)
|
||||
tss_data_node(cleanup_caller_t caller_,cleanup_func_t func_,void* value_):
|
||||
caller(caller_),func(func_),value(value_)
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -111,8 +116,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 +134,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 +153,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 +172,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,26 +213,26 @@ 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 check()
|
||||
void unlock_if_locked()
|
||||
{
|
||||
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;
|
||||
}
|
||||
@@ -233,7 +240,7 @@ namespace boost
|
||||
|
||||
~interruption_checker() BOOST_NOEXCEPT_IF(false)
|
||||
{
|
||||
check();
|
||||
unlock_if_locked();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
@@ -241,49 +248,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 +265,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
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
// (C) Copyright 2007-8 Anthony Williams
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/thread/detail/thread_heap_alloc.hpp>
|
||||
|
||||
#include <boost/type_traits/add_reference.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
@@ -15,15 +15,13 @@ namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct tss_cleanup_function
|
||||
namespace thread
|
||||
{
|
||||
virtual ~tss_cleanup_function()
|
||||
{}
|
||||
typedef void(*cleanup_func_t)(void*);
|
||||
typedef void(*cleanup_caller_t)(cleanup_func_t, void*);
|
||||
}
|
||||
|
||||
virtual void operator()(void* data)=0;
|
||||
};
|
||||
|
||||
BOOST_THREAD_DECL void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing);
|
||||
BOOST_THREAD_DECL void set_tss_data(void const* key,detail::thread::cleanup_caller_t caller,detail::thread::cleanup_func_t func,void* tss_data,bool cleanup_existing);
|
||||
BOOST_THREAD_DECL void* get_tss_data(void const* key);
|
||||
}
|
||||
|
||||
@@ -34,49 +32,33 @@ namespace boost
|
||||
thread_specific_ptr(thread_specific_ptr&);
|
||||
thread_specific_ptr& operator=(thread_specific_ptr&);
|
||||
|
||||
struct delete_data:
|
||||
detail::tss_cleanup_function
|
||||
typedef void(*original_cleanup_func_t)(T*);
|
||||
|
||||
static void default_deleter(T* data)
|
||||
{
|
||||
void operator()(void* data)
|
||||
{
|
||||
delete static_cast<T*>(data);
|
||||
}
|
||||
};
|
||||
delete data;
|
||||
}
|
||||
|
||||
struct run_custom_cleanup_function:
|
||||
detail::tss_cleanup_function
|
||||
static void cleanup_caller(detail::thread::cleanup_func_t cleanup_function,void* data)
|
||||
{
|
||||
void (*cleanup_function)(T*);
|
||||
|
||||
explicit run_custom_cleanup_function(void (*cleanup_function_)(T*)):
|
||||
cleanup_function(cleanup_function_)
|
||||
{}
|
||||
|
||||
void operator()(void* data)
|
||||
{
|
||||
cleanup_function(static_cast<T*>(data));
|
||||
}
|
||||
};
|
||||
reinterpret_cast<original_cleanup_func_t>(cleanup_function)(static_cast<T*>(data));
|
||||
}
|
||||
|
||||
|
||||
boost::shared_ptr<detail::tss_cleanup_function> cleanup;
|
||||
detail::thread::cleanup_func_t cleanup;
|
||||
|
||||
public:
|
||||
typedef T element_type;
|
||||
|
||||
thread_specific_ptr():
|
||||
cleanup(detail::heap_new<delete_data>(),detail::do_heap_delete<delete_data>())
|
||||
cleanup(reinterpret_cast<detail::thread::cleanup_func_t>(&default_deleter))
|
||||
{}
|
||||
explicit thread_specific_ptr(void (*func_)(T*))
|
||||
{
|
||||
if(func_)
|
||||
{
|
||||
cleanup.reset(detail::heap_new<run_custom_cleanup_function>(func_),detail::do_heap_delete<run_custom_cleanup_function>());
|
||||
}
|
||||
}
|
||||
: cleanup(reinterpret_cast<detail::thread::cleanup_func_t>(func_))
|
||||
{}
|
||||
~thread_specific_ptr()
|
||||
{
|
||||
detail::set_tss_data(this,boost::shared_ptr<detail::tss_cleanup_function>(),0,true);
|
||||
detail::set_tss_data(this,0,0,0,true);
|
||||
}
|
||||
|
||||
T* get() const
|
||||
@@ -87,14 +69,14 @@ namespace boost
|
||||
{
|
||||
return get();
|
||||
}
|
||||
typename boost::detail::sp_dereference< T >::type operator*() const
|
||||
typename add_reference<T>::type operator*() const
|
||||
{
|
||||
return *get();
|
||||
}
|
||||
T* release()
|
||||
{
|
||||
T* const temp=get();
|
||||
detail::set_tss_data(this,boost::shared_ptr<detail::tss_cleanup_function>(),0,false);
|
||||
detail::set_tss_data(this,0,0,0,false);
|
||||
return temp;
|
||||
}
|
||||
void reset(T* new_value=0)
|
||||
@@ -102,7 +84,7 @@ namespace boost
|
||||
T* const current_value=get();
|
||||
if(current_value!=new_value)
|
||||
{
|
||||
detail::set_tss_data(this,cleanup,new_value,true);
|
||||
detail::set_tss_data(this,&cleanup_caller,cleanup,new_value,true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#define BOOST_THREAD_USER_SCHEDULER_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
|
||||
|
||||
#include <boost/thread/detail/delete.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/concurrent_queues/sync_queue.hpp>
|
||||
@@ -200,3 +202,4 @@ namespace boost
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
1246
include/boost/thread/v2/shared_mutex.hpp
Executable file → Normal file
1246
include/boost/thread/v2/shared_mutex.hpp
Executable file → Normal file
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>
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
// Define compiler barriers
|
||||
#if defined(__INTEL_COMPILER)
|
||||
#define BOOST_THREAD_DETAIL_COMPILER_BARRIER() __memory_barrier()
|
||||
#elif defined(__clang__)
|
||||
#define BOOST_THREAD_DETAIL_COMPILER_BARRIER() __atomic_signal_fence(__ATOMIC_SEQ_CST)
|
||||
#elif defined(_MSC_VER) && !defined(_WIN32_WCE)
|
||||
extern "C" void _ReadWriteBarrier(void);
|
||||
#pragma intrinsic(_ReadWriteBarrier)
|
||||
@@ -87,9 +89,9 @@ namespace boost
|
||||
{
|
||||
void* const res=
|
||||
#if defined(_M_ARM64)
|
||||
__iso_volatile_load64((const volatile __int64*)x);
|
||||
(void*)__iso_volatile_load64((const volatile __int64*)x);
|
||||
#else
|
||||
__iso_volatile_load32((const volatile __int32*)x);
|
||||
(void*)__iso_volatile_load32((const volatile __int32*)x);
|
||||
#endif
|
||||
BOOST_THREAD_DETAIL_COMPILER_BARRIER();
|
||||
__dmb(0xB); // _ARM_BARRIER_ISH, see armintr.h from MSVC 11 and later
|
||||
|
||||
@@ -27,12 +27,12 @@ inline BOOL WINAPI ExtRawDllMain(HINSTANCE, DWORD dwReason, LPVOID)
|
||||
return TRUE; // ok
|
||||
}
|
||||
|
||||
extern "C" __declspec(selectany) BOOL (WINAPI * const _pRawDllMainOrig)(HANDLE, DWORD, LPVOID) = &ExtRawDllMain;
|
||||
extern "C" __declspec(selectany) BOOL (WINAPI * const _pRawDllMainOrig)(HINSTANCE, DWORD, LPVOID) = &ExtRawDllMain;
|
||||
|
||||
# elif defined(_USRDLL)
|
||||
|
||||
extern "C" BOOL WINAPI RawDllMain(HANDLE, DWORD dwReason, LPVOID);
|
||||
extern "C" __declspec(selectany) BOOL (WINAPI * const _pRawDllMainOrig)(HANDLE, DWORD, LPVOID) = &RawDllMain;
|
||||
extern "C" BOOL WINAPI RawDllMain(HINSTANCE, DWORD dwReason, LPVOID);
|
||||
extern "C" __declspec(selectany) BOOL (WINAPI * const _pRawDllMainOrig)(HINSTANCE, DWORD, LPVOID) = &RawDllMain;
|
||||
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/detail/invoke.hpp>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/bind/bind.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
@@ -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,12 +2,13 @@
|
||||
#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
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <cstring>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/detail/interlocked.hpp>
|
||||
#include <boost/thread/win32/thread_primitives.hpp>
|
||||
@@ -19,6 +20,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 +31,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 +40,22 @@ 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 std::memcmp(&lhs, &rhs, sizeof(lhs)) == 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
T interlocked_compare_exchange(T* target,T new_value,T comparand)
|
||||
static state_data interlocked_compare_exchange(state_data* target, state_data new_value, state_data comparand)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(sizeof(T)==sizeof(long));
|
||||
BOOST_STATIC_ASSERT(sizeof(state_data) == sizeof(long));
|
||||
long new_val, comp;
|
||||
std::memcpy(&new_val, &new_value, sizeof(new_value));
|
||||
std::memcpy(&comp, &comparand, sizeof(comparand));
|
||||
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);
|
||||
new_val,
|
||||
comp);
|
||||
state_data result;
|
||||
std::memcpy(&result, &res, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
enum
|
||||
@@ -67,19 +72,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 +112,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 +144,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 +235,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 +298,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 +373,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 +386,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 +411,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 +493,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 +549,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 +564,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 +672,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 +764,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 +797,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>
|
||||
|
||||
@@ -79,12 +80,15 @@ namespace boost
|
||||
struct thread_exit_callback_node;
|
||||
struct tss_data_node
|
||||
{
|
||||
boost::shared_ptr<boost::detail::tss_cleanup_function> func;
|
||||
typedef void(*cleanup_func_t)(void*);
|
||||
typedef void(*cleanup_caller_t)(cleanup_func_t, void*);
|
||||
|
||||
cleanup_caller_t caller;
|
||||
cleanup_func_t func;
|
||||
void* value;
|
||||
|
||||
tss_data_node(boost::shared_ptr<boost::detail::tss_cleanup_function> func_,
|
||||
void* value_):
|
||||
func(func_),value(value_)
|
||||
tss_data_node(cleanup_caller_t caller_,cleanup_func_t func_,void* value_):
|
||||
caller(caller_),func(func_),value(value_)
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -112,8 +116,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 +134,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 +161,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 +173,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,14 +95,14 @@ 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,
|
||||
(type ? create_event_manual_reset : 0) | (state ? create_event_initial_set : 0),
|
||||
event_all_access);
|
||||
#endif
|
||||
return res;
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user