mirror of
https://github.com/boostorg/thread.git
synced 2026-02-03 09:42:16 +00:00
Compare commits
177 Commits
feature/ad
...
pdimov-pat
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
13959e3a5e | ||
|
|
3556f298c7 | ||
|
|
091e8c8088 | ||
|
|
eda6b64491 | ||
|
|
ee24ff8dd1 | ||
|
|
dfe39c630f | ||
|
|
a1460b6b0d | ||
|
|
02f3290765 | ||
|
|
5f0eeeff66 | ||
|
|
e63257ff7f | ||
|
|
39c23ddf5a | ||
|
|
3ee73c866d | ||
|
|
584b9c2d29 | ||
|
|
349f59d92d | ||
|
|
e99ec0a283 | ||
|
|
5920e4c7af | ||
|
|
13f3d7ed87 | ||
|
|
738ab19573 | ||
|
|
510e66aef7 | ||
|
|
19c590a881 | ||
|
|
395e3d786b | ||
|
|
fdc0cbcd8c | ||
|
|
f27a2921da | ||
|
|
bb32aa3164 | ||
|
|
70b887a7bd | ||
|
|
28bf345c96 | ||
|
|
6a1eed0fa8 | ||
|
|
c4d5488f7a | ||
|
|
24a22b66ef | ||
|
|
9579dc2056 | ||
|
|
89e694cc56 | ||
|
|
047205fbbd | ||
|
|
23e7135f2c | ||
|
|
d4cff01c72 | ||
|
|
5f7dc381c7 | ||
|
|
ea0bc01400 | ||
|
|
3bc883d114 | ||
|
|
2e2850ff94 | ||
|
|
1a8019f499 | ||
|
|
bf4b38b0af | ||
|
|
f78b10a450 | ||
|
|
603689372c | ||
|
|
5b05d6a8c8 | ||
|
|
12c0fe14cd | ||
|
|
ace2b8f89e | ||
|
|
24188f295c | ||
|
|
653671bc0e | ||
|
|
c251497758 | ||
|
|
69435fa44e | ||
|
|
6bc6fcab9a | ||
|
|
50bac8c0eb | ||
|
|
d709d4707c | ||
|
|
879db6841d | ||
|
|
2ce385b949 | ||
|
|
21458fcc67 | ||
|
|
d83b7ddc0f | ||
|
|
5ee3e8d04b | ||
|
|
dcafe1e17d | ||
|
|
8dfa7c2e42 | ||
|
|
c83d30f526 | ||
|
|
51b367df53 | ||
|
|
da83662e1a | ||
|
|
36861e5b67 | ||
|
|
67df4dd84e | ||
|
|
676521808d | ||
|
|
65f98979ff | ||
|
|
496acc1161 | ||
|
|
30dff7f84a | ||
|
|
7cb5d5bb46 | ||
|
|
74c98b7fab | ||
|
|
2ed0c2ad5f | ||
|
|
c969a6cf9c | ||
|
|
c7348b29cf | ||
|
|
0d850b47ab | ||
|
|
9bbf9bed80 | ||
|
|
aadf0acce3 | ||
|
|
bd0379af57 | ||
|
|
544eda51bd | ||
|
|
e16705a72a | ||
|
|
61a26492c3 | ||
|
|
854c61f597 | ||
|
|
4d4ddcdc36 | ||
|
|
9347d9b731 | ||
|
|
0a4733c9ad | ||
|
|
b96d05461f | ||
|
|
41f19bb098 | ||
|
|
050a45aaa4 | ||
|
|
23cff22e5a | ||
|
|
a75995475a | ||
|
|
3ac5fd0916 | ||
|
|
56bce64d32 | ||
|
|
4385984215 | ||
|
|
425b9924f0 | ||
|
|
1309e9aa4b | ||
|
|
50a926e973 | ||
|
|
a0bda34054 | ||
|
|
3a9a296e55 | ||
|
|
184d7504b7 | ||
|
|
2f8b5794b7 | ||
|
|
7e7d3bf1a7 | ||
|
|
f8b76aa907 | ||
|
|
7eeae5b265 | ||
|
|
e71f52f9ed | ||
|
|
cd41de6e3f | ||
|
|
c70647988d | ||
|
|
866ff746ae | ||
|
|
807f429e17 | ||
|
|
5450e98c6b | ||
|
|
c52a34c2cf | ||
|
|
fc748dbddf | ||
|
|
e34d343c12 | ||
|
|
eeb24a6a6a | ||
|
|
25b2062881 | ||
|
|
9d33a59542 | ||
|
|
41f93eb513 | ||
|
|
63484911c6 | ||
|
|
bb2c38aa61 | ||
|
|
8cf36f18cc | ||
|
|
7ffdc5e10a | ||
|
|
25864ce33a | ||
|
|
f0c50a00c0 | ||
|
|
b511472614 | ||
|
|
13c15cd002 | ||
|
|
1296bf4de9 | ||
|
|
9c80dd207e | ||
|
|
0f2fed0577 | ||
|
|
96390e1b46 | ||
|
|
e2ff1e4c67 | ||
|
|
49ab2e8619 | ||
|
|
96b96b4e42 | ||
|
|
a774cac3f2 | ||
|
|
6ec16408fc | ||
|
|
850f3eced3 | ||
|
|
fde2e061f5 | ||
|
|
e5c086cef4 | ||
|
|
0b5e4f88b5 | ||
|
|
8d150587fa | ||
|
|
206ff0ba7c | ||
|
|
0ef1b1b760 | ||
|
|
ab9f931bce | ||
|
|
21b084384c | ||
|
|
ccca616330 | ||
|
|
2c3acef281 | ||
|
|
587ad42548 | ||
|
|
ef401d81db | ||
|
|
57f34e1ea4 | ||
|
|
daae305bf7 | ||
|
|
55a1325f30 | ||
|
|
46f0be2dce | ||
|
|
98dbc9da41 | ||
|
|
640e1acb98 | ||
|
|
7f2535015d | ||
|
|
aab2891cdb | ||
|
|
8bbe005bbc | ||
|
|
db5898ba46 | ||
|
|
c7a5122fd3 | ||
|
|
b932b8c015 | ||
|
|
411798367b | ||
|
|
e29a4129e8 | ||
|
|
f6febf8dfc | ||
|
|
2fd8a8dd55 | ||
|
|
9db70b803d | ||
|
|
47357de276 | ||
|
|
382ac5a426 | ||
|
|
317a735836 | ||
|
|
ae22c68ab7 | ||
|
|
4fb88b29fa | ||
|
|
a45f36cbc6 | ||
|
|
5fba7f88a6 | ||
|
|
ad7b36dd34 | ||
|
|
408d82ded9 | ||
|
|
3f5c0bfb6c | ||
|
|
8a5cf38a3c | ||
|
|
0ddc3d40fa | ||
|
|
565c8e0bb8 | ||
|
|
6954e6ca64 | ||
|
|
568275dc5f |
365
.travis.yml
Normal file
365
.travis.yml
Normal file
@@ -0,0 +1,365 @@
|
||||
# Copyright 2016, 2017 Peter Dimov
|
||||
# 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)
|
||||
|
||||
language: cpp
|
||||
|
||||
sudo: false
|
||||
|
||||
python: "2.7"
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- develop
|
||||
- /feature\/.*/
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- BOGUS_JOB=true
|
||||
|
||||
matrix:
|
||||
|
||||
exclude:
|
||||
- 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
|
||||
dist: trusty
|
||||
compiler: g++-7
|
||||
env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=c++98
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-7
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
dist: trusty
|
||||
compiler: g++-7
|
||||
env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=c++11
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-7
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
dist: trusty
|
||||
compiler: g++-7
|
||||
env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=c++14
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-7
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
dist: trusty
|
||||
compiler: g++-7
|
||||
env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=c++1z
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-7
|
||||
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
|
||||
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
|
||||
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++14
|
||||
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++1z
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-4.0
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-4.0
|
||||
|
||||
- os: osx
|
||||
compiler: clang++
|
||||
env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++98
|
||||
|
||||
- os: osx
|
||||
compiler: clang++
|
||||
env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++11
|
||||
|
||||
- os: osx
|
||||
compiler: clang++
|
||||
env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++14
|
||||
|
||||
- os: osx
|
||||
compiler: clang++
|
||||
env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++1z
|
||||
|
||||
install:
|
||||
- BOOST_BRANCH=develop && [ "$TRAVIS_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 $TRAVIS_BUILD_DIR/* libs/thread
|
||||
- python tools/boostdep/depinst/depinst.py thread
|
||||
- ./bootstrap.sh
|
||||
- ./b2 headers
|
||||
|
||||
script:
|
||||
- |-
|
||||
echo "using $TOOLSET : : $COMPILER : <cxxflags>-std=$CXXSTD ;" > ~/user-config.jam
|
||||
- ./b2 -j3 libs/thread/test toolset=$TOOLSET
|
||||
|
||||
notifications:
|
||||
email:
|
||||
on_success: always
|
||||
131
README.md
131
README.md
@@ -7,135 +7,4 @@ Portable C++ multi-threading. C++11, C++14.
|
||||
|
||||
Distributed under the [Boost Software License, Version 1.0](http://boost.org/LICENSE_1_0.txt).
|
||||
|
||||
### Current Jenkins CI Test Status for unstable (develop) branch
|
||||
Overall build (nightly): <a href='https://ci.nedprod.com/view/All/job/Boost.Thread%20Build/'><img src='https://ci.nedprod.com/buildStatus/icon?job=Boost.Thread%20Build'></a> Overall tests (weekly, on Sundays): <a href='https://ci.nedprod.com/view/All/job/Boost.Thread%20Test/'><img src='https://ci.nedprod.com/buildStatus/icon?job=Boost.Thread%20Test'></a>
|
||||
|
||||
#### Build (nightly):
|
||||
<table id="configuration-matrix" width="100%" border="1">
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="6" valign="top">android-ndk</td><td class="matrix-leftcolumn" rowspan="2" valign="top">c++03</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.6,LINKTYPE=static,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.6</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.8,LINKTYPE=static,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.8</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.5,LINKTYPE=static,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.6,LINKTYPE=shared,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.6</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.8,LINKTYPE=shared,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.8</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.5,LINKTYPE=shared,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="2" valign="top">c++11</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=g++-4.8,LINKTYPE=static,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.8</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.5,LINKTYPE=static,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=g++-4.8,LINKTYPE=shared,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.8</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.5,LINKTYPE=shared,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="2" valign="top">c++14</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=clang++-3.5,LINKTYPE=static,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=clang++-3.5,LINKTYPE=shared,label=android-ndk/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="6" valign="top">winphone8</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td/>
|
||||
</tr>
|
||||
<tr>
|
||||
<td/>
|
||||
</tr>
|
||||
<tr>
|
||||
<td/>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="2" valign="top">c++14</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-11.0,LINKTYPE=static,label=winphone8/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-11.0</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-12.0,LINKTYPE=static,label=winphone8/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-12.0</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-14.0,LINKTYPE=static,label=winphone8/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-14.0</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-11.0,LINKTYPE=shared,label=winphone8/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-11.0</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-12.0,LINKTYPE=shared,label=winphone8/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-12.0</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-14.0,LINKTYPE=shared,label=winphone8/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-14.0</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="6" valign="top">arm-gcc-clang</td><td class="matrix-leftcolumn" rowspan="2" valign="top">c++03</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.9,LINKTYPE=static,label=arm-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.5,LINKTYPE=static,label=arm-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.9,LINKTYPE=shared,label=arm-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.5,LINKTYPE=shared,label=arm-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="2" valign="top">c++11</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=g++-4.9,LINKTYPE=static,label=arm-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.5,LINKTYPE=static,label=arm-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=g++-4.9,LINKTYPE=shared,label=arm-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.5,LINKTYPE=shared,label=arm-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="2" valign="top">c++14</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=g++-4.9,LINKTYPE=static,label=arm-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=g++-4.9,LINKTYPE=shared,label=arm-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="6" valign="top">freebsd10-clang3.3</td><td class="matrix-leftcolumn" rowspan="2" valign="top">c++03</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.3,LINKTYPE=static,label=freebsd10-clang3.3/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.3</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.3,LINKTYPE=shared,label=freebsd10-clang3.3/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.3</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="2" valign="top">c++11</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.3,LINKTYPE=static,label=freebsd10-clang3.3/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.3</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.3,LINKTYPE=shared,label=freebsd10-clang3.3/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.3</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td/>
|
||||
</tr>
|
||||
<tr>
|
||||
<td/>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="6" valign="top">linux-gcc-clang</td><td class="matrix-leftcolumn" rowspan="2" valign="top">c++03</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.6,LINKTYPE=static,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.6</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.7,LINKTYPE=static,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.7</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.2,LINKTYPE=static,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.2</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.3,LINKTYPE=static,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.3</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.4,LINKTYPE=static,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.4</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.6,LINKTYPE=shared,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.6</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.7,LINKTYPE=shared,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.7</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.2,LINKTYPE=shared,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.2</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.3,LINKTYPE=shared,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.3</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.4,LINKTYPE=shared,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.4</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="2" valign="top">c++11</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=g++-4.7,LINKTYPE=static,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.7</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.2,LINKTYPE=static,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.2</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.3,LINKTYPE=static,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.3</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.4,LINKTYPE=static,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.4</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=g++-4.7,LINKTYPE=shared,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.7</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.2,LINKTYPE=shared,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.2</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.3,LINKTYPE=shared,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.3</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.4,LINKTYPE=shared,label=linux-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.4</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td/>
|
||||
</tr>
|
||||
<tr>
|
||||
<td/>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="6" valign="top">linux64-gcc-clang</td><td class="matrix-leftcolumn" rowspan="2" valign="top">c++03</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-analyse,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Unstable" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/yellow.png" tooltip="Unstable"/></a>clang++-analyse</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.8,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.8</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.9,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.5,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-analyse,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Unstable" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/yellow.png" tooltip="Unstable"/></a>clang++-analyse</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.8,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.8</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=g++-4.9,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=clang++-3.5,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="2" valign="top">c++11</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-analyse,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-analyse</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=g++-4.8,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.8</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=g++-4.9,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.5,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-analyse,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-analyse</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=g++-4.8,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.8</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=g++-4.9,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=clang++-3.5,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="2" valign="top">c++14</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=clang++-analyse,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-analyse</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=g++-4.9,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=clang++-3.5,LINKTYPE=static,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=clang++-analyse,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-analyse</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=g++-4.9,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>g++-4.9</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=clang++-3.5,LINKTYPE=shared,label=linux64-gcc-clang/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>clang++-3.5</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="6" valign="top">win8-msvc-mingw</td><td class="matrix-leftcolumn" rowspan="2" valign="top">c++03</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=mingw32,LINKTYPE=static,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>mingw32</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=mingw64,LINKTYPE=static,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>mingw64</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=mingw32,LINKTYPE=shared,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>mingw32</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++03,CXX=mingw64,LINKTYPE=shared,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>mingw64</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="2" valign="top">c++11</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=mingw32,LINKTYPE=static,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>mingw32</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=mingw64,LINKTYPE=static,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>mingw64</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=mingw32,LINKTYPE=shared,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>mingw32</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++11,CXX=mingw64,LINKTYPE=shared,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>mingw64</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="2" valign="top">c++14</td><td class="matrix-leftcolumn" rowspan="1" valign="top">static</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-10.0,LINKTYPE=static,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-10.0</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-11.0,LINKTYPE=static,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-11.0</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-12.0,LINKTYPE=static,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-12.0</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-14.0,LINKTYPE=static,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-14.0</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="matrix-leftcolumn" rowspan="1" valign="top">shared</td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-analyse,LINKTYPE=shared,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-analyse</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-10.0,LINKTYPE=shared,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-10.0</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-11.0,LINKTYPE=shared,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-11.0</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-12.0,LINKTYPE=shared,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-12.0</div></td><td class="matrix-cell"><div><a class="model-link inside" href="https://ci.nedprod.com/job/Boost.Thread%20Build/CPPSTD=c++14,CXX=msvc-14.0,LINKTYPE=shared,label=win8-msvc-mingw/"><img height="24" alt="Success" width="24" src="https://ci.nedprod.com/static/5e289396/images/24x24/blue.png" tooltip="Success"/></a>msvc-14.0</div></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
41
appveyor.yml
Normal file
41
appveyor.yml
Normal file
@@ -0,0 +1,41 @@
|
||||
# Copyright 2016, 2017 Peter Dimov
|
||||
# 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)
|
||||
|
||||
version: 1.0.{build}-{branch}
|
||||
|
||||
shallow_clone: true
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- develop
|
||||
- /feature\/.*/
|
||||
|
||||
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
|
||||
|
||||
install:
|
||||
- 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
|
||||
- cmd /c bootstrap
|
||||
- b2 headers
|
||||
|
||||
build: off
|
||||
|
||||
test_script:
|
||||
- b2 libs/mp11/test toolset=%TOOLSET%
|
||||
@@ -126,6 +126,8 @@ project boost/thread
|
||||
<toolset>msvc:<cxxflags>/wd4512
|
||||
<toolset>msvc:<cxxflags>/wd6246
|
||||
|
||||
<target-os>windows:<define>WIN32_LEAN_AND_MEAN
|
||||
<target-os>windows:<define>BOOST_USE_WINDOWS_H
|
||||
|
||||
# : default-build <threading>multi
|
||||
: usage-requirements # pass these requirement to dependents (i.e. users)
|
||||
@@ -316,3 +318,5 @@ lib boost_thread
|
||||
<link>static:<define>BOOST_THREAD_USE_LIB=1
|
||||
<conditional>@usage-requirements
|
||||
;
|
||||
|
||||
boost-install boost_thread ;
|
||||
@@ -29,4 +29,12 @@ boostbook standalone
|
||||
<xsl:param>boost.root=../../../..
|
||||
;
|
||||
|
||||
|
||||
###############################################################################
|
||||
alias boostdoc
|
||||
: thread
|
||||
:
|
||||
:
|
||||
: ;
|
||||
explicit boostdoc ;
|
||||
alias boostrelease ;
|
||||
explicit boostrelease ;
|
||||
|
||||
@@ -112,7 +112,7 @@ A question arises of which of these executors (or others) be included in this li
|
||||
[////////////////////////]
|
||||
[section:rationale Design Rationale]
|
||||
|
||||
The authors of Boost.Thread have taken a different approach respect to N3785. Instead of basing all the design on a abstract executor class we make executor concepts. We believe that this is the good direction as a static polymorphic executor can be seen as a dynamic polymorphic executor using a simple adaptor. We believe also that it would make the library more usable, and more convenient for users.
|
||||
The authors of Boost.Thread have taken a different approach respect to N3785. Instead of basing all the design on an abstract executor class we make executor concepts. We believe that this is the good direction as a static polymorphic executor can be seen as a dynamic polymorphic executor using a simple adaptor. We believe also that it would make the library more usable, and more convenient for users.
|
||||
|
||||
The major design decisions concern deciding what a unit of work is, how to manage with units of work and time related functions in a polymorphic way.
|
||||
|
||||
@@ -364,8 +364,8 @@ A type `E` meets the `Executor` requirements if the following expressions are we
|
||||
where
|
||||
|
||||
* `e` denotes a value of type `E`,
|
||||
* `lc` denotes a lvalue referece of type `Closure`,
|
||||
* `rc` denotes a rvalue referece of type `Closure`
|
||||
* `lc` denotes a lvalue reference of type `Closure`,
|
||||
* `rc` denotes a rvalue reference of type `Closure`
|
||||
* `p` denotes a value of type `Predicate`
|
||||
|
||||
[/////////////////////////////////////]
|
||||
@@ -388,7 +388,7 @@ If invoked closure throws an exception the executor will call std::terminate, as
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:submitrc `e.submit(lc);`]
|
||||
[section:submitrc `e.submit(rc);`]
|
||||
|
||||
[variablelist
|
||||
|
||||
@@ -417,7 +417,7 @@ If invoked closure throws an exception the executor will call std::terminate, as
|
||||
|
||||
[[Return type:] [`void`.]]
|
||||
|
||||
[[Throws:] [Whatever exception that can be throw while ensuring the thread safety.]]
|
||||
[[Throws:] [Whatever exception that can be thrown while ensuring the thread safety.]]
|
||||
|
||||
[[Exception safety:] [If an exception is thrown then the executor state is unmodified.]]
|
||||
|
||||
@@ -462,7 +462,7 @@ If invoked closure throws an exception the executor will call std::terminate, as
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Requires:] [This must be called from an scheduled work]]
|
||||
[[Requires:] [This must be called from a scheduled work]]
|
||||
|
||||
[[Effects:] [reschedule works until `p()`.]]
|
||||
|
||||
@@ -533,7 +533,7 @@ Executor abstract base class.
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Constructs a executor. ]]
|
||||
[[Effects:] [Constructs an executor. ]]
|
||||
|
||||
[[Throws:] [Nothing. ]]
|
||||
|
||||
@@ -600,7 +600,7 @@ Polymorphic adaptor of a model of Executor to an executor.
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Constructs a executor_adaptor. ]]
|
||||
[[Effects:] [Constructs an executor_adaptor. ]]
|
||||
|
||||
[[Throws:] [Nothing. ]]
|
||||
|
||||
@@ -1521,7 +1521,7 @@ A serial executor ensuring that there are no two work units that executes concur
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Constructs a inline_executor. ]]
|
||||
[[Effects:] [Constructs an inline_executor. ]]
|
||||
|
||||
[[Throws:] [Nothing. ]]
|
||||
|
||||
@@ -1709,7 +1709,7 @@ A user scheduled executor.
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [creates a executor that runs closures using one of its closure-executing methods. ]]
|
||||
[[Effects:] [creates an executor that runs closures using one of its closure-executing methods. ]]
|
||||
|
||||
[[Throws:] [Whatever exception is thrown while initializing the needed resources. ]]
|
||||
|
||||
|
||||
125
doc/changes.qbk
125
doc/changes.qbk
@@ -1,6 +1,6 @@
|
||||
[/
|
||||
(C) Copyright 2007-11 Anthony Williams.
|
||||
(C) Copyright 2011-15 Vicente J. Botet Escriba.
|
||||
(C) Copyright 2011-17 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,125 @@
|
||||
|
||||
[section:changes History]
|
||||
|
||||
[heading Version 4.8.0 - boost 1.66]
|
||||
|
||||
[*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:]
|
||||
|
||||
* [@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/13163 #13163] boost::detail::heap_new does not have a variadic variant
|
||||
|
||||
* [@https://github.com/boostorg/thread/issues/130 #130] windows: Bug in boost::condition_variable on Windows
|
||||
|
||||
[heading Version 4.7.4 - boost 1.65]
|
||||
|
||||
[*Fixed Bugs:]
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/6787 #6787] boost::thread::sleep() hangs if system time is rolled back
|
||||
* [@http://svn.boost.org/trac/boost/ticket/12519 #12519] boost::thread::try_join_for does not return after timeout
|
||||
* [@http://svn.boost.org/trac/boost/ticket/12874 #12874] future<> extension constructor must be under BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
|
||||
* [@http://svn.boost.org/trac/boost/ticket/12888 #12888] Linking with boost thread does not work on mingw/gcc 4.4
|
||||
* [@http://svn.boost.org/trac/boost/ticket/12958 #12958] sync_bounded_queue::wait_pull_front( lve ) might throw
|
||||
* [@http://svn.boost.org/trac/boost/ticket/13077 #13077] Linking to static 64bit libboost_thread fails DLL initialization
|
||||
* [@http://svn.boost.org/trac/boost/ticket/13155 #13155] log doesn't build on a system with pthreads
|
||||
|
||||
* [@https://github.com/boostorg/thread/issues/121 #121] on_tls_prepare is broken under VS2017
|
||||
|
||||
[heading Version 4.7.3 - boost 1.64]
|
||||
|
||||
[*Fixed Bugs:]
|
||||
|
||||
* [@https://github.com/boostorg/thread/issues/113 #113] Add a Thread template on all the scoped thread and thread guard classes
|
||||
* [@https://github.com/boostorg/thread/issues/117 #117] loop_executor should block on it's work_queue instead of polling
|
||||
* [@https://github.com/boostorg/thread/issues/119 #119] basic_condition_variable::relocker::~relocker can throw an exception
|
||||
|
||||
[heading Version 4.7.2 - boost 1.63]
|
||||
|
||||
[*Fixed Bugs:]
|
||||
|
||||
* fix boost::synchronized_value<>::load()
|
||||
* fix relational operators of boost::synchronized_value<>
|
||||
* fix compile failed with boost::user_scheduler
|
||||
* Fix minor possibility of loosing the notify
|
||||
|
||||
[heading Version 4.7.1 - boost 1.62]
|
||||
|
||||
[*Know Bugs:]
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/3926 #3926] thread_specific_ptr + dlopen library causes a SIGSEGV.
|
||||
|
||||
Please define BOOST_THREAD_PATCH to apply the patch that could unfortunately results is a regression as described in [@http://svn.boost.org/trac/boost/ticket/12049 #12049].
|
||||
|
||||
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:]
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11097 #11097] test_scheduled_tp - ThreadSanitizer: heap-use-after-free
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11951 #11951] Memory leak in boost::when_all
|
||||
* [@http://svn.boost.org/trac/boost/ticket/12102 #12102] condition_variable_fwd.hpp fails to compile when BOOST_THREAD_PROVIDES_INTERRUPTIONS is disabled
|
||||
* [@http://svn.boost.org/trac/boost/ticket/12120 #12120] Performance improvement in thread/barrier.hpp
|
||||
* [@http://svn.boost.org/trac/boost/ticket/12146 #12146] make_exceptional_future is not mentioned in the docs
|
||||
* [@http://svn.boost.org/trac/boost/ticket/12202 #12202] shared_lock should be in shared_mutex header
|
||||
* [@http://svn.boost.org/trac/boost/ticket/12220 #12220] Memory leak in future::then()
|
||||
* [@http://svn.boost.org/trac/boost/ticket/12293 #12293] boost::future::then lambda called before future is ready.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/12350 #12350] shared_mutex (pthreads) unlocked too early in unlock_shared()
|
||||
* [@http://svn.boost.org/trac/boost/ticket/12371 #12371] boost thread/future.hpp fails to build
|
||||
|
||||
|
||||
and several PR
|
||||
|
||||
* #88 fix typos in boost::upgrade_lock
|
||||
* #89 fix a bug in upgrade_to_unique_lock<>::operator=()
|
||||
* #90 fix a bug in try_lock_wrapper<>::operator=()
|
||||
* #91 Add shared_lock_guard to the included lock types
|
||||
* #92 Fixed compilation with MSVC-8.
|
||||
* #93 Fix variable shadowing warnings (Clang)
|
||||
* #94 fix bugs in boost::barrier
|
||||
* #95 fix a mistake in boost::completion_latch
|
||||
* #96 rename async_func.hpp to invoker.hpp.
|
||||
* #97 fix a mistake in sync_timed_queue<>::pull_until()
|
||||
|
||||
[heading Version 4.7.0 - boost 1.61]
|
||||
|
||||
[*Know Bugs:]
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/3926 #3926] thread_specific_ptr + dlopen library causes a SIGSEGV.
|
||||
|
||||
Please define BOOST_THREAD_PATCH to apply the patch that could unfortunately results is a regression as described in [@http://svn.boost.org/trac/boost/ticket/12049 #12049].
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/4833 #4833] MinGW/test_tss_lib: Support of automatic tss cleanup for native threading API not available
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8600 #8600] wait_for_any hangs, if called with multiple copies of shared_future referencing same task
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9118 #9118] Seg fault on thread join when llvm and libc++ are used
|
||||
|
||||
Please take a look at [@https://svn.boost.org/trac/boost/query?status=assigned&status=new&status=reopened&component=thread&type=!Feature+Requests&col=id&col=summary&order=id thread Know Bugs] to see the current state.
|
||||
|
||||
Please take a look at [@http://www.boost.org/development/tests/master/developer/thread.html thread trunk regression test] to see the last regression test snapshot.
|
||||
|
||||
[*New Experimental Features:]
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11772 #11772] Add a launch::sync policy
|
||||
|
||||
[*Fixed Bugs:]
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11494 #11494] boost::this_thread::yield() is marked as deprecated in the synopsis
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11562 #11562] (condition_variable_any::wait_until + recursive_mutex + steady_clock) timer expires after computer time is set forward on Ubuntu 64-bit
|
||||
* [@http://svn.boost.org/trac/boost/ticket/12013 #12013] F_pass and FArgs_pass tests segfault
|
||||
* [@http://svn.boost.org/trac/boost/ticket/12036 #12036] boost::physical_concurrency always returns 0 if BOOST_USE_WINAPI_VERSION is not defined
|
||||
|
||||
[heading Version 4.6.0 - boost 1.60]
|
||||
|
||||
[*Know Bugs:]
|
||||
@@ -26,14 +145,13 @@ Please take a look at [@http://www.boost.org/development/tests/master/developer/
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11231 #11231] Allow to set continuation future's destructor behavior to non-blocking
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11424 #11424] Provide shared_timed_mutex as an alternative name for shared_mutex and deprecate the use of shared_mutex as a timed mutex
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11734 #11734] future::then(Cont) should be able to execute the contination on undetermined thread
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11734 #11734] future::then(Cont) should be able to execute the continuation on undetermined thread
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11736 #11736] Allow to use launch::executor on future::then(launch::executor, cont)
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11737 #11737] Add a launch::inherit policy that can be used on ::then() to use the policy of the parent future
|
||||
|
||||
|
||||
[*Fixed 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/6377 #6377] Condition variable blocks when changing time
|
||||
* [@http://svn.boost.org/trac/boost/ticket/6787 #6787] boost::thread::sleep() hangs if system time is rolled back
|
||||
* [@http://svn.boost.org/trac/boost/ticket/7665 #7665] this_thread::sleep_for no longer uses steady_clock in thread
|
||||
@@ -67,6 +185,7 @@ Please take a look at [@http://www.boost.org/development/tests/master/developer/
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11817 #11817] 'sync_queue_is_closed' was not declared in boost/thread/executors/thread_executor.hpp
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11818 #11818] future.then will be blocked if promise is set after the invocation of then
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/12049 #12049] Assertion failure from detached threads during shutdown
|
||||
|
||||
[heading Version 4.5.0 - boost 1.58]
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ When `BOOST_THREAD_VERSION>3` && defined BOOST_THREAD_PLATFORM_PTHREAD define `
|
||||
|
||||
[section:move Boost.Atomic]
|
||||
|
||||
Boost.Thread uses by default an Boost.Atomic in POSIX platforms to implement call_once..
|
||||
Boost.Thread uses by default Boost.Atomic in POSIX platforms to implement call_once..
|
||||
|
||||
Define `BOOST_THREAD_USES_ATOMIC ` if you want to use Boost.Atomic.
|
||||
Define `BOOST_THREAD_DONT_USE_ATOMIC ` if you don't want to use Boost.Atomic or if it is not supported in your platform.
|
||||
|
||||
@@ -267,7 +267,7 @@ The library provides un implicit conversion to an undefined type that can be use
|
||||
explicit operator bool() const;
|
||||
#endif
|
||||
|
||||
The user should use the lock.owns_lock() when a explicit conversion is required.
|
||||
The user should use the lock.owns_lock() when an explicit conversion is required.
|
||||
|
||||
[section:bool_conversion `operator `['unspecified-bool-type]`() const`]
|
||||
|
||||
@@ -324,7 +324,7 @@ the library declare these types as
|
||||
}
|
||||
BOOST_SCOPED_ENUM_DECLARE_END(future_errc)
|
||||
|
||||
These macros allows to use 'future_errc' in almost all the cases as an scoped enum.
|
||||
These macros allows to use 'future_errc' in almost all the cases as a scoped enum.
|
||||
|
||||
There are however some limitations:
|
||||
|
||||
|
||||
@@ -127,10 +127,10 @@
|
||||
future<typename decay<T>::type> make_ready_future(T&& value); // EXTENSION
|
||||
future<void> make_ready_future(); // EXTENSION
|
||||
|
||||
exceptional_ptr make_exceptional(exception_ptr ex); // EXTENSION
|
||||
exceptional_ptr make_exceptional_future(exception_ptr ex); // EXTENSION
|
||||
template <typename E>
|
||||
exceptional_ptr make_exceptional(E ex); // EXTENSION
|
||||
exceptional_ptr make_exceptional(); // EXTENSION
|
||||
exceptional_ptr make_exceptional_future(E ex); // EXTENSION
|
||||
exceptional_ptr make_exceptional_future(); // EXTENSION
|
||||
|
||||
|
||||
template <typename T>
|
||||
@@ -349,7 +349,7 @@ The object's `name` virtual function returns a pointer to the string "future".]]
|
||||
|
||||
// move support
|
||||
__unique_future__(__unique_future__ && other) noexcept;
|
||||
__unique_future__(__unique_future__<__unique_future__<R>>&& rhs); // EXTENSION
|
||||
explicit __unique_future__(__unique_future__<__unique_future__<R>>&& rhs); // EXTENSION
|
||||
__unique_future__& operator=(__unique_future__ && other) noexcept;
|
||||
|
||||
// factories
|
||||
@@ -358,7 +358,7 @@ The object's `name` virtual function returns a pointer to the string "future".]]
|
||||
template<typename F>
|
||||
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
|
||||
then(F&& func); // EXTENSION
|
||||
template<typename S, typename F>
|
||||
template<typename Ex, typename F>
|
||||
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
|
||||
then(Ex& executor, F&& func); // EXTENSION
|
||||
template<typename F>
|
||||
@@ -453,7 +453,7 @@ associated with `*this`. `other` is not associated with any shared state.]]
|
||||
[///////////////////////////////////////////////////////////////////]
|
||||
[section:unwrap_move_constructor Unwrap Move Constructor - EXTENSION]
|
||||
|
||||
__unique_future__(__unique_future__<__unique_future__<R>>&& other); // EXTENSION
|
||||
explicit __unique_future__(__unique_future__<__unique_future__<R>>&& other); // EXTENSION
|
||||
|
||||
[warning This constructor is experimental and subject to change in future versions.
|
||||
There are not too much tests yet, so it is possible that you can find out some trivial bugs :(]
|
||||
@@ -848,7 +848,7 @@ stored exception, `false` otherwise.]]
|
||||
[[Effects:] [If `*this` is associated with a shared state, waits until the result is ready. If the result is not ready on
|
||||
entry, and the result has a ['wait callback] set, that callback is invoked prior to waiting.]]
|
||||
|
||||
[[Returns:] [a exception_ptr, storring or not an exception.]]
|
||||
[[Returns:] [an exception_ptr, storing or not an exception.]]
|
||||
|
||||
[[Remarks:] [The result of this function is not stable and the future could lost its exception even if the function returned a valid `exception_ptr` or vice-versa.]]
|
||||
|
||||
@@ -898,7 +898,7 @@ associated with `*this` is ready for retrieval, __waiting__ otherwise.]]
|
||||
template<typename F>
|
||||
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
|
||||
then(F&& func); // EXTENSION
|
||||
template<typename S, typename F>
|
||||
template<typename Ex, typename F>
|
||||
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
|
||||
then(Ex& executor, F&& func); // EXTENSION
|
||||
template<typename F>
|
||||
@@ -913,7 +913,7 @@ There are not too much tests yet, so it is possible that you can find out some t
|
||||
[variablelist
|
||||
|
||||
[[Notes:] [The three functions differ only by input parameters. The first only takes a callable object which accepts a
|
||||
future object as a parameter. The second function takes a executor as the first parameter and a callable object as
|
||||
future object as a parameter. The second function takes an executor as the first parameter and a callable object as
|
||||
the second parameter. The third function takes a launch policy as the first parameter and a callable object as the
|
||||
second parameter.]]
|
||||
|
||||
@@ -1357,7 +1357,7 @@ stored exception, `false` otherwise.]]
|
||||
[[Effects:] [If `*this` is associated with a shared state, waits until the result is ready. If the result is not ready on
|
||||
entry, and the result has a ['wait callback] set, that callback is invoked prior to waiting.]]
|
||||
|
||||
[[Returns:] [a exception_ptr, storring or not an exception.]]
|
||||
[[Returns:] [an exception_ptr, storing or not an exception.]]
|
||||
|
||||
[[Throws:] [Whatever `mutex::lock()/mutex::unlock()` can throw.]]
|
||||
|
||||
@@ -1387,7 +1387,7 @@ associated with `*this` is ready for retrieval, __waiting__ otherwise.]]
|
||||
template<typename F>
|
||||
__unique_future__<typename boost::result_of<F(shared_future)>::type>
|
||||
then(F&& func) const; // EXTENSION
|
||||
template<typename S, typename F>
|
||||
template<typename Ex, typename F>
|
||||
__unique_future__<typename boost::result_of<F(shared_future)>::type>
|
||||
then(Ex& executor, F&& func) const; // EXTENSION
|
||||
template<typename F>
|
||||
@@ -2451,12 +2451,12 @@ Otherwise the value is copied to the shared state of the returned future.
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////////////////////////////////////////////]
|
||||
[section:make_exceptional Non-member function `make_exceptional()` EXTENSION]
|
||||
[section:make_exceptional_future Non-member function `make_exceptional_future()` EXTENSION]
|
||||
|
||||
exceptional_ptr make_exceptional(exception_ptr ex); // EXTENSION
|
||||
exceptional_ptr make_exceptional_future(exception_ptr ex); // EXTENSION
|
||||
template <typename E>
|
||||
exceptional_ptr make_exceptional(E ex); // EXTENSION
|
||||
exceptional_ptr make_exceptional(); // EXTENSION
|
||||
exceptional_ptr make_exceptional_future(E ex); // EXTENSION
|
||||
exceptional_ptr make_exceptional_future(); // EXTENSION
|
||||
|
||||
[variablelist
|
||||
|
||||
|
||||
@@ -240,9 +240,9 @@ The following class describes a so-called monitor pattern.
|
||||
template <
|
||||
typename Lockable=mutex
|
||||
>
|
||||
class basic_monitor : protected basic_lockable_adapter<Lockable> { // behaves like an BasicLockable for the derived classes
|
||||
class basic_monitor : protected basic_lockable_adapter<Lockable> { // behaves like a BasicLockable for the derived classes
|
||||
protected:
|
||||
typedef unspecified synchronizer; // is an strict lock guard
|
||||
typedef unspecified synchronizer; // is a strict lock guard
|
||||
};
|
||||
|
||||
[/shared_monitor]
|
||||
|
||||
@@ -869,7 +869,7 @@ any other threads have shared ownership, blocks until exclusive ownership can be
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Precondition:] [The calling thread shall hold a upgrade lock on the mutex.]]
|
||||
[[Precondition:] [The calling thread shall hold an upgrade lock on the mutex.]]
|
||||
|
||||
[[Effects:] [The function attempts to atomically convert the ownership from upgrade to exclusive for the calling thread without blocking.
|
||||
For this conversion to be successful, this thread must be the only thread holding any ownership of the lock.
|
||||
@@ -893,7 +893,7 @@ If the conversion is not successful, the upgrade ownership of m is retained.]]
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Precondition:] [The calling thread shall hold a upgrade lock on the mutex.]]
|
||||
[[Precondition:] [The calling thread shall hold an upgrade lock on the mutex.]]
|
||||
|
||||
[[Effects:] [If the tick period of `rel_time` is not exactly convertible to the native tick period, the duration shall be rounded up to the nearest native tick period.
|
||||
The function attempts to atomically convert the ownership from upgrade to exclusive for the calling thread within the relative timeout specified by `rel_time`.
|
||||
@@ -919,7 +919,7 @@ If the conversion is not successful, the upgrade ownership of m is retained.]]
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Precondition:] [The calling thread shall hold a upgrade lock on the mutex.]]
|
||||
[[Precondition:] [The calling thread shall hold an upgrade lock on the mutex.]]
|
||||
|
||||
[[Effects:] [The function attempts to atomically convert the ownership from upgrade to exclusive for the calling thread within the absolute timeout specified by `abs_time`.
|
||||
If `abs_time` has already passed, the function attempts to obtain exclusive ownership without blocking (as if by calling `__try_unlock_upgrade_and_lock()`).
|
||||
@@ -2150,7 +2150,7 @@ object passed to the constructor.]]
|
||||
__nested_strict_lock is a model of __StrictLock.
|
||||
|
||||
A nested strict lock is a scoped lock guard ensuring a mutex is locked on its
|
||||
scope, by taking ownership of an nesting lock, locking the mutex on construction if not already locked
|
||||
scope, by taking ownership of a nesting lock, locking the mutex on construction if not already locked
|
||||
and restoring the ownership to the nesting lock on destruction.
|
||||
|
||||
|
||||
@@ -3034,8 +3034,8 @@ An instance of __reverse_lock doesn't ['own] the lock never.
|
||||
[[Effects:] [Locks the __lockable_concept_type__ objects supplied as
|
||||
arguments in an unspecified and indeterminate order in a way that
|
||||
avoids deadlock. It is safe to call this function concurrently from
|
||||
multiple threads with the same mutexes (or other lockable objects) in
|
||||
different orders without risk of deadlock. If any of the __lock_ref__
|
||||
multiple threads for any set of mutexes (or other lockable objects) in
|
||||
any order without risk of deadlock. If any of the __lock_ref__
|
||||
or __try_lock_ref__ operations on the supplied
|
||||
__lockable_concept_type__ objects throws an exception any locks
|
||||
acquired by the function will be released before the function exits.]]
|
||||
@@ -3062,8 +3062,8 @@ are locked by the calling thread.]]
|
||||
[[Effects:] [Locks all the __lockable_concept_type__ objects in the
|
||||
supplied range in an unspecified and indeterminate order in a way that
|
||||
avoids deadlock. It is safe to call this function concurrently from
|
||||
multiple threads with the same mutexes (or other lockable objects) in
|
||||
different orders without risk of deadlock. If any of the __lock_ref__
|
||||
multiple threads for any set of mutexes (or other lockable objects) in
|
||||
any order without risk of deadlock. If any of the __lock_ref__
|
||||
or __try_lock_ref__ operations on the __lockable_concept_type__
|
||||
objects in the supplied range throws an exception any locks acquired
|
||||
by the function will be released before the function exits.]]
|
||||
|
||||
@@ -15,11 +15,12 @@
|
||||
struct detach;
|
||||
struct join_if_joinable;
|
||||
struct interrupt_and_join_if_joinable;
|
||||
template <class CallableThread = join_if_joinable>
|
||||
template <class CallableThread = join_if_joinable, class Thread = thread>
|
||||
class strict_scoped_thread;
|
||||
template <class CallableThread = join_if_joinable>
|
||||
template <class CallableThread = join_if_joinable, class Thread = thread>
|
||||
class scoped_thread;
|
||||
void swap(scoped_thread& lhs,scoped_thread& rhs) noexcept;
|
||||
template <class CallableThread, class Thread = thread>
|
||||
void swap(scoped_thread<Callable, Thread>& lhs, scoped_threadCallable, Thread>& rhs) noexcept;
|
||||
|
||||
[section:motivation Motivation]
|
||||
Based on the scoped_thread class defined in C++ Concurrency in Action Boost.Thread defines a thread wrapper class that instead of calling terminate if the thread is joinable on destruction, call a specific action given as template parameter.
|
||||
@@ -54,7 +55,8 @@ The difference between strict_scoped_thread and scoped_thread is that the strict
|
||||
|
||||
struct detach
|
||||
{
|
||||
void operator()(thread& t)
|
||||
template <class Thread>
|
||||
void operator()(Thread& t)
|
||||
{
|
||||
t.detach();
|
||||
}
|
||||
@@ -64,7 +66,8 @@ The difference between strict_scoped_thread and scoped_thread is that the strict
|
||||
|
||||
struct join_if_joinable
|
||||
{
|
||||
void operator()(thread& t)
|
||||
template <class Thread>
|
||||
void operator()(Thread& t)
|
||||
{
|
||||
if (t.joinable())
|
||||
{
|
||||
@@ -79,7 +82,8 @@ The difference between strict_scoped_thread and scoped_thread is that the strict
|
||||
|
||||
struct interrupt_and_join_if_joinable
|
||||
{
|
||||
void operator()(thread& t)
|
||||
template <class Thread>
|
||||
void operator()(Thread& t)
|
||||
{
|
||||
t.interrupt();
|
||||
if (t.joinable())
|
||||
@@ -96,7 +100,7 @@ The difference between strict_scoped_thread and scoped_thread is that the strict
|
||||
|
||||
// #include <boost/thread/scoped_thread.hpp>
|
||||
|
||||
template <class CallableThread = join_if_joinable>
|
||||
template <class CallableThread = join_if_joinable, class Thread = ::boost::thread>
|
||||
class strict_scoped_thread
|
||||
{
|
||||
thread t_; // for exposition purposes only
|
||||
@@ -105,7 +109,7 @@ The difference between strict_scoped_thread and scoped_thread is that the strict
|
||||
strict_scoped_thread(strict_scoped_thread const&) = delete;
|
||||
strict_scoped_thread& operator=(strict_scoped_thread const&) = delete;
|
||||
|
||||
explicit strict_scoped_thread(thread&& t) noexcept;
|
||||
explicit strict_scoped_thread(Thread&& t) noexcept;
|
||||
template <typename F&&, typename ...Args>
|
||||
explicit strict_scoped_thread(F&&, Args&&...);
|
||||
|
||||
@@ -130,7 +134,7 @@ This wrapper can be used to join the thread before destroying it.
|
||||
|
||||
[section:default_constructor Constructor from a __thread]
|
||||
|
||||
explicit strict_scoped_thread(thread&& t) noexcept;
|
||||
explicit strict_scoped_thread(Thread&& t) noexcept;
|
||||
|
||||
[variablelist
|
||||
|
||||
@@ -150,7 +154,7 @@ This wrapper can be used to join the thread before destroying it.
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Construct a internal thread in place.]]
|
||||
[[Effects:] [Construct an internal thread in place.]]
|
||||
|
||||
[[Postconditions:] [`*this.t_` refers to the newly created thread of execution and `this->get_id()!=thread::id()`.]]
|
||||
|
||||
@@ -180,7 +184,7 @@ This wrapper can be used to join the thread before destroying it.
|
||||
|
||||
#include <boost/thread/scoped_thread.hpp>
|
||||
|
||||
template <class CallableThread>
|
||||
template <class CallableThread, class Thread = thread>
|
||||
class scoped_thread
|
||||
{
|
||||
thread t_; // for exposition purposes only
|
||||
@@ -230,7 +234,8 @@ This wrapper can be used to join the thread before destroying it.
|
||||
|
||||
};
|
||||
|
||||
void swap(scoped_thread& lhs,scoped_thread& rhs) noexcept;
|
||||
template <class CallableThread, class Thread = thread>
|
||||
void swap(scoped_thread<CallableThread,Thread>& lhs,scoped_thread<CallableThread,Thread>& rhs) noexcept;
|
||||
|
||||
|
||||
RAII __thread wrapper adding a specific destroyer allowing to master what can be done at destruction time.
|
||||
@@ -291,16 +296,14 @@ same non-deprecated interface with the exception of the construction.
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Transfers ownership of the scoped_thread managed by `other` (if
|
||||
any) to `*this`.
|
||||
any) to `*this` after having called to `CallableThread()(t_)`.
|
||||
|
||||
- if defined `BOOST_THREAD_DONT_PROVIDE_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE`: If there was a `scoped_thread` previously associated with `*this` then that `scoped_thread` is detached, DEPRECATED
|
||||
|
||||
- if defined `BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE`: If the `scoped_thread` is joinable calls to std::terminate.
|
||||
]]
|
||||
|
||||
[[Postconditions:] [`other->get_id()==thread::id()` and `get_id()` returns the value of `other.get_id()` prior to the assignment.]]
|
||||
|
||||
[[Throws:] [Nothing]]
|
||||
[[Throws:] [Nothing: The `CallableThread()(t_)` should not throw when joining the thread as the scoped variable is on a scope outside the thread function.]]
|
||||
|
||||
|
||||
]
|
||||
|
||||
@@ -506,7 +509,8 @@ any) to `*this`.
|
||||
|
||||
#include <boost/thread/scoped_thread.hpp>
|
||||
|
||||
void swap(scoped_thread& lhs,scoped_thread& rhs) noexcept;
|
||||
template <class CallableThread, class Thread = thread>
|
||||
void swap(scoped_thread<Callable, Thread>& lhs, scoped_threadCallable, Thread>& rhs) noexcept;
|
||||
|
||||
[variablelist
|
||||
|
||||
|
||||
@@ -769,22 +769,14 @@ Closed queues add the following valid expressions
|
||||
void push(const value_type& x);
|
||||
void push(BOOST_THREAD_RV_REF(value_type) x);
|
||||
|
||||
void pull(value_type& x);
|
||||
value_type pull();
|
||||
|
||||
queue_op_status try_push(const value_type& x);
|
||||
queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x);
|
||||
|
||||
queue_op_status try_pull(value_type& x);
|
||||
|
||||
|
||||
queue_op_status nonblocking_push(const value_type& x);
|
||||
queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x);
|
||||
|
||||
queue_op_status nonblocking_pull(value_type& x);
|
||||
|
||||
queue_op_status wait_push(const value_type& x);
|
||||
queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x);
|
||||
queue_op_status wait_pull_front(value_type& x);
|
||||
|
||||
};
|
||||
|
||||
@@ -812,24 +804,13 @@ Closed queues add the following valid expressions
|
||||
// Modifiers
|
||||
void close();
|
||||
|
||||
void push(const value_type& x);
|
||||
void push(BOOST_THREAD_RV_REF(value_type) x);
|
||||
|
||||
void pull(value_type& x);
|
||||
value_type pull();
|
||||
|
||||
queue_op_status try_push(const value_type& x);
|
||||
queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x);
|
||||
|
||||
queue_op_status try_pull(value_type& x);
|
||||
|
||||
queue_op_status nonblocking_push(const value_type& x);
|
||||
queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x);
|
||||
|
||||
queue_op_status nonblocking_pull(value_type& x);
|
||||
|
||||
queue_op_status wait_push(const value_type& x);
|
||||
queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x);
|
||||
queue_op_status wait_pull(value_type& x);
|
||||
|
||||
};
|
||||
|
||||
@@ -156,7 +156,7 @@ object passed to the constructor.]]
|
||||
};
|
||||
}
|
||||
|
||||
`externally_locked_stream` cloaks a reference to an stream of type `Stream`, and actually
|
||||
`externally_locked_stream` cloaks a reference to a stream of type `Stream`, and actually
|
||||
provides full access to that object through the `get` member functions, provided you
|
||||
pass a reference to a strict lock object.
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ Both forms of pointer dereference return a proxy object rather than a real refer
|
||||
|
||||
The pointer-like semantics work very well for simple accesses such as assignment and calls to member functions. However, sometimes you need to perform an operation that requires multiple accesses under protection of the same lock, and that's what the synchronize() method provides.
|
||||
|
||||
By calling synchronize() you obtain an strict_lock_ptr object that holds a lock on the mutex protecting the data, and which can be used to access the protected data. The lock is held until the strict_lock_ptr object is destroyed, so you can safely perform multi-part operations. The strict_lock_ptr object also acts as a pointer-to-T, just like synchronized_value does, but this time the lock is already held. For example, the following function adds a trailing slash to a path held in a synchronized_value. The use of the strict_lock_ptr object ensures that the string hasn't changed in between the query and the update.
|
||||
By calling synchronize() you obtain a strict_lock_ptr object that holds a lock on the mutex protecting the data, and which can be used to access the protected data. The lock is held until the strict_lock_ptr object is destroyed, so you can safely perform multi-part operations. The strict_lock_ptr object also acts as a pointer-to-T, just like synchronized_value does, but this time the lock is already held. For example, the following function adds a trailing slash to a path held in a synchronized_value. The use of the strict_lock_ptr object ensures that the string hasn't changed in between the query and the update.
|
||||
|
||||
void addTrailingSlashIfMissing(boost::synchronized_value<std::string> & path)
|
||||
{
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
|
||||
[library Thread
|
||||
[quickbook 1.5]
|
||||
[version 4.6.0]
|
||||
[version 4.8.0]
|
||||
[authors [Williams, Anthony] [Botet Escriba, Vicente J.]]
|
||||
[copyright 2007-11 Anthony Williams]
|
||||
[copyright 2011-15 Vicente J. Botet Escriba]
|
||||
[copyright 2011-17 Vicente J. Botet Escriba]
|
||||
[purpose C++ Library for launching threads and synchronizing data between them]
|
||||
[category text]
|
||||
[license
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
{
|
||||
thread::id get_id() noexcept;
|
||||
template<typename TimeDuration>
|
||||
void yield() noexcept; // DEPRECATED
|
||||
void yield() noexcept;
|
||||
template <class Clock, class Duration>
|
||||
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
|
||||
template <class Rep, class Period>
|
||||
@@ -289,9 +289,11 @@ You can use a thread_joiner to ensure that the thread has been joined at the thr
|
||||
|
||||
A running thread can be ['interrupted] by invoking the __interrupt__ member function of the corresponding __thread__ object. When the
|
||||
interrupted thread next executes one of the specified __interruption_points__ (or if it is currently __blocked__ whilst executing one)
|
||||
with interruption enabled, then a __thread_interrupted__ exception will be thrown in the interrupted thread. If not caught,
|
||||
this will cause the execution of the interrupted thread to terminate. As with any other exception, the stack will be unwound, and
|
||||
destructors for objects of automatic storage duration will be executed.
|
||||
with interruption enabled, then a __thread_interrupted__ exception will be thrown in the interrupted thread. Unless this exception is
|
||||
caught inside the interrupted thread's thread-main function, the stack unwinding process (as with any other exception) causes the
|
||||
destructors with automatic storage duration to be executed. Unlike other exceptions, when __thread_interrupted__ is propagated out of
|
||||
thread-main function, this does not cause the call to `std::terminate`; the effect is as though the thread-main function has returned
|
||||
normally.
|
||||
|
||||
If a thread wishes to avoid being interrupted, it can create an instance of __disable_interruption__. Objects of this class disable
|
||||
interruption for the thread that created them on construction, and restore the interruption state to whatever it was before on
|
||||
@@ -711,7 +713,7 @@ are copied into internal storage for access by the new thread.]]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
[[Note:] [The reason to moving to std::terminate is that either implicitly detaching or joining a `joinable()` thread in its destructor could result in difficult to debug correctness (for `detach`) or performance (for `join`) bugs encountered only when an exception is raised. Thus the programmer must ensure that the destructor is never executed while the thread is still joinable. Join the thread before destroying or use an scoped thread.]]
|
||||
[[Note:] [The reason to moving to std::terminate is that either implicitly detaching or joining a `joinable()` thread in its destructor could result in difficult to debug correctness (for `detach`) or performance (for `join`) bugs encountered only when an exception is raised. Thus the programmer must ensure that the destructor is never executed while the thread is still joinable. Join the thread before destroying or use a scoped thread.]]
|
||||
|
||||
]
|
||||
|
||||
@@ -953,7 +955,7 @@ a default-constructed __thread_id__.]]
|
||||
|
||||
[[Effects:] [If `*this` refers to a thread of execution, request that the thread will be interrupted the next time it enters one of
|
||||
the predefined __interruption_points__ with interruption enabled, or if it is currently __blocked__ in a call to one of the
|
||||
predefined __interruption_points__ with interruption enabled .]]
|
||||
predefined __interruption_points__ with interruption enabled. Otherwise do noting.]]
|
||||
|
||||
[[Throws:] [Nothing]]
|
||||
|
||||
@@ -1304,7 +1306,7 @@ instances of __thread_id__ `a` and `b` is the same if `a==b`, and different if `
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Stores the stack size to be used to create a thread. This is an hint that the implementation can choose a better size if to small or too big or not aligned to a page.]]
|
||||
[[Effects:] [Stores the stack size to be used to create a thread. This is a hint that the implementation can choose a better size if to small or too big or not aligned to a page.]]
|
||||
|
||||
[[Postconditions:] [`this-> get_stack_size()` returns the chosen stack size.]]
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
||||
|
||||
int p1()
|
||||
|
||||
@@ -44,7 +44,7 @@ int main()
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
{
|
||||
boost::future<int> inner_future = boost::async(boost::launch::async, &p2);
|
||||
boost::future<int> inner_future = boost::async(boost::launch::async, &p2).unwrap();
|
||||
inner_future.wait();
|
||||
int ii = inner_future.get();
|
||||
BOOST_THREAD_LOG << "ii= "<< ii << "" << BOOST_THREAD_END_LOG;
|
||||
|
||||
@@ -39,36 +39,23 @@ void do_something_in_current_thread()
|
||||
{
|
||||
}
|
||||
|
||||
//void do_something_with_current_thread(boost::thread&& th)
|
||||
//{
|
||||
// th.join();
|
||||
//}
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
int some_local_state;
|
||||
int some_local_state=0;
|
||||
boost::strict_scoped_thread<> t( (boost::thread(func(some_local_state))));
|
||||
|
||||
do_something_in_current_thread();
|
||||
}
|
||||
{
|
||||
int some_local_state;
|
||||
int some_local_state=0;
|
||||
boost::thread t(( func(some_local_state) ));
|
||||
boost::strict_scoped_thread<> g( (boost::move(t)) );
|
||||
|
||||
do_something_in_current_thread();
|
||||
}
|
||||
// {
|
||||
// int some_local_state;
|
||||
// boost::thread t(( func(some_local_state) ));
|
||||
// boost::strict_scoped_thread<> g( (boost::move(t)) );
|
||||
//
|
||||
// do_something_in_current_thread();
|
||||
// do_something_with_current_thread(boost::thread(g));
|
||||
// }
|
||||
{
|
||||
int some_local_state;
|
||||
int some_local_state=0;
|
||||
boost::scoped_thread<> t( (boost::thread(func(some_local_state))));
|
||||
|
||||
if (t.joinable())
|
||||
@@ -76,14 +63,17 @@ int main()
|
||||
else
|
||||
do_something_in_current_thread();
|
||||
}
|
||||
#if 0
|
||||
{
|
||||
int some_local_state;
|
||||
int some_local_state=0;
|
||||
boost::thread t(( func(some_local_state) ));
|
||||
boost::scoped_thread<> g( (boost::move(t)) );
|
||||
t.detach();
|
||||
if (g.joinable())
|
||||
g.detach();
|
||||
|
||||
do_something_in_current_thread();
|
||||
}
|
||||
#endif
|
||||
{
|
||||
boost::scoped_thread<> g( &f, 1, 2 );
|
||||
do_something_in_current_thread();
|
||||
|
||||
112
example/std_scoped_thread.cpp
Normal file
112
example/std_scoped_thread.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
// (C) Copyright 2009-2012 Anthony Williams
|
||||
// (C) Copyright 2012 Vicente Botet
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if __cplusplus < 201103L
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
|
||||
#define BOOST_THREAD_VERSION 3
|
||||
|
||||
#include <iostream>
|
||||
#include <boost/thread/scoped_thread.hpp>
|
||||
#include <thread>
|
||||
#include <cassert>
|
||||
|
||||
void do_something(int& i)
|
||||
{
|
||||
++i;
|
||||
}
|
||||
void f(int, int)
|
||||
{
|
||||
}
|
||||
|
||||
struct func
|
||||
{
|
||||
int& i;
|
||||
|
||||
func(int& i_) :
|
||||
i(i_)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()()
|
||||
{
|
||||
for (unsigned j = 0; j < 1000000; ++j)
|
||||
{
|
||||
do_something(i);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void do_something_in_current_thread()
|
||||
{
|
||||
}
|
||||
|
||||
using strict_scoped_thread = boost::strict_scoped_thread<boost::join_if_joinable, std::thread>;
|
||||
using scoped_thread = boost::scoped_thread<boost::join_if_joinable, std::thread>;
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
int some_local_state=0;
|
||||
strict_scoped_thread t( (std::thread(func(some_local_state))));
|
||||
|
||||
do_something_in_current_thread();
|
||||
}
|
||||
{
|
||||
int some_local_state=0;
|
||||
std::thread t(( func(some_local_state) ));
|
||||
strict_scoped_thread g( (boost::move(t)) );
|
||||
|
||||
do_something_in_current_thread();
|
||||
}
|
||||
{
|
||||
int some_local_state=0;
|
||||
std::thread t(( func(some_local_state) ));
|
||||
strict_scoped_thread g( (std::move(t)) );
|
||||
|
||||
do_something_in_current_thread();
|
||||
}
|
||||
{
|
||||
int some_local_state=1;
|
||||
scoped_thread t( (std::thread(func(some_local_state))));
|
||||
|
||||
if (t.joinable()) {
|
||||
t.join();
|
||||
assert( ! t.joinable() );
|
||||
}
|
||||
else
|
||||
do_something_in_current_thread();
|
||||
}
|
||||
#if 0
|
||||
try
|
||||
{
|
||||
int some_local_state=1;
|
||||
std::thread t(( func(some_local_state) ));
|
||||
scoped_thread g( (boost::move(t)) );
|
||||
if (g.joinable()) {
|
||||
// CLANG crash here
|
||||
g.detach();
|
||||
assert( ! g.joinable() );
|
||||
}
|
||||
|
||||
do_something_in_current_thread();
|
||||
}
|
||||
catch (...) {
|
||||
assert( false);
|
||||
}
|
||||
#endif
|
||||
{
|
||||
scoped_thread g( &f, 1, 2 );
|
||||
do_something_in_current_thread();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
66
example/std_thread_guard.cpp
Normal file
66
example/std_thread_guard.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
// (C) Copyright 2009-2012 Anthony Williams
|
||||
// (C) Copyright 2012 Vicente Botet
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if __cplusplus < 201103L
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <boost/thread/thread_only.hpp>
|
||||
#include <boost/thread/thread_guard.hpp>
|
||||
#include <thread>
|
||||
|
||||
void do_something(int& i)
|
||||
{
|
||||
++i;
|
||||
}
|
||||
|
||||
struct func
|
||||
{
|
||||
int& i;
|
||||
|
||||
func(int& i_):i(i_){}
|
||||
|
||||
void operator()()
|
||||
{
|
||||
for(unsigned j=0;j<1000000;++j)
|
||||
{
|
||||
do_something(i);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
func& operator=(func const&);
|
||||
|
||||
};
|
||||
|
||||
void do_something_in_current_thread()
|
||||
{}
|
||||
|
||||
using thread_guard = boost::thread_guard<boost::join_if_joinable, std::thread>;
|
||||
|
||||
|
||||
void f()
|
||||
{
|
||||
int some_local_state;
|
||||
func my_func(some_local_state);
|
||||
std::thread t(my_func);
|
||||
thread_guard g(t);
|
||||
|
||||
do_something_in_current_thread();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
f();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -145,7 +145,7 @@ namespace boost
|
||||
unsigned int count,
|
||||
BOOST_THREAD_RV_REF(F) funct,
|
||||
typename enable_if<
|
||||
typename is_void<typename result_of<F>::type>::type, dummy*
|
||||
typename is_void<typename result_of<F()>::type>::type, dummy*
|
||||
>::type=0
|
||||
)
|
||||
: m_count(check_counter(count)),
|
||||
@@ -160,7 +160,7 @@ namespace boost
|
||||
unsigned int count,
|
||||
F &funct,
|
||||
typename enable_if<
|
||||
typename is_void<typename result_of<F>::type>::type, dummy*
|
||||
typename is_void<typename result_of<F()>::type>::type, dummy*
|
||||
>::type=0
|
||||
)
|
||||
: m_count(check_counter(count)),
|
||||
@@ -176,7 +176,7 @@ namespace boost
|
||||
unsigned int count,
|
||||
BOOST_THREAD_RV_REF(F) funct,
|
||||
typename enable_if<
|
||||
typename is_same<typename result_of<F>::type, unsigned int>::type, dummy*
|
||||
typename is_same<typename result_of<F()>::type, unsigned int>::type, dummy*
|
||||
>::type=0
|
||||
)
|
||||
: m_count(check_counter(count)),
|
||||
@@ -189,7 +189,7 @@ namespace boost
|
||||
unsigned int count,
|
||||
F& funct,
|
||||
typename enable_if<
|
||||
typename is_same<typename result_of<F>::type, unsigned int>::type, dummy*
|
||||
typename is_same<typename result_of<F()>::type, unsigned int>::type, dummy*
|
||||
>::type=0
|
||||
)
|
||||
: m_count(check_counter(count)),
|
||||
@@ -225,6 +225,7 @@ namespace boost
|
||||
m_generation++;
|
||||
m_count = static_cast<unsigned int>(fct_());
|
||||
BOOST_ASSERT(m_count != 0);
|
||||
lock.unlock();
|
||||
m_cond.notify_all();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -96,7 +96,6 @@ namespace boost
|
||||
leavers_(0)
|
||||
{
|
||||
}
|
||||
template <typename F>
|
||||
completion_latch(std::size_t count, void(*funct)()) :
|
||||
count_(count), funct_(funct), waiters_(0), leavers_(0)
|
||||
{
|
||||
|
||||
@@ -76,26 +76,15 @@ namespace concurrent
|
||||
// Modifiers
|
||||
void close() { queue->close(); }
|
||||
|
||||
void push(const value_type& x) { queue->push_front(x); }
|
||||
|
||||
void pull(value_type& x) { queue->pull(x); };
|
||||
// enable_if is_nothrow_copy_movable<value_type>
|
||||
value_type pull() { return queue->pull(); }
|
||||
|
||||
queue_op_status try_push(const value_type& x) { return queue->try_push_front(x); }
|
||||
|
||||
queue_op_status try_pull(value_type& x) { return queue->try_pull(x); }
|
||||
|
||||
queue_op_status nonblocking_push(const value_type& x) { return queue->nonblocking_push_front(x); }
|
||||
|
||||
queue_op_status nonblocking_pull(value_type& x) { return queue->nonblocking_pull(x); }
|
||||
|
||||
queue_op_status wait_push(const value_type& x) { return queue->wait_push_front(x); }
|
||||
queue_op_status wait_pull(value_type& x) { return queue->wait_pull(x); }
|
||||
void push(BOOST_THREAD_RV_REF(value_type) x) { queue->push_front(forward<value_type>(x)); }
|
||||
queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->try_push_front(forward<value_type>(x)); }
|
||||
queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->nonblocking_push_front(forward<value_type>(x)); }
|
||||
queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->wait_push_front(forward<value_type>(x)); }
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ namespace concurrent
|
||||
inline size_type size(lock_guard<mutex>& lk) const BOOST_NOEXCEPT
|
||||
{
|
||||
if (full(lk)) return capacity(lk);
|
||||
return ((out_+capacity(lk)-in_) % capacity(lk));
|
||||
return ((in_+capacity(lk)-out_) % capacity(lk));
|
||||
}
|
||||
|
||||
inline void throw_if_closed(unique_lock<mutex>&);
|
||||
@@ -484,7 +484,9 @@ namespace concurrent
|
||||
queue_op_status sync_bounded_queue<ValueType>::wait_pull_front(ValueType& elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
if (empty(lk) && closed(lk)) {return queue_op_status::closed;}
|
||||
wait_until_not_empty(lk);
|
||||
bool is_closed = false;
|
||||
wait_until_not_empty(lk, is_closed);
|
||||
if (is_closed) {return queue_op_status::closed;}
|
||||
pull_front(elem, lk);
|
||||
return queue_op_status::success;
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace detail
|
||||
class sync_timed_queue
|
||||
: private sync_priority_queue<detail::scheduled_type<T, Clock> >
|
||||
{
|
||||
typedef detail::scheduled_type<T> stype;
|
||||
typedef detail::scheduled_type<T, Clock> stype;
|
||||
typedef sync_priority_queue<stype> super;
|
||||
public:
|
||||
typedef T value_type;
|
||||
@@ -229,7 +229,8 @@ namespace detail
|
||||
if (super::closed(lk)) return true;
|
||||
while (! super::empty(lk)) {
|
||||
if (! time_not_reached(lk)) return false;
|
||||
super::not_empty_.wait_until(lk, super::data_.top().time);
|
||||
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;
|
||||
@@ -245,7 +246,8 @@ namespace detail
|
||||
while (time_not_reached(lk))
|
||||
{
|
||||
super::throw_if_closed(lk);
|
||||
super::not_empty_.wait_until(lk,super::data_.top().time);
|
||||
time_point tp = super::data_.top().time;
|
||||
super::not_empty_.wait_until(lk,tp);
|
||||
super::wait_until_not_empty(lk);
|
||||
}
|
||||
return pull(lk);
|
||||
@@ -260,7 +262,7 @@ namespace detail
|
||||
while (time_not_reached(lk))
|
||||
{
|
||||
super::throw_if_closed(lk);
|
||||
if (queue_op_status::timeout == super::not_empty_.wait_until(lk, tpmin)) {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -12,19 +12,19 @@
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/thread/detail/platform.hpp>
|
||||
|
||||
//#define BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
|
||||
//#define BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS
|
||||
// ATTRIBUTE_MAY_ALIAS
|
||||
|
||||
#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
|
||||
//#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
|
||||
#if !defined(BOOST_NO_MAY_ALIAS)
|
||||
|
||||
// GCC since 3.3 has may_alias attribute that helps to alleviate optimizer issues with
|
||||
// regard to violation of the strict aliasing rules.
|
||||
// GCC since 3.3 and some other compilers have may_alias attribute that helps
|
||||
// to alleviate optimizer issues with regard to violation of the strict aliasing rules.
|
||||
|
||||
#define BOOST_THREAD_DETAIL_USE_ATTRIBUTE_MAY_ALIAS
|
||||
#define BOOST_THREAD_ATTRIBUTE_MAY_ALIAS __attribute__((__may_alias__))
|
||||
#else
|
||||
#define BOOST_THREAD_ATTRIBUTE_MAY_ALIAS
|
||||
#endif
|
||||
#define BOOST_THREAD_ATTRIBUTE_MAY_ALIAS BOOST_MAY_ALIAS
|
||||
|
||||
|
||||
#if defined BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
|
||||
@@ -100,8 +100,8 @@
|
||||
#if !defined BOOST_THREAD_VERSION
|
||||
#define BOOST_THREAD_VERSION 2
|
||||
#else
|
||||
#if BOOST_THREAD_VERSION!=2 && BOOST_THREAD_VERSION!=3 && BOOST_THREAD_VERSION!=4
|
||||
#error "BOOST_THREAD_VERSION must be 2, 3 or 4"
|
||||
#if BOOST_THREAD_VERSION!=2 && BOOST_THREAD_VERSION!=3 && BOOST_THREAD_VERSION!=4 && BOOST_THREAD_VERSION!=5
|
||||
#error "BOOST_THREAD_VERSION must be 2, 3, 4 or 5"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -304,6 +304,13 @@
|
||||
|
||||
#endif // BOOST_THREAD_VERSION>=4
|
||||
|
||||
|
||||
#if BOOST_THREAD_VERSION>=5
|
||||
//#define BOOST_THREAD_FUTURE_BLOCKING
|
||||
#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
|
||||
|
||||
@@ -155,7 +155,15 @@ 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:
|
||||
@@ -291,7 +299,7 @@ namespace boost
|
||||
template <class F>
|
||||
explicit thread(F f
|
||||
, typename disable_if_c<
|
||||
boost::thread_detail::is_rv<F>::value // todo ass a thread_detail::is_rv
|
||||
boost::thread_detail::is_rv<F>::value // todo as a thread_detail::is_rv
|
||||
//boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F)>::value
|
||||
//|| is_same<typename decay<F>::type, thread>::value
|
||||
, dummy* >::type=0
|
||||
@@ -482,13 +490,14 @@ namespace boost
|
||||
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 {
|
||||
system_clock::time_point s_now = system_clock::now();
|
||||
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);
|
||||
@@ -496,10 +505,10 @@ namespace boost
|
||||
return true;
|
||||
}
|
||||
template <class Duration>
|
||||
bool try_join_until(const chrono::time_point<chrono::system_clock, Duration>& t)
|
||||
bool try_join_until(const chrono::time_point<thread_detail::internal_clock_t, Duration>& t)
|
||||
{
|
||||
using namespace chrono;
|
||||
typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
|
||||
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
|
||||
@@ -514,7 +523,7 @@ namespace boost
|
||||
//}
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
bool try_join_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
|
||||
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());
|
||||
@@ -535,7 +544,7 @@ namespace boost
|
||||
}
|
||||
#endif
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
bool try_join_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
|
||||
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();
|
||||
|
||||
@@ -40,19 +40,19 @@ namespace boost
|
||||
typedef system::system_error base_type;
|
||||
public:
|
||||
thread_exception()
|
||||
: base_type(0,system::system_category())
|
||||
: base_type(0,system::generic_category())
|
||||
{}
|
||||
|
||||
thread_exception(int sys_error_code)
|
||||
: base_type(sys_error_code, system::system_category())
|
||||
: base_type(sys_error_code, system::generic_category())
|
||||
{}
|
||||
|
||||
thread_exception( int ev, const char * what_arg )
|
||||
: base_type(system::error_code(ev, system::system_category()), what_arg)
|
||||
: base_type(system::error_code(ev, system::generic_category()), what_arg)
|
||||
{
|
||||
}
|
||||
thread_exception( int ev, const std::string & what_arg )
|
||||
: base_type(system::error_code(ev, system::system_category()), what_arg)
|
||||
: base_type(system::error_code(ev, system::generic_category()), what_arg)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -74,18 +74,18 @@ namespace boost
|
||||
typedef system::system_error base_type;
|
||||
public:
|
||||
condition_error()
|
||||
: base_type(system::error_code(0, system::system_category()), "Condition error")
|
||||
: base_type(system::error_code(0, system::generic_category()), "Condition error")
|
||||
{}
|
||||
condition_error( int ev )
|
||||
: base_type(system::error_code(ev, system::system_category()), "Condition error")
|
||||
: base_type(system::error_code(ev, system::generic_category()), "Condition error")
|
||||
{
|
||||
}
|
||||
condition_error( int ev, const char * what_arg )
|
||||
: base_type(system::error_code(ev, system::system_category()), what_arg)
|
||||
: base_type(system::error_code(ev, system::generic_category()), what_arg)
|
||||
{
|
||||
}
|
||||
condition_error( int ev, const std::string & what_arg )
|
||||
: base_type(system::error_code(ev, system::system_category()), what_arg)
|
||||
: base_type(system::error_code(ev, system::generic_category()), what_arg)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
@@ -86,11 +86,18 @@ namespace executors
|
||||
for(;;)
|
||||
{
|
||||
work task;
|
||||
queue_op_status st = work_queue.wait_pull(task);
|
||||
if (st == queue_op_status::closed) {
|
||||
try
|
||||
{
|
||||
queue_op_status st = work_queue.wait_pull(task);
|
||||
if (st == queue_op_status::closed) {
|
||||
return;
|
||||
}
|
||||
task();
|
||||
}
|
||||
catch (boost::thread_interrupted&)
|
||||
{
|
||||
return;
|
||||
}
|
||||
task();
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
@@ -234,6 +241,7 @@ namespace executors
|
||||
{
|
||||
for (unsigned i = 0; i < threads.size(); ++i)
|
||||
{
|
||||
threads[i].interrupt();
|
||||
threads[i].join();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,10 +57,16 @@ namespace detail
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
work task;
|
||||
queue_op_status st = _workq.wait_pull(task);
|
||||
if (st == queue_op_status::closed) return;
|
||||
task();
|
||||
try {
|
||||
work task;
|
||||
queue_op_status st = _workq.wait_pull(task);
|
||||
if (st == queue_op_status::closed) return;
|
||||
task();
|
||||
}
|
||||
catch (boost::thread_interrupted&)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace boost
|
||||
* \par Synchronization
|
||||
* The completion of all the closures happen before the completion of the executor destructor.
|
||||
*/
|
||||
virtual ~executor() {};
|
||||
virtual ~executor() {}
|
||||
|
||||
/**
|
||||
* \par Effects
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace boost
|
||||
|
||||
/// executor is not copyable.
|
||||
BOOST_THREAD_NO_COPYABLE(executor_ref)
|
||||
executor_ref(Executor& ex) : ex(ex) {}
|
||||
executor_ref(Executor& ex_) : ex(ex_) {}
|
||||
|
||||
/**
|
||||
* \par Effects
|
||||
@@ -41,7 +41,7 @@ namespace boost
|
||||
* \par Synchronization
|
||||
* The completion of all the closures happen before the completion of the executor destructor.
|
||||
*/
|
||||
~executor_ref() {};
|
||||
~executor_ref() {}
|
||||
|
||||
/**
|
||||
* \par Effects
|
||||
@@ -98,9 +98,9 @@ namespace boost
|
||||
typedef executors::work work;
|
||||
|
||||
template<typename Executor>
|
||||
generic_executor_ref(Executor& ex)
|
||||
//: ex(make_shared<executor_ref<Executor> >(ex)) // todo check why this doesn't works with C++03
|
||||
: ex( new executor_ref<Executor>(ex) )
|
||||
generic_executor_ref(Executor& ex_)
|
||||
//: ex(make_shared<executor_ref<Executor> >(ex_)) // todo check why this doesn't works with C++03
|
||||
: ex( new executor_ref<Executor>(ex_) )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/concurrent_queues/sync_queue.hpp>
|
||||
#include <boost/thread/executors/work.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
@@ -40,15 +41,33 @@ namespace executors
|
||||
* Throws: whatever the current task constructor throws or the task() throws.
|
||||
*/
|
||||
bool try_executing_one()
|
||||
{
|
||||
return execute_one(/*wait:*/false);
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Effects: Execute one task.
|
||||
* Remark: If wait is true, waits until a task is available or the executor
|
||||
* is closed. If wait is false, returns false immediately if no
|
||||
* task is available.
|
||||
* Returns: whether a task has been executed (if wait is true, only returns false if closed).
|
||||
* Throws: whatever the current task constructor throws or the task() throws.
|
||||
*/
|
||||
bool execute_one(bool wait)
|
||||
{
|
||||
work task;
|
||||
try
|
||||
{
|
||||
if (work_queue.try_pull(task) == queue_op_status::success)
|
||||
queue_op_status status = wait ?
|
||||
work_queue.wait_pull(task) :
|
||||
work_queue.try_pull(task);
|
||||
if (status == queue_op_status::success)
|
||||
{
|
||||
task();
|
||||
return true;
|
||||
}
|
||||
BOOST_ASSERT(!wait || status == queue_op_status::closed);
|
||||
return false;
|
||||
}
|
||||
catch (...)
|
||||
@@ -57,21 +76,6 @@ namespace executors
|
||||
//return false;
|
||||
}
|
||||
}
|
||||
private:
|
||||
/**
|
||||
* Effects: schedule one task or yields
|
||||
* Throws: whatever the current task constructor throws or the task() throws.
|
||||
*/
|
||||
void schedule_one_or_yield()
|
||||
{
|
||||
if ( ! try_executing_one())
|
||||
{
|
||||
this_thread::yield();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public:
|
||||
/// loop_executor is not copyable.
|
||||
@@ -101,10 +105,10 @@ namespace executors
|
||||
*/
|
||||
void loop()
|
||||
{
|
||||
while (!closed())
|
||||
while (execute_one(/*wait:*/true))
|
||||
{
|
||||
schedule_one_or_yield();
|
||||
}
|
||||
BOOST_ASSERT(closed());
|
||||
while (try_executing_one())
|
||||
{
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace executors
|
||||
~scheduled_thread_pool()
|
||||
{
|
||||
this->close();
|
||||
_workers.interrupt_all();
|
||||
_workers.join_all();
|
||||
}
|
||||
|
||||
|
||||
@@ -231,6 +231,7 @@ namespace boost
|
||||
~scheduler()
|
||||
{
|
||||
this->close();
|
||||
thr.interrupt();
|
||||
thr.join();
|
||||
}
|
||||
template <class Ex>
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace executors
|
||||
~scheduling_adpator()
|
||||
{
|
||||
this->close();
|
||||
_scheduler.interrupt();
|
||||
_scheduler.join();
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
// due to boost::exception::exception_ptr dependency
|
||||
|
||||
//#define BOOST_THREAD_CONTINUATION_SYNC
|
||||
#define BOOST_THREAD_FUTURE_BLOCKING
|
||||
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
|
||||
@@ -177,8 +176,8 @@ namespace boost
|
||||
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),
|
||||
@@ -300,7 +299,7 @@ namespace boost
|
||||
}
|
||||
do_continuation(lock);
|
||||
}
|
||||
void make_ready()
|
||||
void notify_deferred()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lock(this->mutex);
|
||||
mark_finished_internal(lock);
|
||||
@@ -825,6 +824,12 @@ namespace boost
|
||||
{
|
||||
#ifdef BOOST_THREAD_FUTURE_BLOCKING
|
||||
join();
|
||||
#elif defined BOOST_THREAD_ASYNC_FUTURE_WAITS
|
||||
unique_lock<boost::mutex> lk(this->mutex);
|
||||
while(!this->done)
|
||||
{
|
||||
this->waiters.wait(lk);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -853,9 +858,9 @@ namespace boost
|
||||
void init(BOOST_THREAD_FWD_REF(Fp) f)
|
||||
{
|
||||
#ifdef BOOST_THREAD_FUTURE_BLOCKING
|
||||
this->thr_ = thread(&future_async_shared_state::run, static_shared_from_this(this), boost::forward<Fp>(f));
|
||||
this->thr_ = boost::thread(&future_async_shared_state::run, static_shared_from_this(this), boost::forward<Fp>(f));
|
||||
#else
|
||||
thread(&future_async_shared_state::run, static_shared_from_this(this), boost::forward<Fp>(f)).detach();
|
||||
boost::thread(&future_async_shared_state::run, static_shared_from_this(this), boost::forward<Fp>(f)).detach();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -878,9 +883,9 @@ namespace boost
|
||||
void init(BOOST_THREAD_FWD_REF(Fp) f)
|
||||
{
|
||||
#ifdef BOOST_THREAD_FUTURE_BLOCKING
|
||||
this->thr_ = thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f));
|
||||
this->thr_ = boost::thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f));
|
||||
#else
|
||||
thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f)).detach();
|
||||
boost::thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f)).detach();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -904,9 +909,9 @@ namespace boost
|
||||
void init(BOOST_THREAD_FWD_REF(Fp) f)
|
||||
{
|
||||
#ifdef BOOST_THREAD_FUTURE_BLOCKING
|
||||
this->thr_ = thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f));
|
||||
this->thr_ = boost::thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f));
|
||||
#else
|
||||
thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f)).detach();
|
||||
boost::thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f)).detach();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1330,7 +1335,7 @@ namespace boost
|
||||
|
||||
bool valid() const BOOST_NOEXCEPT
|
||||
{
|
||||
return future_ != 0 && future_->valid();
|
||||
return future_.get() != 0 && future_->valid();
|
||||
}
|
||||
|
||||
void wait() const
|
||||
@@ -1350,7 +1355,7 @@ namespace boost
|
||||
boost::throw_exception(future_uninitialized());
|
||||
}
|
||||
return future_->mutex;
|
||||
};
|
||||
}
|
||||
|
||||
notify_when_ready_handle notify_when_ready(boost::condition_variable_any& cv)
|
||||
{
|
||||
@@ -1634,7 +1639,9 @@ namespace boost
|
||||
base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
|
||||
{
|
||||
}
|
||||
inline BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other); // EXTENSION
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
|
||||
inline explicit BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other); // EXTENSION
|
||||
#endif
|
||||
|
||||
explicit BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(shared_future<R>) other) :
|
||||
base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
|
||||
@@ -1675,7 +1682,7 @@ namespace boost
|
||||
// retrieving the value
|
||||
move_dest_type get()
|
||||
{
|
||||
if (this->future_ == 0)
|
||||
if (this->future_.get() == 0)
|
||||
{
|
||||
boost::throw_exception(future_uninitialized());
|
||||
}
|
||||
@@ -1695,7 +1702,7 @@ namespace boost
|
||||
get_or(BOOST_THREAD_RV_REF(R2) v)
|
||||
{
|
||||
|
||||
if (this->future_ == 0)
|
||||
if (this->future_.get() == 0)
|
||||
{
|
||||
boost::throw_exception(future_uninitialized());
|
||||
}
|
||||
@@ -1721,7 +1728,7 @@ namespace boost
|
||||
typename boost::disable_if< is_void<R2>, move_dest_type>::type
|
||||
get_or(R2 const& v) // EXTENSION
|
||||
{
|
||||
if (this->future_ == 0)
|
||||
if (this->future_.get() == 0)
|
||||
{
|
||||
boost::throw_exception(future_uninitialized());
|
||||
}
|
||||
@@ -1936,7 +1943,7 @@ namespace boost
|
||||
// retrieving the value
|
||||
move_dest_type get()
|
||||
{
|
||||
if (this->future_ == 0)
|
||||
if (this->future_.get() == 0)
|
||||
{
|
||||
boost::throw_exception(future_uninitialized());
|
||||
}
|
||||
@@ -1952,7 +1959,7 @@ namespace boost
|
||||
}
|
||||
move_dest_type get_or(BOOST_THREAD_RV_REF(R) v) // EXTENSION
|
||||
{
|
||||
if (this->future_ == 0)
|
||||
if (this->future_.get() == 0)
|
||||
{
|
||||
boost::throw_exception(future_uninitialized());
|
||||
}
|
||||
@@ -1971,7 +1978,7 @@ namespace boost
|
||||
|
||||
move_dest_type get_or(R const& v) // EXTENSION
|
||||
{
|
||||
if (this->future_ == 0)
|
||||
if (this->future_.get() == 0)
|
||||
{
|
||||
boost::throw_exception(future_uninitialized());
|
||||
}
|
||||
@@ -4379,9 +4386,9 @@ namespace detail
|
||||
void launch_continuation() {
|
||||
#if defined BOOST_THREAD_FUTURE_BLOCKING
|
||||
boost::lock_guard<boost::mutex> lk(this->mutex);
|
||||
this->thr_ = thread(&future_async_continuation_shared_state::run, static_shared_from_this(this));
|
||||
this->thr_ = boost::thread(&future_async_continuation_shared_state::run, static_shared_from_this(this));
|
||||
#else
|
||||
thread(&base_type::run, static_shared_from_this(this)).detach();
|
||||
boost::thread(&base_type::run, static_shared_from_this(this)).detach();
|
||||
#endif
|
||||
}
|
||||
};
|
||||
@@ -4498,9 +4505,9 @@ namespace detail {
|
||||
void launch_continuation() {
|
||||
#if defined BOOST_THREAD_FUTURE_BLOCKING
|
||||
boost::lock_guard<boost::mutex> lk(this->mutex);
|
||||
this->thr_ = thread(&base_type::run, static_shared_from_this(this));
|
||||
this->thr_ = boost::thread(&base_type::run, static_shared_from_this(this));
|
||||
#else
|
||||
thread(&base_type::run, static_shared_from_this(this)).detach();
|
||||
boost::thread(&base_type::run, static_shared_from_this(this)).detach();
|
||||
#endif
|
||||
}
|
||||
};
|
||||
@@ -4742,7 +4749,7 @@ namespace detail {
|
||||
inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
|
||||
BOOST_THREAD_FUTURE<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func) {
|
||||
typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
|
||||
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
|
||||
BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
|
||||
|
||||
// keep state alive as we move ourself but hold the lock
|
||||
shared_ptr<detail::shared_state_base> sentinel(this->future_);
|
||||
@@ -4767,17 +4774,17 @@ namespace detail {
|
||||
#endif
|
||||
} else if (underlying_cast<int>(policy) & int(launch::inherit)) {
|
||||
|
||||
launch policy = this->launch_policy(lock);
|
||||
if (underlying_cast<int>(policy) & int(launch::async)) {
|
||||
launch policy_ = this->launch_policy(lock);
|
||||
if (underlying_cast<int>(policy_) & int(launch::async)) {
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_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::deferred)) {
|
||||
} else if (underlying_cast<int>(policy_) & int(launch::deferred)) {
|
||||
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)
|
||||
)));
|
||||
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
} else if (underlying_cast<int>(policy) & int(launch::executor)) {
|
||||
} else if (underlying_cast<int>(policy_) & int(launch::executor)) {
|
||||
assert(this->future_->get_executor());
|
||||
typedef executor Ex;
|
||||
Ex& ex = *(this->future_->get_executor());
|
||||
@@ -4806,7 +4813,7 @@ namespace detail {
|
||||
inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
|
||||
BOOST_THREAD_FUTURE<R>::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) {
|
||||
typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
|
||||
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
|
||||
BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
|
||||
|
||||
// keep state alive as we move ourself but hold the lock
|
||||
shared_ptr<detail::shared_state_base> sentinel(this->future_);
|
||||
@@ -4830,7 +4837,7 @@ namespace detail {
|
||||
return this->then(this->launch_policy(), boost::forward<F>(func));
|
||||
#else
|
||||
typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
|
||||
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
|
||||
BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
|
||||
|
||||
// keep state alive as we move ourself but hold the lock
|
||||
shared_ptr<detail::shared_state_base> sentinel(this->future_);
|
||||
@@ -4860,7 +4867,7 @@ namespace detail {
|
||||
BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(launch policy, BOOST_THREAD_FWD_REF(F) func) {
|
||||
typedef BOOST_THREAD_FUTURE<R2> R;
|
||||
typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
|
||||
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
|
||||
BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
|
||||
|
||||
// keep state alive as we move ourself but hold the lock
|
||||
shared_ptr<detail::shared_state_base> sentinel(this->future_);
|
||||
@@ -4888,22 +4895,22 @@ namespace detail {
|
||||
)));
|
||||
#endif
|
||||
} else if (underlying_cast<int>(policy) & int(launch::inherit)) {
|
||||
launch policy = this->launch_policy(lock);
|
||||
launch policy_ = this->launch_policy(lock);
|
||||
|
||||
if (underlying_cast<int>(policy) & int(launch::async)) {
|
||||
if (underlying_cast<int>(policy_) & int(launch::async)) {
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_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::deferred)) {
|
||||
} else if (underlying_cast<int>(policy_) & int(launch::deferred)) {
|
||||
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)) {
|
||||
} 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)) {
|
||||
} else if (underlying_cast<int>(policy_) & int(launch::executor)) {
|
||||
assert(this->future_->get_executor());
|
||||
typedef executor Ex;
|
||||
Ex& ex = *(this->future_->get_executor());
|
||||
@@ -4934,7 +4941,7 @@ namespace detail {
|
||||
BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) {
|
||||
typedef BOOST_THREAD_FUTURE<R2> R;
|
||||
typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
|
||||
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
|
||||
BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
|
||||
|
||||
// keep state alive as we move ourself but hold the lock
|
||||
shared_ptr<detail::shared_state_base> sentinel(this->future_);
|
||||
@@ -4960,7 +4967,7 @@ namespace detail {
|
||||
#else
|
||||
typedef BOOST_THREAD_FUTURE<R2> R;
|
||||
typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
|
||||
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
|
||||
BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
|
||||
|
||||
// keep state alive as we move ourself but hold the lock
|
||||
shared_ptr<detail::shared_state_base> sentinel(this->future_);
|
||||
@@ -4990,7 +4997,7 @@ namespace detail {
|
||||
shared_future<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func) const
|
||||
{
|
||||
typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
|
||||
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
|
||||
BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
|
||||
|
||||
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
|
||||
if (underlying_cast<int>(policy) & int(launch::async)) {
|
||||
@@ -5015,21 +5022,21 @@ namespace detail {
|
||||
#endif
|
||||
} else if (underlying_cast<int>(policy) & int(launch::inherit)) {
|
||||
|
||||
launch policy = this->launch_policy(lock);
|
||||
if (underlying_cast<int>(policy) & int(launch::async)) {
|
||||
launch policy_ = this->launch_policy(lock);
|
||||
if (underlying_cast<int>(policy_) & int(launch::async)) {
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type>(
|
||||
lock, *this, boost::forward<F>(func)
|
||||
)));
|
||||
} else if (underlying_cast<int>(policy) & int(launch::deferred)) {
|
||||
} else if (underlying_cast<int>(policy_) & int(launch::deferred)) {
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_deferred_continuation_shared_state<shared_future<R>, future_type>(
|
||||
lock, *this, boost::forward<F>(func)
|
||||
)));
|
||||
} else if (underlying_cast<int>(policy) & int(launch::sync)) {
|
||||
} else if (underlying_cast<int>(policy_) & int(launch::sync)) {
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_sync_continuation_shared_state<shared_future<R>, future_type>(
|
||||
lock, *this, boost::forward<F>(func)
|
||||
)));
|
||||
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
} else if (underlying_cast<int>(policy) & int(launch::executor)) {
|
||||
} else if (underlying_cast<int>(policy_) & int(launch::executor)) {
|
||||
typedef executor Ex;
|
||||
Ex& ex = *(this->future_->get_executor());
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state<Ex, shared_future<R>, future_type>(ex,
|
||||
@@ -5059,7 +5066,7 @@ namespace detail {
|
||||
shared_future<R>::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) const
|
||||
{
|
||||
typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
|
||||
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
|
||||
BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
|
||||
|
||||
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state<Ex, shared_future<R>, future_type>(ex,
|
||||
@@ -5080,7 +5087,7 @@ namespace detail {
|
||||
return this->then(this->launch_policy(), boost::forward<F>(func));
|
||||
#else
|
||||
typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
|
||||
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
|
||||
BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
|
||||
|
||||
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
|
||||
launch policy = this->launch_policy(lock);
|
||||
@@ -5252,7 +5259,7 @@ namespace detail
|
||||
BOOST_THREAD_FUTURE<R2>
|
||||
BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::unwrap()
|
||||
{
|
||||
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
|
||||
BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
|
||||
|
||||
// keep state alive as we move ourself but hold the lock
|
||||
shared_ptr<detail::shared_state_base> sentinel(this->future_);
|
||||
@@ -5311,9 +5318,9 @@ namespace detail
|
||||
return;
|
||||
}
|
||||
#ifdef BOOST_THREAD_FUTURE_BLOCKING
|
||||
this->thr_ = thread(&future_when_all_vector_shared_state::run, this->shared_from_this());
|
||||
this->thr_ = boost::thread(&future_when_all_vector_shared_state::run, this->shared_from_this());
|
||||
#else
|
||||
thread(&future_when_all_vector_shared_state::run, this->shared_from_this()).detach();
|
||||
boost::thread(&future_when_all_vector_shared_state::run, this->shared_from_this()).detach();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -5382,9 +5389,9 @@ namespace detail
|
||||
}
|
||||
|
||||
#ifdef BOOST_THREAD_FUTURE_BLOCKING
|
||||
this->thr_ = thread(&future_when_any_vector_shared_state::run, this->shared_from_this());
|
||||
this->thr_ = boost::thread(&future_when_any_vector_shared_state::run, this->shared_from_this());
|
||||
#else
|
||||
thread(&future_when_any_vector_shared_state::run, this->shared_from_this()).detach();
|
||||
boost::thread(&future_when_any_vector_shared_state::run, this->shared_from_this()).detach();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -5489,9 +5496,9 @@ namespace detail
|
||||
return;
|
||||
}
|
||||
#ifdef BOOST_THREAD_FUTURE_BLOCKING
|
||||
this->thr_ = thread(&future_when_all_tuple_shared_state::run, this->shared_from_this());
|
||||
this->thr_ = boost::thread(&future_when_all_tuple_shared_state::run, this->shared_from_this());
|
||||
#else
|
||||
thread(&future_when_all_tuple_shared_state::run, this->shared_from_this()).detach();
|
||||
boost::thread(&future_when_all_tuple_shared_state::run, this->shared_from_this()).detach();
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -5560,9 +5567,9 @@ namespace detail
|
||||
}
|
||||
|
||||
#ifdef BOOST_THREAD_FUTURE_BLOCKING
|
||||
this->thr_ = thread(&future_when_any_tuple_shared_state::run, this->shared_from_this());
|
||||
this->thr_ = boost::thread(&future_when_any_tuple_shared_state::run, this->shared_from_this());
|
||||
#else
|
||||
thread(&future_when_any_tuple_shared_state::run, this->shared_from_this()).detach();
|
||||
boost::thread(&future_when_any_tuple_shared_state::run, this->shared_from_this()).detach();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -5651,5 +5658,5 @@ namespace detail
|
||||
#endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
|
||||
}
|
||||
|
||||
#endif // BOOST_NO_EXCEPTION
|
||||
#endif // BOOST_NO_EXCEPTIONS
|
||||
#endif // header
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace boost
|
||||
}
|
||||
#else
|
||||
template<typename F1, typename... Fs>
|
||||
void wait_for_all(F1& f1, Fs&... fs)
|
||||
typename boost::enable_if<is_future_type<F1>,void>::type wait_for_all(F1& f1, Fs&... fs)
|
||||
{
|
||||
bool dummy[] = { (f1.wait(), true), (fs.wait(), true)... };
|
||||
|
||||
|
||||
@@ -934,7 +934,7 @@ namespace boost
|
||||
if (m == 0)
|
||||
{
|
||||
boost::throw_exception(
|
||||
boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
|
||||
boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost upgrade_lock has no mutex"));
|
||||
}
|
||||
if (owns_lock())
|
||||
{
|
||||
@@ -949,7 +949,7 @@ namespace boost
|
||||
if (m == 0)
|
||||
{
|
||||
boost::throw_exception(
|
||||
boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
|
||||
boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost upgrade_lock has no mutex"));
|
||||
}
|
||||
if (owns_lock())
|
||||
{
|
||||
@@ -964,7 +964,7 @@ namespace boost
|
||||
if (m == 0)
|
||||
{
|
||||
boost::throw_exception(
|
||||
boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
|
||||
boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost upgrade_lock has no mutex"));
|
||||
}
|
||||
if (!owns_lock())
|
||||
{
|
||||
@@ -980,11 +980,11 @@ namespace boost
|
||||
{
|
||||
if(m==0)
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost upgrade_lock has no mutex"));
|
||||
}
|
||||
if(owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost upgrade_lock owns already the mutex"));
|
||||
}
|
||||
is_locked=m->try_lock_upgrade_for(rel_time);
|
||||
return is_locked;
|
||||
@@ -994,11 +994,11 @@ namespace boost
|
||||
{
|
||||
if(m==0)
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost upgrade_lock has no mutex"));
|
||||
}
|
||||
if(owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost upgrade_lock owns already the mutex"));
|
||||
}
|
||||
is_locked=m->try_lock_upgrade_until(abs_time);
|
||||
return is_locked;
|
||||
@@ -1080,7 +1080,7 @@ namespace boost
|
||||
//std-2104 unique_lock move-assignment should not be noexcept
|
||||
upgrade_to_unique_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_to_unique_lock<Mutex> BOOST_THREAD_RV_REF_END other) //BOOST_NOEXCEPT
|
||||
{
|
||||
upgrade_to_unique_lock temp(other);
|
||||
upgrade_to_unique_lock temp(::boost::move(other));
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
@@ -1167,7 +1167,7 @@ private unique_lock<Mutex>
|
||||
#endif
|
||||
try_lock_wrapper& operator=(BOOST_THREAD_RV_REF_BEG try_lock_wrapper<Mutex> BOOST_THREAD_RV_REF_END other)
|
||||
{
|
||||
try_lock_wrapper temp(other);
|
||||
try_lock_wrapper temp(::boost::move(other));
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <boost/thread/lock_algorithms.hpp>
|
||||
#include <boost/thread/lock_types.hpp>
|
||||
#include <boost/thread/lock_guard.hpp>
|
||||
#include <boost/thread/shared_lock_guard.hpp>
|
||||
#include <boost/thread/lockable_traits.hpp>
|
||||
#include <boost/thread/lock_options.hpp>
|
||||
|
||||
|
||||
@@ -45,9 +45,17 @@ namespace boost
|
||||
m_.unlock();
|
||||
m=&m_;
|
||||
}
|
||||
~lock_on_exit()
|
||||
void deactivate()
|
||||
{
|
||||
if(m)
|
||||
if (m)
|
||||
{
|
||||
m->lock();
|
||||
}
|
||||
m = 0;
|
||||
}
|
||||
~lock_on_exit() BOOST_NOEXCEPT_IF(false)
|
||||
{
|
||||
if (m)
|
||||
{
|
||||
m->lock();
|
||||
}
|
||||
@@ -70,17 +78,18 @@ 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();
|
||||
guard.deactivate();
|
||||
#else
|
||||
pthread_mutex_t* the_mutex = m.mutex()->native_handle();
|
||||
res = pthread_cond_wait(&cond,the_mutex);
|
||||
#endif
|
||||
do {
|
||||
res = pthread_cond_wait(&cond,the_mutex);
|
||||
} while (res == EINTR);
|
||||
}
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
this_thread::interruption_point();
|
||||
#endif
|
||||
if(res)
|
||||
if(res && res != EINTR)
|
||||
{
|
||||
boost::throw_exception(condition_error(res, "boost::condition_variable::wait failed in pthread_cond_wait"));
|
||||
}
|
||||
@@ -103,10 +112,13 @@ 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();
|
||||
guard.deactivate();
|
||||
#else
|
||||
pthread_mutex_t* the_mutex = m.mutex()->native_handle();
|
||||
#endif
|
||||
cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout);
|
||||
#endif
|
||||
}
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
this_thread::interruption_point();
|
||||
@@ -178,6 +190,8 @@ namespace boost
|
||||
#endif
|
||||
guard.activate(m);
|
||||
res=pthread_cond_wait(&cond,&internal_mutex);
|
||||
check_for_interruption.check();
|
||||
guard.deactivate();
|
||||
}
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
this_thread::interruption_point();
|
||||
@@ -336,14 +350,15 @@ namespace boost
|
||||
cv_status::timeout;
|
||||
}
|
||||
|
||||
template <class lock_type>
|
||||
inline cv_status wait_until(
|
||||
unique_lock<mutex>& lk,
|
||||
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(lk, ts)) return cv_status::no_timeout;
|
||||
if (do_wait_until(lock, ts)) return cv_status::no_timeout;
|
||||
else return cv_status::timeout;
|
||||
}
|
||||
|
||||
@@ -391,7 +406,7 @@ namespace boost
|
||||
private: // used by boost::thread::try_join_until
|
||||
|
||||
template <class lock_type>
|
||||
inline bool do_wait_until(
|
||||
bool do_wait_until(
|
||||
lock_type& m,
|
||||
struct timespec const &timeout)
|
||||
{
|
||||
@@ -405,6 +420,8 @@ namespace boost
|
||||
#endif
|
||||
guard.activate(m);
|
||||
res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
|
||||
check_for_interruption.check();
|
||||
guard.deactivate();
|
||||
}
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
this_thread::interruption_point();
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
#include <boost/thread/xtime.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
#include <boost/chrono/system_clocks.hpp>
|
||||
#include <boost/chrono/ceil.hpp>
|
||||
@@ -52,9 +53,9 @@ namespace boost
|
||||
class condition_variable
|
||||
{
|
||||
private:
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
pthread_mutex_t internal_mutex;
|
||||
#endif
|
||||
//#endif
|
||||
pthread_cond_t cond;
|
||||
|
||||
public:
|
||||
@@ -68,38 +69,50 @@ namespace boost
|
||||
unique_lock<mutex>& lock,
|
||||
struct timespec const &timeout)
|
||||
{
|
||||
return do_wait_until(lock, boost::detail::timespec_plus(timeout, boost::detail::timespec_now()));
|
||||
#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
|
||||
}
|
||||
|
||||
public:
|
||||
BOOST_THREAD_NO_COPYABLE(condition_variable)
|
||||
condition_variable()
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
int res=pthread_mutex_init(&internal_mutex,NULL);
|
||||
int res;
|
||||
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
// Even if it is not used, the internal_mutex exists (see
|
||||
// above) and must be initialized (etc) in case some
|
||||
// compilation units provide interruptions and others
|
||||
// don't.
|
||||
res=pthread_mutex_init(&internal_mutex,NULL);
|
||||
if(res)
|
||||
{
|
||||
boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread_mutex_init"));
|
||||
}
|
||||
#endif
|
||||
//#endif
|
||||
res = detail::monotonic_pthread_cond_init(cond);
|
||||
if (res)
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
// ditto
|
||||
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
|
||||
#endif
|
||||
//#endif
|
||||
boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in detail::monotonic_pthread_cond_init"));
|
||||
}
|
||||
}
|
||||
~condition_variable()
|
||||
{
|
||||
int ret;
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
// ditto
|
||||
do {
|
||||
ret = pthread_mutex_destroy(&internal_mutex);
|
||||
} while (ret == EINTR);
|
||||
BOOST_ASSERT(!ret);
|
||||
#endif
|
||||
//#endif
|
||||
do {
|
||||
ret = pthread_cond_destroy(&cond);
|
||||
} while (ret == EINTR);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#ifndef BOOST_PTHREAD_MUTEX_SCOPED_LOCK_HPP
|
||||
#define BOOST_PTHREAD_MUTEX_SCOPED_LOCK_HPP
|
||||
// (C) Copyright 2007-8 Anthony Williams
|
||||
// (C) Copyright 2007-8 Anthony Williams
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -20,41 +20,47 @@ namespace boost
|
||||
pthread_mutex_t* m;
|
||||
bool locked;
|
||||
public:
|
||||
explicit pthread_mutex_scoped_lock(pthread_mutex_t* m_):
|
||||
explicit pthread_mutex_scoped_lock(pthread_mutex_t* m_) BOOST_NOEXCEPT:
|
||||
m(m_),locked(true)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_lock(m));
|
||||
}
|
||||
void unlock()
|
||||
void unlock() BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_unlock(m));
|
||||
locked=false;
|
||||
}
|
||||
|
||||
~pthread_mutex_scoped_lock()
|
||||
void check() BOOST_NOEXCEPT
|
||||
{
|
||||
if(locked)
|
||||
{
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
~pthread_mutex_scoped_lock() BOOST_NOEXCEPT
|
||||
{
|
||||
if(locked)
|
||||
{
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
class pthread_mutex_scoped_unlock
|
||||
{
|
||||
pthread_mutex_t* m;
|
||||
public:
|
||||
explicit pthread_mutex_scoped_unlock(pthread_mutex_t* m_):
|
||||
explicit pthread_mutex_scoped_unlock(pthread_mutex_t* m_) BOOST_NOEXCEPT:
|
||||
m(m_)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_unlock(m));
|
||||
}
|
||||
~pthread_mutex_scoped_unlock()
|
||||
~pthread_mutex_scoped_unlock() BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_lock(m));
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include <boost/chrono/ceil.hpp>
|
||||
#endif
|
||||
#include <boost/thread/detail/delete.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
@@ -269,13 +268,13 @@ namespace boost
|
||||
// avoid other threads to lock, lock_upgrade or lock_shared, so only this thread is notified.
|
||||
state.upgrade=false;
|
||||
state.exclusive=true;
|
||||
lk.unlock();
|
||||
//lk.unlock();
|
||||
upgrade_cond.notify_one();
|
||||
}
|
||||
else
|
||||
{
|
||||
state.exclusive_waiting_blocked=false;
|
||||
lk.unlock();
|
||||
//lk.unlock();
|
||||
}
|
||||
release_waiters();
|
||||
}
|
||||
|
||||
@@ -50,7 +50,11 @@ namespace boost
|
||||
// stack
|
||||
void set_stack_size(std::size_t size) BOOST_NOEXCEPT {
|
||||
if (size==0) return;
|
||||
#ifdef BOOST_THREAD_USES_GETPAGESIZE
|
||||
std::size_t page_size = getpagesize();
|
||||
#else
|
||||
std::size_t page_size = ::sysconf( _SC_PAGESIZE);
|
||||
#endif
|
||||
#ifdef PTHREAD_STACK_MIN
|
||||
if (size<PTHREAD_STACK_MIN) size=PTHREAD_STACK_MIN;
|
||||
#endif
|
||||
@@ -177,6 +181,7 @@ namespace boost
|
||||
thread_data_base* const thread_info;
|
||||
pthread_mutex_t* m;
|
||||
bool set;
|
||||
bool done;
|
||||
|
||||
void check_for_interruption()
|
||||
{
|
||||
@@ -193,7 +198,7 @@ namespace boost
|
||||
public:
|
||||
explicit interruption_checker(pthread_mutex_t* cond_mutex,pthread_cond_t* cond):
|
||||
thread_info(detail::get_current_thread_data()),m(cond_mutex),
|
||||
set(thread_info && thread_info->interrupt_enabled)
|
||||
set(thread_info && thread_info->interrupt_enabled), done(false)
|
||||
{
|
||||
if(set)
|
||||
{
|
||||
@@ -208,9 +213,10 @@ namespace boost
|
||||
BOOST_VERIFY(!pthread_mutex_lock(m));
|
||||
}
|
||||
}
|
||||
~interruption_checker()
|
||||
void check()
|
||||
{
|
||||
if(set)
|
||||
if ( ! done) {
|
||||
if (set)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_unlock(m));
|
||||
lock_guard<mutex> guard(thread_info->data_mutex);
|
||||
@@ -221,6 +227,13 @@ namespace boost
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_unlock(m));
|
||||
}
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
|
||||
~interruption_checker() BOOST_NOEXCEPT_IF(false)
|
||||
{
|
||||
check();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
@@ -228,38 +241,42 @@ namespace boost
|
||||
|
||||
namespace this_thread
|
||||
{
|
||||
namespace hiden
|
||||
namespace hidden
|
||||
{
|
||||
void BOOST_THREAD_DECL sleep_for(const timespec& ts);
|
||||
void BOOST_THREAD_DECL sleep_until(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::hiden::sleep_for(boost::detail::to_timespec(ns));
|
||||
return boost::this_thread::hidden::sleep_for(boost::detail::to_timespec(ns));
|
||||
}
|
||||
#endif
|
||||
#endif // BOOST_THREAD_USES_CHRONO
|
||||
|
||||
namespace no_interruption_point
|
||||
{
|
||||
namespace hiden
|
||||
namespace hidden
|
||||
{
|
||||
void BOOST_THREAD_DECL sleep_for(const timespec& ts);
|
||||
void BOOST_THREAD_DECL sleep_until(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::no_interruption_point::hiden::sleep_for(boost::detail::to_timespec(ns));
|
||||
return boost::this_thread::no_interruption_point::hidden::sleep_for(boost::detail::to_timespec(ns));
|
||||
}
|
||||
#endif
|
||||
#endif // BOOST_THREAD_USES_CHRONO
|
||||
@@ -275,7 +292,7 @@ namespace boost
|
||||
#endif
|
||||
inline void sleep(system_time const& abs_time)
|
||||
{
|
||||
return boost::this_thread::hiden::sleep_until(boost::detail::to_timespec(abs_time));
|
||||
return boost::this_thread::hidden::sleep_until_realtime(boost::detail::to_timespec(abs_time));
|
||||
}
|
||||
|
||||
template<typename TimeDuration>
|
||||
|
||||
@@ -16,8 +16,13 @@ namespace boost
|
||||
{
|
||||
return new T();
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) && ! defined (BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
template<typename T,typename... Args>
|
||||
inline T* heap_new(Args&&... args)
|
||||
{
|
||||
return new T(static_cast<Args&&>(args)...);
|
||||
}
|
||||
#elif ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
template<typename T,typename A1>
|
||||
inline T* heap_new(A1&& a1)
|
||||
{
|
||||
@@ -61,6 +66,31 @@ namespace boost
|
||||
{
|
||||
return new T(a1,a2,a3,a4);
|
||||
}
|
||||
template<typename T,typename A1,typename A2,typename A3,typename A4,typename A5>
|
||||
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5)
|
||||
{
|
||||
return new T(a1,a2,a3,a4,a5);
|
||||
}
|
||||
template<typename T,typename A1,typename A2,typename A3,typename A4,typename A5,typename A6>
|
||||
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6)
|
||||
{
|
||||
return new T(a1,a2,a3,a4,a5,a6);
|
||||
}
|
||||
template<typename T,typename A1,typename A2,typename A3,typename A4,typename A5,typename A6,typename A7>
|
||||
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7)
|
||||
{
|
||||
return new T(a1,a2,a3,a4,a5,a6,a7);
|
||||
}
|
||||
template<typename T,typename A1,typename A2,typename A3,typename A4,typename A5,typename A6,typename A7,typename A8>
|
||||
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8)
|
||||
{
|
||||
return new T(a1,a2,a3,a4,a5,a6,a7,a8);
|
||||
}
|
||||
template<typename T,typename A1,typename A2,typename A3,typename A4,typename A5,typename A6,typename A7,typename A8,typename A9>
|
||||
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8,A9 a9)
|
||||
{
|
||||
return new T(a1,a2,a3,a4,a5,a6,a7,a8,a9);
|
||||
}
|
||||
|
||||
template<typename T,typename A1>
|
||||
inline T* heap_new(A1 const& a1)
|
||||
|
||||
@@ -71,7 +71,23 @@ namespace boost
|
||||
{
|
||||
return (ts.tv_sec >= 0) || (ts.tv_nsec >= 0);
|
||||
}
|
||||
inline timespec timespec_now()
|
||||
#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;
|
||||
|
||||
@@ -83,6 +99,8 @@ namespace boost
|
||||
#else
|
||||
if ( ::clock_gettime( CLOCK_REALTIME, &ts ) )
|
||||
{
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 0;
|
||||
BOOST_ASSERT(0 && "Boost::Thread - Internal Error");
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -34,10 +34,10 @@ namespace boost
|
||||
* boost::strict_scoped_thread<> t((boost::thread(F)));
|
||||
*
|
||||
*/
|
||||
template <class CallableThread = join_if_joinable>
|
||||
template <class CallableThread = join_if_joinable, class Thread=::boost::thread>
|
||||
class strict_scoped_thread
|
||||
{
|
||||
thread t_;
|
||||
Thread t_;
|
||||
struct dummy;
|
||||
public:
|
||||
|
||||
@@ -47,13 +47,13 @@ namespace boost
|
||||
*
|
||||
*/
|
||||
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template <class F, class ...Args, typename = typename disable_if<is_same<typename decay<F>::type, thread>, void* >::type>
|
||||
template <class F, class ...Args, typename = typename disable_if<is_same<typename decay<F>::type, Thread>, void* >::type>
|
||||
explicit strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Args)... args) :
|
||||
t_(boost::forward<F>(f), boost::forward<Args>(args)...) {}
|
||||
#else
|
||||
template <class F>
|
||||
explicit strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f,
|
||||
typename disable_if<is_same<typename decay<F>::type, thread>, void* >::type=0) :
|
||||
typename disable_if<is_same<typename decay<F>::type, Thread>, void* >::type=0) :
|
||||
t_(boost::forward<F>(f)) {}
|
||||
template <class F, class A1>
|
||||
strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1) :
|
||||
@@ -73,7 +73,7 @@ namespace boost
|
||||
*
|
||||
* Effects: move the thread to own @c t.
|
||||
*/
|
||||
explicit strict_scoped_thread(BOOST_THREAD_RV_REF(thread) t) BOOST_NOEXCEPT :
|
||||
explicit strict_scoped_thread(BOOST_THREAD_RV_REF(Thread) t) BOOST_NOEXCEPT :
|
||||
t_(boost::move(t))
|
||||
{
|
||||
}
|
||||
@@ -111,14 +111,15 @@ namespace boost
|
||||
* t.interrupt();
|
||||
*
|
||||
*/
|
||||
template <class CallableThread = join_if_joinable>
|
||||
template <class CallableThread = join_if_joinable, class Thread=::boost::thread>
|
||||
class scoped_thread
|
||||
{
|
||||
thread t_;
|
||||
Thread t_;
|
||||
struct dummy;
|
||||
public:
|
||||
|
||||
typedef thread::id id;
|
||||
typedef typename Thread::id id;
|
||||
typedef typename Thread::native_handle_type native_handle_type;
|
||||
|
||||
BOOST_THREAD_MOVABLE_ONLY( scoped_thread) /// Movable only
|
||||
|
||||
@@ -137,13 +138,13 @@ namespace boost
|
||||
*/
|
||||
|
||||
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template <class F, class ...Args, typename = typename disable_if<is_same<typename decay<F>::type, thread>, void* >::type>
|
||||
template <class F, class ...Args, typename = typename disable_if<is_same<typename decay<F>::type, Thread>, void* >::type>
|
||||
explicit scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Args)... args) :
|
||||
t_(boost::forward<F>(f), boost::forward<Args>(args)...) {}
|
||||
#else
|
||||
template <class F>
|
||||
explicit scoped_thread(BOOST_THREAD_FWD_REF(F) f,
|
||||
typename disable_if<is_same<typename decay<F>::type, thread>, void* >::type=0) :
|
||||
typename disable_if<is_same<typename decay<F>::type, Thread>, void* >::type=0) :
|
||||
t_(boost::forward<F>(f)) {}
|
||||
template <class F, class A1>
|
||||
scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1) :
|
||||
@@ -163,12 +164,12 @@ namespace boost
|
||||
*
|
||||
* Effects: move the thread to own @c t.
|
||||
*/
|
||||
explicit scoped_thread(BOOST_THREAD_RV_REF(thread) t) BOOST_NOEXCEPT :
|
||||
explicit scoped_thread(BOOST_THREAD_RV_REF(Thread) t) BOOST_NOEXCEPT :
|
||||
t_(boost::move(t))
|
||||
{
|
||||
}
|
||||
|
||||
// explicit operator thread()
|
||||
// explicit operator Thread()
|
||||
// {
|
||||
// return boost::move(t_);
|
||||
// }
|
||||
@@ -197,6 +198,9 @@ namespace boost
|
||||
*/
|
||||
scoped_thread& operator=(BOOST_RV_REF(scoped_thread) x)
|
||||
{
|
||||
CallableThread on_destructor;
|
||||
|
||||
on_destructor(t_);
|
||||
t_ = boost::move(BOOST_THREAD_RV(x).t_);
|
||||
return *this;
|
||||
}
|
||||
@@ -210,7 +214,7 @@ namespace boost
|
||||
}
|
||||
|
||||
// forwarded thread functions
|
||||
inline thread::id get_id() const BOOST_NOEXCEPT
|
||||
inline id get_id() const BOOST_NOEXCEPT
|
||||
{
|
||||
return t_.get_id();
|
||||
}
|
||||
@@ -239,7 +243,7 @@ namespace boost
|
||||
}
|
||||
#endif
|
||||
|
||||
thread::native_handle_type native_handle()BOOST_NOEXCEPT
|
||||
native_handle_type native_handle()BOOST_NOEXCEPT
|
||||
{
|
||||
return t_.native_handle();
|
||||
}
|
||||
@@ -263,13 +267,13 @@ namespace boost
|
||||
|
||||
static unsigned hardware_concurrency() BOOST_NOEXCEPT
|
||||
{
|
||||
return thread::hardware_concurrency();
|
||||
return Thread::hardware_concurrency();
|
||||
}
|
||||
|
||||
#ifdef BOOST_THREAD_PROVIDES_PHYSICAL_CONCURRENCY
|
||||
static unsigned physical_concurrency() BOOST_NOEXCEPT
|
||||
{
|
||||
return thread::physical_concurrency();
|
||||
return Thread::physical_concurrency();
|
||||
}
|
||||
#endif
|
||||
};
|
||||
@@ -277,12 +281,13 @@ namespace boost
|
||||
/**
|
||||
* Effects: swaps the contents of two scoped threads.
|
||||
*/
|
||||
template <class Destroyer>
|
||||
void swap(scoped_thread<Destroyer>& lhs, scoped_thread<Destroyer>& rhs)
|
||||
template <class Destroyer, class Thread >
|
||||
void swap(scoped_thread<Destroyer, Thread>& lhs, scoped_thread<Destroyer, Thread>& rhs)
|
||||
BOOST_NOEXCEPT {
|
||||
return lhs.swap(rhs);
|
||||
}
|
||||
|
||||
typedef scoped_thread<> joining_thread;
|
||||
}
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
|
||||
@@ -827,7 +827,7 @@ namespace boost
|
||||
* @effects loads the value type from the input stream @c is.
|
||||
*/
|
||||
template <typename IStream>
|
||||
void load(IStream& is) const
|
||||
void load(IStream& is)
|
||||
{
|
||||
strict_lock<mutex_type> lk(mtx_);
|
||||
is >> value_;
|
||||
@@ -971,22 +971,22 @@ namespace boost
|
||||
template <typename T, typename L>
|
||||
bool operator<(T const& lhs, synchronized_value<T,L> const&rhs)
|
||||
{
|
||||
return rhs>=lhs;
|
||||
return rhs>lhs;
|
||||
}
|
||||
template <typename T, typename L>
|
||||
bool operator<=(T const& lhs, synchronized_value<T,L> const&rhs)
|
||||
{
|
||||
return rhs>lhs;
|
||||
return rhs>=lhs;
|
||||
}
|
||||
template <typename T, typename L>
|
||||
bool operator>(T const& lhs, synchronized_value<T,L> const&rhs)
|
||||
{
|
||||
return rhs<=lhs;
|
||||
return rhs<lhs;
|
||||
}
|
||||
template <typename T, typename L>
|
||||
bool operator>=(T const& lhs, synchronized_value<T,L> const&rhs)
|
||||
{
|
||||
return rhs<lhs;
|
||||
return rhs<=lhs;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -999,7 +999,7 @@ namespace boost
|
||||
return os;
|
||||
}
|
||||
template <typename IStream, typename T, typename L>
|
||||
inline IStream& operator>>(IStream& is, synchronized_value<T,L> const& rhs)
|
||||
inline IStream& operator>>(IStream& is, synchronized_value<T,L>& rhs)
|
||||
{
|
||||
rhs.load(is);
|
||||
return is;
|
||||
|
||||
@@ -21,15 +21,29 @@ namespace boost
|
||||
|
||||
struct detach
|
||||
{
|
||||
void operator()(thread& t)
|
||||
template <class Thread>
|
||||
void operator()(Thread& t)
|
||||
{
|
||||
t.detach();
|
||||
}
|
||||
};
|
||||
|
||||
struct detach_if_joinable
|
||||
{
|
||||
template <class Thread>
|
||||
void operator()(Thread& t)
|
||||
{
|
||||
if (t.joinable())
|
||||
{
|
||||
t.detach();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct join_if_joinable
|
||||
{
|
||||
void operator()(thread& t)
|
||||
template <class Thread>
|
||||
void operator()(Thread& t)
|
||||
{
|
||||
if (t.joinable())
|
||||
{
|
||||
@@ -41,11 +55,12 @@ namespace boost
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
struct interrupt_and_join_if_joinable
|
||||
{
|
||||
void operator()(thread& t)
|
||||
template <class Thread>
|
||||
void operator()(Thread& t)
|
||||
{
|
||||
t.interrupt();
|
||||
if (t.joinable())
|
||||
{
|
||||
t.interrupt();
|
||||
t.join();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,14 +21,14 @@ namespace boost
|
||||
/**
|
||||
* Non-copyable RAII scoped thread guard joiner which join the thread if joinable when destroyed.
|
||||
*/
|
||||
template <class CallableThread = join_if_joinable>
|
||||
template <class CallableThread = join_if_joinable, class Thread=::boost::thread>
|
||||
class thread_guard
|
||||
{
|
||||
thread& t_;
|
||||
Thread& t_;
|
||||
public:
|
||||
BOOST_THREAD_NO_COPYABLE( thread_guard)
|
||||
|
||||
explicit thread_guard(thread& t) :
|
||||
explicit thread_guard(Thread& t) :
|
||||
t_(t)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace boost
|
||||
class user_scheduler
|
||||
{
|
||||
/// type-erasure to store the works to do
|
||||
typedef thread_detail::work work;
|
||||
typedef executors::work work;
|
||||
|
||||
/// the thread safe work queue
|
||||
sync_queue<work > work_queue;
|
||||
|
||||
@@ -44,13 +44,13 @@ namespace boost
|
||||
|
||||
bool try_lock() BOOST_NOEXCEPT
|
||||
{
|
||||
long const current_thread_id=win32::GetCurrentThreadId();
|
||||
long const current_thread_id=boost::detail::winapi::GetCurrentThreadId();
|
||||
return try_recursive_lock(current_thread_id) || try_basic_lock(current_thread_id);
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
long const current_thread_id=win32::GetCurrentThreadId();
|
||||
long const current_thread_id=boost::detail::winapi::GetCurrentThreadId();
|
||||
if(!try_recursive_lock(current_thread_id))
|
||||
{
|
||||
mutex.lock();
|
||||
@@ -61,7 +61,7 @@ namespace boost
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
bool timed_lock(::boost::system_time const& target)
|
||||
{
|
||||
long const current_thread_id=win32::GetCurrentThreadId();
|
||||
long const current_thread_id=boost::detail::winapi::GetCurrentThreadId();
|
||||
return try_recursive_lock(current_thread_id) || try_timed_lock(current_thread_id,target);
|
||||
}
|
||||
template<typename Duration>
|
||||
@@ -75,13 +75,13 @@ namespace boost
|
||||
template <class Rep, class Period>
|
||||
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
|
||||
{
|
||||
long const current_thread_id=win32::GetCurrentThreadId();
|
||||
long const current_thread_id=boost::detail::winapi::GetCurrentThreadId();
|
||||
return try_recursive_lock(current_thread_id) || try_timed_lock_for(current_thread_id,rel_time);
|
||||
}
|
||||
template <class Clock, class Duration>
|
||||
bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
long const current_thread_id=win32::GetCurrentThreadId();
|
||||
long const current_thread_id=boost::detail::winapi::GetCurrentThreadId();
|
||||
return try_recursive_lock(current_thread_id) || try_timed_lock_until(current_thread_id,t);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace boost
|
||||
#endif
|
||||
if(old_event)
|
||||
{
|
||||
win32::CloseHandle(old_event);
|
||||
winapi::CloseHandle(old_event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,9 +81,9 @@ namespace boost
|
||||
|
||||
do
|
||||
{
|
||||
unsigned const retval(win32::WaitForSingleObjectEx(sem, ::boost::detail::win32::infinite,0));
|
||||
unsigned const retval(winapi::WaitForSingleObjectEx(sem, ::boost::detail::win32::infinite,0));
|
||||
BOOST_VERIFY(0 == retval || ::boost::detail::win32::wait_abandoned == retval);
|
||||
// BOOST_VERIFY(win32::WaitForSingleObject(
|
||||
// BOOST_VERIFY(winapi::WaitForSingleObject(
|
||||
// sem,::boost::detail::win32::infinite)==0);
|
||||
clear_waiting_and_try_lock(old_count);
|
||||
lock_acquired=!(old_count&lock_flag_value);
|
||||
@@ -142,7 +142,7 @@ namespace boost
|
||||
|
||||
do
|
||||
{
|
||||
if(win32::WaitForSingleObjectEx(sem,::boost::detail::get_milliseconds_until(wait_until),0)!=0)
|
||||
if(winapi::WaitForSingleObjectEx(sem,::boost::detail::get_milliseconds_until(wait_until),0)!=0)
|
||||
{
|
||||
BOOST_INTERLOCKED_DECREMENT(&active_count);
|
||||
return false;
|
||||
@@ -210,7 +210,7 @@ namespace boost
|
||||
}
|
||||
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-now);
|
||||
|
||||
if(win32::WaitForSingleObjectEx(sem,static_cast<unsigned long>(rel_time.count()),0)!=0)
|
||||
if(winapi::WaitForSingleObjectEx(sem,static_cast<unsigned long>(rel_time.count()),0)!=0)
|
||||
{
|
||||
BOOST_INTERLOCKED_DECREMENT(&active_count);
|
||||
return false;
|
||||
@@ -232,7 +232,7 @@ namespace boost
|
||||
{
|
||||
if(!win32::interlocked_bit_test_and_set(&active_count,event_set_flag_bit))
|
||||
{
|
||||
win32::SetEvent(get_event());
|
||||
winapi::SetEvent(get_event());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -256,7 +256,7 @@ namespace boost
|
||||
#endif
|
||||
if(old_event!=0)
|
||||
{
|
||||
win32::CloseHandle(new_event);
|
||||
winapi::CloseHandle(new_event);
|
||||
return old_event;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace boost
|
||||
void release(unsigned count_to_release)
|
||||
{
|
||||
notified=true;
|
||||
detail::win32::ReleaseSemaphore(semaphore,count_to_release,0);
|
||||
detail::winapi::ReleaseSemaphore(semaphore,count_to_release,0);
|
||||
}
|
||||
|
||||
void release_waiters()
|
||||
@@ -96,7 +96,7 @@ namespace boost
|
||||
|
||||
bool woken()
|
||||
{
|
||||
unsigned long const woken_result=detail::win32::WaitForSingleObjectEx(wake_sem,0,0);
|
||||
unsigned long const woken_result=detail::winapi::WaitForSingleObjectEx(wake_sem,0,0);
|
||||
BOOST_ASSERT((woken_result==detail::win32::timeout) || (woken_result==0));
|
||||
return woken_result==0;
|
||||
}
|
||||
@@ -135,39 +135,45 @@ namespace boost
|
||||
void wake_waiters(long count_to_wake)
|
||||
{
|
||||
detail::interlocked_write_release(&total_count,total_count-count_to_wake);
|
||||
detail::win32::ReleaseSemaphore(wake_sem,count_to_wake,0);
|
||||
detail::winapi::ReleaseSemaphore(wake_sem,count_to_wake,0);
|
||||
}
|
||||
|
||||
template<typename lock_type>
|
||||
struct relocker
|
||||
{
|
||||
BOOST_THREAD_NO_COPYABLE(relocker)
|
||||
lock_type& lock;
|
||||
bool unlocked;
|
||||
lock_type& _lock;
|
||||
bool _unlocked;
|
||||
|
||||
relocker(lock_type& lock_):
|
||||
lock(lock_),unlocked(false)
|
||||
_lock(lock_), _unlocked(false)
|
||||
{}
|
||||
void unlock()
|
||||
{
|
||||
lock.unlock();
|
||||
unlocked=true;
|
||||
if ( ! _unlocked )
|
||||
{
|
||||
_lock.unlock();
|
||||
_unlocked=true;
|
||||
}
|
||||
}
|
||||
~relocker()
|
||||
void lock()
|
||||
{
|
||||
if(unlocked)
|
||||
{
|
||||
lock.lock();
|
||||
}
|
||||
|
||||
if ( _unlocked )
|
||||
{
|
||||
_lock.lock();
|
||||
_unlocked=false;
|
||||
}
|
||||
}
|
||||
~relocker() BOOST_NOEXCEPT_IF(false)
|
||||
{
|
||||
lock();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
entry_ptr get_wait_entry()
|
||||
{
|
||||
boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
|
||||
|
||||
boost::lock_guard<boost::mutex> lk(internal_mutex);
|
||||
if(!wake_sem)
|
||||
{
|
||||
wake_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
|
||||
@@ -190,18 +196,32 @@ namespace boost
|
||||
|
||||
struct entry_manager
|
||||
{
|
||||
entry_ptr const entry;
|
||||
entry_ptr entry;
|
||||
boost::mutex& internal_mutex;
|
||||
|
||||
|
||||
BOOST_THREAD_NO_COPYABLE(entry_manager)
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
entry_manager(entry_ptr&& entry_, boost::mutex& mutex_):
|
||||
entry(static_cast< entry_ptr&& >(entry_)), internal_mutex(mutex_)
|
||||
{}
|
||||
#else
|
||||
entry_manager(entry_ptr const& entry_, boost::mutex& mutex_):
|
||||
entry(entry_), internal_mutex(mutex_)
|
||||
{}
|
||||
#endif
|
||||
|
||||
~entry_manager()
|
||||
void remove_waiter_and_reset()
|
||||
{
|
||||
if (entry) {
|
||||
boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
|
||||
entry->remove_waiter();
|
||||
entry.reset();
|
||||
}
|
||||
}
|
||||
~entry_manager() BOOST_NOEXCEPT_IF(false)
|
||||
{
|
||||
remove_waiter_and_reset();
|
||||
}
|
||||
|
||||
list_entry* operator->()
|
||||
@@ -215,23 +235,24 @@ namespace boost
|
||||
template<typename lock_type>
|
||||
bool do_wait(lock_type& lock,timeout abs_time)
|
||||
{
|
||||
relocker<lock_type> locker(lock);
|
||||
relocker<lock_type> locker(lock);
|
||||
entry_manager entry(get_wait_entry(), internal_mutex);
|
||||
locker.unlock();
|
||||
|
||||
entry_manager entry(get_wait_entry(), internal_mutex);
|
||||
bool woken=false;
|
||||
while(!woken)
|
||||
{
|
||||
if(!entry->wait(abs_time))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
locker.unlock();
|
||||
|
||||
bool woken=false;
|
||||
while(!woken)
|
||||
{
|
||||
if(!entry->wait(abs_time))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
woken=entry->woken();
|
||||
}
|
||||
return woken;
|
||||
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>
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
//
|
||||
// (C) Copyright 2005-8 Anthony Williams
|
||||
// (C) Copyright 2012 Vicente J. Botet Escriba
|
||||
// (C) Copyright 2017 Andrey Semashev
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -15,36 +16,172 @@
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
// Define compiler barriers
|
||||
#if defined(__INTEL_COMPILER)
|
||||
#define BOOST_THREAD_DETAIL_COMPILER_BARRIER() __memory_barrier()
|
||||
#elif defined(_MSC_VER) && !defined(_WIN32_WCE)
|
||||
extern "C" void _ReadWriteBarrier(void);
|
||||
#pragma intrinsic(_ReadWriteBarrier)
|
||||
#define BOOST_THREAD_DETAIL_COMPILER_BARRIER() _ReadWriteBarrier()
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_THREAD_DETAIL_COMPILER_BARRIER
|
||||
#define BOOST_THREAD_DETAIL_COMPILER_BARRIER()
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
|
||||
|
||||
// Since VS2005 and until VS2012 volatile reads always acquire and volatile writes are always release.
|
||||
// But VS2012 adds a compiler switch that can change behavior to the standard. On x86 though
|
||||
// the compiler generates a single instruction for the load/store, which is enough synchronization
|
||||
// as far as uarch is concerned. To prevent compiler reordering code around the load/store we add
|
||||
// compiler barriers.
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
// Since VS2005 volatile reads always acquire
|
||||
inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
|
||||
{
|
||||
long const res=*x;
|
||||
BOOST_THREAD_DETAIL_COMPILER_BARRIER();
|
||||
return res;
|
||||
}
|
||||
inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
|
||||
{
|
||||
void* const res=*x;
|
||||
BOOST_THREAD_DETAIL_COMPILER_BARRIER();
|
||||
return res;
|
||||
}
|
||||
|
||||
// Since VS2005 volatile writes always release
|
||||
inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_THREAD_DETAIL_COMPILER_BARRIER();
|
||||
*x=value;
|
||||
}
|
||||
inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_THREAD_DETAIL_COMPILER_BARRIER();
|
||||
*x=value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(_MSC_VER) && _MSC_VER >= 1700 && (defined(_M_ARM) || defined(_M_ARM64))
|
||||
|
||||
#include <intrin.h>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
|
||||
{
|
||||
long const res=__iso_volatile_load32((const volatile __int32*)x);
|
||||
BOOST_THREAD_DETAIL_COMPILER_BARRIER();
|
||||
__dmb(0xB); // _ARM_BARRIER_ISH, see armintr.h from MSVC 11 and later
|
||||
BOOST_THREAD_DETAIL_COMPILER_BARRIER();
|
||||
return res;
|
||||
}
|
||||
inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
|
||||
{
|
||||
void* const res=
|
||||
#if defined(_M_ARM64)
|
||||
__iso_volatile_load64((const volatile __int64*)x);
|
||||
#else
|
||||
__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
|
||||
BOOST_THREAD_DETAIL_COMPILER_BARRIER();
|
||||
return res;
|
||||
}
|
||||
|
||||
inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_THREAD_DETAIL_COMPILER_BARRIER();
|
||||
__dmb(0xB); // _ARM_BARRIER_ISH, see armintr.h from MSVC 11 and later
|
||||
BOOST_THREAD_DETAIL_COMPILER_BARRIER();
|
||||
__iso_volatile_store32((volatile __int32*)x, (__int32)value);
|
||||
}
|
||||
inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_THREAD_DETAIL_COMPILER_BARRIER();
|
||||
__dmb(0xB); // _ARM_BARRIER_ISH, see armintr.h from MSVC 11 and later
|
||||
BOOST_THREAD_DETAIL_COMPILER_BARRIER();
|
||||
#if defined(_M_ARM64)
|
||||
__iso_volatile_store64((volatile __int64*)x, (__int64)value);
|
||||
#else
|
||||
__iso_volatile_store32((volatile __int32*)x, (__int32)value);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(__GNUC__) && (((__GNUC__ * 100 + __GNUC_MINOR__) >= 407) || (defined(__clang__) && (__clang_major__ * 100 + __clang_minor__) >= 302))
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
|
||||
{
|
||||
return __atomic_load_n((long*)x, __ATOMIC_ACQUIRE);
|
||||
}
|
||||
inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
|
||||
{
|
||||
return __atomic_load_n((void**)x, __ATOMIC_ACQUIRE);
|
||||
}
|
||||
|
||||
inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
|
||||
{
|
||||
__atomic_store_n((long*)x, value, __ATOMIC_RELEASE);
|
||||
}
|
||||
inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
|
||||
{
|
||||
__atomic_store_n((void**)x, value, __ATOMIC_RELEASE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
|
||||
{
|
||||
long res;
|
||||
__asm__ __volatile__ ("movl %1, %0" : "=r" (res) : "m" (*x) : "memory");
|
||||
return res;
|
||||
}
|
||||
inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
|
||||
{
|
||||
void* res;
|
||||
#if defined(__x86_64__)
|
||||
__asm__ __volatile__ ("movq %1, %0" : "=r" (res) : "m" (*x) : "memory");
|
||||
#else
|
||||
__asm__ __volatile__ ("movl %1, %0" : "=r" (res) : "m" (*x) : "memory");
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
|
||||
{
|
||||
__asm__ __volatile__ ("movl %1, %0" : "=m" (*x) : "r" (value) : "memory");
|
||||
}
|
||||
inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
|
||||
{
|
||||
#if defined(__x86_64__)
|
||||
__asm__ __volatile__ ("movq %1, %0" : "=m" (*x) : "r" (value) : "memory");
|
||||
#else
|
||||
__asm__ __volatile__ ("movl %1, %0" : "=m" (*x) : "r" (value) : "memory");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
namespace boost
|
||||
@@ -53,19 +190,19 @@ namespace boost
|
||||
{
|
||||
inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
|
||||
{
|
||||
return BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,0,0);
|
||||
return BOOST_INTERLOCKED_COMPARE_EXCHANGE((long*)x,0,0);
|
||||
}
|
||||
inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
|
||||
{
|
||||
return BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(x,0,0);
|
||||
return BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER((void**)x,0,0);
|
||||
}
|
||||
inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_INTERLOCKED_EXCHANGE(x,value);
|
||||
BOOST_INTERLOCKED_EXCHANGE((long*)x,value);
|
||||
}
|
||||
inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_INTERLOCKED_EXCHANGE_POINTER(x,value);
|
||||
BOOST_INTERLOCKED_EXCHANGE_POINTER((void**)x,value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ namespace boost
|
||||
std::memcpy(mutex_name,fixed_mutex_name,sizeof(fixed_mutex_name));
|
||||
detail::int_to_string(reinterpret_cast<std::ptrdiff_t>(flag_address),
|
||||
mutex_name + once_mutex_name_fixed_length);
|
||||
detail::int_to_string(win32::GetCurrentProcessId(),
|
||||
detail::int_to_string(winapi::GetCurrentProcessId(),
|
||||
mutex_name + once_mutex_name_fixed_length + sizeof(void*)*2);
|
||||
}
|
||||
|
||||
@@ -136,9 +136,9 @@ namespace boost
|
||||
}
|
||||
|
||||
#ifdef BOOST_NO_ANSI_APIS
|
||||
return ::boost::detail::win32::OpenEventW(
|
||||
return ::boost::detail::winapi::OpenEventW(
|
||||
#else
|
||||
return ::boost::detail::win32::OpenEventA(
|
||||
return ::boost::detail::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::win32::ResetEvent(ctx.event_handle);
|
||||
::boost::detail::winapi::ResetEvent(ctx.event_handle);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -207,7 +207,7 @@ namespace boost
|
||||
}
|
||||
if(ctx.event_handle)
|
||||
{
|
||||
::boost::detail::win32::SetEvent(ctx.event_handle);
|
||||
::boost::detail::winapi::SetEvent(ctx.event_handle);
|
||||
}
|
||||
}
|
||||
inline void rollback_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT
|
||||
@@ -219,7 +219,7 @@ namespace boost
|
||||
}
|
||||
if(ctx.event_handle)
|
||||
{
|
||||
::boost::detail::win32::SetEvent(ctx.event_handle);
|
||||
::boost::detail::winapi::SetEvent(ctx.event_handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -264,7 +264,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite, 0));
|
||||
}
|
||||
}
|
||||
@@ -308,7 +308,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -355,7 +355,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -400,7 +400,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -443,7 +443,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -486,7 +486,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -529,7 +529,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -574,7 +574,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -617,7 +617,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -660,7 +660,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -703,7 +703,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -748,7 +748,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -793,7 +793,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -839,7 +839,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -886,7 +886,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -930,7 +930,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -977,7 +977,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -1024,7 +1024,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
@@ -1073,7 +1073,7 @@ namespace boost
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
|
||||
BOOST_VERIFY(!::boost::detail::winapi::WaitForSingleObjectEx(
|
||||
ctx.event_handle,::boost::detail::win32::infinite,0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,19 +67,19 @@ namespace boost
|
||||
{
|
||||
if(old_state.exclusive_waiting)
|
||||
{
|
||||
BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[exclusive_sem],1,0)!=0);
|
||||
BOOST_VERIFY(detail::winapi::ReleaseSemaphore(semaphores[exclusive_sem],1,0)!=0);
|
||||
}
|
||||
|
||||
if(old_state.shared_waiting || old_state.exclusive_waiting)
|
||||
{
|
||||
BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
|
||||
BOOST_VERIFY(detail::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::win32::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
|
||||
BOOST_VERIFY(detail::winapi::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,9 +107,9 @@ namespace boost
|
||||
|
||||
~shared_mutex()
|
||||
{
|
||||
detail::win32::CloseHandle(upgrade_sem);
|
||||
detail::win32::CloseHandle(semaphores[unlock_sem]);
|
||||
detail::win32::CloseHandle(semaphores[exclusive_sem]);
|
||||
detail::winapi::CloseHandle(upgrade_sem);
|
||||
detail::winapi::CloseHandle(semaphores[unlock_sem]);
|
||||
detail::winapi::CloseHandle(semaphores[exclusive_sem]);
|
||||
}
|
||||
|
||||
bool try_lock_shared()
|
||||
@@ -191,7 +191,7 @@ namespace boost
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned long const res=detail::win32::WaitForSingleObjectEx(semaphores[unlock_sem],::boost::detail::get_milliseconds_until(wait_until), 0);
|
||||
unsigned long const res=detail::winapi::WaitForSingleObjectEx(semaphores[unlock_sem],::boost::detail::get_milliseconds_until(wait_until), 0);
|
||||
if(res==detail::win32::timeout)
|
||||
{
|
||||
for(;;)
|
||||
@@ -296,7 +296,7 @@ namespace boost
|
||||
unsigned long res;
|
||||
if (tp>n) {
|
||||
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-n);
|
||||
res=detail::win32::WaitForSingleObjectEx(semaphores[unlock_sem],
|
||||
res=detail::winapi::WaitForSingleObjectEx(semaphores[unlock_sem],
|
||||
static_cast<unsigned long>(rel_time.count()), 0);
|
||||
} else {
|
||||
res=detail::win32::timeout;
|
||||
@@ -375,7 +375,7 @@ namespace boost
|
||||
{
|
||||
if(old_state.upgrade)
|
||||
{
|
||||
BOOST_VERIFY(detail::win32::ReleaseSemaphore(upgrade_sem,1,0)!=0);
|
||||
BOOST_VERIFY(detail::winapi::ReleaseSemaphore(upgrade_sem,1,0)!=0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -474,7 +474,7 @@ namespace boost
|
||||
#else
|
||||
const bool wait_all = false;
|
||||
#endif
|
||||
unsigned long const wait_res=detail::win32::WaitForMultipleObjectsEx(2,semaphores,wait_all,::boost::detail::get_milliseconds_until(wait_until), 0);
|
||||
unsigned long const wait_res=detail::winapi::WaitForMultipleObjectsEx(2,semaphores,wait_all,::boost::detail::get_milliseconds_until(wait_until), 0);
|
||||
if(wait_res==detail::win32::timeout)
|
||||
{
|
||||
for(;;)
|
||||
@@ -500,7 +500,7 @@ namespace boost
|
||||
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
|
||||
if (must_notify)
|
||||
{
|
||||
BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],1,0)!=0);
|
||||
BOOST_VERIFY(detail::winapi::ReleaseSemaphore(semaphores[unlock_sem],1,0)!=0);
|
||||
}
|
||||
|
||||
if(current_state==old_state)
|
||||
@@ -586,7 +586,7 @@ namespace boost
|
||||
unsigned long wait_res;
|
||||
if (tp>n) {
|
||||
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now());
|
||||
wait_res=detail::win32::WaitForMultipleObjectsEx(2,semaphores,wait_all,
|
||||
wait_res=detail::winapi::WaitForMultipleObjectsEx(2,semaphores,wait_all,
|
||||
static_cast<unsigned long>(rel_time.count()), 0);
|
||||
} else {
|
||||
wait_res=detail::win32::timeout;
|
||||
@@ -616,7 +616,7 @@ namespace boost
|
||||
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
|
||||
if (must_notify)
|
||||
{
|
||||
BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],1,0)!=0);
|
||||
BOOST_VERIFY(detail::winapi::ReleaseSemaphore(semaphores[unlock_sem],1,0)!=0);
|
||||
}
|
||||
if(current_state==old_state)
|
||||
{
|
||||
@@ -698,7 +698,7 @@ namespace boost
|
||||
return;
|
||||
}
|
||||
|
||||
BOOST_VERIFY(!detail::win32::WaitForSingleObjectEx(semaphores[unlock_sem],detail::win32::infinite, 0));
|
||||
BOOST_VERIFY(!detail::winapi::WaitForSingleObjectEx(semaphores[unlock_sem],detail::winapi::infinite, 0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -790,7 +790,7 @@ namespace boost
|
||||
{
|
||||
if(!last_reader)
|
||||
{
|
||||
BOOST_VERIFY(!detail::win32::WaitForSingleObjectEx(upgrade_sem,detail::win32::infinite, 0));
|
||||
BOOST_VERIFY(!detail::winapi::WaitForSingleObjectEx(upgrade_sem,detail::win32::infinite, 0));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ namespace boost
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
void interrupt()
|
||||
{
|
||||
BOOST_VERIFY(detail::win32::SetEvent(interruption_handle)!=0);
|
||||
BOOST_VERIFY(detail::winapi::SetEvent(interruption_handle)!=0);
|
||||
}
|
||||
#endif
|
||||
typedef detail::win32::handle native_handle_type;
|
||||
|
||||
@@ -12,45 +12,7 @@
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/core/no_exceptions_support.hpp>
|
||||
|
||||
#if defined( BOOST_USE_WINDOWS_H )
|
||||
# include <windows.h>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
namespace win32
|
||||
{
|
||||
using ::GetProcessHeap;
|
||||
using ::HeapAlloc;
|
||||
using ::HeapFree;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
# ifdef HeapAlloc
|
||||
# undef HeapAlloc
|
||||
# endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
namespace win32
|
||||
{
|
||||
extern "C"
|
||||
{
|
||||
__declspec(dllimport) handle __stdcall GetProcessHeap();
|
||||
__declspec(dllimport) void* __stdcall HeapAlloc(handle,unsigned long,ulong_ptr);
|
||||
__declspec(dllimport) int __stdcall HeapFree(handle,unsigned long,void*);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#include <boost/detail/winapi/heap_memory.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
@@ -60,7 +22,7 @@ namespace boost
|
||||
{
|
||||
inline void* allocate_raw_heap_memory(unsigned size)
|
||||
{
|
||||
void* const heap_memory=detail::win32::HeapAlloc(detail::win32::GetProcessHeap(),0,size);
|
||||
void* const heap_memory=detail::winapi::HeapAlloc(detail::winapi::GetProcessHeap(),0,size);
|
||||
if(!heap_memory)
|
||||
{
|
||||
boost::throw_exception(std::bad_alloc());
|
||||
@@ -70,9 +32,26 @@ namespace boost
|
||||
|
||||
inline void free_raw_heap_memory(void* heap_memory)
|
||||
{
|
||||
BOOST_VERIFY(detail::win32::HeapFree(detail::win32::GetProcessHeap(),0,heap_memory)!=0);
|
||||
BOOST_VERIFY(detail::winapi::HeapFree(detail::winapi::GetProcessHeap(),0,heap_memory)!=0);
|
||||
}
|
||||
|
||||
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) && ! defined (BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
template<typename T,typename... Args>
|
||||
inline T* heap_new(Args&&... args)
|
||||
{
|
||||
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
|
||||
BOOST_TRY
|
||||
{
|
||||
T* const data=new (heap_memory) T(static_cast<Args&&>(args)...);
|
||||
return data;
|
||||
}
|
||||
BOOST_CATCH(...)
|
||||
{
|
||||
free_raw_heap_memory(heap_memory);
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
#else
|
||||
template<typename T>
|
||||
inline T* heap_new()
|
||||
{
|
||||
@@ -225,6 +204,86 @@ namespace boost
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
template<typename T,typename A1,typename A2,typename A3,typename A4,typename A5>
|
||||
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5)
|
||||
{
|
||||
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
|
||||
BOOST_TRY
|
||||
{
|
||||
T* const data=new (heap_memory) T(a1,a2,a3,a4,a5);
|
||||
return data;
|
||||
}
|
||||
BOOST_CATCH(...)
|
||||
{
|
||||
free_raw_heap_memory(heap_memory);
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
template<typename T,typename A1,typename A2,typename A3,typename A4,typename A5,typename A6>
|
||||
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6)
|
||||
{
|
||||
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
|
||||
BOOST_TRY
|
||||
{
|
||||
T* const data=new (heap_memory) T(a1,a2,a3,a4,a5,a6);
|
||||
return data;
|
||||
}
|
||||
BOOST_CATCH(...)
|
||||
{
|
||||
free_raw_heap_memory(heap_memory);
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
template<typename T,typename A1,typename A2,typename A3,typename A4,typename A5,typename A6,typename A7>
|
||||
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7)
|
||||
{
|
||||
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
|
||||
BOOST_TRY
|
||||
{
|
||||
T* const data=new (heap_memory) T(a1,a2,a3,a4,a5,a6,a7);
|
||||
return data;
|
||||
}
|
||||
BOOST_CATCH(...)
|
||||
{
|
||||
free_raw_heap_memory(heap_memory);
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
template<typename T,typename A1,typename A2,typename A3,typename A4,typename A5,typename A6,typename A7,typename A8>
|
||||
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8)
|
||||
{
|
||||
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
|
||||
BOOST_TRY
|
||||
{
|
||||
T* const data=new (heap_memory) T(a1,a2,a3,a4,a5,a6,a7,a8);
|
||||
return data;
|
||||
}
|
||||
BOOST_CATCH(...)
|
||||
{
|
||||
free_raw_heap_memory(heap_memory);
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
template<typename T,typename A1,typename A2,typename A3,typename A4,typename A5,typename A6,typename A7,typename A8,typename A9>
|
||||
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8,A9 a9)
|
||||
{
|
||||
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
|
||||
BOOST_TRY
|
||||
{
|
||||
T* const data=new (heap_memory) T(a1,a2,a3,a4,a5,a6,a7,a8,a9);
|
||||
return data;
|
||||
}
|
||||
BOOST_CATCH(...)
|
||||
{
|
||||
free_raw_heap_memory(heap_memory);
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
|
||||
|
||||
template<typename T,typename A1>
|
||||
@@ -384,6 +443,7 @@ namespace boost
|
||||
return heap_new_impl<T,A1&,A2&,A3&,A4&>(a1,a2,a3,a4);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
template<typename T>
|
||||
inline void heap_delete(T* data)
|
||||
|
||||
@@ -16,207 +16,53 @@
|
||||
#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/detail/winapi/synchronization.hpp>
|
||||
#include <boost/thread/win32/interlocked_read.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
#include <thread>
|
||||
#endif
|
||||
|
||||
#if defined( BOOST_USE_WINDOWS_H )
|
||||
# include <windows.h>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
namespace win32
|
||||
{
|
||||
typedef HANDLE handle;
|
||||
typedef SYSTEM_INFO system_info;
|
||||
typedef ::boost::detail::winapi::HANDLE_ handle;
|
||||
typedef ::boost::detail::winapi::SYSTEM_INFO_ system_info;
|
||||
typedef unsigned __int64 ticks_type;
|
||||
typedef FARPROC farproc_t;
|
||||
unsigned const infinite=INFINITE;
|
||||
unsigned const timeout=WAIT_TIMEOUT;
|
||||
handle const invalid_handle_value=INVALID_HANDLE_VALUE;
|
||||
unsigned const event_modify_state=EVENT_MODIFY_STATE;
|
||||
unsigned const synchronize=SYNCHRONIZE;
|
||||
unsigned const wait_abandoned=WAIT_ABANDONED;
|
||||
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_;
|
||||
unsigned const create_event_initial_set = 0x00000002;
|
||||
unsigned const create_event_manual_reset = 0x00000001;
|
||||
unsigned const event_all_access = EVENT_ALL_ACCESS;
|
||||
unsigned const semaphore_all_access = SEMAPHORE_ALL_ACCESS;
|
||||
|
||||
|
||||
# ifdef BOOST_NO_ANSI_APIS
|
||||
# if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA
|
||||
using ::CreateMutexW;
|
||||
using ::CreateEventW;
|
||||
using ::CreateSemaphoreW;
|
||||
# else
|
||||
using ::CreateMutexExW;
|
||||
using ::CreateEventExW;
|
||||
using ::CreateSemaphoreExW;
|
||||
# endif
|
||||
using ::OpenEventW;
|
||||
using ::GetModuleHandleW;
|
||||
# else
|
||||
using ::CreateMutexA;
|
||||
using ::CreateEventA;
|
||||
using ::OpenEventA;
|
||||
using ::CreateSemaphoreA;
|
||||
using ::GetModuleHandleA;
|
||||
# endif
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
using ::GetNativeSystemInfo;
|
||||
using ::GetTickCount64;
|
||||
#else
|
||||
using ::GetSystemInfo;
|
||||
using ::GetTickCount;
|
||||
#endif
|
||||
using ::CloseHandle;
|
||||
using ::ReleaseMutex;
|
||||
using ::ReleaseSemaphore;
|
||||
using ::SetEvent;
|
||||
using ::ResetEvent;
|
||||
using ::WaitForMultipleObjectsEx;
|
||||
using ::WaitForSingleObjectEx;
|
||||
using ::GetCurrentProcessId;
|
||||
using ::GetCurrentThreadId;
|
||||
using ::GetCurrentThread;
|
||||
using ::GetCurrentProcess;
|
||||
using ::DuplicateHandle;
|
||||
#if !BOOST_PLAT_WINDOWS_RUNTIME
|
||||
using ::SleepEx;
|
||||
using ::Sleep;
|
||||
using ::QueueUserAPC;
|
||||
using ::GetProcAddress;
|
||||
#endif
|
||||
unsigned const event_all_access = ::boost::detail::winapi::EVENT_ALL_ACCESS_;
|
||||
unsigned const semaphore_all_access = boost::detail::winapi::SEMAPHORE_ALL_ACCESS_;
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ )
|
||||
|
||||
# ifdef UNDER_CE
|
||||
# ifndef WINAPI
|
||||
# ifndef _WIN32_WCE_EMULATION
|
||||
# define WINAPI __cdecl // Note this doesn't match the desktop definition
|
||||
# else
|
||||
# define WINAPI __stdcall
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
typedef int BOOL;
|
||||
typedef unsigned long DWORD;
|
||||
typedef void* HANDLE;
|
||||
# include <kfuncs.h>
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
struct _SYSTEM_INFO;
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
namespace win32
|
||||
{
|
||||
# ifdef _WIN64
|
||||
typedef unsigned __int64 ulong_ptr;
|
||||
# else
|
||||
typedef unsigned long ulong_ptr;
|
||||
# endif
|
||||
typedef void* handle;
|
||||
typedef _SYSTEM_INFO system_info;
|
||||
typedef unsigned __int64 ticks_type;
|
||||
typedef int (__stdcall *farproc_t)();
|
||||
unsigned const infinite=~0U;
|
||||
unsigned const timeout=258U;
|
||||
handle const invalid_handle_value=(handle)(-1);
|
||||
unsigned const event_modify_state=2;
|
||||
unsigned const synchronize=0x100000u;
|
||||
unsigned const wait_abandoned=0x00000080u;
|
||||
unsigned const create_event_initial_set = 0x00000002;
|
||||
unsigned const create_event_manual_reset = 0x00000001;
|
||||
unsigned const event_all_access = 0x1F0003;
|
||||
unsigned const semaphore_all_access = 0x1F0003;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
struct _SECURITY_ATTRIBUTES;
|
||||
# ifdef BOOST_NO_ANSI_APIS
|
||||
# if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA
|
||||
__declspec(dllimport) void* __stdcall CreateMutexW(_SECURITY_ATTRIBUTES*,int,wchar_t const*);
|
||||
__declspec(dllimport) void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*);
|
||||
__declspec(dllimport) void* __stdcall CreateEventW(_SECURITY_ATTRIBUTES*,int,int,wchar_t const*);
|
||||
# else
|
||||
__declspec(dllimport) void* __stdcall CreateMutexExW(_SECURITY_ATTRIBUTES*,wchar_t const*,unsigned long,unsigned long);
|
||||
__declspec(dllimport) void* __stdcall CreateEventExW(_SECURITY_ATTRIBUTES*,wchar_t const*,unsigned long,unsigned long);
|
||||
__declspec(dllimport) void* __stdcall CreateSemaphoreExW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*,unsigned long,unsigned long);
|
||||
# endif
|
||||
__declspec(dllimport) void* __stdcall OpenEventW(unsigned long,int,wchar_t const*);
|
||||
__declspec(dllimport) void* __stdcall GetModuleHandleW(wchar_t const*);
|
||||
# else
|
||||
__declspec(dllimport) void* __stdcall CreateMutexA(_SECURITY_ATTRIBUTES*,int,char const*);
|
||||
__declspec(dllimport) void* __stdcall CreateSemaphoreA(_SECURITY_ATTRIBUTES*,long,long,char const*);
|
||||
__declspec(dllimport) void* __stdcall CreateEventA(_SECURITY_ATTRIBUTES*,int,int,char const*);
|
||||
__declspec(dllimport) void* __stdcall OpenEventA(unsigned long,int,char const*);
|
||||
__declspec(dllimport) void* __stdcall GetModuleHandleA(char const*);
|
||||
# endif
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
__declspec(dllimport) void __stdcall GetNativeSystemInfo(_SYSTEM_INFO*);
|
||||
__declspec(dllimport) ticks_type __stdcall GetTickCount64();
|
||||
#else
|
||||
__declspec(dllimport) void __stdcall GetSystemInfo(_SYSTEM_INFO*);
|
||||
__declspec(dllimport) unsigned long __stdcall GetTickCount();
|
||||
#endif
|
||||
__declspec(dllimport) int __stdcall CloseHandle(void*);
|
||||
__declspec(dllimport) int __stdcall ReleaseMutex(void*);
|
||||
__declspec(dllimport) unsigned long __stdcall WaitForSingleObjectEx(void*,unsigned long,int);
|
||||
__declspec(dllimport) unsigned long __stdcall WaitForMultipleObjectsEx(unsigned long nCount,void* const * lpHandles,int bWaitAll,unsigned long dwMilliseconds,int bAlertable);
|
||||
__declspec(dllimport) int __stdcall ReleaseSemaphore(void*,long,long*);
|
||||
__declspec(dllimport) int __stdcall DuplicateHandle(void*,void*,void*,void**,unsigned long,int,unsigned long);
|
||||
#if !BOOST_PLAT_WINDOWS_RUNTIME
|
||||
__declspec(dllimport) unsigned long __stdcall SleepEx(unsigned long,int);
|
||||
__declspec(dllimport) void __stdcall Sleep(unsigned long);
|
||||
typedef void (__stdcall *queue_user_apc_callback_function)(ulong_ptr);
|
||||
__declspec(dllimport) unsigned long __stdcall QueueUserAPC(queue_user_apc_callback_function,void*,ulong_ptr);
|
||||
__declspec(dllimport) farproc_t __stdcall GetProcAddress(void *, const char *);
|
||||
#endif
|
||||
|
||||
# ifndef UNDER_CE
|
||||
__declspec(dllimport) unsigned long __stdcall GetCurrentProcessId();
|
||||
__declspec(dllimport) unsigned long __stdcall GetCurrentThreadId();
|
||||
__declspec(dllimport) void* __stdcall GetCurrentThread();
|
||||
__declspec(dllimport) void* __stdcall GetCurrentProcess();
|
||||
__declspec(dllimport) int __stdcall SetEvent(void*);
|
||||
__declspec(dllimport) int __stdcall ResetEvent(void*);
|
||||
# else
|
||||
using ::GetCurrentProcessId;
|
||||
using ::GetCurrentThreadId;
|
||||
using ::GetCurrentThread;
|
||||
using ::GetCurrentProcess;
|
||||
using ::SetEvent;
|
||||
using ::ResetEvent;
|
||||
# endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
# error "Win32 functions not available"
|
||||
#endif
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
@@ -243,19 +89,19 @@ namespace boost
|
||||
// Borrowed from https://stackoverflow.com/questions/8211820/userland-interrupt-timer-access-such-as-via-kequeryinterrupttime-or-similar
|
||||
inline ticks_type __stdcall GetTickCount64emulation()
|
||||
{
|
||||
static volatile long count = 0xFFFFFFFF;
|
||||
static long count = -1l;
|
||||
unsigned long previous_count, current_tick32, previous_count_zone, current_tick32_zone;
|
||||
ticks_type current_tick64;
|
||||
|
||||
previous_count = (unsigned long) _InterlockedCompareExchange(&count, 0, 0);
|
||||
current_tick32 = GetTickCount();
|
||||
previous_count = (unsigned long) boost::detail::interlocked_read_acquire(&count);
|
||||
current_tick32 = ::boost::detail::winapi::GetTickCount();
|
||||
|
||||
if(previous_count == 0xFFFFFFFF)
|
||||
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, initial_count, 0xFFFFFFFF);
|
||||
previous_count = (unsigned long) _InterlockedCompareExchange(&count, (long)initial_count, -1l);
|
||||
|
||||
current_tick64 = initial_count;
|
||||
current_tick64 <<= 28;
|
||||
@@ -278,8 +124,9 @@ namespace boost
|
||||
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.
|
||||
_InterlockedCompareExchange(&count, previous_count + 1, previous_count);
|
||||
current_tick64 = previous_count + 1;
|
||||
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;
|
||||
@@ -299,13 +146,13 @@ namespace boost
|
||||
// GetTickCount and GetModuleHandle are not allowed in the Windows Runtime,
|
||||
// and kernel32 isn't used in Windows Phone.
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
gettickcount64impl = &GetTickCount64;
|
||||
gettickcount64impl = &::boost::detail::winapi::GetTickCount64;
|
||||
#else
|
||||
farproc_t addr=GetProcAddress(
|
||||
#if !defined(BOOST_NO_ANSI_APIS)
|
||||
GetModuleHandleA("KERNEL32.DLL"),
|
||||
::boost::detail::winapi::GetModuleHandleA("KERNEL32.DLL"),
|
||||
#else
|
||||
GetModuleHandleW(L"KERNEL32.DLL"),
|
||||
::boost::detail::winapi::GetModuleHandleW(L"KERNEL32.DLL"),
|
||||
#endif
|
||||
"GetTickCount64");
|
||||
if(addr)
|
||||
@@ -338,11 +185,11 @@ namespace boost
|
||||
initial_event_state state)
|
||||
{
|
||||
#if !defined(BOOST_NO_ANSI_APIS)
|
||||
handle const res = win32::CreateEventA(0, type, state, mutex_name);
|
||||
handle const res = ::boost::detail::winapi::CreateEventA(0, type, state, mutex_name);
|
||||
#elif BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA
|
||||
handle const res = win32::CreateEventW(0, type, state, mutex_name);
|
||||
handle const res = ::boost::detail::winapi::CreateEventW(0, type, state, mutex_name);
|
||||
#else
|
||||
handle const res = win32::CreateEventExW(
|
||||
handle const res = ::boost::detail::winapi::CreateEventExW(
|
||||
0,
|
||||
mutex_name,
|
||||
type ? create_event_manual_reset : 0 | state ? create_event_initial_set : 0,
|
||||
@@ -364,12 +211,12 @@ namespace boost
|
||||
inline handle create_anonymous_semaphore_nothrow(long initial_count,long max_count)
|
||||
{
|
||||
#if !defined(BOOST_NO_ANSI_APIS)
|
||||
handle const res=win32::CreateSemaphoreA(0,initial_count,max_count,0);
|
||||
handle const res=::boost::detail::winapi::CreateSemaphoreA(0,initial_count,max_count,0);
|
||||
#else
|
||||
#if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA
|
||||
handle const res=win32::CreateSemaphoreEx(0,initial_count,max_count,0,0);
|
||||
handle const res=::boost::detail::winapi::CreateSemaphoreEx(0,initial_count,max_count,0,0);
|
||||
#else
|
||||
handle const res=win32::CreateSemaphoreExW(0,initial_count,max_count,0,0,semaphore_all_access);
|
||||
handle const res=::boost::detail::winapi::CreateSemaphoreExW(0,initial_count,max_count,0,0,semaphore_all_access);
|
||||
#endif
|
||||
#endif
|
||||
return res;
|
||||
@@ -387,10 +234,10 @@ namespace boost
|
||||
|
||||
inline handle duplicate_handle(handle source)
|
||||
{
|
||||
handle const current_process=GetCurrentProcess();
|
||||
handle const current_process=::boost::detail::winapi::GetCurrentProcess();
|
||||
long const same_access_flag=2;
|
||||
handle new_handle=0;
|
||||
bool const success=DuplicateHandle(current_process,source,current_process,&new_handle,0,false,same_access_flag)!=0;
|
||||
bool const success=::boost::detail::winapi::DuplicateHandle(current_process,source,current_process,&new_handle,0,false,same_access_flag)!=0;
|
||||
if(!success)
|
||||
{
|
||||
boost::throw_exception(thread_resource_error());
|
||||
@@ -400,15 +247,15 @@ namespace boost
|
||||
|
||||
inline void release_semaphore(handle semaphore,long count)
|
||||
{
|
||||
BOOST_VERIFY(ReleaseSemaphore(semaphore,count,0)!=0);
|
||||
BOOST_VERIFY(::boost::detail::winapi::ReleaseSemaphore(semaphore,count,0)!=0);
|
||||
}
|
||||
|
||||
inline void get_system_info(system_info *info)
|
||||
{
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
win32::GetNativeSystemInfo(info);
|
||||
::boost::detail::winapi::GetNativeSystemInfo(info);
|
||||
#else
|
||||
win32::GetSystemInfo(info);
|
||||
::boost::detail::winapi::GetSystemInfo(info);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -419,15 +266,15 @@ namespace boost
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
std::this_thread::yield();
|
||||
#else
|
||||
::boost::detail::win32::Sleep(0);
|
||||
::boost::detail::winapi::Sleep(0);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
::boost::detail::win32::WaitForSingleObjectEx(::boost::detail::win32::GetCurrentThread(), milliseconds, 0);
|
||||
::boost::detail::winapi::WaitForSingleObjectEx(::boost::detail::winapi::GetCurrentThread(), milliseconds, 0);
|
||||
#else
|
||||
::boost::detail::win32::Sleep(milliseconds);
|
||||
::boost::detail::winapi::Sleep(milliseconds);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -443,7 +290,7 @@ namespace boost
|
||||
{
|
||||
if (m_completionHandle != ::boost::detail::win32::invalid_handle_value)
|
||||
{
|
||||
CloseHandle(m_completionHandle);
|
||||
::boost::detail::winapi::CloseHandle(m_completionHandle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -471,7 +318,7 @@ namespace boost
|
||||
{
|
||||
if(handle_to_manage && handle_to_manage!=invalid_handle_value)
|
||||
{
|
||||
BOOST_VERIFY(CloseHandle(handle_to_manage));
|
||||
BOOST_VERIFY(::boost::detail::winapi::CloseHandle(handle_to_manage));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ namespace boost
|
||||
}
|
||||
}
|
||||
|
||||
#if defined BOOST_THREAD_PATCH
|
||||
const pthread_once_t pthread_once_init_value=PTHREAD_ONCE_INIT;
|
||||
struct BOOST_THREAD_DECL delete_epoch_tss_key_on_dlclose_t
|
||||
{
|
||||
@@ -52,11 +53,15 @@ namespace boost
|
||||
{
|
||||
if(memcmp(&epoch_tss_key_flag, &pthread_once_init_value, sizeof(pthread_once_t)))
|
||||
{
|
||||
void* data = pthread_getspecific(epoch_tss_key);
|
||||
if (data)
|
||||
delete_epoch_tss_data(data);
|
||||
pthread_key_delete(epoch_tss_key);
|
||||
}
|
||||
}
|
||||
};
|
||||
delete_epoch_tss_key_on_dlclose_t delete_epoch_tss_key_on_dlclose;
|
||||
#endif
|
||||
}
|
||||
|
||||
uintmax_atomic_t& get_once_per_thread_epoch()
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace boost
|
||||
for (async_states_t::iterator i = async_states_.begin(), e = async_states_.end();
|
||||
i != e; ++i)
|
||||
{
|
||||
(*i)->make_ready();
|
||||
(*i)->notify_deferred();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,6 +115,7 @@ namespace boost
|
||||
}
|
||||
}
|
||||
|
||||
#if defined BOOST_THREAD_PATCH
|
||||
struct delete_current_thread_tls_key_on_dlclose_t
|
||||
{
|
||||
delete_current_thread_tls_key_on_dlclose_t()
|
||||
@@ -125,12 +126,15 @@ namespace boost
|
||||
const boost::once_flag uninitialized = BOOST_ONCE_INIT;
|
||||
if (memcmp(¤t_thread_tls_init_flag, &uninitialized, sizeof(boost::once_flag)))
|
||||
{
|
||||
void* data = pthread_getspecific(current_thread_tls_key);
|
||||
if (data)
|
||||
tls_destructor(data);
|
||||
pthread_key_delete(current_thread_tls_key);
|
||||
}
|
||||
}
|
||||
};
|
||||
delete_current_thread_tls_key_on_dlclose_t delete_current_thread_tls_key_on_dlclose;
|
||||
|
||||
#endif
|
||||
void create_current_thread_tls_key()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_key_create(¤t_thread_tls_key,&tls_destructor));
|
||||
@@ -426,7 +430,7 @@ namespace boost
|
||||
{
|
||||
namespace no_interruption_point
|
||||
{
|
||||
namespace hiden
|
||||
namespace hidden
|
||||
{
|
||||
void BOOST_THREAD_DECL sleep_for(const timespec& ts)
|
||||
{
|
||||
@@ -453,9 +457,9 @@ namespace boost
|
||||
}
|
||||
}
|
||||
|
||||
void BOOST_THREAD_DECL sleep_until(const timespec& ts)
|
||||
void BOOST_THREAD_DECL sleep_until_realtime(const timespec& ts)
|
||||
{
|
||||
timespec now = boost::detail::timespec_now();
|
||||
timespec now = boost::detail::timespec_now_realtime();
|
||||
if (boost::detail::timespec_gt(ts, now))
|
||||
{
|
||||
for (int foo=0; foo < 5; ++foo)
|
||||
@@ -475,7 +479,7 @@ namespace boost
|
||||
condition_variable cond;
|
||||
cond.do_wait_until(lock, ts);
|
||||
# endif
|
||||
timespec now2 = boost::detail::timespec_now();
|
||||
timespec now2 = boost::detail::timespec_now_realtime();
|
||||
if (boost::detail::timespec_ge(now2, ts))
|
||||
{
|
||||
return;
|
||||
@@ -483,10 +487,9 @@ namespace boost
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
namespace hiden
|
||||
namespace hidden
|
||||
{
|
||||
void BOOST_THREAD_DECL sleep_for(const timespec& ts)
|
||||
{
|
||||
@@ -499,11 +502,11 @@ namespace boost
|
||||
}
|
||||
else
|
||||
{
|
||||
boost::this_thread::no_interruption_point::hiden::sleep_for(ts);
|
||||
boost::this_thread::no_interruption_point::hidden::sleep_for(ts);
|
||||
}
|
||||
}
|
||||
|
||||
void BOOST_THREAD_DECL sleep_until(const timespec& ts)
|
||||
void BOOST_THREAD_DECL sleep_until_realtime(const timespec& ts)
|
||||
{
|
||||
boost::detail::thread_data_base* const thread_info=boost::detail::get_current_thread_data();
|
||||
|
||||
@@ -514,10 +517,10 @@ namespace boost
|
||||
}
|
||||
else
|
||||
{
|
||||
boost::this_thread::no_interruption_point::hiden::sleep_until(ts);
|
||||
boost::this_thread::no_interruption_point::hidden::sleep_until_realtime(ts);
|
||||
}
|
||||
}
|
||||
} // hiden
|
||||
} // hidden
|
||||
} // this_thread
|
||||
|
||||
namespace this_thread
|
||||
@@ -538,7 +541,7 @@ namespace boost
|
||||
timespec ts;
|
||||
ts.tv_sec= 0;
|
||||
ts.tv_nsec= 0;
|
||||
hiden::sleep_for(ts);
|
||||
hidden::sleep_for(ts);
|
||||
# endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,15 +5,9 @@
|
||||
// (C) Copyright 2007 David Deakins
|
||||
// (C) Copyright 2011-2013 Vicente J. Botet Escriba
|
||||
|
||||
#ifndef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x400
|
||||
#endif
|
||||
|
||||
#ifndef WINVER
|
||||
#define WINVER 0x400
|
||||
#endif
|
||||
//#define BOOST_THREAD_VERSION 3
|
||||
|
||||
#include <boost/detail/winapi/config.hpp>
|
||||
#include <boost/thread/thread_only.hpp>
|
||||
#include <boost/thread/once.hpp>
|
||||
#include <boost/thread/tss.hpp>
|
||||
@@ -24,6 +18,7 @@
|
||||
#include <boost/cstdint.hpp>
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
#include <boost/date_time/posix_time/conversion.hpp>
|
||||
#include <boost/thread/thread_time.hpp>
|
||||
#endif
|
||||
#include <boost/thread/csbl/memory/unique_ptr.hpp>
|
||||
#include <memory>
|
||||
@@ -62,7 +57,7 @@ namespace boost
|
||||
for (async_states_t::iterator i = async_states_.begin(), e = async_states_.end();
|
||||
i != e; ++i)
|
||||
{
|
||||
(*i)->make_ready();
|
||||
(*i)->notify_deferred();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -467,7 +462,7 @@ namespace boost
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
bool thread::timed_join(boost::system_time const& wait_until)
|
||||
{
|
||||
return do_try_join_until(get_milliseconds_until(wait_until));
|
||||
return do_try_join_until(boost::detail::get_milliseconds_until(wait_until));
|
||||
}
|
||||
#endif
|
||||
bool thread::do_try_join_until_noexcept(uintmax_t milli, bool& res)
|
||||
@@ -513,7 +508,7 @@ namespace boost
|
||||
bool thread::interruption_requested() const BOOST_NOEXCEPT
|
||||
{
|
||||
detail::thread_data_ptr local_thread_info=(get_thread_info)();
|
||||
return local_thread_info.get() && (detail::win32::WaitForSingleObjectEx(local_thread_info->interruption_handle,0,0)==0);
|
||||
return local_thread_info.get() && (detail::winapi::WaitForSingleObjectEx(local_thread_info->interruption_handle,0,0)==0);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -743,7 +738,7 @@ namespace boost
|
||||
|
||||
if(handle_count)
|
||||
{
|
||||
unsigned long const notified_index=detail::win32::WaitForMultipleObjectsEx(handle_count,handles,false,using_timer?INFINITE:time_left.milliseconds, 0);
|
||||
unsigned long const notified_index=detail::winapi::WaitForMultipleObjectsEx(handle_count,handles,false,using_timer?INFINITE:time_left.milliseconds, 0);
|
||||
if(notified_index<handle_count)
|
||||
{
|
||||
if(notified_index==wait_handle_index)
|
||||
@@ -753,7 +748,7 @@ namespace boost
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
else if(notified_index==interruption_index)
|
||||
{
|
||||
detail::win32::ResetEvent(detail::get_current_thread_data()->interruption_handle);
|
||||
detail::winapi::ResetEvent(detail::get_current_thread_data()->interruption_handle);
|
||||
throw thread_interrupted();
|
||||
}
|
||||
#endif
|
||||
@@ -828,7 +823,7 @@ namespace boost
|
||||
|
||||
if(handle_count)
|
||||
{
|
||||
unsigned long const notified_index=detail::win32::WaitForMultipleObjectsEx(handle_count,handles,false,using_timer?INFINITE:time_left.milliseconds, 0);
|
||||
unsigned long const notified_index=detail::winapi::WaitForMultipleObjectsEx(handle_count,handles,false,using_timer?INFINITE:time_left.milliseconds, 0);
|
||||
if(notified_index<handle_count)
|
||||
{
|
||||
if(notified_index==wait_handle_index)
|
||||
@@ -865,7 +860,7 @@ namespace boost
|
||||
return current_thread_data->id;
|
||||
}
|
||||
#endif
|
||||
return detail::win32::GetCurrentThreadId();
|
||||
return detail::winapi::GetCurrentThreadId();
|
||||
#else
|
||||
return thread::id(get_or_make_current_thread_data());
|
||||
#endif
|
||||
@@ -876,7 +871,7 @@ namespace boost
|
||||
{
|
||||
if(interruption_enabled() && interruption_requested())
|
||||
{
|
||||
detail::win32::ResetEvent(detail::get_current_thread_data()->interruption_handle);
|
||||
detail::winapi::ResetEvent(detail::get_current_thread_data()->interruption_handle);
|
||||
throw thread_interrupted();
|
||||
}
|
||||
}
|
||||
@@ -888,7 +883,7 @@ namespace boost
|
||||
|
||||
bool interruption_requested() BOOST_NOEXCEPT
|
||||
{
|
||||
return detail::get_current_thread_data() && (detail::win32::WaitForSingleObjectEx(detail::get_current_thread_data()->interruption_handle,0,0)==0);
|
||||
return detail::get_current_thread_data() && (detail::winapi::WaitForSingleObjectEx(detail::get_current_thread_data()->interruption_handle,0,0)==0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/detail/winapi/config.hpp>
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
|
||||
@@ -10,7 +11,6 @@
|
||||
|
||||
#include <boost/thread/detail/tss_hooks.hpp>
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
#if defined(__BORLANDC__)
|
||||
|
||||
@@ -7,9 +7,10 @@
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/detail/winapi/config.hpp>
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB)
|
||||
#if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB)
|
||||
|
||||
#if (defined(__MINGW32__) && !defined(_WIN64)) || defined(__MINGW64__) || (__MINGW64_VERSION_MAJOR)
|
||||
|
||||
@@ -38,7 +39,7 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__MINGW64__) || (__MINGW64_VERSION_MAJOR) || (__MINGW32_MAJOR_VERSION >3) || \
|
||||
#if defined(__MINGW64__) || (__MINGW64_VERSION_MAJOR) || (__MINGW32__) || (__MINGW32_MAJOR_VERSION >3) || \
|
||||
((__MINGW32_MAJOR_VERSION==3) && (__MINGW32_MINOR_VERSION>=18))
|
||||
extern "C"
|
||||
{
|
||||
@@ -77,7 +78,6 @@ extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
@@ -111,15 +111,27 @@ extern BOOL (WINAPI * const _pDefaultRawDllMainOrig)(HANDLE, DWORD, LPVOID) = NU
|
||||
|
||||
|
||||
//Definitions required by implementation
|
||||
|
||||
#if (_MSC_VER < 1300) // 1300 == VC++ 7.0
|
||||
typedef void (__cdecl *_PVFV)();
|
||||
#define INIRETSUCCESS
|
||||
#define PVAPI void __cdecl
|
||||
#if (_MSC_VER < 1300) || ((_MSC_VER > 1900) && (_MSC_VER < 1910)) // 1300 == VC++ 7.0, 1900 == VC++ 14.0, 1910 == VC++ 2017
|
||||
typedef void ( __cdecl *_PVFV_ )();
|
||||
typedef void ( __cdecl *_PIFV_ )();
|
||||
#define INIRETSUCCESS_V
|
||||
#define INIRETSUCCESS_I
|
||||
#define PVAPI_V void __cdecl
|
||||
#define PVAPI_I void __cdecl
|
||||
#elif (_MSC_VER >= 1910)
|
||||
typedef void ( __cdecl *_PVFV_ )();
|
||||
typedef int ( __cdecl *_PIFV_ )();
|
||||
#define INIRETSUCCESS_V
|
||||
#define INIRETSUCCESS_I 0
|
||||
#define PVAPI_V void __cdecl
|
||||
#define PVAPI_I int __cdecl
|
||||
#else
|
||||
typedef int (__cdecl *_PVFV)();
|
||||
#define INIRETSUCCESS 0
|
||||
#define PVAPI int __cdecl
|
||||
typedef int ( __cdecl *_PVFV_ )();
|
||||
typedef int ( __cdecl *_PIFV_ )();
|
||||
#define INIRETSUCCESS_V 0
|
||||
#define INIRETSUCCESS_I 0
|
||||
#define PVAPI_V int __cdecl
|
||||
#define PVAPI_I int __cdecl
|
||||
#endif
|
||||
|
||||
typedef void (NTAPI* _TLSCB)(HINSTANCE, DWORD, PVOID);
|
||||
@@ -136,9 +148,9 @@ extern BOOL (WINAPI * const _pDefaultRawDllMainOrig)(HANDLE, DWORD, LPVOID) = NU
|
||||
{
|
||||
//Forward declarations
|
||||
|
||||
static PVAPI on_tls_prepare();
|
||||
static PVAPI on_process_init();
|
||||
static PVAPI on_process_term();
|
||||
static PVAPI_I on_tls_prepare();
|
||||
static PVAPI_V on_process_init();
|
||||
static PVAPI_V on_process_term();
|
||||
static void NTAPI on_tls_callback(HINSTANCE, DWORD, PVOID);
|
||||
|
||||
//The .CRT$Xxx information is taken from Codeguru:
|
||||
@@ -150,9 +162,9 @@ extern BOOL (WINAPI * const _pDefaultRawDllMainOrig)(HANDLE, DWORD, LPVOID) = NU
|
||||
#pragma section(".CRT$XTU",long,read)
|
||||
#pragma section(".CRT$XLC",long,read)
|
||||
__declspec(allocate(".CRT$XLC")) _TLSCB __xl_ca=on_tls_callback;
|
||||
__declspec(allocate(".CRT$XIU"))_PVFV p_tls_prepare = on_tls_prepare;
|
||||
__declspec(allocate(".CRT$XCU"))_PVFV p_process_init = on_process_init;
|
||||
__declspec(allocate(".CRT$XTU"))_PVFV p_process_term = on_process_term;
|
||||
__declspec(allocate(".CRT$XIU"))_PIFV_ p_tls_prepare = on_tls_prepare;
|
||||
__declspec(allocate(".CRT$XCU"))_PVFV_ p_process_init = on_process_init;
|
||||
__declspec(allocate(".CRT$XTU"))_PVFV_ p_process_term = on_process_term;
|
||||
#else
|
||||
#if (_MSC_VER >= 1300) // 1300 == VC++ 7.0
|
||||
# pragma data_seg(push, old_seg)
|
||||
@@ -164,13 +176,13 @@ extern BOOL (WINAPI * const _pDefaultRawDllMainOrig)(HANDLE, DWORD, LPVOID) = NU
|
||||
//this could be changed easily if required.
|
||||
|
||||
#pragma data_seg(".CRT$XIU")
|
||||
static _PVFV p_tls_prepare = on_tls_prepare;
|
||||
static _PIFV_ p_tls_prepare = on_tls_prepare;
|
||||
#pragma data_seg()
|
||||
|
||||
//Callback after all global ctors.
|
||||
|
||||
#pragma data_seg(".CRT$XCU")
|
||||
static _PVFV p_process_init = on_process_init;
|
||||
static _PVFV_ p_process_init = on_process_init;
|
||||
#pragma data_seg()
|
||||
|
||||
//Callback for tls notifications.
|
||||
@@ -181,7 +193,7 @@ extern BOOL (WINAPI * const _pDefaultRawDllMainOrig)(HANDLE, DWORD, LPVOID) = NU
|
||||
//Callback for termination.
|
||||
|
||||
#pragma data_seg(".CRT$XTU")
|
||||
static _PVFV p_process_term = on_process_term;
|
||||
static _PVFV_ p_process_term = on_process_term;
|
||||
#pragma data_seg()
|
||||
#if (_MSC_VER >= 1300) // 1300 == VC++ 7.0
|
||||
# pragma data_seg(pop, old_seg)
|
||||
@@ -193,7 +205,7 @@ extern BOOL (WINAPI * const _pDefaultRawDllMainOrig)(HANDLE, DWORD, LPVOID) = NU
|
||||
#pragma warning(disable:4189)
|
||||
#endif
|
||||
|
||||
PVAPI on_tls_prepare()
|
||||
PVAPI_I on_tls_prepare()
|
||||
{
|
||||
//The following line has an important side effect:
|
||||
//if the TLS directory is not already there, it will
|
||||
@@ -228,13 +240,13 @@ extern BOOL (WINAPI * const _pDefaultRawDllMainOrig)(HANDLE, DWORD, LPVOID) = NU
|
||||
*pfdst = 0;
|
||||
#endif
|
||||
|
||||
return INIRETSUCCESS;
|
||||
return INIRETSUCCESS_I;
|
||||
}
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
PVAPI on_process_init()
|
||||
PVAPI_V on_process_init()
|
||||
{
|
||||
//Schedule on_thread_exit() to be called for the main
|
||||
//thread before destructors of global objects have been
|
||||
@@ -251,13 +263,13 @@ extern BOOL (WINAPI * const _pDefaultRawDllMainOrig)(HANDLE, DWORD, LPVOID) = NU
|
||||
|
||||
boost::on_process_enter();
|
||||
|
||||
return INIRETSUCCESS;
|
||||
return INIRETSUCCESS_V;
|
||||
}
|
||||
|
||||
PVAPI on_process_term()
|
||||
PVAPI_V on_process_term()
|
||||
{
|
||||
boost::on_process_exit();
|
||||
return INIRETSUCCESS;
|
||||
return INIRETSUCCESS_V;
|
||||
}
|
||||
|
||||
void NTAPI on_tls_callback(HINSTANCE /*h*/, DWORD dwReason, PVOID /*pv*/)
|
||||
|
||||
@@ -798,7 +798,9 @@ rule thread-compile ( sources : reqs * : name )
|
||||
[ thread-run2-noit ../example/synchronized_value.cpp : ex_synchronized_value ]
|
||||
[ thread-run2-noit ../example/synchronized_person.cpp : ex_synchronized_person ]
|
||||
[ thread-run2-noit ../example/thread_guard.cpp : ex_thread_guard ]
|
||||
[ thread-run2-noit ../example/std_thread_guard.cpp : ex_std_thread_guard ]
|
||||
[ thread-run2-noit ../example/scoped_thread.cpp : ex_scoped_thread ]
|
||||
[ thread-run2-noit ../example/std_scoped_thread.cpp : ex_std_scoped_thread ]
|
||||
[ thread-run2-noit ../example/strict_lock.cpp : ex_strict_lock ]
|
||||
[ thread-run2-noit ../example/ba_externallly_locked.cpp : ex_ba_externallly_locked ]
|
||||
[ thread-run2 ../example/producer_consumer_bounded.cpp : ex_producer_consumer_bounded ]
|
||||
@@ -964,7 +966,9 @@ rule thread-compile ( sources : reqs * : name )
|
||||
#[ thread-run test_11499.cpp ]
|
||||
#[ thread-run test_11611.cpp ]
|
||||
#[ thread-run test_11818.cpp ]
|
||||
[ thread-run test_11796.cpp ]
|
||||
#[ thread-run test_11796.cpp ]
|
||||
#[ thread-run test_12293.cpp ]
|
||||
[ thread-run test_12949.cpp ]
|
||||
|
||||
;
|
||||
|
||||
|
||||
@@ -12,7 +12,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)
|
||||
|
||||
// <boost/thread/detail/async_func.hpp>
|
||||
// <boost/thread/detail/invoker.hpp>
|
||||
|
||||
#include <boost/thread/detail/invoker.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
@@ -12,14 +12,9 @@
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
|
||||
// <boost/thread/detail/invoker.hpp>
|
||||
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
//#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
|
||||
#include <boost/thread/detail/async_func.hpp>
|
||||
#include <boost/thread/detail/invoker.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
int count = 0;
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <cassert>
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
|
||||
@@ -35,33 +36,39 @@ int runs = 0;
|
||||
|
||||
void f()
|
||||
{
|
||||
typedef boost::chrono::steady_clock Clock;
|
||||
typedef boost::chrono::milliseconds milliseconds;
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
BOOST_TEST(test2 == 0);
|
||||
test1 = 1;
|
||||
cv.notify_one();
|
||||
Clock::time_point t0 = Clock::now();
|
||||
int count=0;
|
||||
while (test2 == 0 && cv.wait_for(lk, milliseconds(250)) == boost::cv_status::no_timeout)
|
||||
count++;
|
||||
Clock::time_point t1 = Clock::now();
|
||||
if (runs == 0)
|
||||
{
|
||||
BOOST_TEST(t1 - t0 < milliseconds(250));
|
||||
BOOST_TEST(test2 != 0);
|
||||
try {
|
||||
typedef boost::chrono::steady_clock Clock;
|
||||
typedef boost::chrono::milliseconds milliseconds;
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
assert(test2 == 0);
|
||||
test1 = 1;
|
||||
cv.notify_one();
|
||||
Clock::time_point t0 = Clock::now();
|
||||
int count=0;
|
||||
while (test2 == 0 && cv.wait_for(lk, milliseconds(250)) == boost::cv_status::no_timeout)
|
||||
count++;
|
||||
Clock::time_point t1 = Clock::now();
|
||||
if (runs == 0)
|
||||
{
|
||||
assert(t1 - t0 < milliseconds(250));
|
||||
assert(test2 != 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
assert(t1 - t0 - milliseconds(250) < milliseconds(count*250+5+1000));
|
||||
assert(test2 == 0);
|
||||
}
|
||||
++runs;
|
||||
} catch(...) {
|
||||
std::cout << "ERROR exception" << __LINE__ << std::endl;
|
||||
assert(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(t1 - t0 - milliseconds(250) < milliseconds(count*250+5+1000));
|
||||
BOOST_TEST(test2 == 0);
|
||||
}
|
||||
++runs;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
boost::thread t(f);
|
||||
@@ -73,9 +80,13 @@ int main()
|
||||
lk.unlock();
|
||||
cv.notify_one();
|
||||
t.join();
|
||||
} catch(...) {
|
||||
std::cout << "ERROR exception" << __LINE__ << std::endl;
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
test1 = 0;
|
||||
test2 = 0;
|
||||
try
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
boost::thread t(f);
|
||||
@@ -85,8 +96,10 @@ int main()
|
||||
BOOST_TEST(test1 != 0);
|
||||
lk.unlock();
|
||||
t.join();
|
||||
} catch(...) {
|
||||
BOOST_TEST(false);
|
||||
std::cout << "ERROR exception" << __LINE__ << std::endl;
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
|
||||
@@ -49,34 +51,40 @@ int runs = 0;
|
||||
|
||||
void f()
|
||||
{
|
||||
typedef boost::chrono::system_clock Clock;
|
||||
typedef boost::chrono::milliseconds milliseconds;
|
||||
boost::unique_lock < boost::mutex > lk(mut);
|
||||
BOOST_TEST(test2 == 0);
|
||||
test1 = 1;
|
||||
cv.notify_one();
|
||||
Clock::time_point t0 = Clock::now();
|
||||
int count=0;
|
||||
//bool r =
|
||||
(void)cv.wait_for(lk, milliseconds(250), Pred(test2));
|
||||
count++;
|
||||
Clock::time_point t1 = Clock::now();
|
||||
if (runs == 0)
|
||||
{
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(t1 - t0 < milliseconds(250+1000));
|
||||
BOOST_TEST(test2 != 0);
|
||||
try {
|
||||
typedef boost::chrono::system_clock Clock;
|
||||
typedef boost::chrono::milliseconds milliseconds;
|
||||
boost::unique_lock < boost::mutex > lk(mut);
|
||||
assert(test2 == 0);
|
||||
test1 = 1;
|
||||
cv.notify_one();
|
||||
Clock::time_point t0 = Clock::now();
|
||||
int count=0;
|
||||
//bool r =
|
||||
(void)cv.wait_for(lk, milliseconds(250), Pred(test2));
|
||||
count++;
|
||||
Clock::time_point t1 = Clock::now();
|
||||
if (runs == 0)
|
||||
{
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
assert(t1 - t0 < milliseconds(250+1000));
|
||||
assert(test2 != 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(t1 - t0 - milliseconds(250) < milliseconds(count*250+2));
|
||||
assert(test2 == 0);
|
||||
}
|
||||
++runs;
|
||||
} catch(...) {
|
||||
std::cout << "ERROR exception" << __LINE__ << std::endl;
|
||||
assert(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_TEST(t1 - t0 - milliseconds(250) < milliseconds(count*250+2));
|
||||
BOOST_TEST(test2 == 0);
|
||||
}
|
||||
++runs;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::unique_lock < boost::mutex > lk(mut);
|
||||
boost::thread t(f);
|
||||
@@ -88,9 +96,13 @@ int main()
|
||||
lk.unlock();
|
||||
cv.notify_one();
|
||||
t.join();
|
||||
} catch(...) {
|
||||
BOOST_TEST(false);
|
||||
std::cout << "ERROR exception" << __LINE__ << std::endl;
|
||||
}
|
||||
test1 = 0;
|
||||
test2 = 0;
|
||||
try
|
||||
{
|
||||
boost::unique_lock < boost::mutex > lk(mut);
|
||||
boost::thread t(f);
|
||||
@@ -100,6 +112,9 @@ int main()
|
||||
BOOST_TEST(test1 != 0);
|
||||
lk.unlock();
|
||||
t.join();
|
||||
} catch(...) {
|
||||
BOOST_TEST(false);
|
||||
std::cout << "ERROR exception" << __LINE__ << std::endl;
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
|
||||
@@ -17,11 +17,13 @@
|
||||
|
||||
// void wait(unique_lock<mutex>& lock);
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
|
||||
@@ -35,31 +37,40 @@ int runs = 0;
|
||||
|
||||
void f()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
BOOST_TEST(test2 == 0);
|
||||
test1 = 1;
|
||||
cv.notify_one();
|
||||
while (test2 == 0) {
|
||||
cv.wait(lk);
|
||||
try {
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
assert(test2 == 0);
|
||||
test1 = 1;
|
||||
cv.notify_one();
|
||||
while (test2 == 0) {
|
||||
cv.wait(lk);
|
||||
}
|
||||
assert(test2 != 0);
|
||||
} catch(...) {
|
||||
std::cout << "ERROR exception" << __LINE__ << std::endl;
|
||||
assert(false);
|
||||
}
|
||||
BOOST_TEST(test2 != 0);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
boost::unique_lock<boost::mutex>lk(mut);
|
||||
boost::thread t(f);
|
||||
BOOST_TEST(test1 == 0);
|
||||
while (test1 == 0)
|
||||
{
|
||||
cv.wait(lk);
|
||||
try {
|
||||
boost::unique_lock<boost::mutex>lk(mut);
|
||||
boost::thread t(f);
|
||||
BOOST_TEST(test1 == 0);
|
||||
while (test1 == 0)
|
||||
{
|
||||
cv.wait(lk);
|
||||
}
|
||||
BOOST_TEST(test1 != 0);
|
||||
test2 = 1;
|
||||
lk.unlock();
|
||||
cv.notify_one();
|
||||
t.join();
|
||||
} catch(...) {
|
||||
BOOST_TEST(false);
|
||||
std::cout << "ERROR exception" << __LINE__ << std::endl;
|
||||
}
|
||||
BOOST_TEST(test1 != 0);
|
||||
test2 = 1;
|
||||
lk.unlock();
|
||||
cv.notify_one();
|
||||
t.join();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
|
||||
@@ -49,32 +51,38 @@ int runs = 0;
|
||||
|
||||
void f()
|
||||
{
|
||||
boost::unique_lock < boost::mutex > lk(mut);
|
||||
BOOST_TEST(test2 == 0);
|
||||
test1 = 1;
|
||||
cv.notify_one();
|
||||
Clock::time_point t0 = Clock::now();
|
||||
Clock::time_point t = t0 + Clock::duration(250);
|
||||
int count=0;
|
||||
while (test2 == 0 && cv.wait_until(lk, t) == boost::cv_status::no_timeout)
|
||||
count++;
|
||||
Clock::time_point t1 = Clock::now();
|
||||
if (runs == 0)
|
||||
{
|
||||
BOOST_TEST(t1 - t0 < Clock::duration(250));
|
||||
BOOST_TEST(test2 != 0);
|
||||
try {
|
||||
boost::unique_lock < boost::mutex > lk(mut);
|
||||
assert(test2 == 0);
|
||||
test1 = 1;
|
||||
cv.notify_one();
|
||||
Clock::time_point t0 = Clock::now();
|
||||
Clock::time_point t = t0 + Clock::duration(250);
|
||||
int count=0;
|
||||
while (test2 == 0 && cv.wait_until(lk, t) == boost::cv_status::no_timeout)
|
||||
count++;
|
||||
Clock::time_point t1 = Clock::now();
|
||||
if (runs == 0)
|
||||
{
|
||||
assert(t1 - t0 < Clock::duration(250));
|
||||
assert(test2 != 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
assert(t1 - t0 - Clock::duration(250) < Clock::duration(count*250+5+1000));
|
||||
assert(test2 == 0);
|
||||
}
|
||||
++runs;
|
||||
} catch(...) {
|
||||
assert(false);
|
||||
std::cout << "ERROR exception" << __LINE__ << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This test is spurious as it depends on the time the thread system switches the threads
|
||||
BOOST_TEST(t1 - t0 - Clock::duration(250) < Clock::duration(count*250+5+1000));
|
||||
BOOST_TEST(test2 == 0);
|
||||
}
|
||||
++runs;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::unique_lock < boost::mutex > lk(mut);
|
||||
boost::thread t(f);
|
||||
@@ -86,9 +94,14 @@ int main()
|
||||
lk.unlock();
|
||||
cv.notify_one();
|
||||
t.join();
|
||||
} catch(...) {
|
||||
BOOST_TEST(false);
|
||||
std::cout << "ERROR exception" << __LINE__ << std::endl;
|
||||
}
|
||||
|
||||
test1 = 0;
|
||||
test2 = 0;
|
||||
try
|
||||
{
|
||||
boost::unique_lock < boost::mutex > lk(mut);
|
||||
boost::thread t(f);
|
||||
@@ -98,6 +111,9 @@ int main()
|
||||
BOOST_TEST(test1 != 0);
|
||||
lk.unlock();
|
||||
t.join();
|
||||
} catch(...) {
|
||||
BOOST_TEST(false);
|
||||
std::cout << "ERROR exception" << __LINE__ << std::endl;
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
#if defined BOOST_THREAD_USES_CHRONO
|
||||
|
||||
@@ -64,31 +66,37 @@ int runs = 0;
|
||||
|
||||
void f()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
BOOST_TEST(test2 == 0);
|
||||
test1 = 1;
|
||||
cv.notify_one();
|
||||
Clock::time_point t0 = Clock::now();
|
||||
Clock::time_point t = t0 + Clock::duration(250);
|
||||
bool r = cv.wait_until(lk, t, Pred(test2));
|
||||
Clock::time_point t1 = Clock::now();
|
||||
if (runs == 0)
|
||||
{
|
||||
BOOST_TEST(t1 - t0 < Clock::duration(250));
|
||||
BOOST_TEST(test2 != 0);
|
||||
BOOST_TEST(r);
|
||||
try {
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
assert(test2 == 0);
|
||||
test1 = 1;
|
||||
cv.notify_one();
|
||||
Clock::time_point t0 = Clock::now();
|
||||
Clock::time_point t = t0 + Clock::duration(250);
|
||||
bool r = cv.wait_until(lk, t, Pred(test2));
|
||||
Clock::time_point t1 = Clock::now();
|
||||
if (runs == 0)
|
||||
{
|
||||
assert(t1 - t0 < Clock::duration(250));
|
||||
assert(test2 != 0);
|
||||
assert(r);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(t1 - t0 - Clock::duration(250) < Clock::duration(250+2));
|
||||
assert(test2 == 0);
|
||||
assert(!r);
|
||||
}
|
||||
++runs;
|
||||
} catch(...) {
|
||||
std::cout << "ERROR exception" << __LINE__ << std::endl;
|
||||
assert(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_TEST(t1 - t0 - Clock::duration(250) < Clock::duration(250+2));
|
||||
BOOST_TEST(test2 == 0);
|
||||
BOOST_TEST(!r);
|
||||
}
|
||||
++runs;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
boost::thread t(f);
|
||||
@@ -100,9 +108,13 @@ int main()
|
||||
lk.unlock();
|
||||
cv.notify_one();
|
||||
t.join();
|
||||
} catch(...) {
|
||||
BOOST_TEST(false);
|
||||
std::cout << "ERROR exception" << __LINE__ << std::endl;
|
||||
}
|
||||
test1 = 0;
|
||||
test2 = 0;
|
||||
try
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mut);
|
||||
boost::thread t(f);
|
||||
@@ -112,6 +124,9 @@ int main()
|
||||
BOOST_TEST(test1 != 0);
|
||||
lk.unlock();
|
||||
t.join();
|
||||
} catch(...) {
|
||||
BOOST_TEST(false);
|
||||
std::cout << "ERROR exception" << __LINE__ << std::endl;
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
|
||||
@@ -89,12 +89,15 @@ int main()
|
||||
}
|
||||
{
|
||||
// empty queue push rvalue succeeds
|
||||
boost::sync_bounded_queue<int> q(2);
|
||||
boost::sync_bounded_queue<int> q(3);
|
||||
q.push(1);
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
q.push(2);
|
||||
BOOST_TEST_EQ(q.size(), 2u);
|
||||
q.push(2);
|
||||
BOOST_TEST_EQ(q.size(), 3u);
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST( q.full());
|
||||
BOOST_TEST_EQ(q.size(), 2u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
@@ -317,12 +320,15 @@ int main()
|
||||
}
|
||||
{
|
||||
// empty queue push rvalue succeeds
|
||||
boost::sync_bounded_queue<int> q(2);
|
||||
boost::sync_bounded_queue<int> q(3);
|
||||
q.push_back(1);
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
q.push_back(2);
|
||||
BOOST_TEST_EQ(q.size(), 2u);
|
||||
q.push_back(3);
|
||||
BOOST_TEST_EQ(q.size(), 3u);
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST( q.full());
|
||||
BOOST_TEST_EQ(q.size(), 2u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
|
||||
@@ -3,46 +3,64 @@
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
//#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
|
||||
#include <iostream>
|
||||
//#include <thread>
|
||||
|
||||
#define BOOST_THREAD_PROVIDES_FUTURE
|
||||
#define BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
#define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
#include <boost/thread/executors/loop_executor.hpp>
|
||||
#include <boost/thread/executors/serial_executor_cont.hpp>
|
||||
#include <boost/thread/executors/serial_executor.hpp>
|
||||
#endif
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/atomic.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main()
|
||||
{
|
||||
#if __cplusplus >= 201103L
|
||||
static std::size_t const nWorks = 100000;
|
||||
boost::atomic<unsigned> execCount(0u);
|
||||
boost::loop_executor ex;
|
||||
|
||||
//thread t([&ex]()
|
||||
boost::thread t([&ex]()
|
||||
{
|
||||
ex.loop();
|
||||
});
|
||||
|
||||
{
|
||||
//boost::serial_executor_cont serial(ex);
|
||||
boost::serial_executor serial(ex);
|
||||
|
||||
for (size_t i = 0; i < 100000; i++)
|
||||
serial.submit([i] {
|
||||
for (size_t i = 0; i < nWorks; i++)
|
||||
serial.submit([i, &execCount] {
|
||||
//std::cout << i << ".";
|
||||
++execCount;
|
||||
});
|
||||
|
||||
serial.close();
|
||||
}
|
||||
unsigned const cnt = execCount.load();
|
||||
if (cnt != nWorks) {
|
||||
// Since the serial_executor is closed, all work should have been done,
|
||||
// even though the loop_executor ex is not.
|
||||
std::cerr << "Only " << cnt << " of " << nWorks << " works executed!\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ex.try_executing_one()) {
|
||||
std::cerr
|
||||
<< "loop_executor::try_executing_one suceeded on closed executor!\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
ex.close();
|
||||
|
||||
t.join();
|
||||
std::cout << "end" << std::endl;
|
||||
std::cout << "end\n" << std::endl;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
64
test/test_12293.cpp
Normal file
64
test/test_12293.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
// Copyright (C) 2014 Vicente Botet
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
|
||||
// BoostFutureTest.cpp : Defines the entry point for the console application.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
|
||||
// boost version 1.60.0
|
||||
// has the following set.
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
// #define BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
|
||||
#include <boost/thread/future.hpp>
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
#if __cplusplus >= 201103L
|
||||
|
||||
int value = 0;
|
||||
int tmpValue = 0;
|
||||
boost::promise<void> promise1;
|
||||
boost::promise<void> promise2;
|
||||
|
||||
auto future1 = promise1.get_future();
|
||||
|
||||
auto waitFuture = future1.then([&tmpValue, &promise2](boost::future<void> future){
|
||||
assert(future.is_ready()); // this works correctly and is ready.
|
||||
|
||||
auto fut = boost::async(boost::launch::async, [&promise2, &tmpValue](){
|
||||
boost::this_thread::sleep_for(boost::chrono::seconds(1));
|
||||
tmpValue = 1;
|
||||
promise2.set_value();
|
||||
std::cout << "Step 2 "<< std::endl; // should print 1 but prints 0
|
||||
});
|
||||
std::cout << "Step 1 "<< std::endl; // should print 1 but prints 0
|
||||
|
||||
return promise2.get_future();
|
||||
//return ;
|
||||
}).then([&value, &tmpValue](boost::future<boost::future<void>> future){
|
||||
//}).then([&value, &tmpValue](boost::future<void> future){
|
||||
// error: no matching function for call to ‘boost::future<boost::future<void> >::then(main()::<lambda(boost::future<void>)>)’
|
||||
// as expected
|
||||
|
||||
assert(future.is_ready()); // this doesn't work correctly and is not ready.
|
||||
|
||||
|
||||
value = tmpValue;
|
||||
});
|
||||
|
||||
|
||||
promise1.set_value();
|
||||
waitFuture.wait();
|
||||
|
||||
std::cout << "value = " << value << std::endl; // should print 1 but prints 0
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
21
test/test_12949.cpp
Normal file
21
test/test_12949.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright (C) 2017 Vicente Botet
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
//#define BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
|
||||
|
||||
//#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
|
||||
void f()
|
||||
{
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(10)); // **
|
||||
}
|
||||
int main()
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ using namespace boost;
|
||||
|
||||
int main() {
|
||||
atomic<size_t> total(0), failures(0);
|
||||
|
||||
|
||||
#pragma omp parallel shared(total, failures) num_threads(1000)
|
||||
{
|
||||
mutex mtx;
|
||||
@@ -20,10 +20,10 @@ int main() {
|
||||
}
|
||||
if(failures)
|
||||
std::cout << "There were " << failures << " failures out of " << total << " timed waits." << std::endl;
|
||||
if((100*failures)/total>10)
|
||||
if((100*failures)/total>40)
|
||||
{
|
||||
std::cerr << "This exceeds 10%, so failing the test." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/once.hpp>
|
||||
#include <iostream>
|
||||
|
||||
#define LOG \
|
||||
if (false) {} else std::cout << std::endl << __FILE__ << "[" << __LINE__ << "]"
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <boost/thread/xtime.hpp>
|
||||
#include "./util.inl"
|
||||
#include "./shared_mutex_locking_thread.hpp"
|
||||
#include <iostream>
|
||||
|
||||
#define CHECK_LOCKED_VALUE_EQUAL(mutex_name,value,expected_value) \
|
||||
{ \
|
||||
|
||||
@@ -26,26 +26,28 @@
|
||||
unsigned throw_one = 0xFFFF;
|
||||
|
||||
#if defined _GLIBCXX_THROW
|
||||
inline void* operator new(std::size_t s) _GLIBCXX_THROW (std::bad_alloc)
|
||||
void* operator new(std::size_t s) _GLIBCXX_THROW (std::bad_alloc)
|
||||
#elif defined BOOST_MSVC
|
||||
inline void* operator new(std::size_t s)
|
||||
void* operator new(std::size_t s)
|
||||
#elif __cplusplus > 201402L
|
||||
void* operator new(std::size_t s)
|
||||
#else
|
||||
void* operator new(std::size_t s) throw (std::bad_alloc)
|
||||
#endif
|
||||
{
|
||||
std::cout << __FILE__ << ":" << __LINE__ << std::endl;
|
||||
//std::cout << __FILE__ << ":" << __LINE__ << std::endl;
|
||||
if (throw_one == 0) throw std::bad_alloc();
|
||||
--throw_one;
|
||||
return std::malloc(s);
|
||||
}
|
||||
|
||||
#if defined BOOST_MSVC
|
||||
inline void operator delete(void* p)
|
||||
void operator delete(void* p)
|
||||
#else
|
||||
inline void operator delete(void* p) throw ()
|
||||
void operator delete(void* p) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
#endif
|
||||
{
|
||||
std::cout << __FILE__ << ":" << __LINE__ << std::endl;
|
||||
//std::cout << __FILE__ << ":" << __LINE__ << std::endl;
|
||||
std::free(p);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,11 +29,13 @@ unsigned throw_one = 0xFFFF;
|
||||
void* operator new(std::size_t s) _GLIBCXX_THROW (std::bad_alloc)
|
||||
#elif defined BOOST_MSVC
|
||||
void* operator new(std::size_t s)
|
||||
#elif __cplusplus > 201402L
|
||||
void* operator new(std::size_t s)
|
||||
#else
|
||||
void* operator new(std::size_t s) throw (std::bad_alloc)
|
||||
#endif
|
||||
{
|
||||
std::cout << __FILE__ << ":" << __LINE__ << std::endl;
|
||||
//std::cout << __FILE__ << ":" << __LINE__ << std::endl;
|
||||
if (throw_one == 0) throw std::bad_alloc();
|
||||
--throw_one;
|
||||
return std::malloc(s);
|
||||
@@ -42,10 +44,10 @@ void* operator new(std::size_t s) throw (std::bad_alloc)
|
||||
#if defined BOOST_MSVC
|
||||
void operator delete(void* p)
|
||||
#else
|
||||
void operator delete(void* p) throw ()
|
||||
void operator delete(void* p) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
#endif
|
||||
{
|
||||
std::cout << __FILE__ << ":" << __LINE__ << std::endl;
|
||||
//std::cout << __FILE__ << ":" << __LINE__ << std::endl;
|
||||
std::free(p);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,9 +28,11 @@
|
||||
unsigned throw_one = 0xFFFF;
|
||||
|
||||
#if defined _GLIBCXX_THROW
|
||||
inline void* operator new(std::size_t s) _GLIBCXX_THROW (std::bad_alloc)
|
||||
void* operator new(std::size_t s) _GLIBCXX_THROW (std::bad_alloc)
|
||||
#elif defined BOOST_MSVC
|
||||
inline void* operator new(std::size_t s)
|
||||
void* operator new(std::size_t s)
|
||||
#elif __cplusplus > 201402L
|
||||
void* operator new(std::size_t s)
|
||||
#else
|
||||
void* operator new(std::size_t s) throw (std::bad_alloc)
|
||||
#endif
|
||||
@@ -41,9 +43,9 @@ void* operator new(std::size_t s) throw (std::bad_alloc)
|
||||
}
|
||||
|
||||
#if defined BOOST_MSVC
|
||||
inline void operator delete(void* p)
|
||||
void operator delete(void* p)
|
||||
#else
|
||||
inline void operator delete(void* p) throw ()
|
||||
void operator delete(void* p) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
#endif
|
||||
{
|
||||
std::free(p);
|
||||
|
||||
Reference in New Issue
Block a user