mirror of
https://github.com/boostorg/thread.git
synced 2026-02-03 09:42:16 +00:00
Compare commits
227 Commits
feature/no
...
boost-1.65
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
748fdee203 | ||
|
|
db6de8fd42 | ||
|
|
32229388f5 | ||
|
|
333365aefe | ||
|
|
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 | ||
|
|
5363e099e4 | ||
|
|
65f98979ff | ||
|
|
496acc1161 | ||
|
|
30dff7f84a | ||
|
|
7cb5d5bb46 | ||
|
|
74c98b7fab | ||
|
|
2ed0c2ad5f | ||
|
|
c969a6cf9c | ||
|
|
c7348b29cf | ||
|
|
f79d51f099 | ||
|
|
0d850b47ab | ||
|
|
9bbf9bed80 | ||
|
|
aadf0acce3 | ||
|
|
bd0379af57 | ||
|
|
336259c36a | ||
|
|
544eda51bd | ||
|
|
e16705a72a | ||
|
|
61a26492c3 | ||
|
|
854c61f597 | ||
|
|
4d4ddcdc36 | ||
|
|
9347d9b731 | ||
|
|
0a4733c9ad | ||
|
|
b96d05461f | ||
|
|
41f19bb098 | ||
|
|
050a45aaa4 | ||
|
|
23cff22e5a | ||
|
|
a75995475a | ||
|
|
3ac5fd0916 | ||
|
|
56bce64d32 | ||
|
|
4385984215 | ||
|
|
3391bf87c6 | ||
|
|
bc6b31e1f7 | ||
|
|
425b9924f0 | ||
|
|
84720b7664 | ||
|
|
1309e9aa4b | ||
|
|
50a926e973 | ||
|
|
a0bda34054 | ||
|
|
3a9a296e55 | ||
|
|
184d7504b7 | ||
|
|
2f8b5794b7 | ||
|
|
7e7d3bf1a7 | ||
|
|
f8b76aa907 | ||
|
|
7eeae5b265 | ||
|
|
e71f52f9ed | ||
|
|
cd41de6e3f | ||
|
|
7879a4c286 | ||
|
|
c70647988d | ||
|
|
11f18980ca | ||
|
|
866ff746ae | ||
|
|
12e2c8aaca | ||
|
|
807f429e17 | ||
|
|
046d716bbf | ||
|
|
5450e98c6b | ||
|
|
5b9c1fad85 | ||
|
|
c52a34c2cf | ||
|
|
fc748dbddf | ||
|
|
58c6b384cc | ||
|
|
e34d343c12 | ||
|
|
7c1570328e | ||
|
|
eeb24a6a6a | ||
|
|
25b2062881 | ||
|
|
9d33a59542 | ||
|
|
41f93eb513 | ||
|
|
63484911c6 | ||
|
|
bb2c38aa61 | ||
|
|
8cf36f18cc | ||
|
|
97895e410f | ||
|
|
7ffdc5e10a | ||
|
|
25864ce33a | ||
|
|
f0c50a00c0 | ||
|
|
b511472614 | ||
|
|
13c15cd002 | ||
|
|
1296bf4de9 | ||
|
|
9c80dd207e | ||
|
|
0f2fed0577 | ||
|
|
96390e1b46 | ||
|
|
e2ff1e4c67 | ||
|
|
49ab2e8619 | ||
|
|
96b96b4e42 | ||
|
|
a774cac3f2 | ||
|
|
6ec16408fc | ||
|
|
850f3eced3 | ||
|
|
fde2e061f5 | ||
|
|
e5c086cef4 | ||
|
|
0b5e4f88b5 | ||
|
|
8d150587fa | ||
|
|
206ff0ba7c | ||
|
|
0ef1b1b760 | ||
|
|
ab9f931bce | ||
|
|
21b084384c | ||
|
|
ccca616330 | ||
|
|
2494f3fc7a | ||
|
|
2c3acef281 | ||
|
|
587ad42548 | ||
|
|
ef401d81db | ||
|
|
57f34e1ea4 | ||
|
|
daae305bf7 | ||
|
|
55a1325f30 | ||
|
|
46f0be2dce | ||
|
|
98dbc9da41 | ||
|
|
640e1acb98 | ||
|
|
7f2535015d | ||
|
|
aab2891cdb | ||
|
|
8bbe005bbc | ||
|
|
db5898ba46 | ||
|
|
c7a5122fd3 | ||
|
|
b932b8c015 | ||
|
|
411798367b | ||
|
|
e29a4129e8 | ||
|
|
159868ac77 | ||
|
|
f6febf8dfc | ||
|
|
f65e89a85a | ||
|
|
2fd8a8dd55 | ||
|
|
bb47c16939 | ||
|
|
9db70b803d | ||
|
|
47357de276 | ||
|
|
02fd2d041b | ||
|
|
382ac5a426 | ||
|
|
317a735836 | ||
|
|
ae22c68ab7 | ||
|
|
4fb88b29fa | ||
|
|
2661c06698 | ||
|
|
a45f36cbc6 | ||
|
|
5fba7f88a6 | ||
|
|
ad7b36dd34 | ||
|
|
408d82ded9 | ||
|
|
3f5c0bfb6c | ||
|
|
8a5cf38a3c | ||
|
|
0ddc3d40fa | ||
|
|
565c8e0bb8 | ||
|
|
6954e6ca64 | ||
|
|
568275dc5f | ||
|
|
1d04db8887 | ||
|
|
83f877a238 | ||
|
|
7beae6ac06 | ||
|
|
dc078f0394 | ||
|
|
47f615d073 | ||
|
|
6374e09021 | ||
|
|
9f55587ab0 | ||
|
|
7079a80edf | ||
|
|
674e1304ef | ||
|
|
4ad37504ee | ||
|
|
29849ca3ec | ||
|
|
a636c8d605 | ||
|
|
dbf28a4ac4 | ||
|
|
dbf0160b1e | ||
|
|
60a8cb9b5c | ||
|
|
8cba434c59 | ||
|
|
feab8add3f | ||
|
|
f36857ffef | ||
|
|
4ba8415b08 | ||
|
|
aa608685af | ||
|
|
ba43e202c3 | ||
|
|
3edbf67ef0 | ||
|
|
7b67789f98 | ||
|
|
3f7f34b634 | ||
|
|
c0fe04ecc9 | ||
|
|
eb6d819218 | ||
|
|
578bb1b3ed | ||
|
|
40b3dc0c2c | ||
|
|
55536c3e23 | ||
|
|
2866734b15 | ||
|
|
c0317c5206 | ||
|
|
06d2571ec6 | ||
|
|
fdaba4efe7 | ||
|
|
8a7cd83123 | ||
|
|
98a5e343f8 | ||
|
|
89d8e18c82 | ||
|
|
d9492530bd | ||
|
|
f6c732b124 | ||
|
|
dcc3227668 | ||
|
|
b3d237731a | ||
|
|
4321b59c1e | ||
|
|
67759325eb | ||
|
|
8153e2a652 | ||
|
|
7876163c68 | ||
|
|
805fa41a4e | ||
|
|
0e6376d93a | ||
|
|
bf1fc5158e | ||
|
|
1e4e9ab84c | ||
|
|
88ab663ac5 | ||
|
|
9a4fbbec5d | ||
|
|
c7df715709 | ||
|
|
730cb550e6 | ||
|
|
a3497e1ffc | ||
|
|
f25bc8bbab | ||
|
|
0f6a3ebbe5 | ||
|
|
287100119a | ||
|
|
d9594e7fc8 | ||
|
|
855e56076b | ||
|
|
3c6a183aa3 |
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>
|
||||
|
||||
@@ -60,7 +60,8 @@ project boost/thread
|
||||
<toolset>gcc:<cxxflags>-Wno-long-long
|
||||
#<toolset>gcc:<cxxflags>-ansi
|
||||
#<toolset>gcc:<cxxflags>-fpermissive
|
||||
<toolset>gcc:<cxxflags>-Wno-variadic-macros
|
||||
<toolset>gcc-4:<cxxflags>-Wno-variadic-macros
|
||||
<toolset>gcc-5:<cxxflags>-Wno-variadic-macros
|
||||
#<toolset>gcc:<cxxflags>-Wunused-local-typedefs
|
||||
<toolset>gcc:<cxxflags>-Wunused-function
|
||||
<toolset>gcc:<cxxflags>-Wno-unused-parameter
|
||||
@@ -70,7 +71,9 @@ project boost/thread
|
||||
#<toolset>darwin:<cxxflags>-ansi
|
||||
<toolset>darwin:<cxxflags>-fpermissive
|
||||
<toolset>darwin:<cxxflags>-Wno-long-long
|
||||
<toolset>darwin:<cxxflags>-Wno-variadic-macros
|
||||
#<toolset>darwin:<cxxflags>-Wno-variadic-macros
|
||||
<toolset>darwin-4:<cxxflags>-Wno-variadic-macros
|
||||
<toolset>darwin-5:<cxxflags>-Wno-variadic-macros
|
||||
#<toolset>darwin:<cxxflags>-Wunused-local-typedefs
|
||||
<toolset>darwin:<cxxflags>-Wunused-function
|
||||
<toolset>darwin:<cxxflags>-Wno-unused-parameter
|
||||
@@ -123,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)
|
||||
@@ -313,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. ]]
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[/
|
||||
(C) Copyright 2007-11 Anthony Williams.
|
||||
(C) Copyright 2011-15 Vicente J. Botet Escriba.
|
||||
(C) Copyright 2011-16 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,82 @@
|
||||
|
||||
[section:changes History]
|
||||
|
||||
[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 trunk 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:]
|
||||
@@ -23,11 +99,16 @@ Please take a look at [@http://www.boost.org/development/tests/master/developer/
|
||||
|
||||
[*New Experimental Features:]
|
||||
|
||||
|
||||
* [@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 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
|
||||
@@ -35,23 +116,33 @@ Please take a look at [@http://www.boost.org/development/tests/master/developer/
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9309 #9309] test_latch fails often on clang-darwin-tot11
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10788 #10788] GetLogicalProcessor isn't available for Windows platform less or equals to 0x0502
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11090 #11090] ex_future_unwrap- ThreadSanitizer: lock-order-inversion (potential deadlock)
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11158 #11158] Pthread thread deadlock when faketime used
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11174 #11174] boost::condition_variable::timed_wait with predicate unexpectedly wakes up while should wait infinite
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11185 #11185] Incorrect URL redirection
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11192 #11192] boost::future<>::then() with an executor doesn't compile when the callback returns a future
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11250 #11250] future made from make_exceptional fails on assertion in destructor
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11256 #11256] future<>::is_ready() == false in continuation function
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11158 #11158] Pthread thread deadlock when faketime used
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11261 #11261] bad use of scoped threads in basic_thread_pool
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11262 #11262] bad use of direct pointer in shared_state_nullary_task
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11263 #11263] lock already locked lock
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11266 #11266] boost::packaged_task has invalid variadic signature
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11302 #11302] boost thread doesn't build with BOOST_THREAD_PATCH.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11322 #11322] sleep_for() nanoseconds overload will always return too early on windows
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11329 #11329] using declarative for GetProcessHeap, .... fails
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11368 #11368] boost thread's usage of CreateWaitableTimer wakes PC from sleep (doh)
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11377 #11377] Boost condition variable always waits for system clock deadline
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11435 #11435] gcc compiler warning in future.hpp
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11555 #11555] devector.hpp assumes allocator_traits_type is always present
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11562 #11562] Timer (using steady_clock) expires after computer time is set forward on Ubuntu 64-bit
|
||||
* [@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/11672 #11672] Thread: Should use unique_ptr, not auto_ptr
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11688 #11688] thread::try_join_until: Avoid busy wait if system clock changes
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11672 #11716] ::then(f) should inherit the parent Executor
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11795 #11795] Incorrect version specification for documentation of thread destructor
|
||||
* [@http://svn.boost.org/trac/boost/ticket/11796 #11796] Thread move assignment operator, does not detach previous thread data
|
||||
* [@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:
|
||||
|
||||
|
||||
@@ -29,9 +29,11 @@
|
||||
|
||||
enum class launch
|
||||
{
|
||||
none = unspecified,
|
||||
async = unspecified,
|
||||
deferred = unspecified,
|
||||
executor = unspecified,
|
||||
inherit = unspecified,
|
||||
any = async | deferred
|
||||
};
|
||||
|
||||
@@ -125,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>
|
||||
@@ -165,14 +167,27 @@
|
||||
|
||||
enum class launch
|
||||
{
|
||||
none = unspecified,
|
||||
async = unspecified,
|
||||
deferred = unspecified,
|
||||
executor = unspecified,
|
||||
inherit = unspecified,
|
||||
any = async | deferred
|
||||
};
|
||||
|
||||
The enum type launch is a bitmask type with launch::async and launch::deferred denoting individual bits.
|
||||
|
||||
A future created with `promise<>` or with a `packaged_task<>` or with `make_ready_future`/`make_exceptional_future` (has no associated launch policy), has an implicit a launch policy of `launch::none`.
|
||||
|
||||
A future created by `async(launch::async, ...)` or `::then(launch::async, ...)` has associated a launch policy `launch::async`.
|
||||
A future created by `async(launch::deferred, ...)` or `::then(launch::deferred, ...)` has associated a launch policy `launch::deferred`.
|
||||
A future created by `async(Executor, ...)` or `::then(Executor, ...)` or `::then(launch::executor, ...)` has associated a launch policy `launch::executor`.
|
||||
A future created by `async(...)` or `::then(...)` has associated a launch policy `launch::none`.
|
||||
|
||||
A future created by `::then(launch::inherit, ...)` has associated a launch policy parent future.
|
||||
|
||||
The `executor` and the `inherit` launch policies have a sense only can be user only on `then()`.
|
||||
|
||||
[endsect]
|
||||
[///////////////////////////////////////////////////////////////////////////]
|
||||
[section:is_error_code_enum Specialization `is_error_code_enum<future_errc>`]
|
||||
@@ -334,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
|
||||
@@ -343,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>
|
||||
@@ -438,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 :(]
|
||||
@@ -833,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.]]
|
||||
|
||||
@@ -883,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>
|
||||
@@ -898,29 +913,41 @@ 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.]]
|
||||
|
||||
[[Requires:] [`INVOKE(DECAY_COPY (std::forward<F>(func)), std::move(*this))` shall be a valid expression.]]
|
||||
|
||||
[[Effects:] [
|
||||
|
||||
All the functions create a shared state that is associated with the returned future object. The further behavior of the functions is as follows.
|
||||
All the functions create a shared state that is associated with the returned future object. Additionally,
|
||||
|
||||
- The continuation is called when the object's shared state is ready (has a value or exception stored).
|
||||
- When the object's shared state is ready, the continuation
|
||||
`INVOKE(DECAY_COPY(std::forward<F>(func)), std::move(*this))` is called depending on the overload (see below) with the call to DECAY_COPY() being evaluated in the thread that called then.
|
||||
|
||||
- The continuation launches according to the specified policy or executor.
|
||||
- Any value returned from the continuation is stored as the result in the shared state of the resulting `future`.
|
||||
Any exception propagated from the execution of the continuation is stored as the exceptional result in the shared state of the resulting `future`.
|
||||
|
||||
- When the executor or launch policy is not provided the continuation inherits the
|
||||
parent's launch policy or executor.
|
||||
|
||||
- Any value returned from the continuation is stored as the result in the shared state of the resulting `future`. Any exception propagated from the execution of the continuation is stored as the exceptional result in the shared state of the resulting `future`.
|
||||
The continuation launches according to the specified policy or executor or noting.
|
||||
|
||||
- If the parent was created with `promise<>` or with a `packaged_task<>` (has no associated launch policy), the
|
||||
continuation behaves the same as the third overload with a policy argument of `launch::async | launch::deferred` and
|
||||
the same argument for `func`.
|
||||
- When the launch policy is `launch::none` the continuation is called on an unspecified thread of execution.
|
||||
|
||||
- If the parent has a policy of `launch::deferred` and the continuation does not have a specified launch policy or
|
||||
scheduler, then the parent is filled by immediately calling `.wait()`, and the policy of the antecedent is
|
||||
- When the launch policy is `launch::async` the continuation is called on a new thread of execution.
|
||||
|
||||
- When the launch policy is `launch::deferred` the continuation is called on demand.
|
||||
|
||||
- When the launch policy is `launch::executor` the continuation is called on one of the thread of execution of the executor.
|
||||
|
||||
- When the launch policy is `launch::inherit` the continuation inherits the parent's launch policy or executor.
|
||||
|
||||
- When the executor or launch policy is not provided (first overload) is if as if launch::none was specified.
|
||||
|
||||
- When the executor is provided (second overload) the continuation is called on one of the thread of execution of the executor.
|
||||
|
||||
- If the parent has a policy of `launch::deferred` and the continuation does not have a specified launch policy
|
||||
executor, then the parent is filled by immediately calling `.wait()`, and the policy of the antecedent is
|
||||
`launch::deferred`.
|
||||
|
||||
]]
|
||||
@@ -1330,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.]]
|
||||
|
||||
@@ -1360,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>
|
||||
@@ -1380,22 +1407,38 @@ shared_future object as a parameter. The second function takes an executor as th
|
||||
the second parameter. The third function takes a launch policy as the first parameter and a callable object as the
|
||||
second parameter.]]
|
||||
|
||||
[[Requires:] [`INVOKE(DECAY_COPY (std::forward<F>(func)), *this)` shall be a valid expression.]]
|
||||
|
||||
[[Effects:] [
|
||||
|
||||
- The continuation is called when the object's shared state is ready (has a value or exception stored).
|
||||
All the functions create a shared state that is associated with the returned future object. Additionally,
|
||||
|
||||
- The continuation launches according to the specified policy or executor.
|
||||
- When the object's shared state is ready, the continuation
|
||||
`INVOKE(DECAY_COPY(std::forward<F>(func)), *this)` is called depending on the overload (see below) with the call to DECAY_COPY() being evaluated in the thread that called then.
|
||||
|
||||
- When the executor or launch policy is not provided the continuation inherits the
|
||||
parent's launch policy or executor.
|
||||
- Any value returned from the continuation is stored as the result in the shared state of the resulting `future`.
|
||||
Any exception propagated from the execution of the continuation is stored as the exceptional result in the shared state of the resulting `future`.
|
||||
|
||||
- If the parent was created with `promise` or with a `packaged_task` (has no associated launch policy), the
|
||||
continuation behaves the same as the third overload with a policy argument of `launch::async | launch::deferred` and
|
||||
the same argument for func.
|
||||
|
||||
- If the parent has a policy of `launch::deferred` and the continuation does not have a specified launch policy or
|
||||
The continuation launches according to the specified policy or executor or noting.
|
||||
|
||||
- When the launch policy is `launch::none` the continuation is called on an unspecified thread of execution.
|
||||
|
||||
- When the launch policy is `launch::async` the continuation is called on a new thread of execution.
|
||||
|
||||
- When the launch policy is `launch::deferred` the continuation is called on demand.
|
||||
|
||||
- When the launch policy is `launch::executor` the continuation is called on one of the thread of execution of the executor.
|
||||
|
||||
- When the launch policy is `launch::inherit` the continuation inherits the parent's launch policy or executor.
|
||||
|
||||
- When the executor or launch policy is not provided (first overload) is if as if launch::none was specified.
|
||||
|
||||
- When the executor is provided (second overload) the continuation is called on one of the thread of execution of the executor.
|
||||
|
||||
- If the parent has a policy of `launch::deferred` and the continuation does not have a specified launch policy
|
||||
executor, then the parent is filled by immediately calling `.wait()`, and the policy of the antecedent is
|
||||
`launch::deferred`
|
||||
`launch::deferred`.
|
||||
|
||||
]]
|
||||
|
||||
@@ -2408,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
|
||||
|
||||
|
||||
@@ -326,7 +326,7 @@ Using a `shared_future` solves the issue
|
||||
|
||||
[heading share()]
|
||||
|
||||
Namming the return type when declaring the `shared_future` is needed; auto is not available within template argument lists.
|
||||
Naming the return type when declaring the `shared_future` is needed; auto is not available within template argument lists.
|
||||
Here `share()` could be used to simplify the code
|
||||
|
||||
void better_second_use( type arg ) {
|
||||
@@ -344,7 +344,7 @@ Here `share()` could be used to simplify the code
|
||||
|
||||
[heading Writing on get()]
|
||||
|
||||
The user can either read or write the future avariable.
|
||||
The user can either read or write the future variable.
|
||||
|
||||
void write_to_get( type arg ) {
|
||||
|
||||
@@ -365,7 +365,7 @@ The user can either read or write the future avariable.
|
||||
This works because the `shared_future<>::get()` function returns a non-const reference to the appropriate storage.
|
||||
Of course the access to this storage must be ensured by the user. The library doesn't ensure the access to the internal storage is thread safe.
|
||||
|
||||
There has been some work by the C++ standard committe on an `atomic_future` that behaves as an `atomic` variable, that is is thread_safe,
|
||||
There has been some work by the C++ standard committee on an `atomic_future` that behaves as an `atomic` variable, that is thread_safe,
|
||||
and a `shared_future` that can be shared between several threads, but there were not enough consensus and time to get it ready for C++11.
|
||||
|
||||
[endsect]
|
||||
@@ -444,7 +444,7 @@ Input Parameters:
|
||||
success and one for error handling. However this option has not been retained for the moment.
|
||||
The lambda function takes a future as its input which carries the exception
|
||||
through. This makes propagating exceptions straightforward. This approach also simplifies the chaining of continuations.
|
||||
* Executor: Providing an overload to `.then`, to take a executor reference places great flexibility over the execution
|
||||
* Executor: Providing an overload to `.then`, to take an executor reference places great flexibility over the execution
|
||||
of the future in the programmer's hand. As described above, often taking a launch policy is not sufficient for powerful
|
||||
asynchronous operations. The lifetime of the executor must outlive the continuation.
|
||||
* Launch policy: if the additional flexibility that the executor provides is not required.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -110,10 +110,10 @@ where
|
||||
* `q` denotes a value of type `Q`,
|
||||
* `e` denotes a value of type Q::value_type,
|
||||
* `u` denotes a value of type Q::size_type,
|
||||
* `lve` denotes a lvalue referece of type Q::value_type,
|
||||
* `rve` denotes a rvalue referece of type Q::value_type:
|
||||
* `lve` denotes an lvalue reference of type Q::value_type,
|
||||
* `rve` denotes an rvalue reference of type Q::value_type:
|
||||
[/* `spe` denotes a shared_ptr<Q::value_type>]
|
||||
* `qs` denotes a variable of of type `queus_op_status`,
|
||||
* `qs` denotes a variable of of type `queue_op_status`,
|
||||
|
||||
|
||||
[/////////////////////////////////////]
|
||||
@@ -246,8 +246,8 @@ where
|
||||
* `e` denotes a value of type `Q::value_type`,
|
||||
* `s` denotes a value of type `queue_status`,
|
||||
* `u` denotes a value of type `Q::size_type`,
|
||||
* `lve` denotes a lvalue referece of type Q::value_type,
|
||||
* `rve` denotes a rvalue referece of type Q::value_type:
|
||||
* `lve` denotes an lvalue reference of type Q::value_type,
|
||||
* `rve` denotes an rvalue reference of type Q::value_type:
|
||||
[/* `spe` denotes a shared_ptr<Q::value_type>]
|
||||
|
||||
|
||||
@@ -357,8 +357,8 @@ where
|
||||
* `q` denotes a value of type `Q`,
|
||||
* `e` denotes a value of type Q::value_type,
|
||||
* `s` denotes a value of type `queue_status`,
|
||||
* `lve` denotes a lvalue referece of type Q::value_type,
|
||||
* `rve` denotes a rvalue referece of type Q::value_type:
|
||||
* `lve` denotes an lvalue reference of type Q::value_type,
|
||||
* `rve` denotes an rvalue reference of type Q::value_type:
|
||||
[/* `spe` denotes a shared_ptr<Q::value_type>]
|
||||
|
||||
|
||||
@@ -545,7 +545,7 @@ Closed queues add the following valid expressions
|
||||
|
||||
[[Return:] [
|
||||
|
||||
- If the queue is closed retun `queue_op_status::closed`,
|
||||
- If the queue is closed return `queue_op_status::closed`,
|
||||
|
||||
- otherwise, return `queue_op_status::success` if no exception is thrown.
|
||||
|
||||
@@ -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.5.0]
|
||||
[version 4.7.2]
|
||||
[authors [Williams, Anthony] [Botet Escriba, Vicente J.]]
|
||||
[copyright 2007-11 Anthony Williams]
|
||||
[copyright 2011-15 Vicente J. Botet Escriba]
|
||||
[copyright 2011-16 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>
|
||||
@@ -255,7 +255,7 @@ does not complete when the specified time has elapsed or reached respectively.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:destructor1 Destructor V1]
|
||||
[section:destructor1 Destructor V1-2]
|
||||
|
||||
When the __thread__ object that represents a thread of execution is destroyed the thread becomes ['detached]. Once a thread is
|
||||
detached, it will continue executing until the invocation of the function or callable object supplied on construction has completed,
|
||||
@@ -264,7 +264,7 @@ object. In this case, the __thread__ object ceases to represent the now-detached
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:destructor2 Destructor V2]
|
||||
[section:destructor2 Destructor V3-X]
|
||||
|
||||
When the __thread__ object that represents a thread of execution is destroyed the program terminates if the thread is __joinable__.
|
||||
|
||||
@@ -280,7 +280,7 @@ You can use a thread_joiner to ensure that the thread has been joined at the thr
|
||||
{
|
||||
boost::thread t(my_func);
|
||||
boost::thread_joiner g(t);
|
||||
// do someting else
|
||||
// do something else
|
||||
} // here the thread_joiner destructor will join the thread before it is destroyed.
|
||||
|
||||
[endsect]
|
||||
@@ -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
|
||||
@@ -410,7 +412,7 @@ Of course all the synchronization facilities provided by Boost.Thread are also a
|
||||
|
||||
The `boost::this_thread` interrupt related functions behave in a degraded mode when called from a thread created using the native interface, i.e. `boost::this_thread::interruption_enabled()` returns false. As consequence the use of `boost::this_thread::disable_interruption` and `boost::this_thread::restore_interruption` will do nothing and calls to `boost::this_thread::interruption_point()` will be just ignored.
|
||||
|
||||
As the single way to interrupt a thread is through a __thread__ instance, `interruption_request()` wiil returns false for the native threads.
|
||||
As the single way to interrupt a thread is through a __thread__ instance, `interruption_request()` will return false for the native threads.
|
||||
|
||||
[heading `pthread_exit` POSIX limitation]
|
||||
|
||||
@@ -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]]
|
||||
|
||||
@@ -964,7 +966,7 @@ predefined __interruption_points__ with interruption enabled .]]
|
||||
|
||||
[section:hardware_concurrency Static member function `hardware_concurrency()`]
|
||||
|
||||
unsigned hardware_concurrency() noexecpt;
|
||||
unsigned hardware_concurrency() noexcept;
|
||||
|
||||
[variablelist
|
||||
|
||||
@@ -979,7 +981,7 @@ or 0 if this information is not available.]]
|
||||
|
||||
[section:physical_concurrency Static member function `physical_concurrency()`]
|
||||
|
||||
unsigned physical_concurrency() noexecpt;
|
||||
unsigned physical_concurrency() noexcept;
|
||||
|
||||
[variablelist
|
||||
|
||||
@@ -1290,7 +1292,7 @@ instances of __thread_id__ `a` and `b` is the same if `a==b`, and different if `
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Constructs a thread atrributes instance with its default values.]]
|
||||
[[Effects:] [Constructs a thread attributes instance with its default values.]]
|
||||
|
||||
[[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.]]
|
||||
|
||||
@@ -1532,7 +1534,7 @@ do not throw exceptions. __thread_interrupted__ if the current thread of executi
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Suspends the current thread until the duration specified by
|
||||
[[Effects:] [Suspends the current thread until the duration specified
|
||||
by `rel_time` has elapsed.]]
|
||||
|
||||
[[Throws:] [Nothing if operations of chrono::duration<Rep, Period> do not throw exceptions. __thread_interrupted__ if the current thread of execution is interrupted.]]
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -41,10 +41,28 @@ int main()
|
||||
for (int i=0; i< number_of_tests; i++)
|
||||
try
|
||||
{
|
||||
boost::future<boost::future<int> > outer_future = boost::async(boost::launch::async, &p2);
|
||||
boost::future<int> inner_future = outer_future.unwrap();
|
||||
int ii = inner_future.get();
|
||||
BOOST_THREAD_LOG << "ii= "<< ii << "" << BOOST_THREAD_END_LOG;
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
{
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
{
|
||||
boost::future<boost::future<int> > outer_future = boost::async(boost::launch::async, &p2);
|
||||
boost::future<int> inner_future = outer_future.unwrap();
|
||||
inner_future.wait();
|
||||
int ii = inner_future.get();
|
||||
BOOST_THREAD_LOG << "ii= "<< ii << "" << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
{
|
||||
boost::future<boost::future<int> > outer_future = boost::async(boost::launch::async, &p2);
|
||||
boost::future<int> inner_future = outer_future.unwrap();
|
||||
int ii = inner_future.get();
|
||||
BOOST_THREAD_LOG << "ii= "<< ii << "" << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
|
||||
@@ -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,6 +12,8 @@
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/thread/detail/platform.hpp>
|
||||
|
||||
#define BOOST_THREAD_USEFIXES_TIMESPEC
|
||||
//#define BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
|
||||
//#define BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS
|
||||
// ATTRIBUTE_MAY_ALIAS
|
||||
|
||||
@@ -100,8 +102,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 +306,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
|
||||
|
||||
@@ -72,13 +72,21 @@ namespace boost
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker& operator=(BOOST_THREAD_RV_REF(invoker) f)
|
||||
{
|
||||
f_ = boost::move(BOOST_THREAD_RV(f).f_);
|
||||
if (this != &f)
|
||||
{
|
||||
f_ = boost::move(BOOST_THREAD_RV(f).f_);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker& operator=( BOOST_THREAD_COPY_ASSIGN_REF(invoker) f)
|
||||
{
|
||||
f_ = f.f_;
|
||||
if (this != &f)
|
||||
{
|
||||
f_ = f.f_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
result_type operator()()
|
||||
@@ -91,7 +99,7 @@ namespace boost
|
||||
result_type
|
||||
execute(tuple_indices<Indices...>)
|
||||
{
|
||||
return invoke(boost::move(csbl::get<0>(f_)), boost::move(csbl::get<Indices>(f_))...);
|
||||
return detail::invoke(boost::move(csbl::get<0>(f_)), boost::move(csbl::get<Indices>(f_))...);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -128,7 +136,7 @@ namespace boost
|
||||
result_type
|
||||
execute(tuple_indices<Indices...>)
|
||||
{
|
||||
return invoke<R>(boost::move(csbl::get<0>(f_)), boost::move(csbl::get<Indices>(f_))...);
|
||||
return detail::invoke<R>(boost::move(csbl::get<0>(f_)), boost::move(csbl::get<Indices>(f_))...);
|
||||
}
|
||||
};
|
||||
//BOOST_THREAD_DCL_MOVABLE_BEG(X) invoker<Fp> BOOST_THREAD_DCL_MOVABLE_END
|
||||
@@ -182,7 +190,7 @@ namespace boost
|
||||
{} \
|
||||
\
|
||||
result_type operator()() { \
|
||||
return invoke(boost::move(fp_) \
|
||||
return detail::invoke(boost::move(fp_) \
|
||||
BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_DCL, ~) \
|
||||
); \
|
||||
} \
|
||||
@@ -307,7 +315,7 @@ namespace boost
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
return invoke(boost::move(fp_)
|
||||
return detail::invoke(boost::move(fp_)
|
||||
, boost::move(v0_)
|
||||
, boost::move(v1_)
|
||||
, boost::move(v2_)
|
||||
@@ -373,7 +381,7 @@ namespace boost
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
return invoke(boost::move(fp_)
|
||||
return detail::invoke(boost::move(fp_)
|
||||
, boost::move(v0_)
|
||||
, boost::move(v1_)
|
||||
, boost::move(v2_)
|
||||
@@ -434,7 +442,7 @@ namespace boost
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
return invoke(boost::move(fp_)
|
||||
return detail::invoke(boost::move(fp_)
|
||||
, boost::move(v0_)
|
||||
, boost::move(v1_)
|
||||
, boost::move(v2_)
|
||||
@@ -490,7 +498,7 @@ namespace boost
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
return invoke(boost::move(fp_)
|
||||
return detail::invoke(boost::move(fp_)
|
||||
, boost::move(v0_)
|
||||
, boost::move(v1_)
|
||||
, boost::move(v2_)
|
||||
@@ -541,7 +549,7 @@ namespace boost
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
return invoke(boost::move(fp_)
|
||||
return detail::invoke(boost::move(fp_)
|
||||
, boost::move(v0_)
|
||||
, boost::move(v1_)
|
||||
, boost::move(v2_)
|
||||
@@ -587,7 +595,7 @@ namespace boost
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
return invoke(boost::move(fp_)
|
||||
return detail::invoke(boost::move(fp_)
|
||||
, boost::move(v0_)
|
||||
, boost::move(v1_)
|
||||
, boost::move(v2_)
|
||||
@@ -628,7 +636,7 @@ namespace boost
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
return invoke(boost::move(fp_)
|
||||
return detail::invoke(boost::move(fp_)
|
||||
, boost::move(v0_)
|
||||
, boost::move(v1_)
|
||||
, boost::move(v2_)
|
||||
@@ -664,7 +672,7 @@ namespace boost
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
return invoke(boost::move(fp_)
|
||||
return detail::invoke(boost::move(fp_)
|
||||
, boost::move(v0_)
|
||||
, boost::move(v1_)
|
||||
);
|
||||
@@ -695,7 +703,7 @@ namespace boost
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
return invoke(boost::move(fp_)
|
||||
return detail::invoke(boost::move(fp_)
|
||||
, boost::move(v0_)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace boost
|
||||
void run2(tuple_indices<Indices...>)
|
||||
{
|
||||
|
||||
invoke(std::move(std::get<0>(fp)), std::move(std::get<Indices>(fp))...);
|
||||
detail::invoke(std::move(std::get<0>(fp)), std::move(std::get<Indices>(fp))...);
|
||||
}
|
||||
void run()
|
||||
{
|
||||
@@ -155,7 +155,15 @@ namespace boost
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace thread_detail {
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
#if defined(BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC) && defined(BOOST_THREAD_USEFIXES_TIMESPEC)
|
||||
typedef chrono::steady_clock internal_clock_t;
|
||||
#else
|
||||
typedef chrono::system_clock internal_clock_t;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
class BOOST_THREAD_DECL thread
|
||||
{
|
||||
public:
|
||||
@@ -354,6 +362,8 @@ namespace boost
|
||||
|
||||
#if defined BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE
|
||||
if (joinable()) std::terminate();
|
||||
#else
|
||||
detach();
|
||||
#endif
|
||||
thread_info=BOOST_THREAD_RV(other).thread_info;
|
||||
BOOST_THREAD_RV(other).thread_info.reset();
|
||||
@@ -480,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);
|
||||
@@ -494,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
|
||||
@@ -512,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());
|
||||
@@ -533,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)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <boost/thread/thread_only.hpp>
|
||||
#include <boost/thread/scoped_thread.hpp>
|
||||
#include <boost/thread/csbl/vector.hpp>
|
||||
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
|
||||
@@ -13,8 +13,7 @@
|
||||
// boost::thread::future requires exception handling
|
||||
// due to boost::exception::exception_ptr dependency
|
||||
|
||||
#define BOOST_THREAD_CONTINUATION_SYNC
|
||||
//#define BOOST_THREAD_FUTURE_BLOCKING
|
||||
//#define BOOST_THREAD_CONTINUATION_SYNC
|
||||
|
||||
#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),
|
||||
@@ -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)
|
||||
{
|
||||
@@ -1432,6 +1437,10 @@ namespace boost
|
||||
BOOST_THREAD_FUTURE<Rp>
|
||||
make_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
|
||||
|
||||
template <class F, class Rp, class Fp>
|
||||
BOOST_THREAD_FUTURE<Rp>
|
||||
make_future_sync_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
|
||||
|
||||
template <class F, class Rp, class Fp>
|
||||
BOOST_THREAD_FUTURE<Rp>
|
||||
make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
|
||||
@@ -1444,6 +1453,11 @@ namespace boost
|
||||
BOOST_THREAD_FUTURE<Rp>
|
||||
make_shared_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
|
||||
|
||||
template<typename F, typename Rp, typename Fp>
|
||||
BOOST_THREAD_FUTURE<Rp>
|
||||
make_shared_future_sync_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
|
||||
|
||||
|
||||
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
template<typename Ex, typename F, typename Rp, typename Fp>
|
||||
BOOST_THREAD_FUTURE<Rp>
|
||||
@@ -1516,6 +1530,10 @@ namespace boost
|
||||
friend BOOST_THREAD_FUTURE<Rp>
|
||||
detail::make_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
|
||||
|
||||
template <class F, class Rp, class Fp>
|
||||
friend BOOST_THREAD_FUTURE<Rp>
|
||||
detail::make_future_sync_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
|
||||
|
||||
template <class F, class Rp, class Fp>
|
||||
friend BOOST_THREAD_FUTURE<Rp>
|
||||
detail::make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
|
||||
@@ -1528,6 +1546,10 @@ namespace boost
|
||||
friend BOOST_THREAD_FUTURE<Rp>
|
||||
detail::make_shared_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
|
||||
|
||||
template<typename F, typename Rp, typename Fp>
|
||||
friend BOOST_THREAD_FUTURE<Rp>
|
||||
detail::make_shared_future_sync_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
|
||||
|
||||
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
template<typename Ex, typename F, typename Rp, typename Fp>
|
||||
friend BOOST_THREAD_FUTURE<Rp>
|
||||
@@ -1617,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))))
|
||||
@@ -1658,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());
|
||||
}
|
||||
@@ -1678,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());
|
||||
}
|
||||
@@ -1704,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());
|
||||
}
|
||||
@@ -1772,6 +1796,10 @@ namespace boost
|
||||
friend BOOST_THREAD_FUTURE<Rp>
|
||||
detail::make_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
|
||||
|
||||
template <class F, class Rp, class Fp>
|
||||
friend BOOST_THREAD_FUTURE<Rp>
|
||||
detail::make_future_sync_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
|
||||
|
||||
template <class F, class Rp, class Fp>
|
||||
friend BOOST_THREAD_FUTURE<Rp>
|
||||
detail::make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
|
||||
@@ -1784,6 +1812,10 @@ namespace boost
|
||||
friend BOOST_THREAD_FUTURE<Rp>
|
||||
detail::make_shared_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
|
||||
|
||||
template<typename F, typename Rp, typename Fp>
|
||||
friend BOOST_THREAD_FUTURE<Rp>
|
||||
detail::make_shared_future_sync_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
|
||||
|
||||
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
template<typename Ex, typename F, typename Rp, typename Fp>
|
||||
friend BOOST_THREAD_FUTURE<Rp>
|
||||
@@ -1911,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());
|
||||
}
|
||||
@@ -1927,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());
|
||||
}
|
||||
@@ -1946,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());
|
||||
}
|
||||
@@ -2005,6 +2037,10 @@ namespace boost
|
||||
friend BOOST_THREAD_FUTURE<Rp>
|
||||
detail::make_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
|
||||
|
||||
template <class F, class Rp, class Fp>
|
||||
friend BOOST_THREAD_FUTURE<Rp>
|
||||
detail::make_future_sync_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
|
||||
|
||||
template <class F, class Rp, class Fp>
|
||||
friend BOOST_THREAD_FUTURE<Rp>
|
||||
detail::make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
|
||||
@@ -3664,9 +3700,6 @@ namespace detail
|
||||
typename decay<ArgTypes>::type...
|
||||
)>::type>
|
||||
async(launch policy, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) {
|
||||
typedef typename boost::result_of<typename decay<F>::type(
|
||||
typename decay<ArgTypes>::type...
|
||||
)>::type R;
|
||||
typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
|
||||
typedef typename BF::result_type Rp;
|
||||
|
||||
@@ -4213,29 +4246,21 @@ namespace detail {
|
||||
////////////////////////////////
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
||||
|
||||
#if defined BOOST_THREAD_CONTINUATION_SYNC
|
||||
#define continuation_shared_state_base shared_state
|
||||
#else
|
||||
#define continuation_shared_state_base future_async_shared_state_base
|
||||
#endif
|
||||
|
||||
namespace detail
|
||||
{
|
||||
//////////////////////
|
||||
// detail::continuation_shared_state
|
||||
//////////////////////
|
||||
template<typename F, typename Rp, typename Fp, template <class> class ShSt=shared_state>
|
||||
struct continuation_shared_state: ShSt<Rp>
|
||||
template<typename F, typename Rp, typename Fp, class ShSt=shared_state<Rp> >
|
||||
struct continuation_shared_state: ShSt
|
||||
{
|
||||
F parent;
|
||||
Fp continuation;
|
||||
shared_ptr<shared_state_base> centinel;
|
||||
|
||||
public:
|
||||
continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
|
||||
: parent(boost::move(f)),
|
||||
continuation(boost::move(c)),
|
||||
centinel(parent.future_)
|
||||
continuation(boost::move(c))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -4250,6 +4275,31 @@ namespace detail
|
||||
} catch(...) {
|
||||
this->mark_exceptional_finish();
|
||||
}
|
||||
// make sure parent is really cleared to prevent memory "leaks"
|
||||
this->parent = F();
|
||||
}
|
||||
|
||||
void call(boost::unique_lock<boost::mutex>& lck) {
|
||||
try {
|
||||
relocker relock(lck);
|
||||
|
||||
// neither continuation nor parent are protected by the lock - call() must only
|
||||
// be called once, and no one else must modify it.
|
||||
Rp res = this->continuation(boost::move(this->parent));
|
||||
|
||||
// make sure parent is really cleared to prevent memory "leaks"
|
||||
this->parent = F();
|
||||
|
||||
relock.lock();
|
||||
|
||||
this->mark_finished_with_result_internal(boost::move(res), lck);
|
||||
} catch (...) {
|
||||
this->mark_exceptional_finish_internal(current_exception(), lck);
|
||||
|
||||
// make sure parent is really cleared to prevent memory "leaks"
|
||||
relocker relock(lck);
|
||||
this->parent = F();
|
||||
}
|
||||
}
|
||||
|
||||
static void run(shared_ptr<boost::detail::shared_state_base> that_)
|
||||
@@ -4261,18 +4311,16 @@ namespace detail
|
||||
~continuation_shared_state() {}
|
||||
};
|
||||
|
||||
template<typename F, typename Fp, template <class> class ShSt>
|
||||
struct continuation_shared_state<F, void, Fp, ShSt>: ShSt<void>
|
||||
template<typename F, typename Fp, class ShSt>
|
||||
struct continuation_shared_state<F, void, Fp, ShSt>: ShSt
|
||||
{
|
||||
F parent;
|
||||
Fp continuation;
|
||||
shared_ptr<shared_state_base> centinel;
|
||||
|
||||
public:
|
||||
continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
|
||||
: parent(boost::move(f)),
|
||||
continuation(boost::move(c)),
|
||||
centinel(parent.future_)
|
||||
continuation(boost::move(c))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -4289,6 +4337,29 @@ namespace detail
|
||||
} catch(...) {
|
||||
this->mark_exceptional_finish();
|
||||
}
|
||||
// make sure parent is really cleared to prevent memory "leaks"
|
||||
this->parent = F();
|
||||
}
|
||||
|
||||
void call(boost::unique_lock<boost::mutex>& lck) {
|
||||
try {
|
||||
{
|
||||
relocker relock(lck);
|
||||
// neither continuation nor parent are protected by the lock - call() must only
|
||||
// be called once, and no one else must modify it.
|
||||
this->continuation(boost::move(this->parent));
|
||||
|
||||
// make sure parent is really cleared to prevent memory "leaks"
|
||||
this->parent = F();
|
||||
}
|
||||
this->mark_finished_with_result_internal(lck);
|
||||
} catch (...) {
|
||||
this->mark_exceptional_finish_internal(current_exception(), lck);
|
||||
|
||||
// make sure parent is really cleared to prevent memory "leaks"
|
||||
relocker relock(lck);
|
||||
this->parent = F();
|
||||
}
|
||||
}
|
||||
|
||||
static void run(shared_ptr<boost::detail::shared_state_base> that_)
|
||||
@@ -4304,26 +4375,43 @@ namespace detail
|
||||
/////////////////////////
|
||||
|
||||
template<typename F, typename Rp, typename Fp>
|
||||
struct future_async_continuation_shared_state: continuation_shared_state<F,Rp,Fp,continuation_shared_state_base>
|
||||
struct future_async_continuation_shared_state: continuation_shared_state<F,Rp,Fp,future_async_shared_state_base<Rp> >
|
||||
{
|
||||
typedef continuation_shared_state<F,Rp,Fp,continuation_shared_state_base> base_type;
|
||||
typedef continuation_shared_state<F,Rp,Fp,future_async_shared_state_base<Rp> > base_type;
|
||||
public:
|
||||
future_async_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
|
||||
: base_type(boost::move(f), boost::forward<Fp>(c))
|
||||
{ }
|
||||
|
||||
void launch_continuation() {
|
||||
#if defined BOOST_THREAD_CONTINUATION_SYNC
|
||||
this->call();
|
||||
#elif defined BOOST_THREAD_FUTURE_BLOCKING
|
||||
#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(&future_async_continuation_shared_state::run, static_shared_from_this(this)).detach();
|
||||
boost::thread(&base_type::run, static_shared_from_this(this)).detach();
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////
|
||||
/// future_sync_continuation_shared_state
|
||||
/////////////////////////
|
||||
|
||||
template<typename F, typename Rp, typename Fp>
|
||||
struct future_sync_continuation_shared_state: continuation_shared_state<F,Rp,Fp,shared_state<Rp> >
|
||||
{
|
||||
typedef continuation_shared_state<F,Rp,Fp,shared_state<Rp> > base_type;
|
||||
public:
|
||||
future_sync_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
|
||||
: base_type(boost::move(f), boost::forward<Fp>(c))
|
||||
{ }
|
||||
|
||||
void launch_continuation() {
|
||||
this->call();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////
|
||||
/// future_executor_continuation_shared_state
|
||||
/////////////////////////
|
||||
@@ -4404,9 +4492,9 @@ namespace detail {
|
||||
/////////////////////////
|
||||
|
||||
template<typename F, typename Rp, typename Fp>
|
||||
struct shared_future_async_continuation_shared_state: continuation_shared_state<F,Rp,Fp,continuation_shared_state_base>
|
||||
struct shared_future_async_continuation_shared_state: continuation_shared_state<F,Rp,Fp,future_async_shared_state_base<Rp> >
|
||||
{
|
||||
typedef continuation_shared_state<F,Rp,Fp,continuation_shared_state_base> base_type;
|
||||
typedef continuation_shared_state<F,Rp,Fp,future_async_shared_state_base<Rp> > base_type;
|
||||
|
||||
public:
|
||||
shared_future_async_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
|
||||
@@ -4415,19 +4503,36 @@ namespace detail {
|
||||
}
|
||||
|
||||
void launch_continuation() {
|
||||
#if defined BOOST_THREAD_CONTINUATION_SYNC
|
||||
this->call();
|
||||
#elif defined BOOST_THREAD_FUTURE_BLOCKING
|
||||
#if defined BOOST_THREAD_FUTURE_BLOCKING
|
||||
boost::lock_guard<boost::mutex> lk(this->mutex);
|
||||
this->thr_ = thread(&shared_future_async_continuation_shared_state::run, static_shared_from_this(this));
|
||||
this->thr_ = boost::thread(&base_type::run, static_shared_from_this(this));
|
||||
#else
|
||||
thread(&shared_future_async_continuation_shared_state::run, static_shared_from_this(this)).detach();
|
||||
boost::thread(&base_type::run, static_shared_from_this(this)).detach();
|
||||
#endif
|
||||
}
|
||||
|
||||
~shared_future_async_continuation_shared_state() {}
|
||||
};
|
||||
|
||||
/////////////////////////
|
||||
/// shared_future_async_continuation_shared_state
|
||||
/////////////////////////
|
||||
|
||||
template<typename F, typename Rp, typename Fp>
|
||||
struct shared_future_sync_continuation_shared_state: continuation_shared_state<F,Rp,Fp,shared_state<Rp> >
|
||||
{
|
||||
typedef continuation_shared_state<F,Rp,Fp,shared_state<Rp> > base_type;
|
||||
|
||||
public:
|
||||
shared_future_sync_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
|
||||
: base_type(boost::move(f), boost::forward<Fp>(c))
|
||||
{
|
||||
}
|
||||
|
||||
void launch_continuation() {
|
||||
this->call();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////
|
||||
/// shared_future_executor_continuation_shared_state
|
||||
/////////////////////////
|
||||
@@ -4475,62 +4580,12 @@ namespace detail {
|
||||
this->set_deferred();
|
||||
}
|
||||
|
||||
virtual void launch_continuation() {
|
||||
boost::unique_lock<boost::mutex> lk(this->mutex);
|
||||
if (this->is_deferred_) {
|
||||
this->is_deferred_=false;
|
||||
this->execute(lk);
|
||||
}
|
||||
virtual void execute(boost::unique_lock<boost::mutex>& lk) {
|
||||
this->parent.wait();
|
||||
this->call(lk);
|
||||
}
|
||||
|
||||
virtual void execute(boost::unique_lock<boost::mutex>& lck) {
|
||||
try {
|
||||
Fp local_fuct=boost::move(this->continuation);
|
||||
F ftmp = boost::move(this->parent);
|
||||
relocker relock(lck);
|
||||
Rp res = local_fuct(boost::move(ftmp));
|
||||
relock.lock();
|
||||
this->mark_finished_with_result_internal(boost::move(res), lck);
|
||||
} catch (...) {
|
||||
this->mark_exceptional_finish_internal(current_exception(), lck);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename F, typename Fp>
|
||||
struct future_deferred_continuation_shared_state<F,void,Fp>: continuation_shared_state<F,void,Fp>
|
||||
{
|
||||
typedef continuation_shared_state<F,void,Fp> base_type;
|
||||
|
||||
public:
|
||||
future_deferred_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
|
||||
: base_type(boost::move(f), boost::forward<Fp>(c))
|
||||
{
|
||||
this->set_deferred();
|
||||
}
|
||||
|
||||
~future_deferred_continuation_shared_state() {
|
||||
}
|
||||
virtual void launch_continuation() {
|
||||
boost::unique_lock<boost::mutex> lk(this->mutex);
|
||||
if (this->is_deferred_) {
|
||||
this->is_deferred_=false;
|
||||
this->execute(lk);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void execute(boost::unique_lock<boost::mutex>& lck) {
|
||||
try {
|
||||
Fp local_fuct=boost::move(this->continuation);
|
||||
F ftmp = boost::move(this->parent);
|
||||
relocker relock(lck);
|
||||
local_fuct(boost::move(ftmp));
|
||||
relock.lock();
|
||||
this->mark_finished_with_result_internal(lck);
|
||||
} catch (...) {
|
||||
this->mark_exceptional_finish_internal(current_exception(), lck);
|
||||
}
|
||||
}
|
||||
virtual void launch_continuation() { }
|
||||
};
|
||||
|
||||
//////////////////////////
|
||||
@@ -4548,59 +4603,12 @@ namespace detail {
|
||||
this->set_deferred();
|
||||
}
|
||||
|
||||
virtual void launch_continuation() {
|
||||
boost::unique_lock<boost::mutex> lk(this->mutex);
|
||||
if (this->is_deferred_) {
|
||||
this->is_deferred_=false;
|
||||
this->execute(lk);
|
||||
}
|
||||
virtual void execute(boost::unique_lock<boost::mutex>& lk) {
|
||||
this->parent.wait();
|
||||
this->call(lk);
|
||||
}
|
||||
|
||||
virtual void execute(boost::unique_lock<boost::mutex>& lck) {
|
||||
try {
|
||||
Fp local_fuct=boost::move(this->continuation);
|
||||
F ftmp = this->parent;
|
||||
relocker relock(lck);
|
||||
Rp res = local_fuct(ftmp);
|
||||
relock.lock();
|
||||
this->mark_finished_with_result_internal(boost::move(res), lck);
|
||||
} catch (...) {
|
||||
this->mark_exceptional_finish_internal(current_exception(), lck);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename F, typename Fp>
|
||||
struct shared_future_deferred_continuation_shared_state<F,void,Fp>: continuation_shared_state<F,void,Fp>
|
||||
{
|
||||
typedef continuation_shared_state<F,void,Fp> base_type;
|
||||
public:
|
||||
shared_future_deferred_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
|
||||
: base_type(boost::move(f), boost::forward<Fp>(c))
|
||||
{
|
||||
this->set_deferred();
|
||||
}
|
||||
|
||||
virtual void launch_continuation() {
|
||||
boost::unique_lock<boost::mutex> lk(this->mutex);
|
||||
if (this->is_deferred_) {
|
||||
this->is_deferred_=false;
|
||||
this->execute(lk);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void execute(boost::unique_lock<boost::mutex>& lck) {
|
||||
try {
|
||||
Fp local_fuct=boost::move(this->continuation);
|
||||
F ftmp = this->parent;
|
||||
relocker relock(lck);
|
||||
local_fuct(ftmp);
|
||||
relock.lock();
|
||||
this->mark_finished_with_result_internal(lck);
|
||||
} catch (...) {
|
||||
this->mark_exceptional_finish_internal(current_exception(), lck);
|
||||
}
|
||||
}
|
||||
virtual void launch_continuation() { }
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
@@ -4633,6 +4641,21 @@ namespace detail {
|
||||
|
||||
return BOOST_THREAD_FUTURE<Rp>(h);
|
||||
}
|
||||
////////////////////////////////
|
||||
// make_future_sync_continuation_shared_state
|
||||
////////////////////////////////
|
||||
template<typename F, typename Rp, typename Fp>
|
||||
BOOST_THREAD_FUTURE<Rp>
|
||||
make_future_sync_continuation_shared_state(
|
||||
boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f,
|
||||
BOOST_THREAD_FWD_REF(Fp) c) {
|
||||
typedef typename decay<Fp>::type Cont;
|
||||
shared_ptr<future_sync_continuation_shared_state<F,Rp, Cont> >
|
||||
h(new future_sync_continuation_shared_state<F,Rp, Cont>(boost::move(f), boost::forward<Fp>(c)));
|
||||
h->init(lock);
|
||||
|
||||
return BOOST_THREAD_FUTURE<Rp>(h);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
// make_future_executor_continuation_shared_state
|
||||
@@ -4684,6 +4707,21 @@ namespace detail {
|
||||
return BOOST_THREAD_FUTURE<Rp>(h);
|
||||
}
|
||||
////////////////////////////////
|
||||
// make_shared_future_sync_continuation_shared_state
|
||||
////////////////////////////////
|
||||
template<typename F, typename Rp, typename Fp>
|
||||
BOOST_THREAD_FUTURE<Rp>
|
||||
make_shared_future_sync_continuation_shared_state(
|
||||
boost::unique_lock<boost::mutex> &lock, F f,
|
||||
BOOST_THREAD_FWD_REF(Fp) c) {
|
||||
typedef typename decay<Fp>::type Cont;
|
||||
shared_ptr<shared_future_sync_continuation_shared_state<F,Rp, Cont> >
|
||||
h(new shared_future_sync_continuation_shared_state<F,Rp, Cont>(f, boost::forward<Fp>(c)));
|
||||
h->init(lock);
|
||||
|
||||
return BOOST_THREAD_FUTURE<Rp>(h);
|
||||
}
|
||||
////////////////////////////////
|
||||
// make_shared_future_executor_continuation_shared_state
|
||||
////////////////////////////////
|
||||
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
@@ -4711,26 +4749,54 @@ 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_);
|
||||
boost::unique_lock<boost::mutex> lock(sentinel->mutex);
|
||||
|
||||
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
|
||||
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)) {
|
||||
this->future_->wait_internal(lock);
|
||||
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)) {
|
||||
assert(this->future_->get_executor());
|
||||
typedef executor Ex;
|
||||
Ex& ex = *(this->future_->get_executor());
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
|
||||
lock, boost::move(*this), boost::forward<F>(func)
|
||||
)));
|
||||
#endif
|
||||
} else if (underlying_cast<int>(policy) & int(launch::inherit)) {
|
||||
|
||||
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)) {
|
||||
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)) {
|
||||
assert(this->future_->get_executor());
|
||||
typedef executor Ex;
|
||||
Ex& ex = *(this->future_->get_executor());
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
|
||||
lock, boost::move(*this), boost::forward<F>(func)
|
||||
)));
|
||||
#endif
|
||||
} else {
|
||||
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 {
|
||||
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)
|
||||
@@ -4747,9 +4813,12 @@ 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_);
|
||||
boost::unique_lock<boost::mutex> lock(sentinel->mutex);
|
||||
|
||||
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
|
||||
lock, boost::move(*this), boost::forward<F>(func)
|
||||
)));
|
||||
@@ -4763,12 +4832,34 @@ namespace detail {
|
||||
template <typename F>
|
||||
inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
|
||||
BOOST_THREAD_FUTURE<R>::then(BOOST_THREAD_FWD_REF(F) func) {
|
||||
|
||||
#ifndef BOOST_THREAD_CONTINUATION_SYNC
|
||||
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_.get()!=0, future_uninitialized());
|
||||
|
||||
// keep state alive as we move ourself but hold the lock
|
||||
shared_ptr<detail::shared_state_base> sentinel(this->future_);
|
||||
boost::unique_lock<boost::mutex> lock(sentinel->mutex);
|
||||
|
||||
launch policy = this->launch_policy(lock);
|
||||
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 {
|
||||
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)
|
||||
)));
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
// template<typename F>
|
||||
// auto future<future<R2> >::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
|
||||
// auto future<future<R2> >::then(launch, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
|
||||
////////////////////////////////
|
||||
template <typename R2>
|
||||
template <typename F>
|
||||
@@ -4776,9 +4867,12 @@ 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_);
|
||||
boost::unique_lock<boost::mutex> lock(sentinel->mutex);
|
||||
|
||||
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
|
||||
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)
|
||||
@@ -4787,14 +4881,48 @@ namespace detail {
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
|
||||
lock, boost::move(*this), boost::forward<F>(func)
|
||||
)));
|
||||
} else if (underlying_cast<int>(policy) & int(launch::sync)) {
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_sync_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
|
||||
lock, boost::move(*this), boost::forward<F>(func)
|
||||
)));
|
||||
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
} else if (underlying_cast<int>(policy) & int(launch::executor)) {
|
||||
assert(this->future_->get_executor());
|
||||
typedef executor Ex;
|
||||
Ex& ex = *(this->future_->get_executor());
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
|
||||
lock, boost::move(*this), boost::forward<F>(func)
|
||||
)));
|
||||
#endif
|
||||
} else if (underlying_cast<int>(policy) & int(launch::inherit)) {
|
||||
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)) {
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
|
||||
lock, boost::move(*this), boost::forward<F>(func)
|
||||
)));
|
||||
} else if (underlying_cast<int>(policy_) & int(launch::sync)) {
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_sync_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
|
||||
lock, boost::move(*this), boost::forward<F>(func)
|
||||
)));
|
||||
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
} else if (underlying_cast<int>(policy_) & int(launch::executor)) {
|
||||
assert(this->future_->get_executor());
|
||||
typedef executor Ex;
|
||||
Ex& ex = *(this->future_->get_executor());
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
|
||||
lock, boost::move(*this), boost::forward<F>(func)
|
||||
)));
|
||||
#endif
|
||||
} else {
|
||||
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 {
|
||||
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)
|
||||
@@ -4813,9 +4941,12 @@ 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_);
|
||||
boost::unique_lock<boost::mutex> lock(sentinel->mutex);
|
||||
|
||||
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
|
||||
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex,
|
||||
lock, boost::move(*this), boost::forward<F>(func)
|
||||
)));
|
||||
@@ -4831,7 +4962,29 @@ namespace detail {
|
||||
inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >)>::type>
|
||||
BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(BOOST_THREAD_FWD_REF(F) func) {
|
||||
|
||||
#ifndef BOOST_THREAD_CONTINUATION_SYNC
|
||||
return this->then(this->launch_policy(), boost::forward<F>(func));
|
||||
#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_.get()!=0, future_uninitialized());
|
||||
|
||||
// keep state alive as we move ourself but hold the lock
|
||||
shared_ptr<detail::shared_state_base> sentinel(this->future_);
|
||||
boost::unique_lock<boost::mutex> lock(sentinel->mutex);
|
||||
|
||||
launch policy = this->launch_policy(lock);
|
||||
|
||||
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 {
|
||||
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)
|
||||
)));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
@@ -4844,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)) {
|
||||
@@ -4852,10 +5005,13 @@ namespace detail {
|
||||
lock, *this, boost::forward<F>(func)
|
||||
)));
|
||||
} else if (underlying_cast<int>(policy) & int(launch::deferred)) {
|
||||
this->future_->wait_internal(lock);
|
||||
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)) {
|
||||
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)) {
|
||||
typedef executor Ex;
|
||||
@@ -4864,6 +5020,35 @@ namespace detail {
|
||||
lock, *this, boost::forward<F>(func)
|
||||
)));
|
||||
#endif
|
||||
} else if (underlying_cast<int>(policy) & int(launch::inherit)) {
|
||||
|
||||
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)) {
|
||||
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)) {
|
||||
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)) {
|
||||
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,
|
||||
lock, *this, boost::forward<F>(func)
|
||||
)));
|
||||
#endif
|
||||
} else {
|
||||
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 {
|
||||
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)
|
||||
@@ -4881,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,
|
||||
@@ -4898,8 +5083,24 @@ namespace detail {
|
||||
template <typename F>
|
||||
inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type>
|
||||
shared_future<R>::then(BOOST_THREAD_FWD_REF(F) func) const {
|
||||
|
||||
#ifndef BOOST_THREAD_CONTINUATION_SYNC
|
||||
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_.get()!=0, future_uninitialized());
|
||||
|
||||
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
|
||||
launch policy = this->launch_policy(lock);
|
||||
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 {
|
||||
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)
|
||||
)));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace detail
|
||||
@@ -5058,8 +5259,12 @@ namespace detail
|
||||
BOOST_THREAD_FUTURE<R2>
|
||||
BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::unwrap()
|
||||
{
|
||||
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
|
||||
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
|
||||
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_);
|
||||
boost::unique_lock<boost::mutex> lock(sentinel->mutex);
|
||||
|
||||
return boost::detail::make_future_unwrap_shared_state<BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >, R2>(lock, boost::move(*this));
|
||||
}
|
||||
#endif
|
||||
@@ -5113,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
|
||||
}
|
||||
|
||||
@@ -5184,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
|
||||
}
|
||||
|
||||
@@ -5291,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
|
||||
|
||||
}
|
||||
@@ -5362,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
|
||||
}
|
||||
|
||||
@@ -5453,5 +5658,5 @@ namespace detail
|
||||
#endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
|
||||
}
|
||||
|
||||
#endif // BOOST_NO_EXCEPTION
|
||||
#endif // BOOST_NO_EXCEPTIONS
|
||||
#endif // header
|
||||
|
||||
@@ -22,6 +22,8 @@ namespace boost
|
||||
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
executor = 4,
|
||||
#endif
|
||||
inherit = 8,
|
||||
sync = 16,
|
||||
any = async | deferred
|
||||
}
|
||||
BOOST_SCOPED_ENUM_DECLARE_END(launch)
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -68,22 +76,20 @@ namespace boost
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard;
|
||||
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
|
||||
pthread_mutex_t* the_mutex = &internal_mutex;
|
||||
guard.activate(m);
|
||||
do {
|
||||
res = pthread_cond_wait(&cond,&internal_mutex);
|
||||
} while (res == EINTR);
|
||||
res = pthread_cond_wait(&cond,the_mutex);
|
||||
check_for_interruption.check();
|
||||
guard.deactivate();
|
||||
#else
|
||||
//boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
|
||||
pthread_mutex_t* the_mutex = m.mutex()->native_handle();
|
||||
do {
|
||||
res = pthread_cond_wait(&cond,the_mutex);
|
||||
} while (res == EINTR);
|
||||
res = pthread_cond_wait(&cond,the_mutex);
|
||||
#endif
|
||||
}
|
||||
#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"));
|
||||
}
|
||||
@@ -99,15 +105,17 @@ namespace boost
|
||||
boost::throw_exception(condition_error(EPERM, "boost::condition_variable::do_wait_until() failed precondition mutex not owned"));
|
||||
}
|
||||
#endif
|
||||
thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard;
|
||||
int cond_res;
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard;
|
||||
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,&internal_mutex,&timeout);
|
||||
cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout);
|
||||
check_for_interruption.check();
|
||||
guard.deactivate();
|
||||
#else
|
||||
//boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
|
||||
pthread_mutex_t* the_mutex = m.mutex()->native_handle();
|
||||
cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout);
|
||||
#endif
|
||||
@@ -178,10 +186,12 @@ namespace boost
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
|
||||
#else
|
||||
boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
|
||||
boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
|
||||
#endif
|
||||
guard.activate(m);
|
||||
res=pthread_cond_wait(&cond,&internal_mutex);
|
||||
check_for_interruption.check();
|
||||
guard.deactivate();
|
||||
}
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
this_thread::interruption_point();
|
||||
@@ -340,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;
|
||||
}
|
||||
|
||||
@@ -395,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,10 +416,12 @@ namespace boost
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
|
||||
#else
|
||||
boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
|
||||
boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
|
||||
#endif
|
||||
guard.activate(m);
|
||||
res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
|
||||
check_for_interruption.check();
|
||||
guard.deactivate();
|
||||
}
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
this_thread::interruption_point();
|
||||
@@ -423,8 +436,6 @@ namespace boost
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
@@ -68,15 +69,29 @@ 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_USEFIXES_TIMESPEC
|
||||
return do_wait_until(lock, boost::detail::timespec_plus(timeout, boost::detail::timespec_now()));
|
||||
#elif ! defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
|
||||
//using namespace chrono;
|
||||
//nanoseconds ns = chrono::system_clock::now().time_since_epoch();
|
||||
|
||||
struct timespec ts = boost::detail::timespec_now_realtime();
|
||||
//ts.tv_sec = static_cast<long>(chrono::duration_cast<chrono::seconds>(ns).count());
|
||||
//ts.tv_nsec = static_cast<long>((ns - chrono::duration_cast<chrono::seconds>(ns)).count());
|
||||
return do_wait_until(lock, boost::detail::timespec_plus(timeout, ts));
|
||||
#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()
|
||||
{
|
||||
int res;
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
int res=pthread_mutex_init(&internal_mutex,NULL);
|
||||
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"));
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,13 +269,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();
|
||||
}
|
||||
|
||||
@@ -177,6 +177,7 @@ namespace boost
|
||||
thread_data_base* const thread_info;
|
||||
pthread_mutex_t* m;
|
||||
bool set;
|
||||
bool done;
|
||||
|
||||
void check_for_interruption()
|
||||
{
|
||||
@@ -193,7 +194,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 +209,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 +223,13 @@ namespace boost
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_unlock(m));
|
||||
}
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
|
||||
~interruption_checker() BOOST_NOEXCEPT_IF(false)
|
||||
{
|
||||
check();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
@@ -228,7 +237,7 @@ 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);
|
||||
@@ -240,14 +249,14 @@ namespace boost
|
||||
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);
|
||||
@@ -259,7 +268,7 @@ namespace boost
|
||||
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 +284,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(boost::detail::to_timespec(abs_time));
|
||||
}
|
||||
|
||||
template<typename TimeDuration>
|
||||
|
||||
@@ -75,6 +75,33 @@ namespace boost
|
||||
{
|
||||
timespec ts;
|
||||
|
||||
#if defined CLOCK_MONOTONIC && defined BOOST_THREAD_USEFIXES_TIMESPEC
|
||||
if ( ::clock_gettime( CLOCK_MONOTONIC, &ts ) )
|
||||
{
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 0;
|
||||
BOOST_ASSERT(0 && "Boost::Thread - Internal Error");
|
||||
}
|
||||
#elif defined(BOOST_THREAD_TIMESPEC_MAC_API)
|
||||
timeval tv;
|
||||
::gettimeofday(&tv, 0);
|
||||
ts.tv_sec = tv.tv_sec;
|
||||
ts.tv_nsec = tv.tv_usec * 1000;
|
||||
#else
|
||||
if ( ::clock_gettime( CLOCK_REALTIME, &ts ) )
|
||||
{
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 0;
|
||||
BOOST_ASSERT(0 && "Boost::Thread - Internal Error");
|
||||
}
|
||||
#endif
|
||||
return ts;
|
||||
}
|
||||
|
||||
inline timespec timespec_now_realtime()
|
||||
{
|
||||
timespec ts;
|
||||
|
||||
#if defined(BOOST_THREAD_TIMESPEC_MAC_API)
|
||||
timeval tv;
|
||||
::gettimeofday(&tv, 0);
|
||||
@@ -83,6 +110,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;
|
||||
|
||||
@@ -91,7 +91,19 @@ namespace boost
|
||||
cv.wait_until(lk, t);
|
||||
}
|
||||
|
||||
#if defined BOOST_THREAD_SLEEP_FOR_IS_STEADY && ! defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
|
||||
#if defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC && defined BOOST_CHRONO_HAS_CLOCK_STEADY
|
||||
template <class Rep, class Period>
|
||||
void sleep_for(const chrono::duration<Rep, Period>& d)
|
||||
{
|
||||
using namespace chrono;
|
||||
if (d > duration<Rep, Period>::zero())
|
||||
{
|
||||
steady_clock::time_point c_timeout = steady_clock::now() + ceil<nanoseconds>(d);
|
||||
sleep_until(c_timeout);
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined BOOST_THREAD_SLEEP_FOR_IS_STEADY
|
||||
|
||||
template <class Rep, class Period>
|
||||
void sleep_for(const chrono::duration<Rep, Period>& d)
|
||||
@@ -127,7 +139,8 @@ namespace boost
|
||||
using namespace chrono;
|
||||
if (d > duration<Rep, Period>::zero())
|
||||
{
|
||||
steady_clock::time_point c_timeout = steady_clock::now() + ceil<nanoseconds>(d);
|
||||
//system_clock::time_point c_timeout = time_point_cast<system_clock::duration>(system_clock::now() + ceil<nanoseconds>(d));
|
||||
system_clock::time_point c_timeout = system_clock::now() + ceil<system_clock::duration>(d);
|
||||
sleep_until(c_timeout);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,32 +142,38 @@ namespace boost
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#include <boost/detail/interlocked.hpp>
|
||||
#include <boost/detail/winapi/config.hpp>
|
||||
//#include <boost/detail/winapi/synchronization.hpp>
|
||||
#include <boost/thread/win32/interlocked_read.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
@@ -243,19 +245,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);
|
||||
previous_count = (unsigned long) boost::detail::interlocked_read_acquire(&count);
|
||||
current_tick32 = 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 +280,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;
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -80,8 +80,8 @@ namespace boost
|
||||
{
|
||||
static void tls_destructor(void* data)
|
||||
{
|
||||
boost::detail::thread_data_base* thread_info=static_cast<boost::detail::thread_data_base*>(data);
|
||||
//boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(data)->shared_from_this();
|
||||
//boost::detail::thread_data_base* thread_info=static_cast<boost::detail::thread_data_base*>(data);
|
||||
boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(data)->shared_from_this();
|
||||
|
||||
if(thread_info)
|
||||
{
|
||||
@@ -110,14 +110,12 @@ namespace boost
|
||||
thread_info->tss_data.erase(current);
|
||||
}
|
||||
}
|
||||
if (thread_info) // fixme: should we test this?
|
||||
{
|
||||
thread_info->self.reset();
|
||||
}
|
||||
thread_info->self.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined BOOST_THREAD_PATCH
|
||||
struct delete_current_thread_tls_key_on_dlclose_t
|
||||
{
|
||||
delete_current_thread_tls_key_on_dlclose_t()
|
||||
@@ -128,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));
|
||||
@@ -429,7 +430,7 @@ namespace boost
|
||||
{
|
||||
namespace no_interruption_point
|
||||
{
|
||||
namespace hiden
|
||||
namespace hidden
|
||||
{
|
||||
void BOOST_THREAD_DECL sleep_for(const timespec& ts)
|
||||
{
|
||||
@@ -458,7 +459,7 @@ namespace boost
|
||||
|
||||
void BOOST_THREAD_DECL sleep_until(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)
|
||||
@@ -478,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;
|
||||
@@ -489,7 +490,7 @@ namespace boost
|
||||
|
||||
}
|
||||
}
|
||||
namespace hiden
|
||||
namespace hidden
|
||||
{
|
||||
void BOOST_THREAD_DECL sleep_for(const timespec& ts)
|
||||
{
|
||||
@@ -502,7 +503,7 @@ namespace boost
|
||||
}
|
||||
else
|
||||
{
|
||||
boost::this_thread::no_interruption_point::hiden::sleep_for(ts);
|
||||
boost::this_thread::no_interruption_point::hidden::sleep_for(ts);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -517,10 +518,10 @@ namespace boost
|
||||
}
|
||||
else
|
||||
{
|
||||
boost::this_thread::no_interruption_point::hiden::sleep_until(ts);
|
||||
boost::this_thread::no_interruption_point::hidden::sleep_until(ts);
|
||||
}
|
||||
}
|
||||
} // hiden
|
||||
} // hidden
|
||||
} // this_thread
|
||||
|
||||
namespace this_thread
|
||||
@@ -541,7 +542,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>
|
||||
@@ -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)
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -112,15 +112,9 @@ 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
|
||||
#else
|
||||
typedef int (__cdecl *_PVFV)();
|
||||
#define INIRETSUCCESS 0
|
||||
#define PVAPI int __cdecl
|
||||
#endif
|
||||
typedef int (__cdecl *_PVFV)();
|
||||
#define INIRETSUCCESS 0
|
||||
#define PVAPI int __cdecl
|
||||
|
||||
typedef void (NTAPI* _TLSCB)(HINSTANCE, DWORD, PVOID);
|
||||
|
||||
|
||||
@@ -31,7 +31,8 @@ project
|
||||
<toolset>gcc:<cxxflags>-Wno-long-long
|
||||
#<toolset>gcc:<cxxflags>-ansi
|
||||
#<toolset>gcc:<cxxflags>-fpermissive
|
||||
<toolset>gcc:<cxxflags>-Wno-variadic-macros
|
||||
<toolset>gcc-4:<cxxflags>-Wno-variadic-macros
|
||||
<toolset>gcc-5:<cxxflags>-Wno-variadic-macros
|
||||
#<toolset>gcc:<cxxflags>-Wunused-local-typedefs
|
||||
<toolset>gcc:<cxxflags>-Wunused-function
|
||||
<toolset>gcc:<cxxflags>-Wno-unused-parameter
|
||||
@@ -797,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 ]
|
||||
@@ -962,8 +965,11 @@ rule thread-compile ( sources : reqs * : name )
|
||||
#[ thread-run test_11256.cpp ]
|
||||
#[ thread-run test_11499.cpp ]
|
||||
#[ thread-run test_11611.cpp ]
|
||||
[ thread-run2-noit ./sync/futures/shared_future/then_executor_pass.cpp : shared_future__then_executor_p2 ]
|
||||
[ thread-run2-noit ./sync/futures/future/then_executor_pass.cpp : future__then_executor_p2 ]
|
||||
#[ thread-run test_11818.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());
|
||||
}
|
||||
{
|
||||
|
||||
@@ -151,10 +151,12 @@ int main()
|
||||
BOOST_STATIC_ASSERT(std::is_same<decltype(f3), boost::future<boost::future<void> > >::value);
|
||||
f3.wait();
|
||||
}
|
||||
#if 1
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
// fixme
|
||||
for (int i=0; i< number_of_tests; i++)
|
||||
{
|
||||
boost::basic_thread_pool executor(1);
|
||||
boost::basic_thread_pool executor(2);
|
||||
|
||||
auto f1 = boost::make_ready_future().then(executor, TestCallback());
|
||||
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
|
||||
@@ -167,6 +169,7 @@ int main()
|
||||
BOOST_STATIC_ASSERT(std::is_same<decltype(f3), boost::future<boost::future<void> > >::value);
|
||||
f3.wait();
|
||||
}
|
||||
#endif
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
for (int i=0; i< number_of_tests; i++)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
33
test/test_11796.cpp
Normal file
33
test/test_11796.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright (C) 2015 Vicente Botet
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/chrono.hpp>
|
||||
#include <iostream>
|
||||
|
||||
boost::thread th;
|
||||
int main()
|
||||
{
|
||||
|
||||
for (auto ti = 0; ti < 1000; ti++)
|
||||
{
|
||||
th = boost::thread([ti]()
|
||||
{
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
|
||||
std::cout << ti << std::endl;
|
||||
});
|
||||
}
|
||||
std::string st;
|
||||
|
||||
std::cin >> st;
|
||||
|
||||
// for (int i = 0; i < 10; ++i) {
|
||||
// std::cout << "." << i << std::endl;
|
||||
// boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
|
||||
// }
|
||||
th.join();
|
||||
return 0;
|
||||
}
|
||||
|
||||
64
test/test_11818.cpp
Normal file
64
test/test_11818.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
|
||||
#include <boost/config.hpp>
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <thread>
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
{
|
||||
boost::promise<int> promise;
|
||||
boost::future<int> future = promise.get_future();
|
||||
|
||||
boost::future<int> result =
|
||||
future.then
|
||||
(
|
||||
boost::launch::deferred,
|
||||
[](boost::future<int> && f)
|
||||
{
|
||||
std::cout << std::this_thread::get_id() << ": callback" << std::endl;
|
||||
std::cout << "The value is: " << f.get() << std::endl;
|
||||
return f.get();
|
||||
}
|
||||
);
|
||||
|
||||
// We could not reach here.
|
||||
std::cout << std::this_thread::get_id() << ": function" << std::endl;
|
||||
|
||||
promise.set_value(0);
|
||||
}
|
||||
|
||||
{
|
||||
boost::promise<int> promise;
|
||||
boost::shared_future<int> future = promise.get_future().share();
|
||||
|
||||
boost::future<int> result =
|
||||
future.then
|
||||
(
|
||||
boost::launch::deferred,
|
||||
[](boost::shared_future<int> && f)
|
||||
{
|
||||
std::cout << std::this_thread::get_id() << ": callback" << std::endl;
|
||||
std::cout << "The value is: " << f.get() << std::endl;
|
||||
return f.get();
|
||||
}
|
||||
);
|
||||
|
||||
// We could not reach here.
|
||||
std::cout << std::this_thread::get_id() << ": function" << std::endl;
|
||||
|
||||
promise.set_value(0);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -5,12 +5,13 @@
|
||||
|
||||
#define BOOST_THREAD_VERSION 2
|
||||
#define BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
#define BOOST_TEST_MODULE Boost.Threads: 2309
|
||||
#include <boost/test/unit_test.hpp>
|
||||
//#define BOOST_TEST_MODULE Boost.Threads: 2309
|
||||
//#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -40,7 +41,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test)
|
||||
void ticket_2309_test()
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -57,9 +58,13 @@
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_CHECK(false && "exception raised");
|
||||
BOOST_TEST(false && "exception raised");
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
ticket_2309_test();
|
||||
}
|
||||
|
||||
|
||||
@@ -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