mirror of
https://github.com/boostorg/thread.git
synced 2026-02-17 02:02:08 +00:00
Compare commits
390 Commits
feature/se
...
boost-1.65
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
0ab63b9248 | ||
|
|
73053e4abe | ||
|
|
9a4fbbec5d | ||
|
|
b4744a2aa8 | ||
|
|
4169bcee44 | ||
|
|
baf516e82f | ||
|
|
cc309eef8d | ||
|
|
45cc1704ef | ||
|
|
278a06fd47 | ||
|
|
6ed577f4eb | ||
|
|
bf8459cf23 | ||
|
|
ad3cf1189e | ||
|
|
b8db8fef8b | ||
|
|
384c71dbe6 | ||
|
|
111574cf0c | ||
|
|
759601d08a | ||
|
|
c60d152102 | ||
|
|
6ff4fe1a89 | ||
|
|
2c0c4ead7f | ||
|
|
dacd6deb0a | ||
|
|
c7df715709 | ||
|
|
ddd26b5bb8 | ||
|
|
f0228ff559 | ||
|
|
4acaddd166 | ||
|
|
3a65295d7d | ||
|
|
773f8bfcb4 | ||
|
|
8afcbe22af | ||
|
|
450f34daed | ||
|
|
ea9eb62802 | ||
|
|
971c028c9a | ||
|
|
3f8618b42b | ||
|
|
9a8759a3dd | ||
|
|
9ac736a4c4 | ||
|
|
730cb550e6 | ||
|
|
8f5de1d7c3 | ||
|
|
0fdd4fc620 | ||
|
|
a86e2ebcc4 | ||
|
|
18cbf4b055 | ||
|
|
6029447774 | ||
|
|
205a1d7e2b | ||
|
|
2af9c7b98e | ||
|
|
baca517058 | ||
|
|
26486b0288 | ||
|
|
f8ff41e34b | ||
|
|
16ece266a4 | ||
|
|
4224a9f4df | ||
|
|
2e17e028b1 | ||
|
|
febe4a814d | ||
|
|
242cf35c51 | ||
|
|
c1ee2bfbd8 | ||
|
|
b30cde32d4 | ||
|
|
ac3f7eb037 | ||
|
|
9f883f6ad7 | ||
|
|
b332f17825 | ||
|
|
a3497e1ffc | ||
|
|
89b119f65f | ||
|
|
1ae07f3f3a | ||
|
|
0143748de8 | ||
|
|
ac603f6bd1 | ||
|
|
6aeac1e33e | ||
|
|
ff375e2780 | ||
|
|
5b1c755e42 | ||
|
|
b8dbe960b7 | ||
|
|
4f9a08c418 | ||
|
|
44272d3b7c | ||
|
|
ccd1cd5808 | ||
|
|
8c974800f9 | ||
|
|
6e002ae3ec | ||
|
|
2a375808c4 | ||
|
|
55c21919fc | ||
|
|
91e2cded63 | ||
|
|
b980b88474 | ||
|
|
7cb5211e25 | ||
|
|
958b773d05 | ||
|
|
4d45da6c06 | ||
|
|
e39703ff18 | ||
|
|
aafd5ca726 | ||
|
|
9b69912801 | ||
|
|
259c08473d | ||
|
|
6ca3a99cbc | ||
|
|
3dcd875944 | ||
|
|
58e8addad6 | ||
|
|
87615d54dd | ||
|
|
d322aba077 | ||
|
|
c0afe2d873 | ||
|
|
5488482a44 | ||
|
|
1480d6fc99 | ||
|
|
131c92a7d8 | ||
|
|
71d9a0a120 | ||
|
|
b7b2a463cf | ||
|
|
c50d0ac4ba | ||
|
|
1b2736012c | ||
|
|
5205fa71bf | ||
|
|
ba2988a8f7 | ||
|
|
650956bd3b | ||
|
|
e598796eaf | ||
|
|
bce7eabba2 | ||
|
|
0218136ed7 | ||
|
|
461bf803fc | ||
|
|
1bd78bbeea | ||
|
|
348da6b7e4 | ||
|
|
e850218c49 | ||
|
|
385eefd3b3 | ||
|
|
2ddf7aad0b | ||
|
|
c9433c2a5b | ||
|
|
8853a4cbdf | ||
|
|
6f53279b50 | ||
|
|
f25bc8bbab | ||
|
|
5c442e068c | ||
|
|
0bed674233 | ||
|
|
66193b0d38 | ||
|
|
45c9a1d7fd | ||
|
|
0d8ddfe378 | ||
|
|
74f479d5c9 | ||
|
|
dbf793e7eb | ||
|
|
b5c6f760c5 | ||
|
|
0f6a3ebbe5 | ||
|
|
a5c34e7be2 | ||
|
|
287100119a | ||
|
|
ba2f814342 | ||
|
|
5169a5414b | ||
|
|
82b9a4e28c | ||
|
|
e989d2f626 | ||
|
|
331f0b9325 | ||
|
|
ec6a1fcf80 | ||
|
|
dcebe26a11 | ||
|
|
d7721940f3 | ||
|
|
b678edb0d8 | ||
|
|
1371728e02 | ||
|
|
17d802db81 | ||
|
|
9fc06a8741 | ||
|
|
946fac633e | ||
|
|
af1c7d0c26 | ||
|
|
d9594e7fc8 | ||
|
|
0653efff3d | ||
|
|
566199e49b | ||
|
|
c7bb6fa318 | ||
|
|
c678b3794b | ||
|
|
e0ce8af1d9 | ||
|
|
c54dbe30a2 | ||
|
|
b8763b05ad | ||
|
|
3755af2063 | ||
|
|
41172e4814 | ||
|
|
25310eaf7c | ||
|
|
55f9563f60 | ||
|
|
ec770eeb6a | ||
|
|
b9ab307912 | ||
|
|
83ced837fa | ||
|
|
ce2b2801d6 | ||
|
|
1ae96b3820 | ||
|
|
889c178173 | ||
|
|
7ba9591015 | ||
|
|
b07f18facf | ||
|
|
7b1b1b5daa | ||
|
|
63fb28c7d4 | ||
|
|
67e18ff039 | ||
|
|
855e56076b | ||
|
|
cf76bc666c | ||
|
|
d00e39acc7 | ||
|
|
b68702b56d | ||
|
|
e2cda49b0b | ||
|
|
a4e7eba1d4 | ||
|
|
67778b3278 | ||
|
|
a5e6952a95 | ||
|
|
3c6a183aa3 | ||
|
|
5960985355 | ||
|
|
fdf20f1adc | ||
|
|
63098e84a2 | ||
|
|
3431736c88 | ||
|
|
e74fd82060 | ||
|
|
35d7ae0d2e | ||
|
|
d9c7f95617 | ||
|
|
06b3f6a9d7 | ||
|
|
895b4a0ac5 | ||
|
|
9cb72849ee |
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).
|
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>-Wno-long-long
|
||||||
#<toolset>gcc:<cxxflags>-ansi
|
#<toolset>gcc:<cxxflags>-ansi
|
||||||
#<toolset>gcc:<cxxflags>-fpermissive
|
#<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-local-typedefs
|
||||||
<toolset>gcc:<cxxflags>-Wunused-function
|
<toolset>gcc:<cxxflags>-Wunused-function
|
||||||
<toolset>gcc:<cxxflags>-Wno-unused-parameter
|
<toolset>gcc:<cxxflags>-Wno-unused-parameter
|
||||||
@@ -70,7 +71,9 @@ project boost/thread
|
|||||||
#<toolset>darwin:<cxxflags>-ansi
|
#<toolset>darwin:<cxxflags>-ansi
|
||||||
<toolset>darwin:<cxxflags>-fpermissive
|
<toolset>darwin:<cxxflags>-fpermissive
|
||||||
<toolset>darwin:<cxxflags>-Wno-long-long
|
<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-local-typedefs
|
||||||
<toolset>darwin:<cxxflags>-Wunused-function
|
<toolset>darwin:<cxxflags>-Wunused-function
|
||||||
<toolset>darwin:<cxxflags>-Wno-unused-parameter
|
<toolset>darwin:<cxxflags>-Wno-unused-parameter
|
||||||
@@ -123,6 +126,8 @@ project boost/thread
|
|||||||
<toolset>msvc:<cxxflags>/wd4512
|
<toolset>msvc:<cxxflags>/wd4512
|
||||||
<toolset>msvc:<cxxflags>/wd6246
|
<toolset>msvc:<cxxflags>/wd6246
|
||||||
|
|
||||||
|
<target-os>windows:<define>WIN32_LEAN_AND_MEAN
|
||||||
|
<target-os>windows:<define>BOOST_USE_WINDOWS_H
|
||||||
|
|
||||||
# : default-build <threading>multi
|
# : default-build <threading>multi
|
||||||
: usage-requirements # pass these requirement to dependents (i.e. users)
|
: 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
|
<link>static:<define>BOOST_THREAD_USE_LIB=1
|
||||||
<conditional>@usage-requirements
|
<conditional>@usage-requirements
|
||||||
;
|
;
|
||||||
|
|
||||||
|
boost-install boost_thread ;
|
||||||
@@ -29,4 +29,12 @@ boostbook standalone
|
|||||||
<xsl:param>boost.root=../../../..
|
<xsl:param>boost.root=../../../..
|
||||||
;
|
;
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
alias boostdoc
|
||||||
|
: thread
|
||||||
|
:
|
||||||
|
:
|
||||||
|
: ;
|
||||||
|
explicit boostdoc ;
|
||||||
|
alias boostrelease ;
|
||||||
|
explicit boostrelease ;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
[/
|
[/
|
||||||
(C) Copyright 2007-8 Anthony Williams.
|
(C) Copyright 2007-8 Anthony Williams.
|
||||||
|
(C) Copyright 2012-2015 Vicente J. Botet Escriba.
|
||||||
Distributed under the Boost Software License, Version 1.0.
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
(See accompanying file LICENSE_1_0.txt or copy at
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
http://www.boost.org/LICENSE_1_0.txt).
|
http://www.boost.org/LICENSE_1_0.txt).
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[/
|
[/
|
||||||
/ Copyright (c) 2014 Vicente J. Botet Escriba
|
/ Copyright (c) 2014-2015 Vicente J. Botet Escriba
|
||||||
/
|
/
|
||||||
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
/ 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)
|
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
@@ -112,7 +112,7 @@ A question arises of which of these executors (or others) be included in this li
|
|||||||
[////////////////////////]
|
[////////////////////////]
|
||||||
[section:rationale Design Rationale]
|
[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.
|
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.
|
||||||
|
|
||||||
@@ -319,33 +319,23 @@ The reason is that the user can always use a thread_local variable and reset it
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
[
|
||||||
[heading Default executor]
|
[heading Default executor]
|
||||||
|
|
||||||
The library authors share some of the concerns of the C++ standard committee (introduction of a new single shared resource, a singleton, could make it difficult to make it portable to all the environments) and that this library doesn't need to provide a default executor for the time been.
|
The library authors share some of the concerns of the C++ standard committee (introduction of a new single shared resource, a singleton, could make it difficult to make it portable to all the environments) and that this library doesn't need to provide a default executor for the time been.
|
||||||
|
|
||||||
The user can always define his default executor himself and use the `at_thread_entry ` member function to set the default constructor.
|
The user can always define his default executor himself.
|
||||||
|
|
||||||
thread_local default_executor_state_type default_executor_state;
|
boost::generic_executor_ref default_executor()
|
||||||
executor* default_executor() { return default_executor_state.default_executor(); }
|
{
|
||||||
|
static boost::basic_thread_pool tp(4);
|
||||||
// in main
|
return generic_executor_ref(tp);
|
||||||
MyDefaultExecutor myDefaultExecutor(
|
}
|
||||||
// at_thread_entry
|
|
||||||
[](MyDefaultExecutor& ex) {
|
|
||||||
default_executor_state.set_default_executor(ex);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
basic_thread_pool pool(
|
|
||||||
// at_thread_entry
|
|
||||||
[&myDefaultExecutor](basic_thread_pool& pool) {
|
|
||||||
default_executor_state.set_default_executor(myDefaultExecutor);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
|
||||||
|
|
||||||
[/////////////////////]
|
[/////////////////////]
|
||||||
[section:ref Reference]
|
[section:ref Reference]
|
||||||
|
|
||||||
@@ -374,8 +364,8 @@ A type `E` meets the `Executor` requirements if the following expressions are we
|
|||||||
where
|
where
|
||||||
|
|
||||||
* `e` denotes a value of type `E`,
|
* `e` denotes a value of type `E`,
|
||||||
* `lc` denotes a lvalue referece of type `Closure`,
|
* `lc` denotes a lvalue reference of type `Closure`,
|
||||||
* `rc` denotes a rvalue referece of type `Closure`
|
* `rc` denotes a rvalue reference of type `Closure`
|
||||||
* `p` denotes a value of type `Predicate`
|
* `p` denotes a value of type `Predicate`
|
||||||
|
|
||||||
[/////////////////////////////////////]
|
[/////////////////////////////////////]
|
||||||
@@ -398,7 +388,7 @@ If invoked closure throws an exception the executor will call std::terminate, as
|
|||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
[/////////////////////////////////////]
|
[/////////////////////////////////////]
|
||||||
[section:submitrc `e.submit(lc);`]
|
[section:submitrc `e.submit(rc);`]
|
||||||
|
|
||||||
[variablelist
|
[variablelist
|
||||||
|
|
||||||
@@ -421,13 +411,13 @@ If invoked closure throws an exception the executor will call std::terminate, as
|
|||||||
|
|
||||||
[variablelist
|
[variablelist
|
||||||
|
|
||||||
[[Effects:] [close the scheduler/executor `e` for submissions.]]
|
[[Effects:] [close the executor `e` for submissions.]]
|
||||||
|
|
||||||
[[Remark:] [The worker threads will work until there is no more closures to run.]]
|
[[Remark:] [The worker threads will work until there is no more closures to run.]]
|
||||||
|
|
||||||
[[Return type:] [`void`.]]
|
[[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.]]
|
[[Exception safety:] [If an exception is thrown then the executor state is unmodified.]]
|
||||||
|
|
||||||
@@ -441,7 +431,7 @@ If invoked closure throws an exception the executor will call std::terminate, as
|
|||||||
|
|
||||||
[[Return type:] [`bool`.]]
|
[[Return type:] [`bool`.]]
|
||||||
|
|
||||||
[[Return:] [whether the scheduler/executor is closed for submissions.]]
|
[[Return:] [whether the executor is closed for submissions.]]
|
||||||
|
|
||||||
[[Throws:] [Whatever exception that can be throw while ensuring the thread safety.]]
|
[[Throws:] [Whatever exception that can be throw while ensuring the thread safety.]]
|
||||||
|
|
||||||
@@ -472,7 +462,7 @@ If invoked closure throws an exception the executor will call std::terminate, as
|
|||||||
|
|
||||||
[variablelist
|
[variablelist
|
||||||
|
|
||||||
[[Requires:] [This must be called from an scheduled work]]
|
[[Requires:] [This must be called from a scheduled work]]
|
||||||
|
|
||||||
[[Effects:] [reschedule works until `p()`.]]
|
[[Effects:] [reschedule works until `p()`.]]
|
||||||
|
|
||||||
@@ -543,7 +533,7 @@ Executor abstract base class.
|
|||||||
|
|
||||||
[variablelist
|
[variablelist
|
||||||
|
|
||||||
[[Effects:] [Constructs a executor. ]]
|
[[Effects:] [Constructs an executor. ]]
|
||||||
|
|
||||||
[[Throws:] [Nothing. ]]
|
[[Throws:] [Nothing. ]]
|
||||||
|
|
||||||
@@ -610,7 +600,7 @@ Polymorphic adaptor of a model of Executor to an executor.
|
|||||||
|
|
||||||
[variablelist
|
[variablelist
|
||||||
|
|
||||||
[[Effects:] [Constructs a executor_adaptor. ]]
|
[[Effects:] [Constructs an executor_adaptor. ]]
|
||||||
|
|
||||||
[[Throws:] [Nothing. ]]
|
[[Throws:] [Nothing. ]]
|
||||||
|
|
||||||
@@ -824,7 +814,7 @@ Scheduler providing time related functions. Note that `scheduler` is not an Exec
|
|||||||
}
|
}
|
||||||
|
|
||||||
[/////////////////////////////////////]
|
[/////////////////////////////////////]
|
||||||
[section:constructor Constructor `at_executor(Scheduler&)`]
|
[section:constructor Constructor `at_executor(Scheduler&, clock::time_point const&)`]
|
||||||
|
|
||||||
at_executor(Scheduler& sch, clock::time_point const& tp);
|
at_executor(Scheduler& sch, clock::time_point const& tp);
|
||||||
|
|
||||||
@@ -1531,7 +1521,7 @@ A serial executor ensuring that there are no two work units that executes concur
|
|||||||
|
|
||||||
[variablelist
|
[variablelist
|
||||||
|
|
||||||
[[Effects:] [Constructs a inline_executor. ]]
|
[[Effects:] [Constructs an inline_executor. ]]
|
||||||
|
|
||||||
[[Throws:] [Nothing. ]]
|
[[Throws:] [Nothing. ]]
|
||||||
|
|
||||||
@@ -1719,7 +1709,7 @@ A user scheduled executor.
|
|||||||
|
|
||||||
[variablelist
|
[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. ]]
|
[[Throws:] [Whatever exception is thrown while initializing the needed resources. ]]
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[/
|
[/
|
||||||
(C) Copyright 2007-8 Anthony Williams.
|
(C) Copyright 2007-8 Anthony Williams.
|
||||||
(C) Copyright 2013 Vicente J. Botet Escriba.
|
(C) Copyright 2013-2015 Vicente J. Botet Escriba.
|
||||||
Distributed under the Boost Software License, Version 1.0.
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
(See accompanying file LICENSE_1_0.txt or copy at
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
http://www.boost.org/LICENSE_1_0.txt).
|
http://www.boost.org/LICENSE_1_0.txt).
|
||||||
|
|||||||
160
doc/changes.qbk
160
doc/changes.qbk
@@ -1,6 +1,6 @@
|
|||||||
[/
|
[/
|
||||||
(C) Copyright 2007-11 Anthony Williams.
|
(C) Copyright 2007-11 Anthony Williams.
|
||||||
(C) Copyright 2011-14 Vicente J. Botet Escriba.
|
(C) Copyright 2011-16 Vicente J. Botet Escriba.
|
||||||
Distributed under the Boost Software License, Version 1.0.
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
(See accompanying file LICENSE_1_0.txt or copy at
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
http://www.boost.org/LICENSE_1_0.txt).
|
http://www.boost.org/LICENSE_1_0.txt).
|
||||||
@@ -8,46 +8,181 @@
|
|||||||
|
|
||||||
[section:changes History]
|
[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:]
|
||||||
|
|
||||||
|
* [@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
|
||||||
|
* [@http://svn.boost.org/trac/boost/ticket/10942 #10942] Boost.Thread fails to build on Cygwin.
|
||||||
|
|
||||||
|
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/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/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
|
||||||
|
* [@http://svn.boost.org/trac/boost/ticket/7720 #7720] exception lock_error while intensive locking/unlocking of mutex
|
||||||
|
* [@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/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] (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]
|
[heading Version 4.5.0 - boost 1.58]
|
||||||
|
|
||||||
[*Know Bugs:]
|
[*Know Bugs:]
|
||||||
|
|
||||||
* [@http://svn.boost.org/trac/boost/ticket/3926 #3926] thread_specific_ptr + dlopen library causes a SIGSEGV.
|
* [@http://svn.boost.org/trac/boost/ticket/3926 #3926] thread_specific_ptr + dlopen library causes a SIGSEGV.
|
||||||
* [@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/4833 #4833] MinGW/test_tss_lib: Support of automatic tss cleanup for native threading API not available
|
||||||
* [@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/7319 #7319] Take care of c++std-lib-32966 issue
|
|
||||||
* [@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/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
|
* [@http://svn.boost.org/trac/boost/ticket/9118 #9118] Seg fault on thread join when llvm and libc++ are used
|
||||||
* [@http://svn.boost.org/trac/boost/ticket/9309 #9309] test_latch fails often on clang-darwin-tot11
|
* [@http://svn.boost.org/trac/boost/ticket/9309 #9309] test_latch fails often on clang-darwin-tot11
|
||||||
* [@http://svn.boost.org/trac/boost/ticket/9311 #9311] ex_lambda_future fails on msvc-11.0
|
* [@http://svn.boost.org/trac/boost/ticket/9311 #9311] ex_lambda_future fails on msvc-11.0
|
||||||
* [@http://svn.boost.org/trac/boost/ticket/9856 #9856] [windows] condition_variable::wait_for returns wrong cv_status on timeout.
|
* [@http://svn.boost.org/trac/boost/ticket/10942 #10942] Boost.Thread fails to build on Cygwin.
|
||||||
|
|
||||||
|
[/
|
||||||
|
* [@http://svn.boost.org/trac/boost/ticket/7319 #7319] Take care of c++std-lib-32966 issue
|
||||||
* [@http://svn.boost.org/trac/boost/ticket/10651 #10651] boost::thread leaks memory when using the MinGW compiler.
|
* [@http://svn.boost.org/trac/boost/ticket/10651 #10651] boost::thread leaks memory when using the MinGW compiler.
|
||||||
* [@http://svn.boost.org/trac/boost/ticket/10685 #10685] mfc_thread_init.hpp does not compile.
|
* [@http://svn.boost.org/trac/boost/ticket/10685 #10685] mfc_thread_init.hpp does not compile.
|
||||||
* [@http://svn.boost.org/trac/boost/ticket/10942 #10942] Boost.Thread fails to build on Cygwin.
|
|
||||||
* [@http://svn.boost.org/trac/boost/ticket/10967 #10967] Timed wait points inconsistently convert relative to absolute waits.
|
* [@http://svn.boost.org/trac/boost/ticket/10967 #10967] Timed wait points inconsistently convert relative to absolute waits.
|
||||||
* [@http://svn.boost.org/trac/boost/ticket/10968 #10968] The futures returned by async() and future::then() are not blocking.
|
]
|
||||||
|
|
||||||
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 [@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 snapshot.
|
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.
|
||||||
|
|
||||||
[*Sever limitations:]
|
[*Sever limitations:]
|
||||||
|
|
||||||
There are some severe bugs that prevent the use of the library on concrete contexts, in particular:
|
There are some severe bugs that prevent the use of the library on concrete contexts, in particular:
|
||||||
|
|
||||||
* on thread specific storage that prevent the library to be used with dynamic libraries ( [@http://svn.boost.org/trac/boost/ticket/3926 #3926], ),
|
* on thread specific storage that prevent the library to be used with dynamic libraries ( [@http://svn.boost.org/trac/boost/ticket/3926 #3926], ),
|
||||||
* timed operation on windows are inconsistent ( [@http://svn.boost.org/trac/boost/ticket/9856 #9856], [@http://svn.boost.org/trac/boost/ticket/10967 #10967]).
|
|
||||||
* The futures returned by async() and future::then() are not blocking ([@http://svn.boost.org/trac/boost/ticket/10968 #10968]).
|
|
||||||
|
|
||||||
[*New Experimental Features:]
|
[*New Experimental Features:]
|
||||||
|
|
||||||
* [@http://svn.boost.org/trac/boost/ticket/9600 #9600] Async: Add task_region
|
* [@http://svn.boost.org/trac/boost/ticket/9600 #9600] Async: Add task_region
|
||||||
* [@http://svn.boost.org/trac/boost/ticket/10611 #10611] Add emplace promise::set_value and emplace make_ready_future
|
* [@http://svn.boost.org/trac/boost/ticket/10611 #10611] Add emplace promise::set_value and emplace make_ready_future
|
||||||
* [@http://svn.boost.org/trac/boost/ticket/10826 #10826] Add scheduled executor operations
|
* [@http://svn.boost.org/trac/boost/ticket/10826 #10826] Add scheduled executor operations
|
||||||
|
* [@http://svn.boost.org/trac/boost/ticket/11048 #11048] Add a serial_executor based on continuations
|
||||||
|
|
||||||
[*Fixed Bugs:]
|
[*Fixed Bugs:]
|
||||||
|
|
||||||
|
* [@http://svn.boost.org/trac/boost/ticket/6787 #6787] boost::thread::sleep() hangs if system time is rolled back
|
||||||
* [@http://svn.boost.org/trac/boost/ticket/10734 #10734] Submit method work differently on different executors, some throw exception and some silently ignore error (thread_executor and inline_executor)
|
* [@http://svn.boost.org/trac/boost/ticket/10734 #10734] Submit method work differently on different executors, some throw exception and some silently ignore error (thread_executor and inline_executor)
|
||||||
* [@http://svn.boost.org/trac/boost/ticket/10736 #10736] Task exceptions silently ignored. I think std::terminate solution from N3785 and std::thread is better choice and more consistent.
|
* [@http://svn.boost.org/trac/boost/ticket/10736 #10736] Task exceptions silently ignored. I think std::terminate solution from N3785 and std::thread is better choice and more consistent.
|
||||||
* [@http://svn.boost.org/trac/boost/ticket/10737 #10737] In serial_executor we have infinite wait if task throw exception.
|
* [@http://svn.boost.org/trac/boost/ticket/10737 #10737] In serial_executor we have infinite wait if task throw exception.
|
||||||
@@ -55,9 +190,13 @@ There are some severe bugs that prevent the use of the library on concrete conte
|
|||||||
* [@http://svn.boost.org/trac/boost/ticket/10824 #10824] Boost.Thread 1.57 breaks Windows XP compatibility for SP2 and below.
|
* [@http://svn.boost.org/trac/boost/ticket/10824 #10824] Boost.Thread 1.57 breaks Windows XP compatibility for SP2 and below.
|
||||||
* [@http://svn.boost.org/trac/boost/ticket/10963 #10963] future<future<T>>::then Has No Implementation
|
* [@http://svn.boost.org/trac/boost/ticket/10963 #10963] future<future<T>>::then Has No Implementation
|
||||||
* [@http://svn.boost.org/trac/boost/ticket/10964 #10964] future<future<T>>::unwrap().then() Deadlocks
|
* [@http://svn.boost.org/trac/boost/ticket/10964 #10964] future<future<T>>::unwrap().then() Deadlocks
|
||||||
|
* [@http://svn.boost.org/trac/boost/ticket/10968 #10968] The futures returned by async() and future::then() are not blocking.
|
||||||
* [@http://svn.boost.org/trac/boost/ticket/10971 #10971] shared_future::get()/get_or() must be const
|
* [@http://svn.boost.org/trac/boost/ticket/10971 #10971] shared_future::get()/get_or() must be const
|
||||||
* [@http://svn.boost.org/trac/boost/ticket/10972 #10972] shared_future::then() can be called multiple times.
|
* [@http://svn.boost.org/trac/boost/ticket/10972 #10972] shared_future::then() can be called multiple times.
|
||||||
* [@http://svn.boost.org/trac/boost/ticket/10979 #10979] Support T& type deduction when the make_ready_future parameter is reference_wrapper<T>
|
* [@http://svn.boost.org/trac/boost/ticket/10979 #10979] Support T& type deduction when the make_ready_future parameter is reference_wrapper<T>
|
||||||
|
* [@http://svn.boost.org/trac/boost/ticket/10996 #10996] Thread physical_concurrency() is failing on Windows
|
||||||
|
* [@http://svn.boost.org/trac/boost/ticket/11035 #11035] BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE not defined for Android
|
||||||
|
* [@http://svn.boost.org/trac/boost/ticket/11053 #11053] The attached code results in a R6025 - pure virtual function call in run_thread_exit_callbacks
|
||||||
|
|
||||||
|
|
||||||
[heading Version 4.4.0 - boost 1.57]
|
[heading Version 4.4.0 - boost 1.57]
|
||||||
@@ -76,6 +215,7 @@ There are some severe bugs that prevent the use of the library on concrete conte
|
|||||||
* [@http://svn.boost.org/trac/boost/ticket/10537 #10537] Application crash on throw exception
|
* [@http://svn.boost.org/trac/boost/ticket/10537 #10537] Application crash on throw exception
|
||||||
* [@http://svn.boost.org/trac/boost/ticket/10651 #10651] boost::thread leaks memory when using the MinGW compiler
|
* [@http://svn.boost.org/trac/boost/ticket/10651 #10651] boost::thread leaks memory when using the MinGW compiler
|
||||||
|
|
||||||
|
|
||||||
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 [@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 snapshot.
|
Please take a look at [@http://www.boost.org/development/tests/master/developer/thread.html thread trunk regression test] to see the last snapshot.
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
[/
|
[/
|
||||||
(C) Copyright 2011-2013 Vicente J. Botet Escriba.
|
(C) Copyright 2011-2015 Vicente J. Botet Escriba.
|
||||||
Distributed under the Boost Software License, Version 1.0.
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
(See accompanying file LICENSE_1_0.txt or copy at
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
http://www.boost.org/LICENSE_1_0.txt).
|
http://www.boost.org/LICENSE_1_0.txt).
|
||||||
]
|
]
|
||||||
|
|
||||||
[section:compliance Conformance and Extension]
|
[section:compliance Conformance and Extension]
|
||||||
|
[////////////////////////////////////////////]
|
||||||
|
|
||||||
[section:cpp11 C++11 standard Thread library]
|
[section:cpp11 C++11 standard Thread library]
|
||||||
|
[///////////////////////////////////////////]
|
||||||
|
|
||||||
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3376.html C++11 - Standard for Programming Language C++]]]
|
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3376.html C++11 - Standard for Programming Language C++]]]
|
||||||
|
|
||||||
@@ -88,6 +90,7 @@
|
|||||||
]
|
]
|
||||||
[endsect]
|
[endsect]
|
||||||
[section:cxx14 C++14 standard Thread library - accepted changes]
|
[section:cxx14 C++14 standard Thread library - accepted changes]
|
||||||
|
[//////////////////////////////////////////////////////////////]
|
||||||
|
|
||||||
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3797.html Working Draft, Standard for Programming Language C++]]
|
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3797.html Working Draft, Standard for Programming Language C++]]
|
||||||
|
|
||||||
@@ -103,6 +106,7 @@
|
|||||||
|
|
||||||
|
|
||||||
[section:cxx1y C++14 TS Extensions for Concurrency V1 ]
|
[section:cxx1y C++14 TS Extensions for Concurrency V1 ]
|
||||||
|
[/////////////////////////////////////////////////////]
|
||||||
|
|
||||||
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4107.html N4107-Extensions for Concurrency]]
|
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4107.html N4107-Extensions for Concurrency]]
|
||||||
|
|
||||||
@@ -126,8 +130,10 @@
|
|||||||
[endsect]
|
[endsect]
|
||||||
|
|
||||||
[section:cxx1y C++1z TS Concurrency - On going proposals]
|
[section:cxx1y C++1z TS Concurrency - On going proposals]
|
||||||
|
[///////////////////////////////////////////////////////]
|
||||||
|
|
||||||
[section:latch C++ Latches and Barriers]
|
[section:latch C++ Latches and Barriers]
|
||||||
|
[//////////////////////////////////////]
|
||||||
|
|
||||||
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3600.html N3600 C++ Latches and Barriers]]
|
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3600.html N3600 C++ Latches and Barriers]]
|
||||||
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3817.html N3817 C++ Latches and Barriers]]
|
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3817.html N3817 C++ Latches and Barriers]]
|
||||||
@@ -140,6 +146,7 @@
|
|||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
[section:queue C++ Concurrent Queues]
|
[section:queue C++ Concurrent Queues]
|
||||||
|
[///////////////////////////////////]
|
||||||
|
|
||||||
[note [@ http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3533.html N3533 C++ Concurrent Queues]]
|
[note [@ http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3533.html N3533 C++ Concurrent Queues]]
|
||||||
|
|
||||||
@@ -183,24 +190,25 @@
|
|||||||
[[X.3.4] [Managed Indirection] [No] [ - ]]
|
[[X.3.4] [Managed Indirection] [No] [ - ]]
|
||||||
]
|
]
|
||||||
[endsect]
|
[endsect]
|
||||||
[section:executors Asynchronous Executors]
|
[section:executors Executors and Schedulers]
|
||||||
|
[//////////////////////////////////////////]
|
||||||
|
|
||||||
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3785.pdf N3785 Executors and Schedulers]]
|
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3785.pdf N3785 Executors and Schedulers]]
|
||||||
|
|
||||||
[table Asynchronous Executors
|
[table Executors and Schedulers
|
||||||
[[Section] [Description] [Status] [Comments]]
|
[[Section] [Description] [Status] [Comments]]
|
||||||
[[V.1.1] [Class executor] [Yes] [ - ]]
|
[[V.1.1] [Class `executor`] [Yes] [ - ]]
|
||||||
[[V.1.1] [add] [Yes] [ renamed with a function template submit ]]
|
[[V.1.1] [`add`] [Yes] [ renamed with a function template `submit` ]]
|
||||||
[[V.1.1] [num_of_pendin_closures] [No] [ ]]
|
[[V.1.1] [`num_of_pendin_closures`] [No] [ ]]
|
||||||
[[V.1.2] [Class sceduled_executor] [No] [ - ]]
|
[[V.1.2] [Class sceduled_executor] [No] [ - ]]
|
||||||
[[V.1.2] [add_at] [No] [ renamed with a function template submit_at ]]
|
[[V.1.2] [`add_at`] [No] [ renamed with a function template `scheduler::submit_at` ]]
|
||||||
[[V.1.2] [add_after] [No] [ renamed with a function template submit_after ]]
|
[[V.1.2] [`add_after`] [No] [ renamed with a function template `scheduler::submit_after` ]]
|
||||||
[[V.2] [Concrete executor classes] [No] [ - ]]
|
[[V.2] [Concrete executor classes] [No] [ - ]]
|
||||||
[[V.2.1] [thread_pool] [Yes] [ static version Basic_thread_pool, dynamic one execduler_adaptor<basic_thread_pool> ]]
|
[[V.2.1] [`thread_pool`] [Yes] [ static version `basic_thread_pool`, dynamic one `execduler_adaptor<basic_thread_pool>` ]]
|
||||||
[[V.2.2] [serial_executor] [yes] [ - ]]
|
[[V.2.2] [`serial_executor`] [yes] [ - ]]
|
||||||
[[V.2.3] [loop_executor] [Yes] [ static version loop_scheduler, dynamic one execduler_adaptor<loop_scheduler> ]]
|
[[V.2.3] [`loop_executor`] [Yes] [ static version loop_scheduler, dynamic one `execduler_adaptor<loop_scheduler>` ]]
|
||||||
[[V.2.4] [inline_executor] [Yes] [ static version inline_executor, dynamic one execduler_adaptor<inline_executor> ]]
|
[[V.2.4] [`inline_executor`] [Yes] [ static version `inline_executor`, dynamic one `execduler_adaptor<inline_executor>` ]]
|
||||||
[[V.2.5] [thread_executor] [Yes] [ static version thread_executor, dynamic one execduler_adaptor<thread_executor> ]]
|
[[V.2.5] [`thread_executor`] [Yes] [ static version `thread_executor`, dynamic one `execduler_adaptor<thread_executor>` ]]
|
||||||
]
|
]
|
||||||
|
|
||||||
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3784.pdf N3784-Improvements to `std::future<T> and Related APIs]]
|
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3784.pdf N3784-Improvements to `std::future<T> and Related APIs]]
|
||||||
@@ -212,8 +220,31 @@
|
|||||||
[[30.6.8] [`async`] [Yes] [ - ]]
|
[[30.6.8] [`async`] [Yes] [ - ]]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4143.pdf N4143-Executors and schedulers, revision 4]]
|
||||||
|
|
||||||
|
[table Executors and Schedulers - revision 4
|
||||||
|
[[Section] [Description] [Status] [Comments]]
|
||||||
|
[[VI.A] [Executor Concept] [Yes] [ `wrapper_type` renamed by `work` and `spawn by `submit` ]]
|
||||||
|
[[VI.A.1] [`thread_per_task_executor] [Yes] [ renamed `thread_executor`]]
|
||||||
|
[[VI.A.2] [`thread_pool_executor`] [Yes] [ renamed `basic_thread_pool`]]
|
||||||
|
[[VI.A.3] [`system_executor`] [No] [ - ]]
|
||||||
|
[[VI.A.4] [`loop_executor`] [Yes] [ - ]]
|
||||||
|
[[VI.A.5] [`serial_executor`] [yes] [ - ]]
|
||||||
|
[[VI.B] [`executor_ref`] [yes] [ - ]]
|
||||||
|
[[VI.C] [`executor`] [yes] [ renamed `gen_executor_ref` ]]
|
||||||
|
[[VI.D] [Free Functions and Helper Objects] [partial] [ - ]]
|
||||||
|
[[VI.D] [`make_package`] [No] [ - ]]
|
||||||
|
[[VI.D] [`spawn_future`] [No] [ `async(Ex&, ...)` is similar but returns a blocking future. ]]
|
||||||
|
[[VI.D] [`spawn`] [No] [ - ]]
|
||||||
|
[[VI.D] [`task_wrapper`] [No] [ renamed `resubmitter` ]]
|
||||||
|
[[VI.D] [`set_executor`] [No] [ renamed `resubmit` ]]
|
||||||
|
[[VI.D] [`function_wrapper`] [Partial] [ renamed `work` ]]
|
||||||
|
]
|
||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
[//////////////////////////////////////////////////////////////
|
||||||
[section:stream_mutex C++ Stream Mutexes - C++ Stream Guards]
|
[section:stream_mutex C++ Stream Mutexes - C++ Stream Guards]
|
||||||
|
[/////////////////////////////////////////////////////////////]
|
||||||
|
|
||||||
While Boost.Thread implementation of stream mutexes differ in the approach, it is worth comparing with the current trend on the standard.
|
While Boost.Thread implementation of stream mutexes differ in the approach, it is worth comparing with the current trend on the standard.
|
||||||
|
|
||||||
@@ -241,7 +272,7 @@ While Boost.Thread implementation of stream mutexes differ in the approach, it i
|
|||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
|
||||||
|
///////////////////////////////]
|
||||||
[endsect]
|
[endsect]
|
||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[/
|
[/
|
||||||
(C) Copyright 20012 Vicente J. Botet Escriba.
|
(C) Copyright 2012-2015 Vicente J. Botet Escriba.
|
||||||
Distributed under the Boost Software License, Version 1.0.
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
(See accompanying file LICENSE_1_0.txt or copy at
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
http://www.boost.org/LICENSE_1_0.txt).
|
http://www.boost.org/LICENSE_1_0.txt).
|
||||||
@@ -23,6 +23,7 @@
|
|||||||
[[PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN] [DONT_PROVIDE_GENERIC_SHARED_MUTEX_ON_WIN] [NO] [YES] [YES] ]
|
[[PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN] [DONT_PROVIDE_GENERIC_SHARED_MUTEX_ON_WIN] [NO] [YES] [YES] ]
|
||||||
|
|
||||||
[[PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION] [DONT_PROVIDE_SHARED_MUTEX_UPWARDS_CONVERSION] [NO] [YES] [YES] ]
|
[[PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION] [DONT_PROVIDE_SHARED_MUTEX_UPWARDS_CONVERSION] [NO] [YES] [YES] ]
|
||||||
|
[[PROVIDES_EXECUTORS] [-] [NO] [NO] [NO] ]
|
||||||
[[PROVIDES_EXPLICIT_LOCK_CONVERSION] [DONT_PROVIDE_EXPLICIT_LOCK_CONVERSION] [NO] [YES] [YES] ]
|
[[PROVIDES_EXPLICIT_LOCK_CONVERSION] [DONT_PROVIDE_EXPLICIT_LOCK_CONVERSION] [NO] [YES] [YES] ]
|
||||||
[[PROVIDES_FUTURE] [DONT_PROVIDE_FUTURE] [NO] [YES] [YES] ]
|
[[PROVIDES_FUTURE] [DONT_PROVIDE_FUTURE] [NO] [YES] [YES] ]
|
||||||
[[PROVIDES_FUTURE_CTOR_ALLOCATORS] [DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS] [NO] [YES] [YES] ]
|
[[PROVIDES_FUTURE_CTOR_ALLOCATORS] [DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS] [NO] [YES] [YES] ]
|
||||||
@@ -80,7 +81,7 @@ When `BOOST_THREAD_VERSION>3` && defined BOOST_THREAD_PLATFORM_PTHREAD define `
|
|||||||
|
|
||||||
[section:move Boost.Atomic]
|
[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_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.
|
Define `BOOST_THREAD_DONT_USE_ATOMIC ` if you don't want to use Boost.Atomic or if it is not supported in your platform.
|
||||||
|
|||||||
@@ -260,14 +260,14 @@ Locks provide an explicit bool conversion operator when the compiler provides th
|
|||||||
|
|
||||||
The library provides un implicit conversion to an undefined type that can be used as a conditional expression.
|
The library provides un implicit conversion to an undefined type that can be used as a conditional expression.
|
||||||
|
|
||||||
#if defined(BOOST_NO_EXPLICIT_CONVERSION_OPERATORS)
|
#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
|
||||||
operator ``['unspecified-bool-type]``() const;
|
operator ``['unspecified-bool-type]``() const;
|
||||||
bool operator!() const;
|
bool operator!() const;
|
||||||
#else
|
#else
|
||||||
explicit operator bool() const;
|
explicit operator bool() const;
|
||||||
#endif
|
#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`]
|
[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)
|
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:
|
There are however some limitations:
|
||||||
|
|
||||||
@@ -346,14 +346,14 @@ use
|
|||||||
|
|
||||||
And instead of
|
And instead of
|
||||||
|
|
||||||
#ifdef BOOST_NO_SCOPED_ENUMS
|
#ifdef BOOST_NO_CXX11_SCOPED_ENUMS
|
||||||
template <>
|
template <>
|
||||||
struct BOOST_SYMBOL_VISIBLE is_error_code_enum<future_errc> : public true_type { };
|
struct BOOST_SYMBOL_VISIBLE is_error_code_enum<future_errc> : public true_type { };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
use
|
use
|
||||||
|
|
||||||
#ifdef BOOST_NO_SCOPED_ENUMS
|
#ifdef BOOST_NO_CXX11_SCOPED_ENUMS
|
||||||
template <>
|
template <>
|
||||||
struct BOOST_SYMBOL_VISIBLE is_error_code_enum<future_errc::enum_type> : public true_type { };
|
struct BOOST_SYMBOL_VISIBLE is_error_code_enum<future_errc::enum_type> : public true_type { };
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ or inheriting from a class which add these lockable functions.
|
|||||||
The `basic_lockable_adapter` class helps to define the `BankAccount` class as
|
The `basic_lockable_adapter` class helps to define the `BankAccount` class as
|
||||||
|
|
||||||
class BankAccount
|
class BankAccount
|
||||||
: public basic_lockable_adapter<thread_mutex>
|
: public basic_lockable_adapter<boost::mutex>
|
||||||
{
|
{
|
||||||
int balance_;
|
int balance_;
|
||||||
public:
|
public:
|
||||||
@@ -138,7 +138,7 @@ Notice that now acct is being locked by Withdraw after it has already been locke
|
|||||||
As `boost::mutex` is not recursive, we need to use its recursive version `boost::recursive_mutex`.
|
As `boost::mutex` is not recursive, we need to use its recursive version `boost::recursive_mutex`.
|
||||||
|
|
||||||
class BankAccount
|
class BankAccount
|
||||||
: public basic_lockable_adapter<recursive_mutex>
|
: public basic_lockable_adapter<boost::recursive_mutex>
|
||||||
{
|
{
|
||||||
|
|
||||||
// ...
|
// ...
|
||||||
@@ -147,7 +147,7 @@ As `boost::mutex` is not recursive, we need to use its recursive version `boost:
|
|||||||
The caller-ensured locking approach is more flexible and the most efficient, but very dangerous. In an implementation using caller-ensured locking, BankAccount still holds a mutex, but its member functions don't manipulate it at all. Deposit and Withdraw are not thread-safe anymore. Instead, the client code is responsible for locking BankAccount properly.
|
The caller-ensured locking approach is more flexible and the most efficient, but very dangerous. In an implementation using caller-ensured locking, BankAccount still holds a mutex, but its member functions don't manipulate it at all. Deposit and Withdraw are not thread-safe anymore. Instead, the client code is responsible for locking BankAccount properly.
|
||||||
|
|
||||||
class BankAccount
|
class BankAccount
|
||||||
: public basic_lockable_adapter<boost:mutex> {
|
: public basic_lockable_adapter<boost::mutex> {
|
||||||
int balance_;
|
int balance_;
|
||||||
public:
|
public:
|
||||||
void Deposit(int amount) {
|
void Deposit(int amount) {
|
||||||
@@ -271,7 +271,7 @@ Now that we have such a strict `strict_lock`, how do we harness its power in def
|
|||||||
A little code is worth 1,000 words, a (hacked into) saying goes, so here's the new BankAccount class:
|
A little code is worth 1,000 words, a (hacked into) saying goes, so here's the new BankAccount class:
|
||||||
|
|
||||||
class BankAccount
|
class BankAccount
|
||||||
: public basic_lockable_adapter<boost:recursive_mutex>
|
: public basic_lockable_adapter<boost::mutex>
|
||||||
{
|
{
|
||||||
int balance_;
|
int balance_;
|
||||||
public:
|
public:
|
||||||
@@ -280,7 +280,7 @@ A little code is worth 1,000 words, a (hacked into) saying goes, so here's the n
|
|||||||
balance_ += amount;
|
balance_ += amount;
|
||||||
}
|
}
|
||||||
void Deposit(int amount) {
|
void Deposit(int amount) {
|
||||||
strict_lock<boost:mutex> guard(*this); // Internally locked
|
strict_lock<BankAccount> guard(*this); // Internally locked
|
||||||
Deposit(amount, guard);
|
Deposit(amount, guard);
|
||||||
}
|
}
|
||||||
void Withdraw(int amount, strict_lock<BankAccount>&) {
|
void Withdraw(int amount, strict_lock<BankAccount>&) {
|
||||||
@@ -288,7 +288,7 @@ A little code is worth 1,000 words, a (hacked into) saying goes, so here's the n
|
|||||||
balance_ -= amount;
|
balance_ -= amount;
|
||||||
}
|
}
|
||||||
void Withdraw(int amount) {
|
void Withdraw(int amount) {
|
||||||
strict_lock<boost:mutex> guard(*this); // Internally locked
|
strict_lock<BankAccount> guard(*this); // Internally locked
|
||||||
Withdraw(amount, guard);
|
Withdraw(amount, guard);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -327,7 +327,7 @@ The scheme is useful because the likelihood of a programmer forgetting about any
|
|||||||
Using `strict_lock` permits compile-time checking of the most common source of errors, and runtime checking of the less frequent problem.
|
Using `strict_lock` permits compile-time checking of the most common source of errors, and runtime checking of the less frequent problem.
|
||||||
|
|
||||||
Let's see how to enforce that the appropriate BankAccount object is locked. First, we need to add a member function to the `strict_lock` class template.
|
Let's see how to enforce that the appropriate BankAccount object is locked. First, we need to add a member function to the `strict_lock` class template.
|
||||||
The `bool strict_lock<T>::owns_lock(Loclable*)` function returns a reference to the locked object.
|
The `bool strict_lock<T>::owns_lock(Lockable*)` function returns a reference to the locked object.
|
||||||
|
|
||||||
template <class Lockable> class strict_lock {
|
template <class Lockable> class strict_lock {
|
||||||
... as before ...
|
... as before ...
|
||||||
@@ -338,7 +338,7 @@ The `bool strict_lock<T>::owns_lock(Loclable*)` function returns a reference to
|
|||||||
Second, BankAccount needs to use this function compare the locked object against this:
|
Second, BankAccount needs to use this function compare the locked object against this:
|
||||||
|
|
||||||
class BankAccount {
|
class BankAccount {
|
||||||
: public basic_lockable_adapter<boost::recursive_mutex>
|
: public basic_lockable_adapter<boost::mutex>
|
||||||
int balance_;
|
int balance_;
|
||||||
public:
|
public:
|
||||||
void Deposit(int amount, strict_lock<BankAccount>& guard) {
|
void Deposit(int amount, strict_lock<BankAccount>& guard) {
|
||||||
@@ -403,7 +403,7 @@ The solution is to use a little bridge template `externally_locked` that control
|
|||||||
T& get(strict_lock<Lockable>& lock) {
|
T& get(strict_lock<Lockable>& lock) {
|
||||||
|
|
||||||
#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
|
#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
|
||||||
if (!lock.owns_lock(&lockable_)) throw lock_error(); run time check throw if not locks the same
|
if (!lock.owns_lock(&lockable_)) throw lock_error(); //run time check throw if not locks the same
|
||||||
#endif
|
#endif
|
||||||
return obj_;
|
return obj_;
|
||||||
}
|
}
|
||||||
@@ -421,10 +421,10 @@ The solution is to use a little bridge template `externally_locked` that control
|
|||||||
Instead of making `checkingAcct_` and `savingsAcct_` of type `BankAccount`, `AccountManager` holds objects of type `externally_locked<BankAccount, AccountManager>`:
|
Instead of making `checkingAcct_` and `savingsAcct_` of type `BankAccount`, `AccountManager` holds objects of type `externally_locked<BankAccount, AccountManager>`:
|
||||||
|
|
||||||
class AccountManager
|
class AccountManager
|
||||||
: public basic_lockable_adapter<thread_mutex>
|
: public basic_lockable_adapter<boost::mutex>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef basic_lockable_adapter<thread_mutex> lockable_base_type;
|
typedef basic_lockable_adapter<boost::mutex> lockable_base_type;
|
||||||
AccountManager()
|
AccountManager()
|
||||||
: checkingAcct_(*this)
|
: checkingAcct_(*this)
|
||||||
, savingsAcct_(*this)
|
, savingsAcct_(*this)
|
||||||
@@ -498,7 +498,7 @@ Now we need to state that both classes are `strict_lock`s.
|
|||||||
|
|
||||||
Well let me show what this `nested_strict_lock` class looks like and the impacts on the `externally_locked` class and the `AccountManager::AMoreComplicatedFunction` function.
|
Well let me show what this `nested_strict_lock` class looks like and the impacts on the `externally_locked` class and the `AccountManager::AMoreComplicatedFunction` function.
|
||||||
|
|
||||||
First `nested_strict_lock` class will store on a temporary lock the `Locker`, and transfer the lock ownership on the constructor. On destruction it will restore the ownership. Note the use of `lock_traits` and that the `Locker` needs to have a reference to the mutex otherwise and exception is thrown.
|
First `nested_strict_lock` class will store on a temporary lock the `Locker`, and transfer the lock ownership on the constructor. On destruction it will restore the ownership. Note the use of `lock_traits` and that the `Locker` needs to have a reference to the mutex otherwise an exception is thrown.
|
||||||
|
|
||||||
template <typename Locker >
|
template <typename Locker >
|
||||||
class nested_strict_lock
|
class nested_strict_lock
|
||||||
@@ -510,7 +510,7 @@ First `nested_strict_lock` class will store on a temporary lock the `Locker`, an
|
|||||||
|
|
||||||
nested_strict_lock(Locker& lock)
|
nested_strict_lock(Locker& lock)
|
||||||
: lock_(lock) // Store reference to locker
|
: lock_(lock) // Store reference to locker
|
||||||
, tmp_lock_(lock.move()) // Move ownership to temporaty locker
|
, tmp_lock_(lock.move()) // Move ownership to temporary locker
|
||||||
{
|
{
|
||||||
#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
|
#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
|
||||||
if (tmp_lock_.mutex()==0) {
|
if (tmp_lock_.mutex()==0) {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
[/
|
[/
|
||||||
(C) Copyright 2008-11 Anthony Williams.
|
(C) Copyright 2008-11 Anthony Williams.
|
||||||
|
(C) Copyright 2012-2015 Vicente J. Botet Escriba.
|
||||||
Distributed under the Boost Software License, Version 1.0.
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
(See accompanying file LICENSE_1_0.txt or copy at
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
http://www.boost.org/LICENSE_1_0.txt).
|
http://www.boost.org/LICENSE_1_0.txt).
|
||||||
@@ -28,9 +29,11 @@
|
|||||||
|
|
||||||
enum class launch
|
enum class launch
|
||||||
{
|
{
|
||||||
|
none = unspecified,
|
||||||
async = unspecified,
|
async = unspecified,
|
||||||
deferred = unspecified,
|
deferred = unspecified,
|
||||||
executor = unspecified,
|
executor = unspecified,
|
||||||
|
inherit = unspecified,
|
||||||
any = async | deferred
|
any = async | deferred
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -124,10 +127,10 @@
|
|||||||
future<typename decay<T>::type> make_ready_future(T&& value); // EXTENSION
|
future<typename decay<T>::type> make_ready_future(T&& value); // EXTENSION
|
||||||
future<void> make_ready_future(); // 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>
|
template <typename E>
|
||||||
exceptional_ptr make_exceptional(E ex); // EXTENSION
|
exceptional_ptr make_exceptional_future(E ex); // EXTENSION
|
||||||
exceptional_ptr make_exceptional(); // EXTENSION
|
exceptional_ptr make_exceptional_future(); // EXTENSION
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -164,14 +167,27 @@
|
|||||||
|
|
||||||
enum class launch
|
enum class launch
|
||||||
{
|
{
|
||||||
|
none = unspecified,
|
||||||
async = unspecified,
|
async = unspecified,
|
||||||
deferred = unspecified,
|
deferred = unspecified,
|
||||||
executor = unspecified,
|
executor = unspecified,
|
||||||
|
inherit = unspecified,
|
||||||
any = async | deferred
|
any = async | deferred
|
||||||
};
|
};
|
||||||
|
|
||||||
The enum type launch is a bitmask type with launch::async and launch::deferred denoting individual bits.
|
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]
|
[endsect]
|
||||||
[///////////////////////////////////////////////////////////////////////////]
|
[///////////////////////////////////////////////////////////////////////////]
|
||||||
[section:is_error_code_enum Specialization `is_error_code_enum<future_errc>`]
|
[section:is_error_code_enum Specialization `is_error_code_enum<future_errc>`]
|
||||||
@@ -333,7 +349,7 @@ The object's `name` virtual function returns a pointer to the string "future".]]
|
|||||||
|
|
||||||
// move support
|
// move support
|
||||||
__unique_future__(__unique_future__ && other) noexcept;
|
__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;
|
__unique_future__& operator=(__unique_future__ && other) noexcept;
|
||||||
|
|
||||||
// factories
|
// factories
|
||||||
@@ -342,9 +358,9 @@ The object's `name` virtual function returns a pointer to the string "future".]]
|
|||||||
template<typename F>
|
template<typename F>
|
||||||
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
|
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
|
||||||
then(F&& func); // EXTENSION
|
then(F&& func); // EXTENSION
|
||||||
template<typename S, typename F>
|
template<typename Ex, typename F>
|
||||||
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
|
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
|
||||||
then(S& scheduler, F&& func); // EXTENSION
|
then(Ex& executor, F&& func); // EXTENSION
|
||||||
template<typename F>
|
template<typename F>
|
||||||
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
|
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
|
||||||
then(launch policy, F&& func); // EXTENSION
|
then(launch policy, F&& func); // EXTENSION
|
||||||
@@ -437,7 +453,7 @@ associated with `*this`. `other` is not associated with any shared state.]]
|
|||||||
[///////////////////////////////////////////////////////////////////]
|
[///////////////////////////////////////////////////////////////////]
|
||||||
[section:unwrap_move_constructor Unwrap Move Constructor - EXTENSION]
|
[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.
|
[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 :(]
|
There are not too much tests yet, so it is possible that you can find out some trivial bugs :(]
|
||||||
@@ -832,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
|
[[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.]]
|
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.]]
|
[[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.]]
|
||||||
|
|
||||||
@@ -882,9 +898,9 @@ associated with `*this` is ready for retrieval, __waiting__ otherwise.]]
|
|||||||
template<typename F>
|
template<typename F>
|
||||||
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
|
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
|
||||||
then(F&& func); // EXTENSION
|
then(F&& func); // EXTENSION
|
||||||
template<typename S, typename F>
|
template<typename Ex, typename F>
|
||||||
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
|
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
|
||||||
then(S& scheduler, F&& func); // EXTENSION
|
then(Ex& executor, F&& func); // EXTENSION
|
||||||
template<typename F>
|
template<typename F>
|
||||||
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
|
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
|
||||||
then(launch policy, F&& func); // EXTENSION
|
then(launch policy, F&& func); // EXTENSION
|
||||||
@@ -897,29 +913,41 @@ There are not too much tests yet, so it is possible that you can find out some t
|
|||||||
[variablelist
|
[variablelist
|
||||||
|
|
||||||
[[Notes:] [The three functions differ only by input parameters. The first only takes a callable object which accepts a
|
[[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 scheduler 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
|
the second parameter. The third function takes a launch policy as the first parameter and a callable object as the
|
||||||
second parameter.]]
|
second parameter.]]
|
||||||
|
|
||||||
|
[[Requires:] [`INVOKE(DECAY_COPY (std::forward<F>(func)), std::move(*this))` shall be a valid expression.]]
|
||||||
|
|
||||||
[[Effects:] [
|
[[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 scheduler.
|
- 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 scheduler or launch policy is not provided the continuation inherits the
|
|
||||||
parent's launch policy or scheduler.
|
|
||||||
|
|
||||||
- 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
|
- When the launch policy is `launch::none` the continuation is called on an unspecified thread of execution.
|
||||||
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
|
- When the launch policy is `launch::async` the continuation is called on a new thread of execution.
|
||||||
scheduler, then the parent is filled by immediately calling `.wait()`, and the policy of the antecedent is
|
|
||||||
|
- 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`.
|
||||||
|
|
||||||
]]
|
]]
|
||||||
@@ -1329,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
|
[[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.]]
|
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.]]
|
[[Throws:] [Whatever `mutex::lock()/mutex::unlock()` can throw.]]
|
||||||
|
|
||||||
@@ -1359,9 +1387,9 @@ associated with `*this` is ready for retrieval, __waiting__ otherwise.]]
|
|||||||
template<typename F>
|
template<typename F>
|
||||||
__unique_future__<typename boost::result_of<F(shared_future)>::type>
|
__unique_future__<typename boost::result_of<F(shared_future)>::type>
|
||||||
then(F&& func) const; // EXTENSION
|
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>
|
__unique_future__<typename boost::result_of<F(shared_future)>::type>
|
||||||
then(S& scheduler, F&& func) const; // EXTENSION
|
then(Ex& executor, F&& func) const; // EXTENSION
|
||||||
template<typename F>
|
template<typename F>
|
||||||
__unique_future__<typename boost::result_of<F(shared_future)>::type>
|
__unique_future__<typename boost::result_of<F(shared_future)>::type>
|
||||||
then(launch policy, F&& func) const; // EXTENSION
|
then(launch policy, F&& func) const; // EXTENSION
|
||||||
@@ -1375,26 +1403,42 @@ There are not too much tests yet, so it is possible that you can find out some t
|
|||||||
[variablelist
|
[variablelist
|
||||||
|
|
||||||
[[Notes:] [The three functions differ only by input parameters. The first only takes a callable object which accepts a
|
[[Notes:] [The three functions differ only by input parameters. The first only takes a callable object which accepts a
|
||||||
shared_future object as a parameter. The second function takes a scheduler as the first parameter and a callable object as
|
shared_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
|
the second parameter. The third function takes a launch policy as the first parameter and a callable object as the
|
||||||
second parameter.]]
|
second parameter.]]
|
||||||
|
|
||||||
|
[[Requires:] [`INVOKE(DECAY_COPY (std::forward<F>(func)), *this)` shall be a valid expression.]]
|
||||||
|
|
||||||
[[Effects:] [
|
[[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 scheduler.
|
- 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 scheduler or launch policy is not provided the continuation inherits the
|
- Any value returned from the continuation is stored as the result in the shared state of the resulting `future`.
|
||||||
parent's launch policy or scheduler.
|
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.
|
||||||
scheduler, then the parent is filled by immediately calling `.wait()`, and the policy of the antecedent is
|
|
||||||
`launch::deferred`
|
- 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`.
|
||||||
|
|
||||||
]]
|
]]
|
||||||
|
|
||||||
@@ -2407,12 +2451,12 @@ Otherwise the value is copied to the shared state of the returned future.
|
|||||||
|
|
||||||
[endsect]
|
[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>
|
template <typename E>
|
||||||
exceptional_ptr make_exceptional(E ex); // EXTENSION
|
exceptional_ptr make_exceptional_future(E ex); // EXTENSION
|
||||||
exceptional_ptr make_exceptional(); // EXTENSION
|
exceptional_ptr make_exceptional_future(); // EXTENSION
|
||||||
|
|
||||||
[variablelist
|
[variablelist
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
[/
|
[/
|
||||||
(C) Copyright 2008-11 Anthony Williams.
|
(C) Copyright 2008-11 Anthony Williams.
|
||||||
|
(C) Copyright 2012-2015 Vicente J. Botet Escriba.
|
||||||
Distributed under the Boost Software License, Version 1.0.
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
(See accompanying file LICENSE_1_0.txt or copy at
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
http://www.boost.org/LICENSE_1_0.txt).
|
http://www.boost.org/LICENSE_1_0.txt).
|
||||||
@@ -325,7 +326,7 @@ Using a `shared_future` solves the issue
|
|||||||
|
|
||||||
[heading share()]
|
[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
|
Here `share()` could be used to simplify the code
|
||||||
|
|
||||||
void better_second_use( type arg ) {
|
void better_second_use( type arg ) {
|
||||||
@@ -343,7 +344,7 @@ Here `share()` could be used to simplify the code
|
|||||||
|
|
||||||
[heading Writing on get()]
|
[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 ) {
|
void write_to_get( type arg ) {
|
||||||
|
|
||||||
@@ -364,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.
|
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.
|
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.
|
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]
|
[endsect]
|
||||||
@@ -443,10 +444,10 @@ Input Parameters:
|
|||||||
success and one for error handling. However this option has not been retained for the moment.
|
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
|
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.
|
through. This makes propagating exceptions straightforward. This approach also simplifies the chaining of continuations.
|
||||||
* Scheduler: Providing an overload to `.then`, to take a scheduler 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
|
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 scheduler must outlive the continuation.
|
asynchronous operations. The lifetime of the executor must outlive the continuation.
|
||||||
* Launch policy: if the additional flexibility that the scheduler provides is not required.
|
* Launch policy: if the additional flexibility that the executor provides is not required.
|
||||||
|
|
||||||
Return values: The decision to return a future was based primarily on the ability to chain multiple continuations using
|
Return values: The decision to return a future was based primarily on the ability to chain multiple continuations using
|
||||||
`.then()`. This benefit of composability gives the programmer incredible control and flexibility over their code. Returning
|
`.then()`. This benefit of composability gives the programmer incredible control and flexibility over their code. Returning
|
||||||
|
|||||||
@@ -240,9 +240,9 @@ The following class describes a so-called monitor pattern.
|
|||||||
template <
|
template <
|
||||||
typename Lockable=mutex
|
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:
|
protected:
|
||||||
typedef unspecified synchronizer; // is an strict lock guard
|
typedef unspecified synchronizer; // is a strict lock guard
|
||||||
};
|
};
|
||||||
|
|
||||||
[/shared_monitor]
|
[/shared_monitor]
|
||||||
|
|||||||
@@ -869,7 +869,7 @@ any other threads have shared ownership, blocks until exclusive ownership can be
|
|||||||
|
|
||||||
[variablelist
|
[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.
|
[[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.
|
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
|
[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.
|
[[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`.
|
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
|
[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`.
|
[[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()`).
|
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.
|
__nested_strict_lock is a model of __StrictLock.
|
||||||
|
|
||||||
A nested strict lock is a scoped lock guard ensuring a mutex is locked on its
|
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.
|
and restoring the ownership to the nesting lock on destruction.
|
||||||
|
|
||||||
|
|
||||||
@@ -2664,7 +2664,7 @@ Only the specificities respect to __Lockable are described here.
|
|||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
[///////////////////////////////]
|
[///////////////////////////////]
|
||||||
[section:get2 `get(strict_lock<nested_strict_lock<Lock>>&)`]
|
[section:get2 `get(nested_strict_lock<Lock>&)`]
|
||||||
|
|
||||||
template <class Lock>
|
template <class Lock>
|
||||||
T& get(nested_strict_lock<Lock>& lk);
|
T& get(nested_strict_lock<Lock>& lk);
|
||||||
@@ -2684,7 +2684,7 @@ Only the specificities respect to __Lockable are described here.
|
|||||||
[endsect]
|
[endsect]
|
||||||
|
|
||||||
[///////////////////////////////]
|
[///////////////////////////////]
|
||||||
[section:get3 `get(strict_lock<nested_strict_lock<Lock>>&)`]
|
[section:get3 `get(Lock&)`]
|
||||||
|
|
||||||
template <class Lock>
|
template <class Lock>
|
||||||
T& get(Lock& lk);
|
T& get(Lock& lk);
|
||||||
@@ -2826,7 +2826,7 @@ Only the specificities respect to __Lockable are described here.
|
|||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
[///////////////////////////////]
|
[///////////////////////////////]
|
||||||
[section:get2 `get(strict_lock<nested_strict_lock<Lock>>&)`]
|
[section:get2 `get(nested_strict_lock<Lock>&)`]
|
||||||
|
|
||||||
template <class Lock>
|
template <class Lock>
|
||||||
T& get(nested_strict_lock<Lock>& lk);
|
T& get(nested_strict_lock<Lock>& lk);
|
||||||
@@ -2846,7 +2846,7 @@ Only the specificities respect to __Lockable are described here.
|
|||||||
[endsect]
|
[endsect]
|
||||||
|
|
||||||
[///////////////////////////////]
|
[///////////////////////////////]
|
||||||
[section:get3 `get(strict_lock<nested_strict_lock<Lock>>&)`]
|
[section:get3 `get(Lock&)`]
|
||||||
|
|
||||||
template <class Lock>
|
template <class Lock>
|
||||||
T& get(Lock& lk);
|
T& get(Lock& lk);
|
||||||
@@ -3034,8 +3034,8 @@ An instance of __reverse_lock doesn't ['own] the lock never.
|
|||||||
[[Effects:] [Locks the __lockable_concept_type__ objects supplied as
|
[[Effects:] [Locks the __lockable_concept_type__ objects supplied as
|
||||||
arguments in an unspecified and indeterminate order in a way that
|
arguments in an unspecified and indeterminate order in a way that
|
||||||
avoids deadlock. It is safe to call this function concurrently from
|
avoids deadlock. It is safe to call this function concurrently from
|
||||||
multiple threads with the same mutexes (or other lockable objects) in
|
multiple threads for any set of mutexes (or other lockable objects) in
|
||||||
different orders without risk of deadlock. If any of the __lock_ref__
|
any order without risk of deadlock. If any of the __lock_ref__
|
||||||
or __try_lock_ref__ operations on the supplied
|
or __try_lock_ref__ operations on the supplied
|
||||||
__lockable_concept_type__ objects throws an exception any locks
|
__lockable_concept_type__ objects throws an exception any locks
|
||||||
acquired by the function will be released before the function exits.]]
|
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
|
[[Effects:] [Locks all the __lockable_concept_type__ objects in the
|
||||||
supplied range in an unspecified and indeterminate order in a way that
|
supplied range in an unspecified and indeterminate order in a way that
|
||||||
avoids deadlock. It is safe to call this function concurrently from
|
avoids deadlock. It is safe to call this function concurrently from
|
||||||
multiple threads with the same mutexes (or other lockable objects) in
|
multiple threads for any set of mutexes (or other lockable objects) in
|
||||||
different orders without risk of deadlock. If any of the __lock_ref__
|
any order without risk of deadlock. If any of the __lock_ref__
|
||||||
or __try_lock_ref__ operations on the __lockable_concept_type__
|
or __try_lock_ref__ operations on the __lockable_concept_type__
|
||||||
objects in the supplied range throws an exception any locks acquired
|
objects in the supplied range throws an exception any locks acquired
|
||||||
by the function will be released before the function exits.]]
|
by the function will be released before the function exits.]]
|
||||||
|
|||||||
@@ -15,11 +15,12 @@
|
|||||||
struct detach;
|
struct detach;
|
||||||
struct join_if_joinable;
|
struct join_if_joinable;
|
||||||
struct interrupt_and_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;
|
class strict_scoped_thread;
|
||||||
template <class CallableThread = join_if_joinable>
|
template <class CallableThread = join_if_joinable, class Thread = thread>
|
||||||
class scoped_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]
|
[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.
|
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
|
struct detach
|
||||||
{
|
{
|
||||||
void operator()(thread& t)
|
template <class Thread>
|
||||||
|
void operator()(Thread& t)
|
||||||
{
|
{
|
||||||
t.detach();
|
t.detach();
|
||||||
}
|
}
|
||||||
@@ -64,7 +66,8 @@ The difference between strict_scoped_thread and scoped_thread is that the strict
|
|||||||
|
|
||||||
struct join_if_joinable
|
struct join_if_joinable
|
||||||
{
|
{
|
||||||
void operator()(thread& t)
|
template <class Thread>
|
||||||
|
void operator()(Thread& t)
|
||||||
{
|
{
|
||||||
if (t.joinable())
|
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
|
struct interrupt_and_join_if_joinable
|
||||||
{
|
{
|
||||||
void operator()(thread& t)
|
template <class Thread>
|
||||||
|
void operator()(Thread& t)
|
||||||
{
|
{
|
||||||
t.interrupt();
|
t.interrupt();
|
||||||
if (t.joinable())
|
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>
|
// #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
|
class strict_scoped_thread
|
||||||
{
|
{
|
||||||
thread t_; // for exposition purposes only
|
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(strict_scoped_thread const&) = delete;
|
||||||
strict_scoped_thread& operator=(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>
|
template <typename F&&, typename ...Args>
|
||||||
explicit strict_scoped_thread(F&&, 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]
|
[section:default_constructor Constructor from a __thread]
|
||||||
|
|
||||||
explicit strict_scoped_thread(thread&& t) noexcept;
|
explicit strict_scoped_thread(Thread&& t) noexcept;
|
||||||
|
|
||||||
[variablelist
|
[variablelist
|
||||||
|
|
||||||
@@ -150,7 +154,7 @@ This wrapper can be used to join the thread before destroying it.
|
|||||||
|
|
||||||
[variablelist
|
[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()`.]]
|
[[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>
|
#include <boost/thread/scoped_thread.hpp>
|
||||||
|
|
||||||
template <class CallableThread>
|
template <class CallableThread, class Thread = thread>
|
||||||
class scoped_thread
|
class scoped_thread
|
||||||
{
|
{
|
||||||
thread t_; // for exposition purposes only
|
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.
|
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
|
[variablelist
|
||||||
|
|
||||||
[[Effects:] [Transfers ownership of the scoped_thread managed by `other` (if
|
[[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.]]
|
[[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>
|
#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
|
[variablelist
|
||||||
|
|
||||||
|
|||||||
@@ -110,10 +110,10 @@ where
|
|||||||
* `q` denotes a value of type `Q`,
|
* `q` denotes a value of type `Q`,
|
||||||
* `e` denotes a value of type Q::value_type,
|
* `e` denotes a value of type Q::value_type,
|
||||||
* `u` denotes a value of type Q::size_type,
|
* `u` denotes a value of type Q::size_type,
|
||||||
* `lve` denotes a lvalue referece of type Q::value_type,
|
* `lve` denotes an lvalue reference of type Q::value_type,
|
||||||
* `rve` denotes a rvalue referece of type Q::value_type:
|
* `rve` denotes an rvalue reference of type Q::value_type:
|
||||||
[/* `spe` denotes a shared_ptr<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`,
|
||||||
|
|
||||||
|
|
||||||
[/////////////////////////////////////]
|
[/////////////////////////////////////]
|
||||||
@@ -181,7 +181,7 @@ where
|
|||||||
|
|
||||||
[variablelist
|
[variablelist
|
||||||
|
|
||||||
[[Requires:] [Q::value_type is no throw copy movable. This is needed to ensure the exception safety.]]
|
[[Requires:] [Q::value_type is no throw move constructible. This is needed to ensure the exception safety.]]
|
||||||
|
|
||||||
[[Effects:] [Waits until the queue is not empty and not closed. If the queue is empty and closed throws sync_queue_is_closed. Otherwise pull the element from the queue `q` and moves the pulled element.]]
|
[[Effects:] [Waits until the queue is not empty and not closed. If the queue is empty and closed throws sync_queue_is_closed. Otherwise pull the element from the queue `q` and moves the pulled element.]]
|
||||||
|
|
||||||
@@ -206,7 +206,7 @@ where
|
|||||||
|
|
||||||
[variablelist
|
[variablelist
|
||||||
|
|
||||||
[/[Requires:] [Q::value_type is no throw copy movable. This is needed to ensure the exception safety. ]]
|
[/[Requires:] [Q::value_type is no throw move assignable. This is needed to ensure the exception safety. ]]
|
||||||
|
|
||||||
[[Effects:] [Waits until the queue is not empty and not closed. If the queue is empty and closed throws sync_queue_is_closed. Otherwise pull the element from the queue `q` and moves the pulled element into a shared_ptr.]]
|
[[Effects:] [Waits until the queue is not empty and not closed. If the queue is empty and closed throws sync_queue_is_closed. Otherwise pull the element from the queue `q` and moves the pulled element into a shared_ptr.]]
|
||||||
|
|
||||||
@@ -246,8 +246,8 @@ where
|
|||||||
* `e` denotes a value of type `Q::value_type`,
|
* `e` denotes a value of type `Q::value_type`,
|
||||||
* `s` denotes a value of type `queue_status`,
|
* `s` denotes a value of type `queue_status`,
|
||||||
* `u` denotes a value of type `Q::size_type`,
|
* `u` denotes a value of type `Q::size_type`,
|
||||||
* `lve` denotes a lvalue referece of type Q::value_type,
|
* `lve` denotes an lvalue reference of type Q::value_type,
|
||||||
* `rve` denotes a rvalue referece of type Q::value_type:
|
* `rve` denotes an rvalue reference of type Q::value_type:
|
||||||
[/* `spe` denotes a shared_ptr<Q::value_type>]
|
[/* `spe` denotes a shared_ptr<Q::value_type>]
|
||||||
|
|
||||||
|
|
||||||
@@ -314,7 +314,7 @@ where
|
|||||||
|
|
||||||
[variablelist
|
[variablelist
|
||||||
|
|
||||||
[[Effects:] [Waits until the queue is not empty and then pull the element from the queue `q` and moves the pulled element into `lve` (this could need an allocation for unbounded queues).]]
|
[[Effects:] [If the queue is not empty pulls the element from the queue `q` and moves the pulled element into `lve` (this could need an allocation for unbounded queues).]]
|
||||||
|
|
||||||
[[Synchronization:] [Prior pull-like operations on the same object synchronizes with this operation.]]
|
[[Synchronization:] [Prior pull-like operations on the same object synchronizes with this operation.]]
|
||||||
|
|
||||||
@@ -357,8 +357,8 @@ where
|
|||||||
* `q` denotes a value of type `Q`,
|
* `q` denotes a value of type `Q`,
|
||||||
* `e` denotes a value of type Q::value_type,
|
* `e` denotes a value of type Q::value_type,
|
||||||
* `s` denotes a value of type `queue_status`,
|
* `s` denotes a value of type `queue_status`,
|
||||||
* `lve` denotes a lvalue referece of type Q::value_type,
|
* `lve` denotes an lvalue reference of type Q::value_type,
|
||||||
* `rve` denotes a rvalue referece of type Q::value_type:
|
* `rve` denotes an rvalue reference of type Q::value_type:
|
||||||
[/* `spe` denotes a shared_ptr<Q::value_type>]
|
[/* `spe` denotes a shared_ptr<Q::value_type>]
|
||||||
|
|
||||||
|
|
||||||
@@ -393,7 +393,7 @@ where
|
|||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
[/////////////////////////////////////]
|
[/////////////////////////////////////]
|
||||||
[section:nonblocking_push_back_m `s = q.nonblocking_push_back(rve());`]
|
[section:nonblocking_push_back_m `s = q.nonblocking_push_back(rve);`]
|
||||||
|
|
||||||
[variablelist
|
[variablelist
|
||||||
|
|
||||||
@@ -427,7 +427,7 @@ where
|
|||||||
|
|
||||||
[variablelist
|
[variablelist
|
||||||
|
|
||||||
[[Effects:] [Waits until the queue is not empty and then pull the element from the queue `q` and moves the pulled element into `lve` (this could need an allocation for unbounded queues).]]
|
[[Effects:] [If the queue is not empty pulls the element from the queue `q` and moves the pulled element into `lve` (this could need an allocation for unbounded queues).]]
|
||||||
|
|
||||||
[[Synchronization:] [Prior pull-like operations on the same object synchronizes with this operation.]]
|
[[Synchronization:] [Prior pull-like operations on the same object synchronizes with this operation.]]
|
||||||
|
|
||||||
@@ -545,7 +545,7 @@ Closed queues add the following valid expressions
|
|||||||
|
|
||||||
[[Return:] [
|
[[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.
|
- otherwise, return `queue_op_status::success` if no exception is thrown.
|
||||||
|
|
||||||
@@ -636,12 +636,12 @@ Closed queues add the following valid expressions
|
|||||||
|
|
||||||
namespace boost
|
namespace boost
|
||||||
{
|
{
|
||||||
template <typename ValueType>
|
template <typename ValueType, class SizeType=std::size_t>
|
||||||
class queue_base
|
class queue_base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef ValueType value_type;
|
typedef ValueType value_type;
|
||||||
typedef std::size_t size_type;
|
typedef SizeType size_type;
|
||||||
|
|
||||||
// Constructors/Assignment/Destructors
|
// Constructors/Assignment/Destructors
|
||||||
virtual ~queue_base() {};
|
virtual ~queue_base() {};
|
||||||
@@ -671,7 +671,7 @@ Closed queues add the following valid expressions
|
|||||||
|
|
||||||
virtual queue_op_status wait_push_back(const value_type& x) = 0;
|
virtual queue_op_status wait_push_back(const value_type& x) = 0;
|
||||||
virtual queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
virtual queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
||||||
virtual queue_op_status wait_pull_front(ValueType& elem) = 0;
|
virtual queue_op_status wait_pull_front(value_type& elem) = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -685,11 +685,11 @@ Closed queues add the following valid expressions
|
|||||||
namespace boost
|
namespace boost
|
||||||
{
|
{
|
||||||
template <typename Queue>
|
template <typename Queue>
|
||||||
class queue_adaptor : public queue_base<typename Queue::value_type>
|
class queue_adaptor : public queue_base<typename Queue::value_type, typename Queue::size_type>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef typename Queue::value_type value_type;
|
typedef typename Queue::value_type value_type;
|
||||||
typedef std::size_t size_type;
|
typedef typename Queue::size_type size_type;
|
||||||
|
|
||||||
// Constructors/Assignment/Destructors
|
// Constructors/Assignment/Destructors
|
||||||
|
|
||||||
@@ -769,22 +769,14 @@ Closed queues add the following valid expressions
|
|||||||
void push(const value_type& x);
|
void push(const value_type& x);
|
||||||
void push(BOOST_THREAD_RV_REF(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(const value_type& x);
|
||||||
queue_op_status try_push(BOOST_THREAD_RV_REF(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(const value_type& x);
|
||||||
queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(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(const value_type& x);
|
||||||
queue_op_status wait_push(BOOST_THREAD_RV_REF(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
|
// Modifiers
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
void push(const value_type& x);
|
|
||||||
void push(BOOST_THREAD_RV_REF(value_type) x);
|
|
||||||
|
|
||||||
void pull(value_type& x);
|
void pull(value_type& x);
|
||||||
value_type pull();
|
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 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 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);
|
queue_op_status wait_pull(value_type& x);
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -1002,13 +983,13 @@ Closed queues add the following valid expressions
|
|||||||
|
|
||||||
namespace boost
|
namespace boost
|
||||||
{
|
{
|
||||||
template <typename ValueType>
|
template <typename ValueType, class Container = csbl::devector<ValueType>>
|
||||||
class sync_queue
|
class sync_queue
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef ValueType value_type;
|
typedef ValueType value_type;
|
||||||
typedef csbl::deque<ValueType> underlying_queue_type;
|
typedef Container underlying_queue_type;
|
||||||
typedef std::size_t size_type;
|
typedef typename Container::size_type size_type;
|
||||||
|
|
||||||
sync_queue(sync_queue const&) = delete;
|
sync_queue(sync_queue const&) = delete;
|
||||||
sync_queue& operator=(sync_queue const&) = delete;
|
sync_queue& operator=(sync_queue const&) = delete;
|
||||||
|
|||||||
@@ -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
|
provides full access to that object through the `get` member functions, provided you
|
||||||
pass a reference to a strict lock object.
|
pass a reference to a strict lock object.
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,9 @@
|
|||||||
|
|
||||||
[section:tutorial Tutorial]
|
[section:tutorial Tutorial]
|
||||||
|
|
||||||
[@http://home.roadrunner.com/~hinnant/mutexes/locking.html Handling mutexes in C++] is an excellent tutorial. You need just replace std and ting by boost.
|
|
||||||
|
[@http://web.archive.org/web/20140531071228/http://home.roadrunner.com/~hinnant/mutexes/locking.html Handling mutexes in C++] is an excellent tutorial. You need just replace std and ting by boost.
|
||||||
|
|
||||||
|
|
||||||
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2406.html Mutex, Lock, Condition Variable Rationale] adds rationale for the design decisions made for mutexes, locks and condition variables.
|
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2406.html Mutex, Lock, Condition Variable Rationale] adds rationale for the design decisions made for mutexes, locks and condition variables.
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
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)
|
void addTrailingSlashIfMissing(boost::synchronized_value<std::string> & path)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -88,9 +88,9 @@
|
|||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
typedef Lockable mutex_type;
|
typedef Lockable mutex_type;
|
||||||
|
|
||||||
synchronized_value() noexept(is_nothrow_default_constructible<T>::value);
|
synchronized_value() noexcept(is_nothrow_default_constructible<T>::value);
|
||||||
synchronized_value(T const& other) noexept(is_nothrow_copy_constructible<T>::value);
|
synchronized_value(T const& other) noexcept(is_nothrow_copy_constructible<T>::value);
|
||||||
synchronized_value(T&& other) noexept(is_nothrow_move_constructible<T>::value);
|
synchronized_value(T&& other) noexcept(is_nothrow_move_constructible<T>::value);
|
||||||
synchronized_value(synchronized_value const& rhs);
|
synchronized_value(synchronized_value const& rhs);
|
||||||
synchronized_value(synchronized_value&& other);
|
synchronized_value(synchronized_value&& other);
|
||||||
|
|
||||||
@@ -129,7 +129,7 @@
|
|||||||
|
|
||||||
[section:constructor `synchronized_value()`]
|
[section:constructor `synchronized_value()`]
|
||||||
|
|
||||||
synchronized_value() noexept(is_nothrow_default_constructible<T>::value);
|
synchronized_value() noexcept(is_nothrow_default_constructible<T>::value);
|
||||||
|
|
||||||
[variablelist
|
[variablelist
|
||||||
|
|
||||||
@@ -145,7 +145,7 @@
|
|||||||
|
|
||||||
[section:constructor_vt `synchronized_value(T const&)`]
|
[section:constructor_vt `synchronized_value(T const&)`]
|
||||||
|
|
||||||
synchronized_value(T const& other) noexept(is_nothrow_copy_constructible<T>::value);
|
synchronized_value(T const& other) noexcept(is_nothrow_copy_constructible<T>::value);
|
||||||
|
|
||||||
[variablelist
|
[variablelist
|
||||||
|
|
||||||
@@ -175,11 +175,11 @@
|
|||||||
|
|
||||||
[section:move_vt `synchronized_value(T&&)`]
|
[section:move_vt `synchronized_value(T&&)`]
|
||||||
|
|
||||||
synchronized_value(T&& other) noexept(is_nothrow_move_constructible<T>::value);
|
synchronized_value(T&& other) noexcept(is_nothrow_move_constructible<T>::value);
|
||||||
|
|
||||||
[variablelist
|
[variablelist
|
||||||
|
|
||||||
[[Requires:] [`T` is `CopyMovable `.]]
|
[[Requires:] [`T` is `MoveConstructible `.]]
|
||||||
[[Effects:] [Move constructs the cloaked value_type]]
|
[[Effects:] [Move constructs the cloaked value_type]]
|
||||||
|
|
||||||
[[Throws:] [Any exception thrown by `value_type(value_type&&)`.]]
|
[[Throws:] [Any exception thrown by `value_type(value_type&&)`.]]
|
||||||
@@ -194,7 +194,7 @@
|
|||||||
|
|
||||||
[variablelist
|
[variablelist
|
||||||
|
|
||||||
[[Requires:] [`T` is `CopyMovable `.]]
|
[[Requires:] [`T` is `MoveConstructible `.]]
|
||||||
[[Effects:] [Move constructs the cloaked value_type]]
|
[[Effects:] [Move constructs the cloaked value_type]]
|
||||||
|
|
||||||
[[Throws:] [Any exception thrown by `value_type(value_type&&)` or `mtx_.lock()`.]]
|
[[Throws:] [Any exception thrown by `value_type(value_type&&)` or `mtx_.lock()`.]]
|
||||||
@@ -209,7 +209,7 @@
|
|||||||
|
|
||||||
[variablelist
|
[variablelist
|
||||||
|
|
||||||
[[Requires:] [`T` is `Assignale`.]]
|
[[Requires:] [`T` is `Assignable`.]]
|
||||||
[[Effects:] [Copies the underlying value on a scope protected by the two mutexes. The mutex is not copied. The locks are acquired avoiding deadlock. For example, there is no problem if one thread assigns `a = b` and the other assigns `b = a`.]]
|
[[Effects:] [Copies the underlying value on a scope protected by the two mutexes. The mutex is not copied. The locks are acquired avoiding deadlock. For example, there is no problem if one thread assigns `a = b` and the other assigns `b = a`.]]
|
||||||
[[Return:] [`*this`]]
|
[[Return:] [`*this`]]
|
||||||
|
|
||||||
@@ -224,7 +224,7 @@
|
|||||||
|
|
||||||
[variablelist
|
[variablelist
|
||||||
|
|
||||||
[[Requires:] [`T` is `Assignale`.]]
|
[[Requires:] [`T` is `Assignable`.]]
|
||||||
[[Effects:] [Copies the value on a scope protected by the mutex.]]
|
[[Effects:] [Copies the value on a scope protected by the mutex.]]
|
||||||
[[Return:] [`*this`]]
|
[[Return:] [`*this`]]
|
||||||
|
|
||||||
@@ -273,7 +273,7 @@
|
|||||||
|
|
||||||
[variablelist
|
[variablelist
|
||||||
|
|
||||||
[[Requires:] [`T` is `Assignale`.]]
|
[[Requires:] [`T` is `Assignable`.]]
|
||||||
[[Effects:] [Swaps the data on a scope protected by both mutex. Both mutex are acquired to avoid dead-lock. The mutexes are not swapped.]]
|
[[Effects:] [Swaps the data on a scope protected by both mutex. Both mutex are acquired to avoid dead-lock. The mutexes are not swapped.]]
|
||||||
|
|
||||||
[[Throws:] [Any exception thrown by `swap(value_, rhs.value)` or `mtx_.lock()` or `rhs_.mtx_.lock()`.]]
|
[[Throws:] [Any exception thrown by `swap(value_, rhs.value)` or `mtx_.lock()` or `rhs_.mtx_.lock()`.]]
|
||||||
|
|||||||
@@ -8,10 +8,10 @@
|
|||||||
|
|
||||||
[library Thread
|
[library Thread
|
||||||
[quickbook 1.5]
|
[quickbook 1.5]
|
||||||
[version 4.4.0]
|
[version 4.7.2]
|
||||||
[authors [Williams, Anthony] [Botet Escriba, Vicente J.]]
|
[authors [Williams, Anthony] [Botet Escriba, Vicente J.]]
|
||||||
[copyright 2007-11 Anthony Williams]
|
[copyright 2007-11 Anthony Williams]
|
||||||
[copyright 2011-14 Vicente J. Botet Escriba]
|
[copyright 2011-16 Vicente J. Botet Escriba]
|
||||||
[purpose C++ Library for launching threads and synchronizing data between them]
|
[purpose C++ Library for launching threads and synchronizing data between them]
|
||||||
[category text]
|
[category text]
|
||||||
[license
|
[license
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
{
|
{
|
||||||
thread::id get_id() noexcept;
|
thread::id get_id() noexcept;
|
||||||
template<typename TimeDuration>
|
template<typename TimeDuration>
|
||||||
void yield() noexcept; // DEPRECATED
|
void yield() noexcept;
|
||||||
template <class Clock, class Duration>
|
template <class Clock, class Duration>
|
||||||
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
|
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
|
||||||
template <class Rep, class Period>
|
template <class Rep, class Period>
|
||||||
@@ -255,7 +255,7 @@ does not complete when the specified time has elapsed or reached respectively.
|
|||||||
|
|
||||||
[endsect]
|
[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
|
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,
|
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]
|
[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__.
|
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 t(my_func);
|
||||||
boost::thread_joiner g(t);
|
boost::thread_joiner g(t);
|
||||||
// do someting else
|
// do something else
|
||||||
} // here the thread_joiner destructor will join the thread before it is destroyed.
|
} // here the thread_joiner destructor will join the thread before it is destroyed.
|
||||||
|
|
||||||
[endsect]
|
[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
|
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)
|
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,
|
with interruption enabled, then a __thread_interrupted__ exception will be thrown in the interrupted thread. Unless this exception is
|
||||||
this will cause the execution of the interrupted thread to terminate. As with any other exception, the stack will be unwound, and
|
caught inside the interrupted thread's thread-main function, the stack unwinding process (as with any other exception) causes the
|
||||||
destructors for objects of automatic storage duration will be executed.
|
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
|
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
|
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.
|
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]
|
[heading `pthread_exit` POSIX limitation]
|
||||||
|
|
||||||
@@ -711,7 +713,7 @@ are copied into internal storage for access by the new thread.]]]
|
|||||||
|
|
||||||
[[Throws:] [Nothing.]]
|
[[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
|
[[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
|
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]]
|
[[Throws:] [Nothing]]
|
||||||
|
|
||||||
@@ -964,7 +966,7 @@ predefined __interruption_points__ with interruption enabled .]]
|
|||||||
|
|
||||||
[section:hardware_concurrency Static member function `hardware_concurrency()`]
|
[section:hardware_concurrency Static member function `hardware_concurrency()`]
|
||||||
|
|
||||||
unsigned hardware_concurrency() noexecpt;
|
unsigned hardware_concurrency() noexcept;
|
||||||
|
|
||||||
[variablelist
|
[variablelist
|
||||||
|
|
||||||
@@ -979,7 +981,7 @@ or 0 if this information is not available.]]
|
|||||||
|
|
||||||
[section:physical_concurrency Static member function `physical_concurrency()`]
|
[section:physical_concurrency Static member function `physical_concurrency()`]
|
||||||
|
|
||||||
unsigned physical_concurrency() noexecpt;
|
unsigned physical_concurrency() noexcept;
|
||||||
|
|
||||||
[variablelist
|
[variablelist
|
||||||
|
|
||||||
@@ -1290,7 +1292,7 @@ instances of __thread_id__ `a` and `b` is the same if `a==b`, and different if `
|
|||||||
|
|
||||||
[variablelist
|
[variablelist
|
||||||
|
|
||||||
[[Effects:] [Constructs a thread atrributes instance with its default values.]]
|
[[Effects:] [Constructs a thread attributes instance with its default values.]]
|
||||||
|
|
||||||
[[Throws:] [Nothing]]
|
[[Throws:] [Nothing]]
|
||||||
|
|
||||||
@@ -1304,7 +1306,7 @@ instances of __thread_id__ `a` and `b` is the same if `a==b`, and different if `
|
|||||||
|
|
||||||
[variablelist
|
[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.]]
|
[[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
|
[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.]]
|
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.]]
|
[[Throws:] [Nothing if operations of chrono::duration<Rep, Period> do not throw exceptions. __thread_interrupted__ if the current thread of execution is interrupted.]]
|
||||||
|
|||||||
61
example/default_executor.cpp
Normal file
61
example/default_executor.cpp
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
// 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)
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||||
|
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define BOOST_THREAD_VERSION 4
|
||||||
|
#define BOOST_THREAD_PROVIDES_EXECUTORS
|
||||||
|
//#define BOOST_THREAD_USES_LOG
|
||||||
|
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||||
|
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||||
|
|
||||||
|
#include <boost/thread/caller_context.hpp>
|
||||||
|
#include <boost/thread/executors/basic_thread_pool.hpp>
|
||||||
|
#include <boost/thread/executors/generic_executor_ref.hpp>
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <boost/thread/caller_context.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
boost::generic_executor_ref default_executor()
|
||||||
|
{
|
||||||
|
static boost::basic_thread_pool tp(4);
|
||||||
|
return boost::generic_executor_ref(tp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void p2()
|
||||||
|
{
|
||||||
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
|
boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
|
||||||
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void p1()
|
||||||
|
{
|
||||||
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
|
boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
|
||||||
|
default_executor().submit(&p2);
|
||||||
|
boost::this_thread::sleep_for(boost::chrono::milliseconds(400));
|
||||||
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
|
|
||||||
|
default_executor().submit(&p1);
|
||||||
|
|
||||||
|
boost::this_thread::sleep_for(boost::chrono::seconds(5));
|
||||||
|
|
||||||
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||||
#endif
|
#endif
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#define BOOST_THREAD_VERSION 4
|
#define BOOST_THREAD_VERSION 4
|
||||||
#define BOOST_THREAD_PROVIDES_EXECUTORS
|
#define BOOST_THREAD_PROVIDES_EXECUTORS
|
||||||
@@ -27,6 +28,12 @@
|
|||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
boost::future<void> p(boost::future<void> f) {
|
||||||
|
assert(f.is_ready());
|
||||||
|
return boost::make_ready_future();
|
||||||
|
}
|
||||||
|
|
||||||
void p1()
|
void p1()
|
||||||
{
|
{
|
||||||
@@ -42,8 +49,9 @@ void p2()
|
|||||||
|
|
||||||
int f1()
|
int f1()
|
||||||
{
|
{
|
||||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
boost::this_thread::sleep_for(boost::chrono::seconds(1));
|
boost::this_thread::sleep_for(boost::chrono::seconds(1));
|
||||||
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
int f2(int i)
|
int f2(int i)
|
||||||
@@ -72,61 +80,95 @@ void at_th_entry(boost::basic_thread_pool& )
|
|||||||
|
|
||||||
int test_executor_adaptor()
|
int test_executor_adaptor()
|
||||||
{
|
{
|
||||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
boost::executor_adaptor < boost::basic_thread_pool > ea(4);
|
boost::executor_adaptor < boost::basic_thread_pool > ea(4);
|
||||||
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
submit_some( ea);
|
submit_some( ea);
|
||||||
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
|
#if 1
|
||||||
|
// fixme
|
||||||
|
// ERROR= tr1::bad_weak_ptr
|
||||||
{
|
{
|
||||||
boost::future<int> t1 = boost::async(ea, &f1);
|
boost::future<int> t1 = boost::async(ea, &f1);
|
||||||
boost::future<int> t2 = boost::async(ea, &f1);
|
boost::future<int> t2 = boost::async(ea, &f1);
|
||||||
// std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
|
std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
|
||||||
// std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl;
|
std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl;
|
||||||
}
|
}
|
||||||
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
submit_some(ea);
|
submit_some(ea);
|
||||||
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
{
|
{
|
||||||
boost::basic_thread_pool ea3(1);
|
boost::basic_thread_pool ea3(1);
|
||||||
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
boost::future<int> t1 = boost::async(ea3, &f1);
|
boost::future<int> t1 = boost::async(ea3, &f1);
|
||||||
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
boost::future<int> t2 = boost::async(ea3, &f1);
|
boost::future<int> t2 = boost::async(ea3, &f1);
|
||||||
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
//boost::future<int> t2 = boost::async(ea3, f2, 1); // todo this doesn't compiles yet on C++11
|
//boost::future<int> t2 = boost::async(ea3, f2, 1); // todo this doesn't compiles yet on C++11
|
||||||
//boost::future<int> t2 = boost::async(ea3, boost::bind(f2, 1)); // todo this doesn't compiles yet on C++98
|
//boost::future<int> t2 = boost::async(ea3, boost::bind(f2, 1)); // todo this doesn't compiles yet on C++98
|
||||||
// std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
|
std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
|
||||||
// std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl;
|
std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
submit_some(ea);
|
submit_some(ea);
|
||||||
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
}
|
}
|
||||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
{
|
{
|
||||||
boost::executor_adaptor < boost::loop_executor > ea2;
|
boost::executor_adaptor < boost::loop_executor > ea2;
|
||||||
submit_some( ea2);
|
submit_some( ea2);
|
||||||
ea2.underlying_executor().run_queued_closures();
|
ea2.underlying_executor().run_queued_closures();
|
||||||
}
|
}
|
||||||
#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
{
|
{
|
||||||
boost::executor_adaptor < boost::basic_thread_pool > ea1(4);
|
boost::executor_adaptor < boost::basic_thread_pool > ea1(4);
|
||||||
boost::executor_adaptor < boost::serial_executor > ea2(ea1);
|
boost::executor_adaptor < boost::serial_executor > ea2(ea1);
|
||||||
submit_some(ea2);
|
submit_some(ea2);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
{
|
{
|
||||||
boost::executor_adaptor < boost::inline_executor > ea1;
|
boost::executor_adaptor < boost::inline_executor > ea1;
|
||||||
submit_some(ea1);
|
submit_some(ea1);
|
||||||
}
|
}
|
||||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
{
|
{
|
||||||
boost::executor_adaptor < boost::thread_executor > ea1;
|
boost::executor_adaptor < boost::thread_executor > ea1;
|
||||||
submit_some(ea1);
|
submit_some(ea1);
|
||||||
}
|
}
|
||||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
|
#if 1
|
||||||
|
// fixme
|
||||||
|
// ERROR= tr1::bad_weak_ptr
|
||||||
{
|
{
|
||||||
boost::basic_thread_pool ea(4, at_th_entry);
|
boost::basic_thread_pool ea(4, at_th_entry);
|
||||||
boost::future<int> t1 = boost::async(ea, &f1);
|
boost::future<int> t1 = boost::async(ea, &f1);
|
||||||
// std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
|
std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
|
{
|
||||||
|
boost::async(&f1);
|
||||||
|
}
|
||||||
|
#if 1
|
||||||
|
// fixme
|
||||||
|
// ERROR= tr1::bad_weak_ptr
|
||||||
|
|
||||||
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
|
{
|
||||||
|
boost::basic_thread_pool ea(1);
|
||||||
|
boost::async(ea,&f1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
|
boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
|
||||||
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
}
|
}
|
||||||
catch (std::exception& ex)
|
catch (std::exception& ex)
|
||||||
{
|
{
|
||||||
@@ -147,4 +189,19 @@ int test_executor_adaptor()
|
|||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
return test_executor_adaptor();
|
return test_executor_adaptor();
|
||||||
|
|
||||||
|
#if 0 && defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION \
|
||||||
|
&& defined BOOST_THREAD_PROVIDES_EXECUTORS \
|
||||||
|
&& ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||||
|
|
||||||
|
boost::basic_thread_pool executor;
|
||||||
|
// compiles
|
||||||
|
boost::make_ready_future().then(&p);
|
||||||
|
|
||||||
|
// ??
|
||||||
|
boost::make_ready_future().then(executor, &p);
|
||||||
|
|
||||||
|
// doesn't compile
|
||||||
|
boost::make_ready_future().then(executor, &p);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,31 +35,83 @@ int p1()
|
|||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
const int number_of_tests = 100;
|
const int number_of_tests = 200;
|
||||||
BOOST_THREAD_LOG << "<MAIN" << BOOST_THREAD_END_LOG;
|
BOOST_THREAD_LOG << "<MAIN" << BOOST_THREAD_END_LOG;
|
||||||
|
|
||||||
|
{
|
||||||
|
for (int i=0; i< number_of_tests; i++)
|
||||||
|
try
|
||||||
|
{
|
||||||
|
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
||||||
|
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||||
|
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
||||||
|
f1.wait();
|
||||||
|
BOOST_ASSERT(f1.get()==1);
|
||||||
|
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
||||||
|
}
|
||||||
|
catch (std::exception& ex)
|
||||||
|
{
|
||||||
|
std::cout << __FILE__ << "["<< __LINE__<<"] " << "ERRORRRRR "<<ex.what() << "" << std::endl;
|
||||||
|
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
std::cout << __FILE__ << "["<< __LINE__<<"] " << " ERRORRRRR exception thrown" << std::endl;
|
||||||
|
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
for (int i=0; i< number_of_tests; i++)
|
for (int i=0; i< number_of_tests; i++)
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
|
||||||
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
||||||
boost::future<int> f1 = boost::async(&p1);
|
boost::future<int> f1 = boost::async(&p1);
|
||||||
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
||||||
boost::future<int> f2 = f1.fallback_to(-1);
|
boost::future<int> f2 = f1.fallback_to(-1);
|
||||||
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
||||||
f2.wait();
|
f2.wait();
|
||||||
|
//std::cout << __FILE__ << "["<< __LINE__<<"] " << std::endl;
|
||||||
BOOST_ASSERT(f2.get()==1);
|
BOOST_ASSERT(f2.get()==1);
|
||||||
|
//std::cout << __FILE__ << "["<< __LINE__<<"] " << std::endl;
|
||||||
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
||||||
}
|
}
|
||||||
catch (std::exception& ex)
|
catch (std::exception& ex)
|
||||||
{
|
{
|
||||||
std::cout << "ERRORRRRR "<<ex.what() << "" << std::endl;
|
std::cout << __FILE__ << "["<< __LINE__<<"] " << "ERRORRRRR "<<ex.what() << "" << std::endl;
|
||||||
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
|
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
std::cout << " ERRORRRRR exception thrown" << std::endl;
|
std::cout << __FILE__ << "["<< __LINE__<<"] " << " ERRORRRRR exception thrown" << std::endl;
|
||||||
|
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
for (int i=0; i< number_of_tests; i++)
|
||||||
|
try
|
||||||
|
{
|
||||||
|
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
||||||
|
boost::future<int> f1 = boost::async(boost::launch::async, &p1_ex);
|
||||||
|
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
||||||
|
f1.wait();
|
||||||
|
BOOST_ASSERT(f1.get_or(-1)==-1);
|
||||||
|
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
||||||
|
}
|
||||||
|
catch (std::exception& ex)
|
||||||
|
{
|
||||||
|
std::cout << __FILE__ << "["<< __LINE__<<"] " << "ERRORRRRR "<<ex.what() << "" << std::endl;
|
||||||
|
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
std::cout << __FILE__ << "["<< __LINE__<<"] " << " ERRORRRRR exception thrown" << std::endl;
|
||||||
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
|
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
@@ -75,18 +127,20 @@ int main()
|
|||||||
boost::future<int> f2 = f1.fallback_to(-1);
|
boost::future<int> f2 = f1.fallback_to(-1);
|
||||||
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
||||||
f2.wait();
|
f2.wait();
|
||||||
|
//std::cout << __FILE__ << "["<< __LINE__<<"] " << std::endl;
|
||||||
BOOST_ASSERT(f2.get()==-1);
|
BOOST_ASSERT(f2.get()==-1);
|
||||||
|
//std::cout << __FILE__ << "["<< __LINE__<<"] " << std::endl;
|
||||||
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
||||||
}
|
}
|
||||||
catch (std::exception& ex)
|
catch (std::exception& ex)
|
||||||
{
|
{
|
||||||
std::cout << "ERRORRRRR "<<ex.what() << "" << std::endl;
|
std::cout << __FILE__ << "["<< __LINE__<<"] " << "ERRORRRRR "<<ex.what() << "" << std::endl;
|
||||||
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
|
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
std::cout << " ERRORRRRR exception thrown" << std::endl;
|
std::cout << __FILE__ << "["<< __LINE__<<"] " << " ERRORRRRR exception thrown" << std::endl;
|
||||||
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
|
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include <boost/thread/future.hpp>
|
#include <boost/thread/future.hpp>
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
||||||
|
|
||||||
int p1()
|
int p1()
|
||||||
|
|||||||
@@ -41,10 +41,28 @@ int main()
|
|||||||
for (int i=0; i< number_of_tests; i++)
|
for (int i=0; i< number_of_tests; i++)
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
boost::future<boost::future<int> > outer_future = boost::async(boost::launch::async, &p2);
|
|
||||||
boost::future<int> inner_future = outer_future.unwrap();
|
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||||
int ii = inner_future.get();
|
{
|
||||||
BOOST_THREAD_LOG << "ii= "<< ii << "" << BOOST_THREAD_END_LOG;
|
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)
|
catch (std::exception& ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -58,6 +58,8 @@ int p2(boost::future<int> f)
|
|||||||
}
|
}
|
||||||
BOOST_THREAD_LOG
|
BOOST_THREAD_LOG
|
||||||
<< "P2>" << BOOST_THREAD_END_LOG;
|
<< "P2>" << BOOST_THREAD_END_LOG;
|
||||||
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
int p2s(boost::shared_future<int> f)
|
int p2s(boost::shared_future<int> f)
|
||||||
{
|
{
|
||||||
@@ -81,6 +83,7 @@ int p2s(boost::shared_future<int> f)
|
|||||||
}
|
}
|
||||||
BOOST_THREAD_LOG
|
BOOST_THREAD_LOG
|
||||||
<< "P2>" << BOOST_THREAD_END_LOG;
|
<< "P2>" << BOOST_THREAD_END_LOG;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ void at_th_entry(boost::basic_thread_pool& )
|
|||||||
|
|
||||||
int test_generic_executor_ref()
|
int test_generic_executor_ref()
|
||||||
{
|
{
|
||||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -83,8 +83,8 @@ int test_generic_executor_ref()
|
|||||||
{
|
{
|
||||||
boost::future<int> t1 = boost::async(ea, &f1);
|
boost::future<int> t1 = boost::async(ea, &f1);
|
||||||
boost::future<int> t2 = boost::async(ea, &f1);
|
boost::future<int> t2 = boost::async(ea, &f1);
|
||||||
// std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
|
std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
|
||||||
// std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl;
|
std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl;
|
||||||
}
|
}
|
||||||
submit_some(ea);
|
submit_some(ea);
|
||||||
{
|
{
|
||||||
@@ -93,41 +93,51 @@ int test_generic_executor_ref()
|
|||||||
boost::future<int> t2 = boost::async(ea3, &f1);
|
boost::future<int> t2 = boost::async(ea3, &f1);
|
||||||
//boost::future<int> t2 = boost::async(ea3, f2, 1); // todo this doesn't compiles yet on C++11
|
//boost::future<int> t2 = boost::async(ea3, f2, 1); // todo this doesn't compiles yet on C++11
|
||||||
//boost::future<int> t2 = boost::async(ea3, boost::bind(f2, 1)); // todo this doesn't compiles yet on C++98
|
//boost::future<int> t2 = boost::async(ea3, boost::bind(f2, 1)); // todo this doesn't compiles yet on C++98
|
||||||
// std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
|
std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
|
||||||
// std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl;
|
std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl;
|
||||||
}
|
}
|
||||||
submit_some(ea);
|
submit_some(ea);
|
||||||
}
|
}
|
||||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
{
|
{
|
||||||
boost::loop_executor ea2;
|
boost::loop_executor ea2;
|
||||||
submit_some( ea2);
|
submit_some( ea2);
|
||||||
ea2.run_queued_closures();
|
ea2.run_queued_closures();
|
||||||
}
|
}
|
||||||
#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
{
|
{
|
||||||
boost::basic_thread_pool ea1(4);
|
boost::basic_thread_pool ea1(4);
|
||||||
boost::serial_executor ea2(ea1);
|
boost::serial_executor ea2(ea1);
|
||||||
submit_some(ea2);
|
submit_some(ea2);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
{
|
{
|
||||||
boost::inline_executor ea1;
|
boost::inline_executor ea1;
|
||||||
submit_some(ea1);
|
submit_some(ea1);
|
||||||
}
|
}
|
||||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
{
|
{
|
||||||
//boost::thread_executor ea1;
|
//boost::thread_executor ea1;
|
||||||
//submit_some(ea1);
|
//submit_some(ea1);
|
||||||
}
|
}
|
||||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
{
|
{
|
||||||
boost::basic_thread_pool ea(4, at_th_entry);
|
boost::basic_thread_pool ea(4, at_th_entry);
|
||||||
boost::future<int> t1 = boost::async(ea, &f1);
|
boost::future<int> t1 = boost::async(ea, &f1);
|
||||||
// std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
|
std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
|
||||||
}
|
}
|
||||||
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
|
{
|
||||||
|
boost::basic_thread_pool ea(4, at_th_entry);
|
||||||
|
boost::async(ea, &f1);
|
||||||
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
|
}
|
||||||
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
|
boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
|
||||||
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (std::exception& ex)
|
catch (std::exception& ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -42,6 +42,14 @@ int main()
|
|||||||
int result = f2.get();
|
int result = f2.get();
|
||||||
BOOST_THREAD_LOG << "f2 " << result << BOOST_THREAD_END_LOG;
|
BOOST_THREAD_LOG << "f2 " << result << BOOST_THREAD_END_LOG;
|
||||||
}
|
}
|
||||||
|
#if ! defined BOOST_NO_CXX14_GENERIC_LAMBDAS
|
||||||
|
{
|
||||||
|
boost::future<int> f1 = boost::async(boost::launch::async, []() {return 123;});
|
||||||
|
boost::future<int> f2 = f1.then([](auto f) {return 2*f.get(); });
|
||||||
|
int result = f2.get();
|
||||||
|
BOOST_THREAD_LOG << "f2 " << result << BOOST_THREAD_END_LOG;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
catch (std::exception& ex)
|
catch (std::exception& ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -94,6 +94,11 @@ int main()
|
|||||||
f.get();
|
f.get();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
|
||||||
|
boost::future<int> f = compute(-1);
|
||||||
|
f.wait();
|
||||||
|
}
|
||||||
{
|
{
|
||||||
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
|
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
|
||||||
boost::future<int> f = compute(0);
|
boost::future<int> f = compute(0);
|
||||||
@@ -124,11 +129,11 @@ int main()
|
|||||||
boost::future<int const&> f = boost::make_ready_future(boost::cref(i));
|
boost::future<int const&> f = boost::make_ready_future(boost::cref(i));
|
||||||
std::cout << f.get() << std::endl;
|
std::cout << f.get() << std::endl;
|
||||||
}
|
}
|
||||||
// {
|
{
|
||||||
// std::cout << __FILE__ << " "<< __LINE__ << std::endl;
|
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
|
||||||
// boost::future<int> f = compute(2);
|
boost::future<int> f = compute(2);
|
||||||
// std::cout << f.get() << std::endl;
|
std::cout << f.get() << std::endl;
|
||||||
// }
|
}
|
||||||
{
|
{
|
||||||
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
|
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
|
||||||
boost::shared_future<int> f = shared_compute(0);
|
boost::shared_future<int> f = shared_compute(0);
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <boost/thread/concurrent_queues/sync_queue.hpp>
|
#include <boost/thread/concurrent_queues/sync_queue.hpp>
|
||||||
|
|
||||||
void producer(the_ostream &mos, boost::sync_queue<int> & sbq)
|
void producer(the_ostream & /*mos*/, boost::sync_queue<int> & sbq)
|
||||||
{
|
{
|
||||||
using namespace boost;
|
using namespace boost;
|
||||||
try {
|
try {
|
||||||
@@ -32,22 +32,22 @@ void producer(the_ostream &mos, boost::sync_queue<int> & sbq)
|
|||||||
{
|
{
|
||||||
sbq.push(i);
|
sbq.push(i);
|
||||||
//sbq << i;
|
//sbq << i;
|
||||||
mos << "push(" << i << ") "<< sbq.size()<<"\n";
|
//mos << "push(" << i << ") "<< sbq.size()<<"\n";
|
||||||
this_thread::sleep_for(chrono::milliseconds(200));
|
this_thread::sleep_for(chrono::milliseconds(200));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(sync_queue_is_closed&)
|
catch(sync_queue_is_closed&)
|
||||||
{
|
{
|
||||||
mos << "closed !!!\n";
|
//mos << "closed !!!\n";
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
mos << "exception !!!\n";
|
//mos << "exception !!!\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void consumer(
|
void consumer(
|
||||||
the_ostream &mos,
|
the_ostream & /*mos*/,
|
||||||
boost::sync_queue<int> & sbq)
|
boost::sync_queue<int> & sbq)
|
||||||
{
|
{
|
||||||
using namespace boost;
|
using namespace boost;
|
||||||
@@ -57,21 +57,21 @@ void consumer(
|
|||||||
int r;
|
int r;
|
||||||
sbq.pull(r);
|
sbq.pull(r);
|
||||||
//sbq >> r;
|
//sbq >> r;
|
||||||
mos << i << " pull(" << r << ") "<< sbq.size()<<"\n";
|
//mos << i << " pull(" << r << ") "<< sbq.size()<<"\n";
|
||||||
|
|
||||||
this_thread::sleep_for(chrono::milliseconds(250));
|
this_thread::sleep_for(chrono::milliseconds(250));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(sync_queue_is_closed&)
|
catch(sync_queue_is_closed&)
|
||||||
{
|
{
|
||||||
mos << "closed !!!\n";
|
//mos << "closed !!!\n";
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
mos << "exception !!!\n";
|
//mos << "exception !!!\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void consumer2(the_ostream &mos, boost::sync_queue<int> & sbq)
|
void consumer2(the_ostream &/*mos*/, boost::sync_queue<int> & sbq)
|
||||||
{
|
{
|
||||||
using namespace boost;
|
using namespace boost;
|
||||||
try {
|
try {
|
||||||
@@ -81,17 +81,17 @@ void consumer2(the_ostream &mos, boost::sync_queue<int> & sbq)
|
|||||||
queue_op_status st = sbq.try_pull(r);
|
queue_op_status st = sbq.try_pull(r);
|
||||||
if (queue_op_status::closed == st) break;
|
if (queue_op_status::closed == st) break;
|
||||||
if (queue_op_status::success == st) {
|
if (queue_op_status::success == st) {
|
||||||
mos << i << " pull(" << r << ")\n";
|
//mos << i << " pull(" << r << ")\n";
|
||||||
}
|
}
|
||||||
this_thread::sleep_for(chrono::milliseconds(250));
|
this_thread::sleep_for(chrono::milliseconds(250));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
mos << "exception !!!\n";
|
//mos << "exception !!!\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void consumer3(the_ostream &mos, boost::sync_queue<int> & sbq)
|
void consumer3(the_ostream &/*mos*/, boost::sync_queue<int> & sbq)
|
||||||
{
|
{
|
||||||
using namespace boost;
|
using namespace boost;
|
||||||
try {
|
try {
|
||||||
@@ -100,13 +100,13 @@ void consumer3(the_ostream &mos, boost::sync_queue<int> & sbq)
|
|||||||
int r;
|
int r;
|
||||||
queue_op_status res = sbq.wait_pull(r);
|
queue_op_status res = sbq.wait_pull(r);
|
||||||
if (res==queue_op_status::closed) break;
|
if (res==queue_op_status::closed) break;
|
||||||
mos << i << " wait_pull(" << r << ")\n";
|
//mos << i << " wait_pull(" << r << ")\n";
|
||||||
this_thread::sleep_for(chrono::milliseconds(250));
|
this_thread::sleep_for(chrono::milliseconds(250));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
mos << "exception !!!\n";
|
//mos << "exception !!!\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
#include <boost/static_assert.hpp>
|
#include <boost/static_assert.hpp>
|
||||||
#include <boost/type_traits.hpp>
|
#include <boost/type_traits.hpp>
|
||||||
|
|
||||||
void producer(the_ostream &mos, boost::queue_back<int> sbq)
|
void producer(the_ostream &/*mos*/, boost::queue_back<int> sbq)
|
||||||
{
|
{
|
||||||
using namespace boost;
|
using namespace boost;
|
||||||
try {
|
try {
|
||||||
@@ -35,22 +35,22 @@ void producer(the_ostream &mos, boost::queue_back<int> sbq)
|
|||||||
{
|
{
|
||||||
sbq.push(i);
|
sbq.push(i);
|
||||||
//sbq << i;
|
//sbq << i;
|
||||||
mos << "push(" << i << ") " << sbq.size() <<"\n";
|
//mos << "push(" << i << ") " << sbq.size() <<"\n";
|
||||||
this_thread::sleep_for(chrono::milliseconds(200));
|
this_thread::sleep_for(chrono::milliseconds(200));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(sync_queue_is_closed&)
|
catch(sync_queue_is_closed&)
|
||||||
{
|
{
|
||||||
mos << "closed !!!\n";
|
//mos << "closed !!!\n";
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
mos << "exception !!!\n";
|
//mos << "exception !!!\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void consumer(
|
void consumer(
|
||||||
the_ostream &mos,
|
the_ostream &/*mos*/,
|
||||||
boost::queue_front<int> sbq)
|
boost::queue_front<int> sbq)
|
||||||
{
|
{
|
||||||
using namespace boost;
|
using namespace boost;
|
||||||
@@ -60,21 +60,21 @@ void consumer(
|
|||||||
int r;
|
int r;
|
||||||
sbq.pull(r);
|
sbq.pull(r);
|
||||||
//sbq >> r;
|
//sbq >> r;
|
||||||
mos << i << " pull(" << r << ") " << sbq.size() <<"\n";
|
//mos << i << " pull(" << r << ") " << sbq.size() <<"\n";
|
||||||
|
|
||||||
this_thread::sleep_for(chrono::milliseconds(250));
|
this_thread::sleep_for(chrono::milliseconds(250));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(sync_queue_is_closed&)
|
catch(sync_queue_is_closed&)
|
||||||
{
|
{
|
||||||
mos << "closed !!!\n";
|
//mos << "closed !!!\n";
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
mos << "exception !!!\n";
|
//mos << "exception !!!\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void consumer2(the_ostream &mos, boost::queue_front<int> sbq)
|
void consumer2(the_ostream &/*mos*/, boost::queue_front<int> sbq)
|
||||||
{
|
{
|
||||||
using namespace boost;
|
using namespace boost;
|
||||||
try {
|
try {
|
||||||
@@ -84,17 +84,17 @@ void consumer2(the_ostream &mos, boost::queue_front<int> sbq)
|
|||||||
queue_op_status st = sbq.try_pull(r);
|
queue_op_status st = sbq.try_pull(r);
|
||||||
if (queue_op_status::closed == st) break;
|
if (queue_op_status::closed == st) break;
|
||||||
if (queue_op_status::success == st) {
|
if (queue_op_status::success == st) {
|
||||||
mos << i << " try_pull(" << r << ")\n";
|
//mos << i << " try_pull(" << r << ")\n";
|
||||||
}
|
}
|
||||||
this_thread::sleep_for(chrono::milliseconds(250));
|
this_thread::sleep_for(chrono::milliseconds(250));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
mos << "exception !!!\n";
|
//mos << "exception !!!\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void consumer3(the_ostream &mos, boost::queue_front<int> sbq)
|
void consumer3(the_ostream &/*mos*/, boost::queue_front<int> sbq)
|
||||||
{
|
{
|
||||||
using namespace boost;
|
using namespace boost;
|
||||||
try {
|
try {
|
||||||
@@ -103,13 +103,13 @@ void consumer3(the_ostream &mos, boost::queue_front<int> sbq)
|
|||||||
int r;
|
int r;
|
||||||
queue_op_status res = sbq.wait_pull(r);
|
queue_op_status res = sbq.wait_pull(r);
|
||||||
if (res==queue_op_status::closed) break;
|
if (res==queue_op_status::closed) break;
|
||||||
mos << i << " wait_pull(" << r << ")\n";
|
//mos << i << " wait_pull(" << r << ")\n";
|
||||||
this_thread::sleep_for(chrono::milliseconds(250));
|
this_thread::sleep_for(chrono::milliseconds(250));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
mos << "exception !!!\n";
|
//mos << "exception !!!\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ counter c;
|
|||||||
|
|
||||||
void change_count()
|
void change_count()
|
||||||
{
|
{
|
||||||
std::cout << "count == " << c.increment() << std::endl;
|
//std::cout << "count == " << c.increment() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int, char*[])
|
int main(int, char*[])
|
||||||
|
|||||||
@@ -39,36 +39,23 @@ void do_something_in_current_thread()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
//void do_something_with_current_thread(boost::thread&& th)
|
|
||||||
//{
|
|
||||||
// th.join();
|
|
||||||
//}
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
int some_local_state;
|
int some_local_state=0;
|
||||||
boost::strict_scoped_thread<> t( (boost::thread(func(some_local_state))));
|
boost::strict_scoped_thread<> t( (boost::thread(func(some_local_state))));
|
||||||
|
|
||||||
do_something_in_current_thread();
|
do_something_in_current_thread();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
int some_local_state;
|
int some_local_state=0;
|
||||||
boost::thread t(( func(some_local_state) ));
|
boost::thread t(( func(some_local_state) ));
|
||||||
boost::strict_scoped_thread<> g( (boost::move(t)) );
|
boost::strict_scoped_thread<> g( (boost::move(t)) );
|
||||||
|
|
||||||
do_something_in_current_thread();
|
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))));
|
boost::scoped_thread<> t( (boost::thread(func(some_local_state))));
|
||||||
|
|
||||||
if (t.joinable())
|
if (t.joinable())
|
||||||
@@ -76,14 +63,17 @@ int main()
|
|||||||
else
|
else
|
||||||
do_something_in_current_thread();
|
do_something_in_current_thread();
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
{
|
{
|
||||||
int some_local_state;
|
int some_local_state=0;
|
||||||
boost::thread t(( func(some_local_state) ));
|
boost::thread t(( func(some_local_state) ));
|
||||||
boost::scoped_thread<> g( (boost::move(t)) );
|
boost::scoped_thread<> g( (boost::move(t)) );
|
||||||
t.detach();
|
if (g.joinable())
|
||||||
|
g.detach();
|
||||||
|
|
||||||
do_something_in_current_thread();
|
do_something_in_current_thread();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
boost::scoped_thread<> g( &f, 1, 2 );
|
boost::scoped_thread<> g( &f, 1, 2 );
|
||||||
do_something_in_current_thread();
|
do_something_in_current_thread();
|
||||||
|
|||||||
@@ -27,16 +27,16 @@
|
|||||||
|
|
||||||
void p1()
|
void p1()
|
||||||
{
|
{
|
||||||
std::cout << BOOST_CONTEXTOF << std::endl;
|
//std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(30));
|
boost::this_thread::sleep_for(boost::chrono::milliseconds(30));
|
||||||
std::cout << BOOST_CONTEXTOF << std::endl;
|
//std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void p2()
|
void p2()
|
||||||
{
|
{
|
||||||
std::cout << BOOST_CONTEXTOF << std::endl;
|
//std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(10));
|
boost::this_thread::sleep_for(boost::chrono::milliseconds(10));
|
||||||
std::cout << BOOST_CONTEXTOF << std::endl;
|
//std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
int f1()
|
int f1()
|
||||||
@@ -54,7 +54,6 @@ int f2(int i)
|
|||||||
|
|
||||||
void submit_some(boost::serial_executor& tp)
|
void submit_some(boost::serial_executor& tp)
|
||||||
{
|
{
|
||||||
std::cout << BOOST_CONTEXTOF << std::endl;
|
|
||||||
for (int i = 0; i < 3; ++i) {
|
for (int i = 0; i < 3; ++i) {
|
||||||
std::cout << BOOST_CONTEXTOF << std::endl;
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
tp.submit(&p2);
|
tp.submit(&p2);
|
||||||
@@ -63,7 +62,6 @@ void submit_some(boost::serial_executor& tp)
|
|||||||
std::cout << BOOST_CONTEXTOF << std::endl;
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
tp.submit(&p1);
|
tp.submit(&p1);
|
||||||
}
|
}
|
||||||
std::cout << BOOST_CONTEXTOF << std::endl;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,13 +73,11 @@ void at_th_entry(boost::basic_thread_pool& )
|
|||||||
|
|
||||||
int test_executor_adaptor()
|
int test_executor_adaptor()
|
||||||
{
|
{
|
||||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
|
||||||
{
|
{
|
||||||
boost::basic_thread_pool ea1(4);
|
boost::basic_thread_pool ea1(4);
|
||||||
boost::serial_executor ea2(ea1);
|
boost::serial_executor ea2(ea1);
|
||||||
@@ -89,7 +85,6 @@ int test_executor_adaptor()
|
|||||||
boost::this_thread::sleep_for(boost::chrono::seconds(10));
|
boost::this_thread::sleep_for(boost::chrono::seconds(10));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
|
||||||
}
|
}
|
||||||
catch (std::exception& ex)
|
catch (std::exception& ex)
|
||||||
{
|
{
|
||||||
@@ -102,7 +97,6 @@ int test_executor_adaptor()
|
|||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
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
|
||||||
@@ -39,7 +39,7 @@ const char* player_name(int state)
|
|||||||
if (state == PLAYER_B)
|
if (state == PLAYER_B)
|
||||||
return "PLAYER-B";
|
return "PLAYER-B";
|
||||||
throw "bad player";
|
throw "bad player";
|
||||||
return 0;
|
//return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void player(int active)
|
void player(int active)
|
||||||
@@ -50,7 +50,7 @@ void player(int active)
|
|||||||
|
|
||||||
while (state < GAME_OVER)
|
while (state < GAME_OVER)
|
||||||
{
|
{
|
||||||
std::cout << player_name(active) << ": Play." << std::endl;
|
//std::cout << player_name(active) << ": Play." << std::endl;
|
||||||
state = other;
|
state = other;
|
||||||
cond.notify_all();
|
cond.notify_all();
|
||||||
do
|
do
|
||||||
|
|||||||
86
example/this_executor.cpp
Normal file
86
example/this_executor.cpp
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
// 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)
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||||
|
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define BOOST_THREAD_VERSION 4
|
||||||
|
#define BOOST_THREAD_PROVIDES_EXECUTORS
|
||||||
|
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||||
|
|
||||||
|
#include <boost/thread/caller_context.hpp>
|
||||||
|
#include <boost/thread/executors/basic_thread_pool.hpp>
|
||||||
|
#include <boost/thread/executors/generic_executor_ref.hpp>
|
||||||
|
#include <boost/smart_ptr/shared_ptr.hpp>
|
||||||
|
#include <boost/smart_ptr/make_shared.hpp>
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <boost/thread/caller_context.hpp>
|
||||||
|
|
||||||
|
struct current_executor_state_type {
|
||||||
|
boost::shared_ptr<boost::generic_executor_ref> current_executor_ptr;
|
||||||
|
|
||||||
|
template <class Executor>
|
||||||
|
void set_current_executor(Executor& ex)
|
||||||
|
{
|
||||||
|
current_executor_ptr = boost::make_shared<boost::generic_executor_ref>(ex);
|
||||||
|
}
|
||||||
|
boost::generic_executor_ref current_executor()
|
||||||
|
{
|
||||||
|
if (current_executor_ptr)
|
||||||
|
return *current_executor_ptr;
|
||||||
|
else
|
||||||
|
throw "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
thread_local current_executor_state_type current_executor_state;
|
||||||
|
|
||||||
|
boost::generic_executor_ref current_executor()
|
||||||
|
{
|
||||||
|
return current_executor_state.current_executor();
|
||||||
|
}
|
||||||
|
|
||||||
|
void p2()
|
||||||
|
{
|
||||||
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
|
boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
|
||||||
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void p1()
|
||||||
|
{
|
||||||
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
|
boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
|
||||||
|
current_executor().submit(&p2);
|
||||||
|
boost::this_thread::sleep_for(boost::chrono::milliseconds(400));
|
||||||
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
|
|
||||||
|
boost::basic_thread_pool tp(4,
|
||||||
|
// at_thread_entry
|
||||||
|
[](boost::basic_thread_pool& pool)
|
||||||
|
{
|
||||||
|
current_executor_state.set_current_executor(pool);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
tp.submit(&p1);
|
||||||
|
|
||||||
|
boost::this_thread::sleep_for(boost::chrono::seconds(5));
|
||||||
|
|
||||||
|
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -59,6 +59,7 @@ int main()
|
|||||||
threads.remove_thread(th);
|
threads.remove_thread(th);
|
||||||
BOOST_TEST(! threads.is_thread_in(th));
|
BOOST_TEST(! threads.is_thread_in(th));
|
||||||
th->join();
|
th->join();
|
||||||
|
delete th;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ void thread_proc()
|
|||||||
increment();
|
increment();
|
||||||
int* p = value.get();
|
int* p = value.get();
|
||||||
assert(*p == i+1);
|
assert(*p == i+1);
|
||||||
|
(void)(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ namespace boost
|
|||||||
unsigned int count,
|
unsigned int count,
|
||||||
BOOST_THREAD_RV_REF(F) funct,
|
BOOST_THREAD_RV_REF(F) funct,
|
||||||
typename enable_if<
|
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
|
>::type=0
|
||||||
)
|
)
|
||||||
: m_count(check_counter(count)),
|
: m_count(check_counter(count)),
|
||||||
@@ -160,7 +160,7 @@ namespace boost
|
|||||||
unsigned int count,
|
unsigned int count,
|
||||||
F &funct,
|
F &funct,
|
||||||
typename enable_if<
|
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
|
>::type=0
|
||||||
)
|
)
|
||||||
: m_count(check_counter(count)),
|
: m_count(check_counter(count)),
|
||||||
@@ -176,7 +176,7 @@ namespace boost
|
|||||||
unsigned int count,
|
unsigned int count,
|
||||||
BOOST_THREAD_RV_REF(F) funct,
|
BOOST_THREAD_RV_REF(F) funct,
|
||||||
typename enable_if<
|
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
|
>::type=0
|
||||||
)
|
)
|
||||||
: m_count(check_counter(count)),
|
: m_count(check_counter(count)),
|
||||||
@@ -189,7 +189,7 @@ namespace boost
|
|||||||
unsigned int count,
|
unsigned int count,
|
||||||
F& funct,
|
F& funct,
|
||||||
typename enable_if<
|
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
|
>::type=0
|
||||||
)
|
)
|
||||||
: m_count(check_counter(count)),
|
: m_count(check_counter(count)),
|
||||||
@@ -225,6 +225,7 @@ namespace boost
|
|||||||
m_generation++;
|
m_generation++;
|
||||||
m_count = static_cast<unsigned int>(fct_());
|
m_count = static_cast<unsigned int>(fct_());
|
||||||
BOOST_ASSERT(m_count != 0);
|
BOOST_ASSERT(m_count != 0);
|
||||||
|
lock.unlock();
|
||||||
m_cond.notify_all();
|
m_cond.notify_all();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// (C) Copyright 2013 Vicente J. Botet Escriba
|
// (C) Copyright 2013,2015 Vicente J. Botet Escriba
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See
|
// Distributed under the Boost Software License, Version 1.0. (See
|
||||||
// accompanying file LICENSE_1_0.txt or copy at
|
// accompanying file LICENSE_1_0.txt or copy at
|
||||||
// http://www.boost.org/LICENSE_1_0.txt)
|
// http://www.boost.org/LICENSE_1_0.txt)
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
#include <boost/thread/thread.hpp>
|
#include <boost/thread/thread.hpp>
|
||||||
#endif
|
#endif
|
||||||
#include <boost/current_function.hpp>
|
#include <boost/current_function.hpp>
|
||||||
|
#include <boost/io/ios_state.hpp>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
|
||||||
#include <boost/config/abi_prefix.hpp>
|
#include <boost/config/abi_prefix.hpp>
|
||||||
@@ -43,9 +44,11 @@ namespace boost
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
io::ios_flags_saver ifs(os);
|
io::ios_flags_saver ifs(os);
|
||||||
os << ctx.filename << "["
|
os << std::setw(50) << ctx.filename << "["
|
||||||
<< std::setw(4) << std::right << std::dec<< ctx.lineno << "] ";
|
<< std::setw(4) << std::right << std::dec<< ctx.lineno << "] ";
|
||||||
|
#if defined BOOST_THREAD_USES_LOG_CURRENT_FUNCTION
|
||||||
os << ctx.func << " " ;
|
os << ctx.func << " " ;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,7 +96,6 @@ namespace boost
|
|||||||
leavers_(0)
|
leavers_(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
template <typename F>
|
|
||||||
completion_latch(std::size_t count, void(*funct)()) :
|
completion_latch(std::size_t count, void(*funct)()) :
|
||||||
count_(count), funct_(funct), waiters_(0), leavers_(0)
|
count_(count), funct_(funct), waiters_(0), leavers_(0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -27,12 +27,12 @@ namespace detail
|
|||||||
|
|
||||||
template <typename Queue>
|
template <typename Queue>
|
||||||
class deque_adaptor_copyable_only :
|
class deque_adaptor_copyable_only :
|
||||||
public boost::deque_base<typename Queue::value_type>
|
public boost::deque_base<typename Queue::value_type, typename Queue::size_type>
|
||||||
{
|
{
|
||||||
Queue queue;
|
Queue queue;
|
||||||
public:
|
public:
|
||||||
typedef typename Queue::value_type value_type;
|
typedef typename Queue::value_type value_type;
|
||||||
typedef std::size_t size_type;
|
typedef typename Queue::size_type size_type;
|
||||||
|
|
||||||
// Constructors/Assignment/Destructors
|
// Constructors/Assignment/Destructors
|
||||||
deque_adaptor_copyable_only() {}
|
deque_adaptor_copyable_only() {}
|
||||||
@@ -63,12 +63,12 @@ namespace detail
|
|||||||
};
|
};
|
||||||
template <typename Queue>
|
template <typename Queue>
|
||||||
class deque_adaptor_movable_only :
|
class deque_adaptor_movable_only :
|
||||||
public boost::deque_base<typename Queue::value_type>
|
public boost::deque_base<typename Queue::value_type, typename Queue::size_type>
|
||||||
{
|
{
|
||||||
Queue queue;
|
Queue queue;
|
||||||
public:
|
public:
|
||||||
typedef typename Queue::value_type value_type;
|
typedef typename Queue::value_type value_type;
|
||||||
typedef std::size_t size_type;
|
typedef typename Queue::size_type size_type;
|
||||||
|
|
||||||
// Constructors/Assignment/Destructors
|
// Constructors/Assignment/Destructors
|
||||||
|
|
||||||
@@ -102,12 +102,12 @@ namespace detail
|
|||||||
|
|
||||||
template <typename Queue>
|
template <typename Queue>
|
||||||
class deque_adaptor_copyable_and_movable :
|
class deque_adaptor_copyable_and_movable :
|
||||||
public boost::deque_base<typename Queue::value_type>
|
public boost::deque_base<typename Queue::value_type, typename Queue::size_type>
|
||||||
{
|
{
|
||||||
Queue queue;
|
Queue queue;
|
||||||
public:
|
public:
|
||||||
typedef typename Queue::value_type value_type;
|
typedef typename Queue::value_type value_type;
|
||||||
typedef std::size_t size_type;
|
typedef typename Queue::size_type size_type;
|
||||||
|
|
||||||
// Constructors/Assignment/Destructors
|
// Constructors/Assignment/Destructors
|
||||||
|
|
||||||
@@ -195,7 +195,7 @@ namespace detail
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef typename Queue::value_type value_type;
|
typedef typename Queue::value_type value_type;
|
||||||
typedef std::size_t size_type;
|
typedef typename Queue::size_type size_type;
|
||||||
// Constructors/Assignment/Destructors
|
// Constructors/Assignment/Destructors
|
||||||
virtual ~deque_adaptor() {};
|
virtual ~deque_adaptor() {};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -27,12 +27,12 @@ namespace concurrent
|
|||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
template <typename ValueType>
|
template <typename ValueType, class SizeType>
|
||||||
class deque_base_copyable_only
|
class deque_base_copyable_only
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef ValueType value_type;
|
typedef ValueType value_type;
|
||||||
typedef std::size_t size_type;
|
typedef SizeType size_type;
|
||||||
|
|
||||||
// Constructors/Assignment/Destructors
|
// Constructors/Assignment/Destructors
|
||||||
virtual ~deque_base_copyable_only() {};
|
virtual ~deque_base_copyable_only() {};
|
||||||
@@ -58,16 +58,16 @@ namespace detail
|
|||||||
virtual queue_op_status nonblocking_pull_front(value_type&) = 0;
|
virtual queue_op_status nonblocking_pull_front(value_type&) = 0;
|
||||||
|
|
||||||
virtual queue_op_status wait_push_back(const value_type& x) = 0;
|
virtual queue_op_status wait_push_back(const value_type& x) = 0;
|
||||||
virtual queue_op_status wait_pull_front(ValueType& elem) = 0;
|
virtual queue_op_status wait_pull_front(value_type& elem) = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename ValueType>
|
template <typename ValueType, class SizeType>
|
||||||
class deque_base_movable_only
|
class deque_base_movable_only
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef ValueType value_type;
|
typedef ValueType value_type;
|
||||||
typedef std::size_t size_type;
|
typedef SizeType size_type;
|
||||||
// Constructors/Assignment/Destructors
|
// Constructors/Assignment/Destructors
|
||||||
virtual ~deque_base_movable_only() {};
|
virtual ~deque_base_movable_only() {};
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ namespace detail
|
|||||||
|
|
||||||
virtual queue_op_status nonblocking_pull_front(value_type&) = 0;
|
virtual queue_op_status nonblocking_pull_front(value_type&) = 0;
|
||||||
|
|
||||||
virtual queue_op_status wait_pull_front(ValueType& elem) = 0;
|
virtual queue_op_status wait_pull_front(value_type& elem) = 0;
|
||||||
|
|
||||||
virtual void push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
virtual void push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
||||||
virtual queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
virtual queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
||||||
@@ -97,12 +97,12 @@ namespace detail
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <typename ValueType>
|
template <typename ValueType, class SizeType>
|
||||||
class deque_base_copyable_and_movable
|
class deque_base_copyable_and_movable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef ValueType value_type;
|
typedef ValueType value_type;
|
||||||
typedef std::size_t size_type;
|
typedef SizeType size_type;
|
||||||
// Constructors/Assignment/Destructors
|
// Constructors/Assignment/Destructors
|
||||||
virtual ~deque_base_copyable_and_movable() {};
|
virtual ~deque_base_copyable_and_movable() {};
|
||||||
|
|
||||||
@@ -129,7 +129,7 @@ namespace detail
|
|||||||
virtual queue_op_status nonblocking_pull_front(value_type&) = 0;
|
virtual queue_op_status nonblocking_pull_front(value_type&) = 0;
|
||||||
|
|
||||||
virtual queue_op_status wait_push_back(const value_type& x) = 0;
|
virtual queue_op_status wait_push_back(const value_type& x) = 0;
|
||||||
virtual queue_op_status wait_pull_front(ValueType& elem) = 0;
|
virtual queue_op_status wait_pull_front(value_type& elem) = 0;
|
||||||
|
|
||||||
virtual void push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
virtual void push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
||||||
virtual queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
virtual queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
||||||
@@ -137,7 +137,7 @@ namespace detail
|
|||||||
virtual queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
virtual queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T,
|
template <class T, class ST,
|
||||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||||
#if defined __GNUC__ && ! defined __clang__
|
#if defined __GNUC__ && ! defined __clang__
|
||||||
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
|
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||||
@@ -166,28 +166,28 @@ namespace detail
|
|||||||
>
|
>
|
||||||
struct deque_base;
|
struct deque_base;
|
||||||
|
|
||||||
template <class T>
|
template <class T, class ST>
|
||||||
struct deque_base<T, true, true> {
|
struct deque_base<T, ST, true, true> {
|
||||||
typedef deque_base_copyable_and_movable<T> type;
|
typedef deque_base_copyable_and_movable<T, ST> type;
|
||||||
};
|
};
|
||||||
template <class T>
|
template <class T, class ST>
|
||||||
struct deque_base<T, true, false> {
|
struct deque_base<T, ST, true, false> {
|
||||||
typedef deque_base_copyable_only<T> type;
|
typedef deque_base_copyable_only<T, ST> type;
|
||||||
};
|
};
|
||||||
template <class T>
|
template <class T, class ST>
|
||||||
struct deque_base<T, false, true> {
|
struct deque_base<T, ST, false, true> {
|
||||||
typedef deque_base_movable_only<T> type;
|
typedef deque_base_movable_only<T, ST> type;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ValueType>
|
template <class ValueType, class SizeType=std::size_t>
|
||||||
class deque_base :
|
class deque_base :
|
||||||
public detail::deque_base<ValueType>::type
|
public detail::deque_base<ValueType, SizeType>::type
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef ValueType value_type;
|
typedef ValueType value_type;
|
||||||
typedef std::size_t size_type;
|
typedef SizeType size_type;
|
||||||
// Constructors/Assignment/Destructors
|
// Constructors/Assignment/Destructors
|
||||||
virtual ~deque_base() {};
|
virtual ~deque_base() {};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace detail
|
|||||||
public:
|
public:
|
||||||
typedef ValueType value_type;
|
typedef ValueType value_type;
|
||||||
typedef Queue underlying_queue_type;
|
typedef Queue underlying_queue_type;
|
||||||
typedef std::size_t size_type;
|
typedef typename Queue::size_type size_type;
|
||||||
typedef queue_op_status op_status;
|
typedef queue_op_status op_status;
|
||||||
|
|
||||||
typedef typename chrono::steady_clock clock;
|
typedef typename chrono::steady_clock clock;
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace detail
|
|||||||
public:
|
public:
|
||||||
typedef ValueType value_type;
|
typedef ValueType value_type;
|
||||||
typedef Queue underlying_queue_type;
|
typedef Queue underlying_queue_type;
|
||||||
typedef std::size_t size_type;
|
typedef typename Queue::size_type size_type;
|
||||||
typedef queue_op_status op_status;
|
typedef queue_op_status op_status;
|
||||||
|
|
||||||
typedef typename chrono::steady_clock clock;
|
typedef typename chrono::steady_clock clock;
|
||||||
|
|||||||
@@ -27,12 +27,12 @@ namespace detail
|
|||||||
|
|
||||||
template <typename Queue>
|
template <typename Queue>
|
||||||
class queue_adaptor_copyable_only :
|
class queue_adaptor_copyable_only :
|
||||||
public boost::queue_base<typename Queue::value_type>
|
public boost::queue_base<typename Queue::value_type, typename Queue::size_type>
|
||||||
{
|
{
|
||||||
Queue queue;
|
Queue queue;
|
||||||
public:
|
public:
|
||||||
typedef typename Queue::value_type value_type;
|
typedef typename Queue::value_type value_type;
|
||||||
typedef std::size_t size_type;
|
typedef typename Queue::size_type size_type;
|
||||||
|
|
||||||
// Constructors/Assignment/Destructors
|
// Constructors/Assignment/Destructors
|
||||||
queue_adaptor_copyable_only() {}
|
queue_adaptor_copyable_only() {}
|
||||||
@@ -63,12 +63,12 @@ namespace detail
|
|||||||
};
|
};
|
||||||
template <typename Queue>
|
template <typename Queue>
|
||||||
class queue_adaptor_movable_only :
|
class queue_adaptor_movable_only :
|
||||||
public boost::queue_base<typename Queue::value_type>
|
public boost::queue_base<typename Queue::value_type, typename Queue::size_type>
|
||||||
{
|
{
|
||||||
Queue queue;
|
Queue queue;
|
||||||
public:
|
public:
|
||||||
typedef typename Queue::value_type value_type;
|
typedef typename Queue::value_type value_type;
|
||||||
typedef std::size_t size_type;
|
typedef typename Queue::size_type size_type;
|
||||||
|
|
||||||
// Constructors/Assignment/Destructors
|
// Constructors/Assignment/Destructors
|
||||||
|
|
||||||
@@ -102,12 +102,12 @@ namespace detail
|
|||||||
|
|
||||||
template <typename Queue>
|
template <typename Queue>
|
||||||
class queue_adaptor_copyable_and_movable :
|
class queue_adaptor_copyable_and_movable :
|
||||||
public boost::queue_base<typename Queue::value_type>
|
public boost::queue_base<typename Queue::value_type, typename Queue::size_type>
|
||||||
{
|
{
|
||||||
Queue queue;
|
Queue queue;
|
||||||
public:
|
public:
|
||||||
typedef typename Queue::value_type value_type;
|
typedef typename Queue::value_type value_type;
|
||||||
typedef std::size_t size_type;
|
typedef typename Queue::size_type size_type;
|
||||||
|
|
||||||
// Constructors/Assignment/Destructors
|
// Constructors/Assignment/Destructors
|
||||||
|
|
||||||
@@ -195,7 +195,7 @@ namespace detail
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef typename Queue::value_type value_type;
|
typedef typename Queue::value_type value_type;
|
||||||
typedef std::size_t size_type;
|
typedef typename Queue::size_type size_type;
|
||||||
// Constructors/Assignment/Destructors
|
// Constructors/Assignment/Destructors
|
||||||
virtual ~queue_adaptor() {};
|
virtual ~queue_adaptor() {};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -27,12 +27,12 @@ namespace concurrent
|
|||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
template <typename ValueType>
|
template <typename ValueType, class SizeType>
|
||||||
class queue_base_copyable_only
|
class queue_base_copyable_only
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef ValueType value_type;
|
typedef ValueType value_type;
|
||||||
typedef std::size_t size_type;
|
typedef SizeType size_type;
|
||||||
|
|
||||||
// Constructors/Assignment/Destructors
|
// Constructors/Assignment/Destructors
|
||||||
virtual ~queue_base_copyable_only() {};
|
virtual ~queue_base_copyable_only() {};
|
||||||
@@ -62,12 +62,12 @@ namespace detail
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename ValueType>
|
template <typename ValueType, class SizeType>
|
||||||
class queue_base_movable_only
|
class queue_base_movable_only
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef ValueType value_type;
|
typedef ValueType value_type;
|
||||||
typedef std::size_t size_type;
|
typedef SizeType size_type;
|
||||||
// Constructors/Assignment/Destructors
|
// Constructors/Assignment/Destructors
|
||||||
virtual ~queue_base_movable_only() {};
|
virtual ~queue_base_movable_only() {};
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ namespace detail
|
|||||||
|
|
||||||
virtual queue_op_status nonblocking_pull(value_type&) = 0;
|
virtual queue_op_status nonblocking_pull(value_type&) = 0;
|
||||||
|
|
||||||
virtual queue_op_status wait_pull(ValueType& elem) = 0;
|
virtual queue_op_status wait_pull(value_type& elem) = 0;
|
||||||
|
|
||||||
virtual void push(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
virtual void push(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
||||||
virtual queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
virtual queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
||||||
@@ -97,12 +97,12 @@ namespace detail
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <typename ValueType>
|
template <typename ValueType, class SizeType>
|
||||||
class queue_base_copyable_and_movable
|
class queue_base_copyable_and_movable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef ValueType value_type;
|
typedef ValueType value_type;
|
||||||
typedef std::size_t size_type;
|
typedef SizeType size_type;
|
||||||
// Constructors/Assignment/Destructors
|
// Constructors/Assignment/Destructors
|
||||||
virtual ~queue_base_copyable_and_movable() {};
|
virtual ~queue_base_copyable_and_movable() {};
|
||||||
|
|
||||||
@@ -129,7 +129,7 @@ namespace detail
|
|||||||
virtual queue_op_status nonblocking_pull(value_type&) = 0;
|
virtual queue_op_status nonblocking_pull(value_type&) = 0;
|
||||||
|
|
||||||
virtual queue_op_status wait_push(const value_type& x) = 0;
|
virtual queue_op_status wait_push(const value_type& x) = 0;
|
||||||
virtual queue_op_status wait_pull(ValueType& elem) = 0;
|
virtual queue_op_status wait_pull(value_type& elem) = 0;
|
||||||
|
|
||||||
virtual void push(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
virtual void push(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
||||||
virtual queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
virtual queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
||||||
@@ -137,7 +137,7 @@ namespace detail
|
|||||||
virtual queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
virtual queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T,
|
template <class T, class ST,
|
||||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||||
#if defined __GNUC__ && ! defined __clang__
|
#if defined __GNUC__ && ! defined __clang__
|
||||||
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
|
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||||
@@ -166,28 +166,28 @@ namespace detail
|
|||||||
>
|
>
|
||||||
struct queue_base;
|
struct queue_base;
|
||||||
|
|
||||||
template <class T>
|
template <class T, class ST>
|
||||||
struct queue_base<T, true, true> {
|
struct queue_base<T, ST, true, true> {
|
||||||
typedef queue_base_copyable_and_movable<T> type;
|
typedef queue_base_copyable_and_movable<T, ST> type;
|
||||||
};
|
};
|
||||||
template <class T>
|
template <class T, class ST>
|
||||||
struct queue_base<T, true, false> {
|
struct queue_base<T, ST, true, false> {
|
||||||
typedef queue_base_copyable_only<T> type;
|
typedef queue_base_copyable_only<T, ST> type;
|
||||||
};
|
};
|
||||||
template <class T>
|
template <class T, class ST>
|
||||||
struct queue_base<T, false, true> {
|
struct queue_base<T, ST, false, true> {
|
||||||
typedef queue_base_movable_only<T> type;
|
typedef queue_base_movable_only<T, ST> type;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ValueType>
|
template <typename ValueType, class SizeType=std::size_t>
|
||||||
class queue_base :
|
class queue_base :
|
||||||
public detail::queue_base<ValueType>::type
|
public detail::queue_base<ValueType, SizeType>::type
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef ValueType value_type;
|
typedef ValueType value_type;
|
||||||
typedef std::size_t size_type;
|
typedef SizeType size_type;
|
||||||
// Constructors/Assignment/Destructors
|
// Constructors/Assignment/Destructors
|
||||||
virtual ~queue_base() {};
|
virtual ~queue_base() {};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -76,26 +76,15 @@ namespace concurrent
|
|||||||
// Modifiers
|
// Modifiers
|
||||||
void close() { queue->close(); }
|
void close() { queue->close(); }
|
||||||
|
|
||||||
void push(const value_type& x) { queue->push_front(x); }
|
|
||||||
|
|
||||||
void pull(value_type& x) { queue->pull(x); };
|
void pull(value_type& x) { queue->pull(x); };
|
||||||
// enable_if is_nothrow_copy_movable<value_type>
|
// enable_if is_nothrow_copy_movable<value_type>
|
||||||
value_type pull() { return queue->pull(); }
|
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 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 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); }
|
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
|
inline size_type size(lock_guard<mutex>& lk) const BOOST_NOEXCEPT
|
||||||
{
|
{
|
||||||
if (full(lk)) return capacity(lk);
|
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>&);
|
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)
|
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;}
|
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);
|
pull_front(elem, lk);
|
||||||
return queue_op_status::success;
|
return queue_op_status::success;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,12 +43,13 @@ namespace detail {
|
|||||||
Compare _compare;
|
Compare _compare;
|
||||||
public:
|
public:
|
||||||
typedef Type value_type;
|
typedef Type value_type;
|
||||||
|
typedef typename Container::size_type size_type;
|
||||||
|
|
||||||
explicit priority_queue(const Compare& compare = Compare())
|
explicit priority_queue(const Compare& compare = Compare())
|
||||||
: _elements(), _compare(compare)
|
: _elements(), _compare(compare)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
std::size_t size() const
|
size_type size() const
|
||||||
{
|
{
|
||||||
return _elements.size();
|
return _elements.size();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
// See http://www.boost.org/libs/thread for documentation.
|
// See http://www.boost.org/libs/thread for documentation.
|
||||||
//
|
//
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include <boost/thread/detail/config.hpp>
|
#include <boost/thread/detail/config.hpp>
|
||||||
#include <boost/thread/concurrent_queues/detail/sync_queue_base.hpp>
|
#include <boost/thread/concurrent_queues/detail/sync_queue_base.hpp>
|
||||||
@@ -150,13 +151,19 @@ namespace concurrent
|
|||||||
template <class ValueType, class Container>
|
template <class ValueType, class Container>
|
||||||
queue_op_status sync_queue<ValueType, Container>::wait_pull(ValueType& elem, unique_lock<mutex>& lk)
|
queue_op_status sync_queue<ValueType, Container>::wait_pull(ValueType& elem, unique_lock<mutex>& lk)
|
||||||
{
|
{
|
||||||
|
//std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||||
if (super::empty(lk))
|
if (super::empty(lk))
|
||||||
{
|
{
|
||||||
|
//std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||||
if (super::closed(lk)) return queue_op_status::closed;
|
if (super::closed(lk)) return queue_op_status::closed;
|
||||||
}
|
}
|
||||||
|
//std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||||
bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
|
bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
|
||||||
|
//std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||||
if (has_been_closed) return queue_op_status::closed;
|
if (has_been_closed) return queue_op_status::closed;
|
||||||
|
//std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||||
pull(elem, lk);
|
pull(elem, lk);
|
||||||
|
//std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||||
return queue_op_status::success;
|
return queue_op_status::success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ namespace detail
|
|||||||
class sync_timed_queue
|
class sync_timed_queue
|
||||||
: private sync_priority_queue<detail::scheduled_type<T, Clock> >
|
: 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;
|
typedef sync_priority_queue<stype> super;
|
||||||
public:
|
public:
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
@@ -106,6 +106,11 @@ namespace detail
|
|||||||
template <class Rep, class Period>
|
template <class Rep, class Period>
|
||||||
void push(const T& elem, chrono::duration<Rep,Period> const& dura);
|
void push(const T& elem, chrono::duration<Rep,Period> const& dura);
|
||||||
|
|
||||||
|
template <class Duration>
|
||||||
|
void push(BOOST_THREAD_RV_REF(T) elem, chrono::time_point<clock,Duration> const& tp);
|
||||||
|
template <class Rep, class Period>
|
||||||
|
void push(BOOST_THREAD_RV_REF(T) elem, chrono::duration<Rep,Period> const& dura);
|
||||||
|
|
||||||
template <class Duration>
|
template <class Duration>
|
||||||
queue_op_status try_push(const T& elem, chrono::time_point<clock,Duration> const& tp);
|
queue_op_status try_push(const T& elem, chrono::time_point<clock,Duration> const& tp);
|
||||||
template <class Rep, class Period>
|
template <class Rep, class Period>
|
||||||
@@ -158,6 +163,22 @@ namespace detail
|
|||||||
push(elem, clock::now() + dura);
|
push(elem, clock::now() + dura);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class T, class Clock>
|
||||||
|
template <class Duration>
|
||||||
|
void sync_timed_queue<T, Clock>::push(BOOST_THREAD_RV_REF(T) elem, chrono::time_point<clock,Duration> const& tp)
|
||||||
|
{
|
||||||
|
super::push(stype(boost::move(elem),tp));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, class Clock>
|
||||||
|
template <class Rep, class Period>
|
||||||
|
void sync_timed_queue<T, Clock>::push(BOOST_THREAD_RV_REF(T) elem, chrono::duration<Rep,Period> const& dura)
|
||||||
|
{
|
||||||
|
push(boost::move(elem), clock::now() + dura);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <class T, class Clock>
|
template <class T, class Clock>
|
||||||
template <class Duration>
|
template <class Duration>
|
||||||
queue_op_status sync_timed_queue<T, Clock>::try_push(const T& elem, chrono::time_point<clock,Duration> const& tp)
|
queue_op_status sync_timed_queue<T, Clock>::try_push(const T& elem, chrono::time_point<clock,Duration> const& tp)
|
||||||
@@ -208,13 +229,14 @@ namespace detail
|
|||||||
if (super::closed(lk)) return true;
|
if (super::closed(lk)) return true;
|
||||||
while (! super::empty(lk)) {
|
while (! super::empty(lk)) {
|
||||||
if (! time_not_reached(lk)) return false;
|
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;
|
||||||
}
|
}
|
||||||
if (super::closed(lk)) return true;
|
if (super::closed(lk)) return true;
|
||||||
super::not_empty_.wait(lk);
|
super::not_empty_.wait(lk);
|
||||||
}
|
}
|
||||||
return false;
|
//return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////
|
///////////////////////////
|
||||||
@@ -224,7 +246,8 @@ namespace detail
|
|||||||
while (time_not_reached(lk))
|
while (time_not_reached(lk))
|
||||||
{
|
{
|
||||||
super::throw_if_closed(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);
|
super::wait_until_not_empty(lk);
|
||||||
}
|
}
|
||||||
return pull(lk);
|
return pull(lk);
|
||||||
@@ -239,7 +262,7 @@ namespace detail
|
|||||||
while (time_not_reached(lk))
|
while (time_not_reached(lk))
|
||||||
{
|
{
|
||||||
super::throw_if_closed(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;
|
if (time_not_reached(lk)) return queue_op_status::not_ready;
|
||||||
return queue_op_status::timeout;
|
return queue_op_status::timeout;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ namespace boost
|
|||||||
template <class T>
|
template <class T>
|
||||||
class devector
|
class devector
|
||||||
{
|
{
|
||||||
typedef vector<T> vector_type;
|
typedef csbl::vector<T> vector_type;
|
||||||
vector<T> data_;
|
vector_type data_;
|
||||||
std::size_t front_index_;
|
std::size_t front_index_;
|
||||||
|
|
||||||
BOOST_COPYABLE_AND_MOVABLE(devector)
|
BOOST_COPYABLE_AND_MOVABLE(devector)
|
||||||
@@ -58,7 +58,9 @@ namespace boost
|
|||||||
}
|
}
|
||||||
|
|
||||||
devector& operator=(BOOST_RV_REF(devector) x)
|
devector& operator=(BOOST_RV_REF(devector) x)
|
||||||
BOOST_NOEXCEPT_IF(vector<T>::allocator_traits_type::propagate_on_container_move_assignment::value)
|
#if defined BOOST_THREAD_USES_BOOST_VECTOR
|
||||||
|
BOOST_NOEXCEPT_IF(vector_type::allocator_traits_type::propagate_on_container_move_assignment::value)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
data_ = boost::move(x.data_);
|
data_ = boost::move(x.data_);
|
||||||
front_index_ = x.front_index_;
|
front_index_ = x.front_index_;
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
#include <boost/detail/workaround.hpp>
|
#include <boost/detail/workaround.hpp>
|
||||||
#include <boost/thread/detail/platform.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
|
//#define BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS
|
||||||
// ATTRIBUTE_MAY_ALIAS
|
// ATTRIBUTE_MAY_ALIAS
|
||||||
|
|
||||||
@@ -100,8 +102,8 @@
|
|||||||
#if !defined BOOST_THREAD_VERSION
|
#if !defined BOOST_THREAD_VERSION
|
||||||
#define BOOST_THREAD_VERSION 2
|
#define BOOST_THREAD_VERSION 2
|
||||||
#else
|
#else
|
||||||
#if BOOST_THREAD_VERSION!=2 && BOOST_THREAD_VERSION!=3 && BOOST_THREAD_VERSION!=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 or 4"
|
#error "BOOST_THREAD_VERSION must be 2, 3, 4 or 5"
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -304,6 +306,13 @@
|
|||||||
|
|
||||||
#endif // BOOST_THREAD_VERSION>=4
|
#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
|
// INTERRUPTIONS
|
||||||
#if ! defined BOOST_THREAD_PROVIDES_INTERRUPTIONS \
|
#if ! defined BOOST_THREAD_PROVIDES_INTERRUPTIONS \
|
||||||
&& ! defined BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS
|
&& ! defined BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS
|
||||||
|
|||||||
@@ -72,13 +72,21 @@ namespace boost
|
|||||||
BOOST_SYMBOL_VISIBLE
|
BOOST_SYMBOL_VISIBLE
|
||||||
invoker& operator=(BOOST_THREAD_RV_REF(invoker) f)
|
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
|
BOOST_SYMBOL_VISIBLE
|
||||||
invoker& operator=( BOOST_THREAD_COPY_ASSIGN_REF(invoker) f)
|
invoker& operator=( BOOST_THREAD_COPY_ASSIGN_REF(invoker) f)
|
||||||
{
|
{
|
||||||
f_ = f.f_;
|
if (this != &f)
|
||||||
|
{
|
||||||
|
f_ = f.f_;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
result_type operator()()
|
result_type operator()()
|
||||||
@@ -91,7 +99,7 @@ namespace boost
|
|||||||
result_type
|
result_type
|
||||||
execute(tuple_indices<Indices...>)
|
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
|
result_type
|
||||||
execute(tuple_indices<Indices...>)
|
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
|
//BOOST_THREAD_DCL_MOVABLE_BEG(X) invoker<Fp> BOOST_THREAD_DCL_MOVABLE_END
|
||||||
@@ -182,7 +190,7 @@ namespace boost
|
|||||||
{} \
|
{} \
|
||||||
\
|
\
|
||||||
result_type operator()() { \
|
result_type operator()() { \
|
||||||
return invoke(boost::move(fp_) \
|
return detail::invoke(boost::move(fp_) \
|
||||||
BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_DCL, ~) \
|
BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_DCL, ~) \
|
||||||
); \
|
); \
|
||||||
} \
|
} \
|
||||||
@@ -307,7 +315,7 @@ namespace boost
|
|||||||
|
|
||||||
result_type operator()()
|
result_type operator()()
|
||||||
{
|
{
|
||||||
return invoke(boost::move(fp_)
|
return detail::invoke(boost::move(fp_)
|
||||||
, boost::move(v0_)
|
, boost::move(v0_)
|
||||||
, boost::move(v1_)
|
, boost::move(v1_)
|
||||||
, boost::move(v2_)
|
, boost::move(v2_)
|
||||||
@@ -373,7 +381,7 @@ namespace boost
|
|||||||
|
|
||||||
result_type operator()()
|
result_type operator()()
|
||||||
{
|
{
|
||||||
return invoke(boost::move(fp_)
|
return detail::invoke(boost::move(fp_)
|
||||||
, boost::move(v0_)
|
, boost::move(v0_)
|
||||||
, boost::move(v1_)
|
, boost::move(v1_)
|
||||||
, boost::move(v2_)
|
, boost::move(v2_)
|
||||||
@@ -434,7 +442,7 @@ namespace boost
|
|||||||
|
|
||||||
result_type operator()()
|
result_type operator()()
|
||||||
{
|
{
|
||||||
return invoke(boost::move(fp_)
|
return detail::invoke(boost::move(fp_)
|
||||||
, boost::move(v0_)
|
, boost::move(v0_)
|
||||||
, boost::move(v1_)
|
, boost::move(v1_)
|
||||||
, boost::move(v2_)
|
, boost::move(v2_)
|
||||||
@@ -490,7 +498,7 @@ namespace boost
|
|||||||
|
|
||||||
result_type operator()()
|
result_type operator()()
|
||||||
{
|
{
|
||||||
return invoke(boost::move(fp_)
|
return detail::invoke(boost::move(fp_)
|
||||||
, boost::move(v0_)
|
, boost::move(v0_)
|
||||||
, boost::move(v1_)
|
, boost::move(v1_)
|
||||||
, boost::move(v2_)
|
, boost::move(v2_)
|
||||||
@@ -541,7 +549,7 @@ namespace boost
|
|||||||
|
|
||||||
result_type operator()()
|
result_type operator()()
|
||||||
{
|
{
|
||||||
return invoke(boost::move(fp_)
|
return detail::invoke(boost::move(fp_)
|
||||||
, boost::move(v0_)
|
, boost::move(v0_)
|
||||||
, boost::move(v1_)
|
, boost::move(v1_)
|
||||||
, boost::move(v2_)
|
, boost::move(v2_)
|
||||||
@@ -587,7 +595,7 @@ namespace boost
|
|||||||
|
|
||||||
result_type operator()()
|
result_type operator()()
|
||||||
{
|
{
|
||||||
return invoke(boost::move(fp_)
|
return detail::invoke(boost::move(fp_)
|
||||||
, boost::move(v0_)
|
, boost::move(v0_)
|
||||||
, boost::move(v1_)
|
, boost::move(v1_)
|
||||||
, boost::move(v2_)
|
, boost::move(v2_)
|
||||||
@@ -628,7 +636,7 @@ namespace boost
|
|||||||
|
|
||||||
result_type operator()()
|
result_type operator()()
|
||||||
{
|
{
|
||||||
return invoke(boost::move(fp_)
|
return detail::invoke(boost::move(fp_)
|
||||||
, boost::move(v0_)
|
, boost::move(v0_)
|
||||||
, boost::move(v1_)
|
, boost::move(v1_)
|
||||||
, boost::move(v2_)
|
, boost::move(v2_)
|
||||||
@@ -664,7 +672,7 @@ namespace boost
|
|||||||
|
|
||||||
result_type operator()()
|
result_type operator()()
|
||||||
{
|
{
|
||||||
return invoke(boost::move(fp_)
|
return detail::invoke(boost::move(fp_)
|
||||||
, boost::move(v0_)
|
, boost::move(v0_)
|
||||||
, boost::move(v1_)
|
, boost::move(v1_)
|
||||||
);
|
);
|
||||||
@@ -695,7 +703,7 @@ namespace boost
|
|||||||
|
|
||||||
result_type operator()()
|
result_type operator()()
|
||||||
{
|
{
|
||||||
return invoke(boost::move(fp_)
|
return detail::invoke(boost::move(fp_)
|
||||||
, boost::move(v0_)
|
, boost::move(v0_)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,6 +94,11 @@ namespace boost
|
|||||||
template <typename T> \
|
template <typename T> \
|
||||||
struct enable_move_utility_emulation_dummy_specialization<
|
struct enable_move_utility_emulation_dummy_specialization<
|
||||||
|
|
||||||
|
#define BOOST_THREAD_DCL_MOVABLE_BEG2(T1, T2) \
|
||||||
|
namespace detail { \
|
||||||
|
template <typename T1, typename T2> \
|
||||||
|
struct enable_move_utility_emulation_dummy_specialization<
|
||||||
|
|
||||||
#define BOOST_THREAD_DCL_MOVABLE_END > \
|
#define BOOST_THREAD_DCL_MOVABLE_END > \
|
||||||
: integral_constant<bool, false> \
|
: integral_constant<bool, false> \
|
||||||
{}; \
|
{}; \
|
||||||
@@ -115,6 +120,11 @@ namespace boost
|
|||||||
template <typename T> \
|
template <typename T> \
|
||||||
struct enable_move_utility_emulation_dummy_specialization<
|
struct enable_move_utility_emulation_dummy_specialization<
|
||||||
|
|
||||||
|
#define BOOST_THREAD_DCL_MOVABLE_BEG2(T1, T2) \
|
||||||
|
namespace detail { \
|
||||||
|
template <typename T1, typename T2> \
|
||||||
|
struct enable_move_utility_emulation_dummy_specialization<
|
||||||
|
|
||||||
#define BOOST_THREAD_DCL_MOVABLE_END > \
|
#define BOOST_THREAD_DCL_MOVABLE_END > \
|
||||||
: integral_constant<bool, false> \
|
: integral_constant<bool, false> \
|
||||||
{}; \
|
{}; \
|
||||||
@@ -136,6 +146,11 @@ namespace boost
|
|||||||
template <typename T> \
|
template <typename T> \
|
||||||
struct enable_move_utility_emulation_dummy_specialization<
|
struct enable_move_utility_emulation_dummy_specialization<
|
||||||
|
|
||||||
|
#define BOOST_THREAD_DCL_MOVABLE_BEG2(T1, T2) \
|
||||||
|
namespace detail { \
|
||||||
|
template <typename T1, typename T2> \
|
||||||
|
struct enable_move_utility_emulation_dummy_specialization<
|
||||||
|
|
||||||
#define BOOST_THREAD_DCL_MOVABLE_END > \
|
#define BOOST_THREAD_DCL_MOVABLE_END > \
|
||||||
: integral_constant<bool, false> \
|
: integral_constant<bool, false> \
|
||||||
{}; \
|
{}; \
|
||||||
@@ -161,6 +176,10 @@ struct enable_move_utility_emulation< TYPE > \
|
|||||||
template <typename T> \
|
template <typename T> \
|
||||||
struct enable_move_utility_emulation<
|
struct enable_move_utility_emulation<
|
||||||
|
|
||||||
|
#define BOOST_THREAD_DCL_MOVABLE_BEG2(T1, T2) \
|
||||||
|
template <typename T1, typename T2> \
|
||||||
|
struct enable_move_utility_emulation<
|
||||||
|
|
||||||
#define BOOST_THREAD_DCL_MOVABLE_END > \
|
#define BOOST_THREAD_DCL_MOVABLE_END > \
|
||||||
{ \
|
{ \
|
||||||
static const bool value = false; \
|
static const bool value = false; \
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ namespace boost
|
|||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
//BOOST_THREAD_DCL_MOVABLE_BEG(F) detail::nullary_function<F> BOOST_THREAD_DCL_MOVABLE_END
|
BOOST_THREAD_DCL_MOVABLE_BEG(F) detail::nullary_function<F> BOOST_THREAD_DCL_MOVABLE_END
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // header
|
#endif // header
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ namespace boost
|
|||||||
void run2(tuple_indices<Indices...>)
|
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()
|
void run()
|
||||||
{
|
{
|
||||||
@@ -155,7 +155,15 @@ namespace boost
|
|||||||
};
|
};
|
||||||
#endif
|
#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
|
class BOOST_THREAD_DECL thread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -173,7 +181,6 @@ namespace boost
|
|||||||
private:
|
private:
|
||||||
bool start_thread_noexcept();
|
bool start_thread_noexcept();
|
||||||
bool start_thread_noexcept(const attributes& attr);
|
bool start_thread_noexcept(const attributes& attr);
|
||||||
//public:
|
|
||||||
void start_thread()
|
void start_thread()
|
||||||
{
|
{
|
||||||
if (!start_thread_noexcept())
|
if (!start_thread_noexcept())
|
||||||
@@ -355,6 +362,8 @@ namespace boost
|
|||||||
|
|
||||||
#if defined BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE
|
#if defined BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE
|
||||||
if (joinable()) std::terminate();
|
if (joinable()) std::terminate();
|
||||||
|
#else
|
||||||
|
detach();
|
||||||
#endif
|
#endif
|
||||||
thread_info=BOOST_THREAD_RV(other).thread_info;
|
thread_info=BOOST_THREAD_RV(other).thread_info;
|
||||||
BOOST_THREAD_RV(other).thread_info.reset();
|
BOOST_THREAD_RV(other).thread_info.reset();
|
||||||
@@ -481,13 +490,14 @@ namespace boost
|
|||||||
return try_join_until(chrono::steady_clock::now() + rel_time);
|
return try_join_until(chrono::steady_clock::now() + rel_time);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <class Clock, class Duration>
|
template <class Clock, class Duration>
|
||||||
bool try_join_until(const chrono::time_point<Clock, Duration>& t)
|
bool try_join_until(const chrono::time_point<Clock, Duration>& t)
|
||||||
{
|
{
|
||||||
using namespace chrono;
|
using namespace chrono;
|
||||||
system_clock::time_point s_now = system_clock::now();
|
|
||||||
bool joined= false;
|
bool joined= false;
|
||||||
do {
|
do {
|
||||||
|
thread_detail::internal_clock_t::time_point s_now = thread_detail::internal_clock_t::now();
|
||||||
typename Clock::duration d = ceil<nanoseconds>(t-Clock::now());
|
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
|
if (d <= Clock::duration::zero()) return false; // in case the Clock::time_point t is already reached
|
||||||
joined = try_join_until(s_now + d);
|
joined = try_join_until(s_now + d);
|
||||||
@@ -495,10 +505,10 @@ namespace boost
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
template <class Duration>
|
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;
|
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())));
|
return try_join_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -513,7 +523,7 @@ namespace boost
|
|||||||
//}
|
//}
|
||||||
|
|
||||||
#ifdef BOOST_THREAD_USES_CHRONO
|
#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());
|
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now());
|
||||||
return do_try_join_until(rel_time.count());
|
return do_try_join_until(rel_time.count());
|
||||||
@@ -534,7 +544,7 @@ namespace boost
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef BOOST_THREAD_USES_CHRONO
|
#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;
|
using namespace chrono;
|
||||||
nanoseconds d = tp.time_since_epoch();
|
nanoseconds d = tp.time_since_epoch();
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
// (C) Copyright 2007-9 Anthony Williams
|
// (C) Copyright 2007-9 Anthony Williams
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <boost/thread/csbl/memory/unique_ptr.hpp>
|
||||||
#include <boost/thread/shared_mutex.hpp>
|
#include <boost/thread/shared_mutex.hpp>
|
||||||
#include <boost/thread/mutex.hpp>
|
#include <boost/thread/mutex.hpp>
|
||||||
#include <boost/thread/lock_guard.hpp>
|
#include <boost/thread/lock_guard.hpp>
|
||||||
@@ -75,7 +76,7 @@ namespace boost
|
|||||||
thread* create_thread(F threadfunc)
|
thread* create_thread(F threadfunc)
|
||||||
{
|
{
|
||||||
boost::lock_guard<shared_mutex> guard(m);
|
boost::lock_guard<shared_mutex> guard(m);
|
||||||
std::auto_ptr<thread> new_thread(new thread(threadfunc));
|
boost::csbl::unique_ptr<thread> new_thread(new thread(threadfunc));
|
||||||
threads.push_back(new_thread.get());
|
threads.push_back(new_thread.get());
|
||||||
return new_thread.release();
|
return new_thread.release();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
// (C) Copyright 2013 Vicente J. Botet Escriba
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See
|
|
||||||
// accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
// http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
|
|
||||||
#ifndef BOOST_THREAD_DETAIL_WORK_HPP
|
|
||||||
#define BOOST_THREAD_DETAIL_WORK_HPP
|
|
||||||
|
|
||||||
|
|
||||||
#include <boost/thread/detail/nullary_function.hpp>
|
|
||||||
|
|
||||||
namespace boost
|
|
||||||
{
|
|
||||||
namespace thread_detail
|
|
||||||
{
|
|
||||||
|
|
||||||
typedef detail::nullary_function<void()> work;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace boost
|
|
||||||
|
|
||||||
#endif // BOOST_THREAD_DETAIL_MEMORY_HPP
|
|
||||||
@@ -40,19 +40,19 @@ namespace boost
|
|||||||
typedef system::system_error base_type;
|
typedef system::system_error base_type;
|
||||||
public:
|
public:
|
||||||
thread_exception()
|
thread_exception()
|
||||||
: base_type(0,system::system_category())
|
: base_type(0,system::generic_category())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
thread_exception(int sys_error_code)
|
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 )
|
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 )
|
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;
|
typedef system::system_error base_type;
|
||||||
public:
|
public:
|
||||||
condition_error()
|
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 )
|
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 )
|
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 )
|
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)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
#include <boost/thread/detail/config.hpp>
|
#include <boost/thread/detail/config.hpp>
|
||||||
#include <boost/thread/detail/delete.hpp>
|
#include <boost/thread/detail/delete.hpp>
|
||||||
#include <boost/thread/detail/move.hpp>
|
#include <boost/thread/detail/move.hpp>
|
||||||
#include <boost/thread/scoped_thread.hpp>
|
#include <boost/thread/thread.hpp>
|
||||||
#include <boost/thread/concurrent_queues/sync_queue.hpp>
|
#include <boost/thread/concurrent_queues/sync_queue.hpp>
|
||||||
#include <boost/thread/executors/work.hpp>
|
#include <boost/thread/executors/work.hpp>
|
||||||
#include <boost/thread/csbl/vector.hpp>
|
#include <boost/thread/csbl/vector.hpp>
|
||||||
@@ -30,15 +30,14 @@ namespace executors
|
|||||||
/// type-erasure to store the works to do
|
/// type-erasure to store the works to do
|
||||||
typedef executors::work work;
|
typedef executors::work work;
|
||||||
private:
|
private:
|
||||||
/// the kind of stored threads are scoped threads to ensure that the threads are joined.
|
typedef thread thread_t;
|
||||||
/// A move aware vector type
|
/// A move aware vector type
|
||||||
typedef scoped_thread<> thread_t;
|
|
||||||
typedef csbl::vector<thread_t> thread_vector;
|
typedef csbl::vector<thread_t> thread_vector;
|
||||||
|
|
||||||
/// the thread safe work queue
|
|
||||||
concurrent::sync_queue<work > work_queue;
|
|
||||||
/// A move aware vector
|
/// A move aware vector
|
||||||
thread_vector threads;
|
thread_vector threads;
|
||||||
|
/// the thread safe work queue
|
||||||
|
concurrent::sync_queue<work > work_queue;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
@@ -61,7 +60,7 @@ namespace executors
|
|||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
std::terminate();
|
std::terminate();
|
||||||
return false;
|
//return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -88,7 +87,9 @@ namespace executors
|
|||||||
{
|
{
|
||||||
work task;
|
work task;
|
||||||
queue_op_status st = work_queue.wait_pull(task);
|
queue_op_status st = work_queue.wait_pull(task);
|
||||||
if (st == queue_op_status::closed) return;
|
if (st == queue_op_status::closed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
task();
|
task();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -222,7 +223,8 @@ namespace executors
|
|||||||
{
|
{
|
||||||
// signal to all the worker threads that there will be no more submissions.
|
// signal to all the worker threads that there will be no more submissions.
|
||||||
close();
|
close();
|
||||||
// joins all the threads as the threads were scoped_threads
|
// joins all the threads before destroying the thread pool resources (e.g. the queue).
|
||||||
|
join();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -264,23 +266,28 @@ namespace executors
|
|||||||
* \b Throws: \c sync_queue_is_closed if the thread pool is closed.
|
* \b Throws: \c sync_queue_is_closed if the thread pool is closed.
|
||||||
* Whatever exception that can be throw while storing the closure.
|
* Whatever exception that can be throw while storing the closure.
|
||||||
*/
|
*/
|
||||||
|
void submit(BOOST_THREAD_RV_REF(work) closure) {
|
||||||
|
work_queue.push(boost::move(closure));
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||||
template <typename Closure>
|
template <typename Closure>
|
||||||
void submit(Closure & closure)
|
void submit(Closure & closure)
|
||||||
{
|
{
|
||||||
work_queue.push(work(closure));
|
submit(work(closure));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
void submit(void (*closure)())
|
void submit(void (*closure)())
|
||||||
{
|
{
|
||||||
work_queue.push(work(closure));
|
submit(work(closure));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Closure>
|
template <typename Closure>
|
||||||
void submit(BOOST_THREAD_RV_REF(Closure) closure)
|
void submit(BOOST_THREAD_FWD_REF(Closure) closure)
|
||||||
{
|
{
|
||||||
work_queue.push(work(boost::forward<Closure>(closure)));
|
//submit(work(boost::forward<Closure>(closure)));
|
||||||
|
work w((boost::forward<Closure>(closure)));
|
||||||
|
submit(boost::move(w));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ namespace detail
|
|||||||
class priority_executor_base
|
class priority_executor_base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef boost::function<void()> work;
|
//typedef boost::function<void()> work;
|
||||||
//typedef executors::work work;
|
typedef executors::work_pq work;
|
||||||
protected:
|
protected:
|
||||||
typedef Queue queue_type;
|
typedef Queue queue_type;
|
||||||
queue_type _workq;
|
queue_type _workq;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright (C) 2014 Ian Forbed
|
// Copyright (C) 2014 Ian Forbed
|
||||||
// Copyright (C) 2014 Vicente J. Botet Escriba
|
// Copyright (C) 2014-2015 Vicente J. Botet Escriba
|
||||||
//
|
//
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
// 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)
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
@@ -16,6 +16,8 @@
|
|||||||
#include <boost/atomic.hpp>
|
#include <boost/atomic.hpp>
|
||||||
#include <boost/function.hpp>
|
#include <boost/function.hpp>
|
||||||
|
|
||||||
|
#include <boost/config/abi_prefix.hpp>
|
||||||
|
|
||||||
namespace boost
|
namespace boost
|
||||||
{
|
{
|
||||||
namespace executors
|
namespace executors
|
||||||
@@ -23,11 +25,10 @@ namespace executors
|
|||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
template <class Clock=chrono::steady_clock>
|
template <class Clock=chrono::steady_clock>
|
||||||
class scheduled_executor_base : public priority_executor_base<concurrent::sync_timed_queue<boost::function<void()>, Clock > >
|
class scheduled_executor_base : public priority_executor_base<concurrent::sync_timed_queue<executors::work_pq, Clock > >
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef boost::function<void()> work;
|
typedef executors::work_pq work;
|
||||||
//typedef executors::work work;
|
|
||||||
typedef Clock clock;
|
typedef Clock clock;
|
||||||
typedef typename clock::duration duration;
|
typedef typename clock::duration duration;
|
||||||
typedef typename clock::time_point time_point;
|
typedef typename clock::time_point time_point;
|
||||||
@@ -46,12 +47,12 @@ namespace detail
|
|||||||
|
|
||||||
void submit_at(work w, const time_point& tp)
|
void submit_at(work w, const time_point& tp)
|
||||||
{
|
{
|
||||||
this->_workq.push(w, tp);
|
this->_workq.push(boost::move(w), tp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void submit_after(work w, const duration& dura)
|
void submit_after(work w, const duration& dura)
|
||||||
{
|
{
|
||||||
this->_workq.push(w, dura+clock::now());
|
this->_workq.push(boost::move(w), dura+clock::now());
|
||||||
}
|
}
|
||||||
|
|
||||||
}; //end class
|
}; //end class
|
||||||
@@ -59,4 +60,7 @@ namespace detail
|
|||||||
} //end detail namespace
|
} //end detail namespace
|
||||||
} //end executors namespace
|
} //end executors namespace
|
||||||
} //end boost namespace
|
} //end boost namespace
|
||||||
|
|
||||||
|
#include <boost/config/abi_suffix.hpp>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ namespace boost
|
|||||||
* \par Synchronization
|
* \par Synchronization
|
||||||
* The completion of all the closures happen before the completion of the executor destructor.
|
* The completion of all the closures happen before the completion of the executor destructor.
|
||||||
*/
|
*/
|
||||||
virtual ~executor() {};
|
virtual ~executor() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \par Effects
|
* \par Effects
|
||||||
@@ -99,9 +99,10 @@ namespace boost
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Closure>
|
template <typename Closure>
|
||||||
void submit(BOOST_THREAD_RV_REF(Closure) closure)
|
void submit(BOOST_THREAD_FWD_REF(Closure) closure)
|
||||||
{
|
{
|
||||||
work w = boost::move(closure);
|
//submit(work(boost::forward<Closure>(closure)));
|
||||||
|
work w((boost::forward<Closure>(closure)));
|
||||||
submit(boost::move(w));
|
submit(boost::move(w));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -98,9 +98,6 @@ namespace executors
|
|||||||
void submit(BOOST_THREAD_RV_REF(work) closure) {
|
void submit(BOOST_THREAD_RV_REF(work) closure) {
|
||||||
return ex.submit(boost::move(closure));
|
return ex.submit(boost::move(closure));
|
||||||
}
|
}
|
||||||
// void submit(work & closure) {
|
|
||||||
// return ex.submit(closure);
|
|
||||||
// }
|
|
||||||
|
|
||||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||||
template <typename Closure>
|
template <typename Closure>
|
||||||
@@ -115,9 +112,11 @@ namespace executors
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Closure>
|
template <typename Closure>
|
||||||
void submit(BOOST_THREAD_RV_REF(Closure) closure)
|
void submit(BOOST_THREAD_FWD_REF(Closure) closure)
|
||||||
{
|
{
|
||||||
submit(work(boost::forward<Closure>(closure)));
|
//submit(work(boost::forward<Closure>(closure)));
|
||||||
|
work w((boost::forward<Closure>(closure)));
|
||||||
|
submit(boost::move(w));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ namespace boost
|
|||||||
|
|
||||||
/// executor is not copyable.
|
/// executor is not copyable.
|
||||||
BOOST_THREAD_NO_COPYABLE(executor_ref)
|
BOOST_THREAD_NO_COPYABLE(executor_ref)
|
||||||
executor_ref(Executor& ex) : ex(ex) {}
|
executor_ref(Executor& ex_) : ex(ex_) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \par Effects
|
* \par Effects
|
||||||
@@ -41,7 +41,7 @@ namespace boost
|
|||||||
* \par Synchronization
|
* \par Synchronization
|
||||||
* The completion of all the closures happen before the completion of the executor destructor.
|
* The completion of all the closures happen before the completion of the executor destructor.
|
||||||
*/
|
*/
|
||||||
~executor_ref() {};
|
~executor_ref() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \par Effects
|
* \par Effects
|
||||||
@@ -98,9 +98,9 @@ namespace boost
|
|||||||
typedef executors::work work;
|
typedef executors::work work;
|
||||||
|
|
||||||
template<typename Executor>
|
template<typename Executor>
|
||||||
generic_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(make_shared<executor_ref<Executor> >(ex_)) // todo check why this doesn't works with C++03
|
||||||
: ex( new executor_ref<Executor>(ex) )
|
: ex( new executor_ref<Executor>(ex_) )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,11 +121,6 @@ namespace boost
|
|||||||
*/
|
*/
|
||||||
bool closed() { return ex->closed(); }
|
bool closed() { return ex->closed(); }
|
||||||
|
|
||||||
void submit(BOOST_THREAD_RV_REF(work) closure)
|
|
||||||
{
|
|
||||||
ex->submit(boost::forward<work>(closure));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \par Requires
|
* \par Requires
|
||||||
* \c Closure is a model of Callable(void()) and a model of CopyConstructible/MoveConstructible.
|
* \c Closure is a model of Callable(void()) and a model of CopyConstructible/MoveConstructible.
|
||||||
@@ -142,24 +137,31 @@ namespace boost
|
|||||||
* Whatever exception that can be throw while storing the closure.
|
* Whatever exception that can be throw while storing the closure.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
void submit(BOOST_THREAD_RV_REF(work) closure)
|
||||||
|
{
|
||||||
|
ex->submit(boost::move(closure));
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||||
template <typename Closure>
|
template <typename Closure>
|
||||||
void submit(Closure & closure)
|
void submit(Closure & closure)
|
||||||
{
|
{
|
||||||
work w ((closure));
|
//work w ((closure));
|
||||||
submit(boost::move(w));
|
//submit(boost::move(w));
|
||||||
|
submit(work(closure));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
void submit(void (*closure)())
|
void submit(void (*closure)())
|
||||||
{
|
{
|
||||||
work w ((closure));
|
work w ((closure));
|
||||||
submit(boost::move(w));
|
submit(boost::move(w));
|
||||||
|
//submit(work(closure));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Closure>
|
template <typename Closure>
|
||||||
void submit(BOOST_THREAD_RV_REF(Closure) closure)
|
void submit(BOOST_THREAD_FWD_REF(Closure) closure)
|
||||||
{
|
{
|
||||||
work w = boost::move(closure);
|
work w((boost::forward<Closure>(closure)));
|
||||||
submit(boost::move(w));
|
submit(boost::move(w));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include <boost/thread/detail/move.hpp>
|
#include <boost/thread/detail/move.hpp>
|
||||||
#include <boost/thread/concurrent_queues/sync_queue.hpp>
|
#include <boost/thread/concurrent_queues/sync_queue.hpp>
|
||||||
#include <boost/thread/executors/work.hpp>
|
#include <boost/thread/executors/work.hpp>
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
#include <boost/config/abi_prefix.hpp>
|
#include <boost/config/abi_prefix.hpp>
|
||||||
|
|
||||||
@@ -40,38 +41,41 @@ namespace executors
|
|||||||
* Throws: whatever the current task constructor throws or the task() throws.
|
* Throws: whatever the current task constructor throws or the task() throws.
|
||||||
*/
|
*/
|
||||||
bool try_executing_one()
|
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;
|
work task;
|
||||||
try
|
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();
|
task();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
BOOST_ASSERT(!wait || status == queue_op_status::closed);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
std::terminate();
|
std::terminate();
|
||||||
return false;
|
//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:
|
public:
|
||||||
/// loop_executor is not copyable.
|
/// loop_executor is not copyable.
|
||||||
@@ -101,10 +105,10 @@ namespace executors
|
|||||||
*/
|
*/
|
||||||
void loop()
|
void loop()
|
||||||
{
|
{
|
||||||
while (!closed())
|
while (execute_one(/*wait:*/true))
|
||||||
{
|
{
|
||||||
schedule_one_or_yield();
|
|
||||||
}
|
}
|
||||||
|
BOOST_ASSERT(closed());
|
||||||
while (try_executing_one())
|
while (try_executing_one())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -138,23 +142,29 @@ namespace executors
|
|||||||
* \b Throws: \c sync_queue_is_closed if the thread pool is closed.
|
* \b Throws: \c sync_queue_is_closed if the thread pool is closed.
|
||||||
* Whatever exception that can be throw while storing the closure.
|
* Whatever exception that can be throw while storing the closure.
|
||||||
*/
|
*/
|
||||||
|
void submit(BOOST_THREAD_RV_REF(work) closure) {
|
||||||
|
work_queue.push(boost::move(closure));
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||||
template <typename Closure>
|
template <typename Closure>
|
||||||
void submit(Closure & closure)
|
void submit(Closure & closure)
|
||||||
{
|
{
|
||||||
work_queue.push(work(closure));
|
submit(work(closure));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void submit(void (*closure)())
|
void submit(void (*closure)())
|
||||||
{
|
{
|
||||||
work_queue.push(work(closure));
|
submit(work(closure));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Closure>
|
template <typename Closure>
|
||||||
void submit(BOOST_THREAD_RV_REF(Closure) closure)
|
void submit(BOOST_THREAD_FWD_REF(Closure) closure)
|
||||||
{
|
{
|
||||||
work_queue.push(work(boost::forward<Closure>(closure)));
|
//work_queue.push(work(boost::forward<Closure>(closure)));
|
||||||
|
work w((boost::forward<Closure>(closure)));
|
||||||
|
submit(boost::move(w));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ namespace executors
|
|||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
std::terminate();
|
std::terminate();
|
||||||
return false;
|
//return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
@@ -165,23 +165,28 @@ namespace executors
|
|||||||
* \b Throws: \c sync_queue_is_closed if the thread pool is closed.
|
* \b Throws: \c sync_queue_is_closed if the thread pool is closed.
|
||||||
* Whatever exception that can be throw while storing the closure.
|
* Whatever exception that can be throw while storing the closure.
|
||||||
*/
|
*/
|
||||||
|
void submit(BOOST_THREAD_RV_REF(work) closure)
|
||||||
|
{
|
||||||
|
work_queue.push(boost::move(closure));
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||||
template <typename Closure>
|
template <typename Closure>
|
||||||
void submit(Closure & closure)
|
void submit(Closure & closure)
|
||||||
{
|
{
|
||||||
work_queue.push(work(closure));
|
submit(work(closure));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
void submit(void (*closure)())
|
void submit(void (*closure)())
|
||||||
{
|
{
|
||||||
work_queue.push(work(closure));
|
submit(work(closure));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Closure>
|
template <typename Closure>
|
||||||
void submit(BOOST_THREAD_RV_REF(Closure) closure)
|
void submit(BOOST_THREAD_FWD_REF(Closure) closure)
|
||||||
{
|
{
|
||||||
work_queue.push(work(boost::forward<Closure>(closure)));
|
work w((boost::forward<Closure>(closure)));
|
||||||
|
submit(boost::move(w));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (C) 2013 Vicente J. Botet Escriba
|
// Copyright (C) 2015 Vicente J. Botet Escriba
|
||||||
//
|
//
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
// 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)
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
@@ -6,8 +6,8 @@
|
|||||||
// 2013/11 Vicente J. Botet Escriba
|
// 2013/11 Vicente J. Botet Escriba
|
||||||
// first implementation of a simple serial scheduler.
|
// first implementation of a simple serial scheduler.
|
||||||
|
|
||||||
#ifndef BOOST_THREAD_SERIAL_EXECUTOR_HPP
|
#ifndef BOOST_THREAD_SERIAL_EXECUTOR_CONT_HPP
|
||||||
#define BOOST_THREAD_SERIAL_EXECUTOR_HPP
|
#define BOOST_THREAD_SERIAL_EXECUTOR_CONT_HPP
|
||||||
|
|
||||||
#include <boost/thread/detail/config.hpp>
|
#include <boost/thread/detail/config.hpp>
|
||||||
#include <boost/thread/detail/delete.hpp>
|
#include <boost/thread/detail/delete.hpp>
|
||||||
@@ -153,7 +153,7 @@ namespace executors
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Closure>
|
template <typename Closure>
|
||||||
void submit(BOOST_THREAD_RV_REF(Closure) closure)
|
void submit(BOOST_THREAD_FWD_REF(Closure) closure)
|
||||||
{
|
{
|
||||||
lock_guard<mutex> lk(mtx_);
|
lock_guard<mutex> lk(mtx_);
|
||||||
if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
|
if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include <boost/thread/thread_only.hpp>
|
#include <boost/thread/thread_only.hpp>
|
||||||
#include <boost/thread/scoped_thread.hpp>
|
#include <boost/thread/scoped_thread.hpp>
|
||||||
#include <boost/thread/csbl/vector.hpp>
|
#include <boost/thread/csbl/vector.hpp>
|
||||||
|
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
|
||||||
|
|
||||||
#include <boost/config/abi_prefix.hpp>
|
#include <boost/config/abi_prefix.hpp>
|
||||||
|
|
||||||
|
|||||||
@@ -8,36 +8,23 @@
|
|||||||
#define BOOST_THREAD_EXECUTORS_WORK_HPP
|
#define BOOST_THREAD_EXECUTORS_WORK_HPP
|
||||||
|
|
||||||
#include <boost/thread/detail/config.hpp>
|
#include <boost/thread/detail/config.hpp>
|
||||||
|
|
||||||
#if ! defined BOOST_THREAD_EXECUTORS_WORK_ACCEPTS_MOVABLE \
|
|
||||||
&& ! defined BOOST_THREAD_EXECUTORS_WORK_DONT_ACCEPT_MOVABLE
|
|
||||||
#define BOOST_THREAD_EXECUTORS_WORK_ACCEPTS_MOVABLE
|
|
||||||
//#define BOOST_THREAD_EXECUTORS_WORK_DONT_ACCEPT_MOVABLE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined BOOST_THREAD_EXECUTORS_WORK_ACCEPTS_MOVABLE
|
|
||||||
|
|
||||||
#include <boost/thread/detail/nullary_function.hpp>
|
#include <boost/thread/detail/nullary_function.hpp>
|
||||||
|
|
||||||
namespace boost
|
|
||||||
{
|
|
||||||
namespace executors
|
|
||||||
{
|
|
||||||
typedef detail::nullary_function<void()> work;
|
|
||||||
}
|
|
||||||
} // namespace boost
|
|
||||||
|
|
||||||
#else
|
|
||||||
#include <boost/thread/csbl/functional.hpp>
|
#include <boost/thread/csbl/functional.hpp>
|
||||||
|
|
||||||
namespace boost
|
namespace boost
|
||||||
{
|
{
|
||||||
namespace executors
|
namespace executors
|
||||||
{
|
{
|
||||||
typedef csbl::function<void()> work;
|
typedef detail::nullary_function<void()> work;
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||||
|
typedef detail::nullary_function<void()> work_pq;
|
||||||
|
//typedef csbl::function<void()> work_pq;
|
||||||
|
#else
|
||||||
|
typedef csbl::function<void()> work_pq;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
} // namespace boost
|
} // namespace boost
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // BOOST_THREAD_EXECUTORS_WORK_HPP
|
#endif // BOOST_THREAD_EXECUTORS_WORK_HPP
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// (C) Copyright Vicente J. Botet Escriba 2014. Distributed under the Boost
|
// (C) Copyright Vicente J. Botet Escriba 2014-2015. Distributed under the Boost
|
||||||
// Software License, Version 1.0. (See accompanying file
|
// Software License, Version 1.0. (See accompanying file
|
||||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
//
|
//
|
||||||
@@ -50,12 +50,13 @@ BOOST_THREAD_INLINE_NAMESPACE(v2)
|
|||||||
void handle_task_region_exceptions(exception_list& errors)
|
void handle_task_region_exceptions(exception_list& errors)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
boost::rethrow_exception(boost::current_exception());
|
throw;
|
||||||
//throw boost::current_exception();
|
|
||||||
}
|
}
|
||||||
catch (task_canceled_exception& ex)
|
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
|
||||||
|
catch (task_canceled_exception&)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
catch (exception_list const& el)
|
catch (exception_list const& el)
|
||||||
{
|
{
|
||||||
for (exception_list::const_iterator it = el.begin(); it != el.end(); ++it)
|
for (exception_list::const_iterator it = el.begin(); it != el.end(); ++it)
|
||||||
@@ -94,7 +95,7 @@ BOOST_THREAD_INLINE_NAMESPACE(v2)
|
|||||||
{
|
{
|
||||||
lock_guard<mutex> lk(tr.mtx);
|
lock_guard<mutex> lk(tr.mtx);
|
||||||
tr.canceled = true;
|
tr.canceled = true;
|
||||||
handle_task_region_exceptions(tr.exs);
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -123,8 +124,6 @@ BOOST_THREAD_INLINE_NAMESPACE(v2)
|
|||||||
{
|
{
|
||||||
wait_for_all(group.begin(), group.end());
|
wait_for_all(group.begin(), group.end());
|
||||||
|
|
||||||
#if ! defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
|
|
||||||
|
|
||||||
for (group_type::iterator it = group.begin(); it != group.end(); ++it)
|
for (group_type::iterator it = group.begin(); it != group.end(); ++it)
|
||||||
{
|
{
|
||||||
future<void>& f = *it;
|
future<void>& f = *it;
|
||||||
@@ -140,11 +139,9 @@ BOOST_THREAD_INLINE_NAMESPACE(v2)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
if (exs.size() != 0)
|
if (exs.size() != 0)
|
||||||
{
|
{
|
||||||
boost::throw_exception(exs);
|
boost::throw_exception(exs);
|
||||||
//throw exs;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
@@ -187,6 +184,7 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
|
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
|
||||||
|
mutable mutex mtx;
|
||||||
bool canceled;
|
bool canceled;
|
||||||
#endif
|
#endif
|
||||||
#if defined BOOST_THREAD_PROVIDES_EXECUTORS
|
#if defined BOOST_THREAD_PROVIDES_EXECUTORS
|
||||||
@@ -195,8 +193,6 @@ protected:
|
|||||||
exception_list exs;
|
exception_list exs;
|
||||||
typedef csbl::vector<future<void> > group_type;
|
typedef csbl::vector<future<void> > group_type;
|
||||||
group_type group;
|
group_type group;
|
||||||
mutable mutex mtx;
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BOOST_DELETED_FUNCTION(task_region_handle_gen(const task_region_handle_gen&))
|
BOOST_DELETED_FUNCTION(task_region_handle_gen(const task_region_handle_gen&))
|
||||||
@@ -207,11 +203,12 @@ protected:
|
|||||||
template<typename F>
|
template<typename F>
|
||||||
void run(BOOST_THREAD_FWD_REF(F) f)
|
void run(BOOST_THREAD_FWD_REF(F) f)
|
||||||
{
|
{
|
||||||
lock_guard<mutex> lk(mtx);
|
|
||||||
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
|
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
|
||||||
if (canceled) {
|
{
|
||||||
boost::throw_exception(task_canceled_exception());
|
lock_guard<mutex> lk(mtx);
|
||||||
//throw task_canceled_exception();
|
if (canceled) {
|
||||||
|
boost::throw_exception(task_canceled_exception());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#if defined BOOST_THREAD_PROVIDES_EXECUTORS
|
#if defined BOOST_THREAD_PROVIDES_EXECUTORS
|
||||||
group.push_back(async(*ex, detail::wrapped<task_region_handle_gen<Executor>, F>(*this, forward<F>(f))));
|
group.push_back(async(*ex, detail::wrapped<task_region_handle_gen<Executor>, F>(*this, forward<F>(f))));
|
||||||
@@ -229,11 +226,12 @@ protected:
|
|||||||
|
|
||||||
void wait()
|
void wait()
|
||||||
{
|
{
|
||||||
lock_guard<mutex> lk(mtx);
|
|
||||||
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
|
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
|
||||||
if (canceled) {
|
{
|
||||||
boost::throw_exception(task_canceled_exception());
|
lock_guard<mutex> lk(mtx);
|
||||||
//throw task_canceled_exception{};
|
if (canceled) {
|
||||||
|
boost::throw_exception(task_canceled_exception());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
wait_all();
|
wait_all();
|
||||||
@@ -276,7 +274,6 @@ protected:
|
|||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
lock_guard<mutex> lk(tr.mtx);
|
|
||||||
detail::handle_task_region_exceptions(tr.exs);
|
detail::handle_task_region_exceptions(tr.exs);
|
||||||
}
|
}
|
||||||
tr.wait_all();
|
tr.wait_all();
|
||||||
@@ -298,7 +295,6 @@ protected:
|
|||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
lock_guard<mutex> lk(tr.mtx);
|
|
||||||
detail::handle_task_region_exceptions(tr.exs);
|
detail::handle_task_region_exceptions(tr.exs);
|
||||||
}
|
}
|
||||||
tr.wait_all();
|
tr.wait_all();
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -22,6 +22,8 @@ namespace boost
|
|||||||
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
||||||
executor = 4,
|
executor = 4,
|
||||||
#endif
|
#endif
|
||||||
|
inherit = 8,
|
||||||
|
sync = 16,
|
||||||
any = async | deferred
|
any = async | deferred
|
||||||
}
|
}
|
||||||
BOOST_SCOPED_ENUM_DECLARE_END(launch)
|
BOOST_SCOPED_ENUM_DECLARE_END(launch)
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ namespace boost
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
template<typename F1, typename... Fs>
|
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)... };
|
bool dummy[] = { (f1.wait(), true), (fs.wait(), true)... };
|
||||||
|
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ namespace boost
|
|||||||
void wait()
|
void wait()
|
||||||
{
|
{
|
||||||
boost::unique_lock<boost::mutex> lk(mutex_);
|
boost::unique_lock<boost::mutex> lk(mutex_);
|
||||||
|
if (count_ == 0) return;
|
||||||
std::size_t generation(generation_);
|
std::size_t generation(generation_);
|
||||||
cond_.wait(lk, detail::not_equal(generation, generation_));
|
cond_.wait(lk, detail::not_equal(generation, generation_));
|
||||||
}
|
}
|
||||||
@@ -89,6 +90,7 @@ namespace boost
|
|||||||
cv_status wait_for(const chrono::duration<Rep, Period>& rel_time)
|
cv_status wait_for(const chrono::duration<Rep, Period>& rel_time)
|
||||||
{
|
{
|
||||||
boost::unique_lock<boost::mutex> lk(mutex_);
|
boost::unique_lock<boost::mutex> lk(mutex_);
|
||||||
|
if (count_ == 0) return cv_status::no_timeout;
|
||||||
std::size_t generation(generation_);
|
std::size_t generation(generation_);
|
||||||
return cond_.wait_for(lk, rel_time, detail::not_equal(generation, generation_))
|
return cond_.wait_for(lk, rel_time, detail::not_equal(generation, generation_))
|
||||||
? cv_status::no_timeout
|
? cv_status::no_timeout
|
||||||
@@ -101,6 +103,7 @@ namespace boost
|
|||||||
cv_status wait_until(const chrono::time_point<Clock, Duration>& abs_time)
|
cv_status wait_until(const chrono::time_point<Clock, Duration>& abs_time)
|
||||||
{
|
{
|
||||||
boost::unique_lock<boost::mutex> lk(mutex_);
|
boost::unique_lock<boost::mutex> lk(mutex_);
|
||||||
|
if (count_ == 0) return cv_status::no_timeout;
|
||||||
std::size_t generation(generation_);
|
std::size_t generation(generation_);
|
||||||
return cond_.wait_until(lk, abs_time, detail::not_equal(generation, generation_))
|
return cond_.wait_until(lk, abs_time, detail::not_equal(generation, generation_))
|
||||||
? cv_status::no_timeout
|
? cv_status::no_timeout
|
||||||
|
|||||||
@@ -934,7 +934,7 @@ namespace boost
|
|||||||
if (m == 0)
|
if (m == 0)
|
||||||
{
|
{
|
||||||
boost::throw_exception(
|
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())
|
if (owns_lock())
|
||||||
{
|
{
|
||||||
@@ -949,7 +949,7 @@ namespace boost
|
|||||||
if (m == 0)
|
if (m == 0)
|
||||||
{
|
{
|
||||||
boost::throw_exception(
|
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())
|
if (owns_lock())
|
||||||
{
|
{
|
||||||
@@ -964,7 +964,7 @@ namespace boost
|
|||||||
if (m == 0)
|
if (m == 0)
|
||||||
{
|
{
|
||||||
boost::throw_exception(
|
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())
|
if (!owns_lock())
|
||||||
{
|
{
|
||||||
@@ -980,11 +980,11 @@ namespace boost
|
|||||||
{
|
{
|
||||||
if(m==0)
|
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())
|
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);
|
is_locked=m->try_lock_upgrade_for(rel_time);
|
||||||
return is_locked;
|
return is_locked;
|
||||||
@@ -994,11 +994,11 @@ namespace boost
|
|||||||
{
|
{
|
||||||
if(m==0)
|
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())
|
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);
|
is_locked=m->try_lock_upgrade_until(abs_time);
|
||||||
return is_locked;
|
return is_locked;
|
||||||
@@ -1080,7 +1080,7 @@ namespace boost
|
|||||||
//std-2104 unique_lock move-assignment should not be noexcept
|
//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& 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);
|
swap(temp);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -1167,7 +1167,7 @@ private unique_lock<Mutex>
|
|||||||
#endif
|
#endif
|
||||||
try_lock_wrapper& operator=(BOOST_THREAD_RV_REF_BEG try_lock_wrapper<Mutex> BOOST_THREAD_RV_REF_END other)
|
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);
|
swap(temp);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include <boost/thread/lock_algorithms.hpp>
|
#include <boost/thread/lock_algorithms.hpp>
|
||||||
#include <boost/thread/lock_types.hpp>
|
#include <boost/thread/lock_types.hpp>
|
||||||
#include <boost/thread/lock_guard.hpp>
|
#include <boost/thread/lock_guard.hpp>
|
||||||
|
#include <boost/thread/shared_lock_guard.hpp>
|
||||||
#include <boost/thread/lockable_traits.hpp>
|
#include <boost/thread/lockable_traits.hpp>
|
||||||
#include <boost/thread/lock_options.hpp>
|
#include <boost/thread/lock_options.hpp>
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ namespace boost
|
|||||||
//]
|
//]
|
||||||
|
|
||||||
//[poly_lockable
|
//[poly_lockable
|
||||||
class poly_lockable : public basic_poly_lockable<Lockable>
|
class poly_lockable : public basic_poly_lockable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ namespace boost
|
|||||||
//]
|
//]
|
||||||
|
|
||||||
//[timed_poly_lockable
|
//[timed_poly_lockable
|
||||||
class timed_poly_lockable: public poly_lockable<TimedLock>
|
class timed_poly_lockable: public poly_lockable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~timed_poly_lockable()=0;
|
virtual ~timed_poly_lockable()=0;
|
||||||
|
|||||||
@@ -45,9 +45,17 @@ namespace boost
|
|||||||
m_.unlock();
|
m_.unlock();
|
||||||
m=&m_;
|
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();
|
m->lock();
|
||||||
}
|
}
|
||||||
@@ -68,22 +76,20 @@ namespace boost
|
|||||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||||
thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard;
|
thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard;
|
||||||
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
|
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
|
||||||
|
pthread_mutex_t* the_mutex = &internal_mutex;
|
||||||
guard.activate(m);
|
guard.activate(m);
|
||||||
do {
|
res = pthread_cond_wait(&cond,the_mutex);
|
||||||
res = pthread_cond_wait(&cond,&internal_mutex);
|
check_for_interruption.check();
|
||||||
} while (res == EINTR);
|
guard.deactivate();
|
||||||
#else
|
#else
|
||||||
//boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
|
|
||||||
pthread_mutex_t* the_mutex = m.mutex()->native_handle();
|
pthread_mutex_t* the_mutex = m.mutex()->native_handle();
|
||||||
do {
|
res = pthread_cond_wait(&cond,the_mutex);
|
||||||
res = pthread_cond_wait(&cond,the_mutex);
|
|
||||||
} while (res == EINTR);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||||
this_thread::interruption_point();
|
this_thread::interruption_point();
|
||||||
#endif
|
#endif
|
||||||
if(res)
|
if(res && res != EINTR)
|
||||||
{
|
{
|
||||||
boost::throw_exception(condition_error(res, "boost::condition_variable::wait failed in pthread_cond_wait"));
|
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"));
|
boost::throw_exception(condition_error(EPERM, "boost::condition_variable::do_wait_until() failed precondition mutex not owned"));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard;
|
|
||||||
int cond_res;
|
int cond_res;
|
||||||
{
|
{
|
||||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
#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);
|
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
|
||||||
|
pthread_mutex_t* the_mutex = &internal_mutex;
|
||||||
guard.activate(m);
|
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
|
#else
|
||||||
//boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
|
|
||||||
pthread_mutex_t* the_mutex = m.mutex()->native_handle();
|
pthread_mutex_t* the_mutex = m.mutex()->native_handle();
|
||||||
cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout);
|
cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout);
|
||||||
#endif
|
#endif
|
||||||
@@ -156,11 +164,11 @@ namespace boost
|
|||||||
{
|
{
|
||||||
boost::throw_exception(thread_resource_error(res, "boost::condition_variable_any::condition_variable_any() failed in pthread_mutex_init"));
|
boost::throw_exception(thread_resource_error(res, "boost::condition_variable_any::condition_variable_any() failed in pthread_mutex_init"));
|
||||||
}
|
}
|
||||||
int const res2=pthread_cond_init(&cond,NULL);
|
int const res2 = detail::monotonic_pthread_cond_init(cond);
|
||||||
if(res2)
|
if(res2)
|
||||||
{
|
{
|
||||||
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
|
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
|
||||||
boost::throw_exception(thread_resource_error(res2, "boost::condition_variable_any::condition_variable_any() failed in pthread_cond_init"));
|
boost::throw_exception(thread_resource_error(res2, "boost::condition_variable_any::condition_variable_any() failed in detail::monotonic_pthread_cond_init"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
~condition_variable_any()
|
~condition_variable_any()
|
||||||
@@ -178,10 +186,12 @@ namespace boost
|
|||||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||||
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
|
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
|
||||||
#else
|
#else
|
||||||
boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
|
boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
|
||||||
#endif
|
#endif
|
||||||
guard.activate(m);
|
guard.activate(m);
|
||||||
res=pthread_cond_wait(&cond,&internal_mutex);
|
res=pthread_cond_wait(&cond,&internal_mutex);
|
||||||
|
check_for_interruption.check();
|
||||||
|
guard.deactivate();
|
||||||
}
|
}
|
||||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||||
this_thread::interruption_point();
|
this_thread::interruption_point();
|
||||||
@@ -240,6 +250,8 @@ namespace boost
|
|||||||
return timed_wait(m,get_system_time()+wait_duration,pred);
|
return timed_wait(m,get_system_time()+wait_duration,pred);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
|
||||||
|
|
||||||
#ifdef BOOST_THREAD_USES_CHRONO
|
#ifdef BOOST_THREAD_USES_CHRONO
|
||||||
template <class lock_type,class Duration>
|
template <class lock_type,class Duration>
|
||||||
cv_status
|
cv_status
|
||||||
@@ -268,22 +280,6 @@ namespace boost
|
|||||||
return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
|
return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class lock_type, class Clock, class Duration, class Predicate>
|
|
||||||
bool
|
|
||||||
wait_until(
|
|
||||||
lock_type& lock,
|
|
||||||
const chrono::time_point<Clock, Duration>& t,
|
|
||||||
Predicate pred)
|
|
||||||
{
|
|
||||||
while (!pred())
|
|
||||||
{
|
|
||||||
if (wait_until(lock, t) == cv_status::timeout)
|
|
||||||
return pred();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <class lock_type, class Rep, class Period>
|
template <class lock_type, class Rep, class Period>
|
||||||
cv_status
|
cv_status
|
||||||
wait_for(
|
wait_for(
|
||||||
@@ -299,24 +295,6 @@ namespace boost
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <class lock_type, class Rep, class Period, class Predicate>
|
|
||||||
bool
|
|
||||||
wait_for(
|
|
||||||
lock_type& lock,
|
|
||||||
const chrono::duration<Rep, Period>& d,
|
|
||||||
Predicate pred)
|
|
||||||
{
|
|
||||||
return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
|
|
||||||
|
|
||||||
// while (!pred())
|
|
||||||
// {
|
|
||||||
// if (wait_for(lock, d) == cv_status::timeout)
|
|
||||||
// return pred();
|
|
||||||
// }
|
|
||||||
// return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class lock_type>
|
template <class lock_type>
|
||||||
cv_status wait_until(
|
cv_status wait_until(
|
||||||
lock_type& lk,
|
lock_type& lk,
|
||||||
@@ -329,6 +307,90 @@ namespace boost
|
|||||||
else return cv_status::timeout;
|
else return cv_status::timeout;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#else // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
|
||||||
|
#ifdef BOOST_THREAD_USES_CHRONO
|
||||||
|
|
||||||
|
template <class lock_type, class Duration>
|
||||||
|
cv_status
|
||||||
|
wait_until(
|
||||||
|
lock_type& lock,
|
||||||
|
const chrono::time_point<chrono::steady_clock, Duration>& t)
|
||||||
|
{
|
||||||
|
using namespace chrono;
|
||||||
|
typedef time_point<steady_clock, nanoseconds> nano_sys_tmpt;
|
||||||
|
wait_until(lock,
|
||||||
|
nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
|
||||||
|
return steady_clock::now() < t ? cv_status::no_timeout :
|
||||||
|
cv_status::timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class lock_type, class Clock, class Duration>
|
||||||
|
cv_status
|
||||||
|
wait_until(
|
||||||
|
lock_type& lock,
|
||||||
|
const chrono::time_point<Clock, Duration>& t)
|
||||||
|
{
|
||||||
|
using namespace chrono;
|
||||||
|
steady_clock::time_point s_now = steady_clock::now();
|
||||||
|
typename Clock::time_point c_now = Clock::now();
|
||||||
|
wait_until(lock, s_now + ceil<nanoseconds>(t - c_now));
|
||||||
|
return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class lock_type, class Rep, class Period>
|
||||||
|
cv_status
|
||||||
|
wait_for(
|
||||||
|
lock_type& lock,
|
||||||
|
const chrono::duration<Rep, Period>& d)
|
||||||
|
{
|
||||||
|
using namespace chrono;
|
||||||
|
steady_clock::time_point c_now = steady_clock::now();
|
||||||
|
wait_until(lock, c_now + ceil<nanoseconds>(d));
|
||||||
|
return steady_clock::now() - c_now < d ? cv_status::no_timeout :
|
||||||
|
cv_status::timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class lock_type>
|
||||||
|
inline cv_status wait_until(
|
||||||
|
lock_type& lock,
|
||||||
|
chrono::time_point<chrono::steady_clock, chrono::nanoseconds> tp)
|
||||||
|
{
|
||||||
|
using namespace chrono;
|
||||||
|
nanoseconds d = tp.time_since_epoch();
|
||||||
|
timespec ts = boost::detail::to_timespec(d);
|
||||||
|
if (do_wait_until(lock, ts)) return cv_status::no_timeout;
|
||||||
|
else return cv_status::timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
|
||||||
|
|
||||||
|
#ifdef BOOST_THREAD_USES_CHRONO
|
||||||
|
template <class lock_type, class Clock, class Duration, class Predicate>
|
||||||
|
bool
|
||||||
|
wait_until(
|
||||||
|
lock_type& lock,
|
||||||
|
const chrono::time_point<Clock, Duration>& t,
|
||||||
|
Predicate pred)
|
||||||
|
{
|
||||||
|
while (!pred())
|
||||||
|
{
|
||||||
|
if (wait_until(lock, t) == cv_status::timeout)
|
||||||
|
return pred();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class lock_type, class Rep, class Period, class Predicate>
|
||||||
|
bool
|
||||||
|
wait_for(
|
||||||
|
lock_type& lock,
|
||||||
|
const chrono::duration<Rep, Period>& d,
|
||||||
|
Predicate pred)
|
||||||
|
{
|
||||||
|
return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void notify_one() BOOST_NOEXCEPT
|
void notify_one() BOOST_NOEXCEPT
|
||||||
{
|
{
|
||||||
@@ -344,7 +406,7 @@ namespace boost
|
|||||||
private: // used by boost::thread::try_join_until
|
private: // used by boost::thread::try_join_until
|
||||||
|
|
||||||
template <class lock_type>
|
template <class lock_type>
|
||||||
inline bool do_wait_until(
|
bool do_wait_until(
|
||||||
lock_type& m,
|
lock_type& m,
|
||||||
struct timespec const &timeout)
|
struct timespec const &timeout)
|
||||||
{
|
{
|
||||||
@@ -354,10 +416,12 @@ namespace boost
|
|||||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||||
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
|
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
|
||||||
#else
|
#else
|
||||||
boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
|
boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
|
||||||
#endif
|
#endif
|
||||||
guard.activate(m);
|
guard.activate(m);
|
||||||
res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
|
res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
|
||||||
|
check_for_interruption.check();
|
||||||
|
guard.deactivate();
|
||||||
}
|
}
|
||||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||||
this_thread::interruption_point();
|
this_thread::interruption_point();
|
||||||
@@ -372,8 +436,6 @@ namespace boost
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#if defined BOOST_THREAD_USES_DATETIME
|
#if defined BOOST_THREAD_USES_DATETIME
|
||||||
#include <boost/thread/xtime.hpp>
|
#include <boost/thread/xtime.hpp>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef BOOST_THREAD_USES_CHRONO
|
#ifdef BOOST_THREAD_USES_CHRONO
|
||||||
#include <boost/chrono/system_clocks.hpp>
|
#include <boost/chrono/system_clocks.hpp>
|
||||||
#include <boost/chrono/ceil.hpp>
|
#include <boost/chrono/ceil.hpp>
|
||||||
@@ -28,6 +29,26 @@
|
|||||||
|
|
||||||
namespace boost
|
namespace boost
|
||||||
{
|
{
|
||||||
|
namespace detail {
|
||||||
|
inline int monotonic_pthread_cond_init(pthread_cond_t& cond) {
|
||||||
|
|
||||||
|
#ifdef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
|
||||||
|
pthread_condattr_t attr;
|
||||||
|
int res = pthread_condattr_init(&attr);
|
||||||
|
if (res)
|
||||||
|
{
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
|
||||||
|
res=pthread_cond_init(&cond,&attr);
|
||||||
|
pthread_condattr_destroy(&attr);
|
||||||
|
return res;
|
||||||
|
#else
|
||||||
|
return pthread_cond_init(&cond,NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class condition_variable
|
class condition_variable
|
||||||
{
|
{
|
||||||
@@ -48,27 +69,41 @@ namespace boost
|
|||||||
unique_lock<mutex>& lock,
|
unique_lock<mutex>& lock,
|
||||||
struct timespec const &timeout)
|
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:
|
public:
|
||||||
BOOST_THREAD_NO_COPYABLE(condition_variable)
|
BOOST_THREAD_NO_COPYABLE(condition_variable)
|
||||||
condition_variable()
|
condition_variable()
|
||||||
{
|
{
|
||||||
|
int res;
|
||||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||||
int const res=pthread_mutex_init(&internal_mutex,NULL);
|
res=pthread_mutex_init(&internal_mutex,NULL);
|
||||||
if(res)
|
if(res)
|
||||||
{
|
{
|
||||||
boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread_mutex_init"));
|
boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread_mutex_init"));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
int const res2=pthread_cond_init(&cond,NULL);
|
res = detail::monotonic_pthread_cond_init(cond);
|
||||||
if(res2)
|
if (res)
|
||||||
{
|
{
|
||||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||||
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
|
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
|
||||||
#endif
|
#endif
|
||||||
boost::throw_exception(thread_resource_error(res2, "boost::condition_variable::condition_variable() constructor failed in pthread_cond_init"));
|
boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in detail::monotonic_pthread_cond_init"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
~condition_variable()
|
~condition_variable()
|
||||||
@@ -94,7 +129,6 @@ namespace boost
|
|||||||
while(!pred()) wait(m);
|
while(!pred()) wait(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if defined BOOST_THREAD_USES_DATETIME
|
#if defined BOOST_THREAD_USES_DATETIME
|
||||||
inline bool timed_wait(
|
inline bool timed_wait(
|
||||||
unique_lock<mutex>& m,
|
unique_lock<mutex>& m,
|
||||||
@@ -120,6 +154,15 @@ namespace boost
|
|||||||
unique_lock<mutex>& m,
|
unique_lock<mutex>& m,
|
||||||
duration_type const& wait_duration)
|
duration_type const& wait_duration)
|
||||||
{
|
{
|
||||||
|
if (wait_duration.is_pos_infinity())
|
||||||
|
{
|
||||||
|
wait(m); // or do_wait(m,detail::timeout::sentinel());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (wait_duration.is_special())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return timed_wait(m,get_system_time()+wait_duration);
|
return timed_wait(m,get_system_time()+wait_duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,10 +192,24 @@ namespace boost
|
|||||||
unique_lock<mutex>& m,
|
unique_lock<mutex>& m,
|
||||||
duration_type const& wait_duration,predicate_type pred)
|
duration_type const& wait_duration,predicate_type pred)
|
||||||
{
|
{
|
||||||
|
if (wait_duration.is_pos_infinity())
|
||||||
|
{
|
||||||
|
while (!pred())
|
||||||
|
{
|
||||||
|
wait(m); // or do_wait(m,detail::timeout::sentinel());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (wait_duration.is_special())
|
||||||
|
{
|
||||||
|
return pred();
|
||||||
|
}
|
||||||
return timed_wait(m,get_system_time()+wait_duration,pred);
|
return timed_wait(m,get_system_time()+wait_duration,pred);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
|
||||||
|
|
||||||
#ifdef BOOST_THREAD_USES_CHRONO
|
#ifdef BOOST_THREAD_USES_CHRONO
|
||||||
|
|
||||||
template <class Duration>
|
template <class Duration>
|
||||||
@@ -182,20 +239,6 @@ namespace boost
|
|||||||
return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
|
return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Clock, class Duration, class Predicate>
|
|
||||||
bool
|
|
||||||
wait_until(
|
|
||||||
unique_lock<mutex>& lock,
|
|
||||||
const chrono::time_point<Clock, Duration>& t,
|
|
||||||
Predicate pred)
|
|
||||||
{
|
|
||||||
while (!pred())
|
|
||||||
{
|
|
||||||
if (wait_until(lock, t) == cv_status::timeout)
|
|
||||||
return pred();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <class Rep, class Period>
|
template <class Rep, class Period>
|
||||||
@@ -213,6 +256,90 @@ namespace boost
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline cv_status wait_until(
|
||||||
|
unique_lock<mutex>& lk,
|
||||||
|
chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp)
|
||||||
|
{
|
||||||
|
using namespace chrono;
|
||||||
|
nanoseconds d = tp.time_since_epoch();
|
||||||
|
timespec ts = boost::detail::to_timespec(d);
|
||||||
|
if (do_wait_until(lk, ts)) return cv_status::no_timeout;
|
||||||
|
else return cv_status::timeout;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
|
||||||
|
#ifdef BOOST_THREAD_USES_CHRONO
|
||||||
|
|
||||||
|
template <class Duration>
|
||||||
|
cv_status
|
||||||
|
wait_until(
|
||||||
|
unique_lock<mutex>& lock,
|
||||||
|
const chrono::time_point<chrono::steady_clock, Duration>& t)
|
||||||
|
{
|
||||||
|
using namespace chrono;
|
||||||
|
typedef time_point<steady_clock, nanoseconds> nano_sys_tmpt;
|
||||||
|
wait_until(lock,
|
||||||
|
nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
|
||||||
|
return steady_clock::now() < t ? cv_status::no_timeout :
|
||||||
|
cv_status::timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Clock, class Duration>
|
||||||
|
cv_status
|
||||||
|
wait_until(
|
||||||
|
unique_lock<mutex>& lock,
|
||||||
|
const chrono::time_point<Clock, Duration>& t)
|
||||||
|
{
|
||||||
|
using namespace chrono;
|
||||||
|
steady_clock::time_point s_now = steady_clock::now();
|
||||||
|
typename Clock::time_point c_now = Clock::now();
|
||||||
|
wait_until(lock, s_now + ceil<nanoseconds>(t - c_now));
|
||||||
|
return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Rep, class Period>
|
||||||
|
cv_status
|
||||||
|
wait_for(
|
||||||
|
unique_lock<mutex>& lock,
|
||||||
|
const chrono::duration<Rep, Period>& d)
|
||||||
|
{
|
||||||
|
using namespace chrono;
|
||||||
|
steady_clock::time_point c_now = steady_clock::now();
|
||||||
|
wait_until(lock, c_now + ceil<nanoseconds>(d));
|
||||||
|
return steady_clock::now() - c_now < d ? cv_status::no_timeout :
|
||||||
|
cv_status::timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline cv_status wait_until(
|
||||||
|
unique_lock<mutex>& lk,
|
||||||
|
chrono::time_point<chrono::steady_clock, chrono::nanoseconds> tp)
|
||||||
|
{
|
||||||
|
using namespace chrono;
|
||||||
|
nanoseconds d = tp.time_since_epoch();
|
||||||
|
timespec ts = boost::detail::to_timespec(d);
|
||||||
|
if (do_wait_until(lk, ts)) return cv_status::no_timeout;
|
||||||
|
else return cv_status::timeout;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
|
||||||
|
|
||||||
|
#ifdef BOOST_THREAD_USES_CHRONO
|
||||||
|
template <class Clock, class Duration, class Predicate>
|
||||||
|
bool
|
||||||
|
wait_until(
|
||||||
|
unique_lock<mutex>& lock,
|
||||||
|
const chrono::time_point<Clock, Duration>& t,
|
||||||
|
Predicate pred)
|
||||||
|
{
|
||||||
|
while (!pred())
|
||||||
|
{
|
||||||
|
if (wait_until(lock, t) == cv_status::timeout)
|
||||||
|
return pred();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
template <class Rep, class Period, class Predicate>
|
template <class Rep, class Period, class Predicate>
|
||||||
bool
|
bool
|
||||||
@@ -222,13 +349,6 @@ namespace boost
|
|||||||
Predicate pred)
|
Predicate pred)
|
||||||
{
|
{
|
||||||
return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
|
return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
|
||||||
|
|
||||||
// while (!pred())
|
|
||||||
// {
|
|
||||||
// if (wait_for(lock, d) == cv_status::timeout)
|
|
||||||
// return pred();
|
|
||||||
// }
|
|
||||||
// return true;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -242,18 +362,7 @@ namespace boost
|
|||||||
void notify_one() BOOST_NOEXCEPT;
|
void notify_one() BOOST_NOEXCEPT;
|
||||||
void notify_all() BOOST_NOEXCEPT;
|
void notify_all() BOOST_NOEXCEPT;
|
||||||
|
|
||||||
#ifdef BOOST_THREAD_USES_CHRONO
|
|
||||||
inline cv_status wait_until(
|
|
||||||
unique_lock<mutex>& lk,
|
|
||||||
chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp)
|
|
||||||
{
|
|
||||||
using namespace chrono;
|
|
||||||
nanoseconds d = tp.time_since_epoch();
|
|
||||||
timespec ts = boost::detail::to_timespec(d);
|
|
||||||
if (do_wait_until(lk, ts)) return cv_status::no_timeout;
|
|
||||||
else return cv_status::timeout;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
|
BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
#ifndef BOOST_THREAD_PTHREAD_MUTEX_HPP
|
#ifndef BOOST_THREAD_PTHREAD_MUTEX_HPP
|
||||||
#define BOOST_THREAD_PTHREAD_MUTEX_HPP
|
#define BOOST_THREAD_PTHREAD_MUTEX_HPP
|
||||||
// (C) Copyright 2007-8 Anthony Williams
|
// (C) Copyright 2007-8 Anthony Williams
|
||||||
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
|
// (C) Copyright 2011,2012,2015 Vicente J. Botet Escriba
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See
|
// Distributed under the Boost Software License, Version 1.0. (See
|
||||||
// accompanying file LICENSE_1_0.txt or copy at
|
// accompanying file LICENSE_1_0.txt or copy at
|
||||||
// http://www.boost.org/LICENSE_1_0.txt)
|
// http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
#include <boost/thread/detail/config.hpp>
|
#include <boost/thread/detail/config.hpp>
|
||||||
|
#include <boost/assert.hpp>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <boost/throw_exception.hpp>
|
#include <boost/throw_exception.hpp>
|
||||||
#include <boost/core/ignore_unused.hpp>
|
#include <boost/core/ignore_unused.hpp>
|
||||||
@@ -26,13 +27,12 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <boost/thread/detail/delete.hpp>
|
#include <boost/thread/detail/delete.hpp>
|
||||||
|
|
||||||
#ifdef _POSIX_TIMEOUTS
|
#if (defined(_POSIX_TIMEOUTS) && (_POSIX_TIMEOUTS-0)>=200112L) \
|
||||||
#if _POSIX_TIMEOUTS >= 0 && _POSIX_TIMEOUTS>=200112L
|
|| (defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__ >= 21)
|
||||||
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
|
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||||
#define BOOST_PTHREAD_HAS_TIMEDLOCK
|
#define BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#include <boost/config/abi_prefix.hpp>
|
#include <boost/config/abi_prefix.hpp>
|
||||||
@@ -123,10 +123,12 @@ namespace boost
|
|||||||
void unlock()
|
void unlock()
|
||||||
{
|
{
|
||||||
int res = posix::pthread_mutex_unlock(&m);
|
int res = posix::pthread_mutex_unlock(&m);
|
||||||
if (res)
|
(void)res;
|
||||||
{
|
BOOST_ASSERT(res == 0);
|
||||||
boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock"));
|
// if (res)
|
||||||
}
|
// {
|
||||||
|
// boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock"));
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
bool try_lock()
|
bool try_lock()
|
||||||
@@ -219,10 +221,12 @@ namespace boost
|
|||||||
void unlock()
|
void unlock()
|
||||||
{
|
{
|
||||||
int res = posix::pthread_mutex_unlock(&m);
|
int res = posix::pthread_mutex_unlock(&m);
|
||||||
if (res)
|
(void)res;
|
||||||
{
|
BOOST_ASSERT(res == 0);
|
||||||
boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock"));
|
// if (res)
|
||||||
}
|
// {
|
||||||
|
// boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock"));
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
bool try_lock()
|
bool try_lock()
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ namespace boost
|
|||||||
thread_detail::commit_once_region(flag);
|
thread_detail::commit_once_region(flag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if !(defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5130))
|
||||||
template<typename Function>
|
template<typename Function>
|
||||||
inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f)
|
inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f)
|
||||||
{
|
{
|
||||||
@@ -302,7 +302,7 @@ namespace boost
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // __SUNPRO_CC
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#ifndef BOOST_PTHREAD_MUTEX_SCOPED_LOCK_HPP
|
#ifndef BOOST_PTHREAD_MUTEX_SCOPED_LOCK_HPP
|
||||||
#define 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
|
// Distributed under the Boost Software License, Version 1.0. (See
|
||||||
// accompanying file LICENSE_1_0.txt or copy at
|
// accompanying file LICENSE_1_0.txt or copy at
|
||||||
@@ -20,41 +20,47 @@ namespace boost
|
|||||||
pthread_mutex_t* m;
|
pthread_mutex_t* m;
|
||||||
bool locked;
|
bool locked;
|
||||||
public:
|
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)
|
m(m_),locked(true)
|
||||||
{
|
{
|
||||||
BOOST_VERIFY(!pthread_mutex_lock(m));
|
BOOST_VERIFY(!pthread_mutex_lock(m));
|
||||||
}
|
}
|
||||||
void unlock()
|
void unlock() BOOST_NOEXCEPT
|
||||||
{
|
{
|
||||||
BOOST_VERIFY(!pthread_mutex_unlock(m));
|
BOOST_VERIFY(!pthread_mutex_unlock(m));
|
||||||
locked=false;
|
locked=false;
|
||||||
}
|
}
|
||||||
|
void check() BOOST_NOEXCEPT
|
||||||
~pthread_mutex_scoped_lock()
|
{
|
||||||
|
if(locked)
|
||||||
|
{
|
||||||
|
unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
~pthread_mutex_scoped_lock() BOOST_NOEXCEPT
|
||||||
{
|
{
|
||||||
if(locked)
|
if(locked)
|
||||||
{
|
{
|
||||||
unlock();
|
unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class pthread_mutex_scoped_unlock
|
class pthread_mutex_scoped_unlock
|
||||||
{
|
{
|
||||||
pthread_mutex_t* m;
|
pthread_mutex_t* m;
|
||||||
public:
|
public:
|
||||||
explicit pthread_mutex_scoped_unlock(pthread_mutex_t* m_):
|
explicit pthread_mutex_scoped_unlock(pthread_mutex_t* m_) BOOST_NOEXCEPT:
|
||||||
m(m_)
|
m(m_)
|
||||||
{
|
{
|
||||||
BOOST_VERIFY(!pthread_mutex_unlock(m));
|
BOOST_VERIFY(!pthread_mutex_unlock(m));
|
||||||
}
|
}
|
||||||
~pthread_mutex_scoped_unlock()
|
~pthread_mutex_scoped_unlock() BOOST_NOEXCEPT
|
||||||
{
|
{
|
||||||
BOOST_VERIFY(!pthread_mutex_lock(m));
|
BOOST_VERIFY(!pthread_mutex_lock(m));
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,16 +27,19 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <boost/thread/detail/delete.hpp>
|
#include <boost/thread/detail/delete.hpp>
|
||||||
|
|
||||||
#ifdef _POSIX_TIMEOUTS
|
#if (defined _POSIX_TIMEOUTS && (_POSIX_TIMEOUTS-0)>=200112L) \
|
||||||
#if _POSIX_TIMEOUTS >= 0 && _POSIX_TIMEOUTS>=200112L
|
|| (defined __ANDROID__ && defined __ANDROID_API__ && __ANDROID_API__ >= 21)
|
||||||
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
|
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||||
#define BOOST_PTHREAD_HAS_TIMEDLOCK
|
#define BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE \
|
||||||
|
|| defined __ANDROID__
|
||||||
|
#define BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE && defined BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||||
#if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) && defined(BOOST_PTHREAD_HAS_TIMEDLOCK)
|
|
||||||
#define BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
|
#define BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -48,7 +51,7 @@ namespace boost
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
pthread_mutex_t m;
|
pthread_mutex_t m;
|
||||||
#ifndef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
|
#ifndef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
|
||||||
pthread_cond_t cond;
|
pthread_cond_t cond;
|
||||||
bool is_locked;
|
bool is_locked;
|
||||||
pthread_t owner;
|
pthread_t owner;
|
||||||
@@ -58,7 +61,7 @@ namespace boost
|
|||||||
BOOST_THREAD_NO_COPYABLE(recursive_mutex)
|
BOOST_THREAD_NO_COPYABLE(recursive_mutex)
|
||||||
recursive_mutex()
|
recursive_mutex()
|
||||||
{
|
{
|
||||||
#ifdef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
|
#ifdef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
|
||||||
pthread_mutexattr_t attr;
|
pthread_mutexattr_t attr;
|
||||||
|
|
||||||
int const init_attr_res=pthread_mutexattr_init(&attr);
|
int const init_attr_res=pthread_mutexattr_init(&attr);
|
||||||
@@ -99,12 +102,12 @@ namespace boost
|
|||||||
~recursive_mutex()
|
~recursive_mutex()
|
||||||
{
|
{
|
||||||
BOOST_VERIFY(!pthread_mutex_destroy(&m));
|
BOOST_VERIFY(!pthread_mutex_destroy(&m));
|
||||||
#ifndef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
|
#ifndef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
|
||||||
BOOST_VERIFY(!pthread_cond_destroy(&cond));
|
BOOST_VERIFY(!pthread_cond_destroy(&cond));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
|
#ifdef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
|
||||||
void lock()
|
void lock()
|
||||||
{
|
{
|
||||||
BOOST_VERIFY(!pthread_mutex_lock(&m));
|
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.
|
// avoid other threads to lock, lock_upgrade or lock_shared, so only this thread is notified.
|
||||||
state.upgrade=false;
|
state.upgrade=false;
|
||||||
state.exclusive=true;
|
state.exclusive=true;
|
||||||
lk.unlock();
|
//lk.unlock();
|
||||||
upgrade_cond.notify_one();
|
upgrade_cond.notify_one();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
state.exclusive_waiting_blocked=false;
|
state.exclusive_waiting_blocked=false;
|
||||||
lk.unlock();
|
//lk.unlock();
|
||||||
}
|
}
|
||||||
release_waiters();
|
release_waiters();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,8 +115,13 @@ namespace boost
|
|||||||
boost::detail::thread_exit_callback_node* thread_exit_callbacks;
|
boost::detail::thread_exit_callback_node* thread_exit_callbacks;
|
||||||
std::map<void const*,boost::detail::tss_data_node> tss_data;
|
std::map<void const*,boost::detail::tss_data_node> tss_data;
|
||||||
|
|
||||||
|
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||||
|
// These data must be at the end so that the access to the other fields doesn't change
|
||||||
|
// when BOOST_THREAD_PROVIDES_INTERRUPTIONS is defined.
|
||||||
|
// Another option is to have them always
|
||||||
pthread_mutex_t* cond_mutex;
|
pthread_mutex_t* cond_mutex;
|
||||||
pthread_cond_t* current_cond;
|
pthread_cond_t* current_cond;
|
||||||
|
//#endif
|
||||||
typedef std::vector<std::pair<condition_variable*, mutex*>
|
typedef std::vector<std::pair<condition_variable*, mutex*>
|
||||||
//, hidden_allocator<std::pair<condition_variable*, mutex*> >
|
//, hidden_allocator<std::pair<condition_variable*, mutex*> >
|
||||||
> notify_list_t;
|
> notify_list_t;
|
||||||
@@ -136,8 +141,10 @@ namespace boost
|
|||||||
thread_handle(0),
|
thread_handle(0),
|
||||||
done(false),join_started(false),joined(false),
|
done(false),join_started(false),joined(false),
|
||||||
thread_exit_callbacks(0),
|
thread_exit_callbacks(0),
|
||||||
|
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||||
cond_mutex(0),
|
cond_mutex(0),
|
||||||
current_cond(0),
|
current_cond(0),
|
||||||
|
//#endif
|
||||||
notify(),
|
notify(),
|
||||||
async_states_()
|
async_states_()
|
||||||
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||||
@@ -170,6 +177,7 @@ namespace boost
|
|||||||
thread_data_base* const thread_info;
|
thread_data_base* const thread_info;
|
||||||
pthread_mutex_t* m;
|
pthread_mutex_t* m;
|
||||||
bool set;
|
bool set;
|
||||||
|
bool done;
|
||||||
|
|
||||||
void check_for_interruption()
|
void check_for_interruption()
|
||||||
{
|
{
|
||||||
@@ -186,7 +194,7 @@ namespace boost
|
|||||||
public:
|
public:
|
||||||
explicit interruption_checker(pthread_mutex_t* cond_mutex,pthread_cond_t* cond):
|
explicit interruption_checker(pthread_mutex_t* cond_mutex,pthread_cond_t* cond):
|
||||||
thread_info(detail::get_current_thread_data()),m(cond_mutex),
|
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)
|
if(set)
|
||||||
{
|
{
|
||||||
@@ -201,9 +209,10 @@ namespace boost
|
|||||||
BOOST_VERIFY(!pthread_mutex_lock(m));
|
BOOST_VERIFY(!pthread_mutex_lock(m));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
~interruption_checker()
|
void check()
|
||||||
{
|
{
|
||||||
if(set)
|
if ( ! done) {
|
||||||
|
if (set)
|
||||||
{
|
{
|
||||||
BOOST_VERIFY(!pthread_mutex_unlock(m));
|
BOOST_VERIFY(!pthread_mutex_unlock(m));
|
||||||
lock_guard<mutex> guard(thread_info->data_mutex);
|
lock_guard<mutex> guard(thread_info->data_mutex);
|
||||||
@@ -214,6 +223,13 @@ namespace boost
|
|||||||
{
|
{
|
||||||
BOOST_VERIFY(!pthread_mutex_unlock(m));
|
BOOST_VERIFY(!pthread_mutex_unlock(m));
|
||||||
}
|
}
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~interruption_checker() BOOST_NOEXCEPT_IF(false)
|
||||||
|
{
|
||||||
|
check();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
@@ -221,7 +237,7 @@ namespace boost
|
|||||||
|
|
||||||
namespace this_thread
|
namespace this_thread
|
||||||
{
|
{
|
||||||
namespace hiden
|
namespace hidden
|
||||||
{
|
{
|
||||||
void BOOST_THREAD_DECL sleep_for(const timespec& ts);
|
void BOOST_THREAD_DECL sleep_for(const timespec& ts);
|
||||||
void BOOST_THREAD_DECL sleep_until(const timespec& ts);
|
void BOOST_THREAD_DECL sleep_until(const timespec& ts);
|
||||||
@@ -233,14 +249,14 @@ namespace boost
|
|||||||
inline
|
inline
|
||||||
void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns)
|
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
|
||||||
#endif // BOOST_THREAD_USES_CHRONO
|
#endif // BOOST_THREAD_USES_CHRONO
|
||||||
|
|
||||||
namespace no_interruption_point
|
namespace no_interruption_point
|
||||||
{
|
{
|
||||||
namespace hiden
|
namespace hidden
|
||||||
{
|
{
|
||||||
void BOOST_THREAD_DECL sleep_for(const timespec& ts);
|
void BOOST_THREAD_DECL sleep_for(const timespec& ts);
|
||||||
void BOOST_THREAD_DECL sleep_until(const timespec& ts);
|
void BOOST_THREAD_DECL sleep_until(const timespec& ts);
|
||||||
@@ -252,7 +268,7 @@ namespace boost
|
|||||||
inline
|
inline
|
||||||
void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns)
|
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
|
||||||
#endif // BOOST_THREAD_USES_CHRONO
|
#endif // BOOST_THREAD_USES_CHRONO
|
||||||
@@ -268,7 +284,7 @@ namespace boost
|
|||||||
#endif
|
#endif
|
||||||
inline void sleep(system_time const& abs_time)
|
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>
|
template<typename TimeDuration>
|
||||||
|
|||||||
@@ -75,6 +75,33 @@ namespace boost
|
|||||||
{
|
{
|
||||||
timespec ts;
|
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)
|
#if defined(BOOST_THREAD_TIMESPEC_MAC_API)
|
||||||
timeval tv;
|
timeval tv;
|
||||||
::gettimeofday(&tv, 0);
|
::gettimeofday(&tv, 0);
|
||||||
@@ -83,6 +110,8 @@ namespace boost
|
|||||||
#else
|
#else
|
||||||
if ( ::clock_gettime( CLOCK_REALTIME, &ts ) )
|
if ( ::clock_gettime( CLOCK_REALTIME, &ts ) )
|
||||||
{
|
{
|
||||||
|
ts.tv_sec = 0;
|
||||||
|
ts.tv_nsec = 0;
|
||||||
BOOST_ASSERT(0 && "Boost::Thread - Internal Error");
|
BOOST_ASSERT(0 && "Boost::Thread - Internal Error");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -34,10 +34,10 @@ namespace boost
|
|||||||
* boost::strict_scoped_thread<> t((boost::thread(F)));
|
* 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
|
class strict_scoped_thread
|
||||||
{
|
{
|
||||||
thread t_;
|
Thread t_;
|
||||||
struct dummy;
|
struct dummy;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -47,13 +47,13 @@ namespace boost
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
#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) :
|
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)...) {}
|
t_(boost::forward<F>(f), boost::forward<Args>(args)...) {}
|
||||||
#else
|
#else
|
||||||
template <class F>
|
template <class F>
|
||||||
explicit strict_scoped_thread(BOOST_THREAD_FWD_REF(F) 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)) {}
|
t_(boost::forward<F>(f)) {}
|
||||||
template <class F, class A1>
|
template <class F, class A1>
|
||||||
strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) 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.
|
* 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))
|
t_(boost::move(t))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -111,14 +111,15 @@ namespace boost
|
|||||||
* t.interrupt();
|
* t.interrupt();
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
template <class CallableThread = join_if_joinable>
|
template <class CallableThread = join_if_joinable, class Thread=::boost::thread>
|
||||||
class scoped_thread
|
class scoped_thread
|
||||||
{
|
{
|
||||||
thread t_;
|
Thread t_;
|
||||||
struct dummy;
|
struct dummy;
|
||||||
public:
|
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
|
BOOST_THREAD_MOVABLE_ONLY( scoped_thread) /// Movable only
|
||||||
|
|
||||||
@@ -137,13 +138,13 @@ namespace boost
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
#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) :
|
explicit scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Args)... args) :
|
||||||
t_(boost::forward<F>(f), boost::forward<Args>(args)...) {}
|
t_(boost::forward<F>(f), boost::forward<Args>(args)...) {}
|
||||||
#else
|
#else
|
||||||
template <class F>
|
template <class F>
|
||||||
explicit scoped_thread(BOOST_THREAD_FWD_REF(F) 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)) {}
|
t_(boost::forward<F>(f)) {}
|
||||||
template <class F, class A1>
|
template <class F, class A1>
|
||||||
scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) 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.
|
* 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))
|
t_(boost::move(t))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// explicit operator thread()
|
// explicit operator Thread()
|
||||||
// {
|
// {
|
||||||
// return boost::move(t_);
|
// return boost::move(t_);
|
||||||
// }
|
// }
|
||||||
@@ -197,6 +198,9 @@ namespace boost
|
|||||||
*/
|
*/
|
||||||
scoped_thread& operator=(BOOST_RV_REF(scoped_thread) x)
|
scoped_thread& operator=(BOOST_RV_REF(scoped_thread) x)
|
||||||
{
|
{
|
||||||
|
CallableThread on_destructor;
|
||||||
|
|
||||||
|
on_destructor(t_);
|
||||||
t_ = boost::move(BOOST_THREAD_RV(x).t_);
|
t_ = boost::move(BOOST_THREAD_RV(x).t_);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -210,7 +214,7 @@ namespace boost
|
|||||||
}
|
}
|
||||||
|
|
||||||
// forwarded thread functions
|
// forwarded thread functions
|
||||||
inline thread::id get_id() const BOOST_NOEXCEPT
|
inline id get_id() const BOOST_NOEXCEPT
|
||||||
{
|
{
|
||||||
return t_.get_id();
|
return t_.get_id();
|
||||||
}
|
}
|
||||||
@@ -239,7 +243,7 @@ namespace boost
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
thread::native_handle_type native_handle()BOOST_NOEXCEPT
|
native_handle_type native_handle()BOOST_NOEXCEPT
|
||||||
{
|
{
|
||||||
return t_.native_handle();
|
return t_.native_handle();
|
||||||
}
|
}
|
||||||
@@ -263,13 +267,13 @@ namespace boost
|
|||||||
|
|
||||||
static unsigned hardware_concurrency() BOOST_NOEXCEPT
|
static unsigned hardware_concurrency() BOOST_NOEXCEPT
|
||||||
{
|
{
|
||||||
return thread::hardware_concurrency();
|
return Thread::hardware_concurrency();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef BOOST_THREAD_PROVIDES_PHYSICAL_CONCURRENCY
|
#ifdef BOOST_THREAD_PROVIDES_PHYSICAL_CONCURRENCY
|
||||||
static unsigned physical_concurrency() BOOST_NOEXCEPT
|
static unsigned physical_concurrency() BOOST_NOEXCEPT
|
||||||
{
|
{
|
||||||
return thread::physical_concurrency();
|
return Thread::physical_concurrency();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
@@ -277,12 +281,13 @@ namespace boost
|
|||||||
/**
|
/**
|
||||||
* Effects: swaps the contents of two scoped threads.
|
* Effects: swaps the contents of two scoped threads.
|
||||||
*/
|
*/
|
||||||
template <class Destroyer>
|
template <class Destroyer, class Thread >
|
||||||
void swap(scoped_thread<Destroyer>& lhs, scoped_thread<Destroyer>& rhs)
|
void swap(scoped_thread<Destroyer, Thread>& lhs, scoped_thread<Destroyer, Thread>& rhs)
|
||||||
BOOST_NOEXCEPT {
|
BOOST_NOEXCEPT {
|
||||||
return lhs.swap(rhs);
|
return lhs.swap(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef scoped_thread<> joining_thread;
|
||||||
}
|
}
|
||||||
#include <boost/config/abi_suffix.hpp>
|
#include <boost/config/abi_suffix.hpp>
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
namespace boost
|
namespace boost
|
||||||
{
|
{
|
||||||
|
typedef shared_mutex shared_timed_mutex;
|
||||||
namespace sync
|
namespace sync
|
||||||
{
|
{
|
||||||
#ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES
|
#ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES
|
||||||
|
|||||||
@@ -827,7 +827,7 @@ namespace boost
|
|||||||
* @effects loads the value type from the input stream @c is.
|
* @effects loads the value type from the input stream @c is.
|
||||||
*/
|
*/
|
||||||
template <typename IStream>
|
template <typename IStream>
|
||||||
void load(IStream& is) const
|
void load(IStream& is)
|
||||||
{
|
{
|
||||||
strict_lock<mutex_type> lk(mtx_);
|
strict_lock<mutex_type> lk(mtx_);
|
||||||
is >> value_;
|
is >> value_;
|
||||||
@@ -971,22 +971,22 @@ namespace boost
|
|||||||
template <typename T, typename L>
|
template <typename T, typename L>
|
||||||
bool operator<(T const& lhs, synchronized_value<T,L> const&rhs)
|
bool operator<(T const& lhs, synchronized_value<T,L> const&rhs)
|
||||||
{
|
{
|
||||||
return rhs>=lhs;
|
return rhs>lhs;
|
||||||
}
|
}
|
||||||
template <typename T, typename L>
|
template <typename T, typename L>
|
||||||
bool operator<=(T const& lhs, synchronized_value<T,L> const&rhs)
|
bool operator<=(T const& lhs, synchronized_value<T,L> const&rhs)
|
||||||
{
|
{
|
||||||
return rhs>lhs;
|
return rhs>=lhs;
|
||||||
}
|
}
|
||||||
template <typename T, typename L>
|
template <typename T, typename L>
|
||||||
bool operator>(T const& lhs, synchronized_value<T,L> const&rhs)
|
bool operator>(T const& lhs, synchronized_value<T,L> const&rhs)
|
||||||
{
|
{
|
||||||
return rhs<=lhs;
|
return rhs<lhs;
|
||||||
}
|
}
|
||||||
template <typename T, typename L>
|
template <typename T, typename L>
|
||||||
bool operator>=(T const& lhs, synchronized_value<T,L> const&rhs)
|
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;
|
return os;
|
||||||
}
|
}
|
||||||
template <typename IStream, typename T, typename L>
|
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);
|
rhs.load(is);
|
||||||
return is;
|
return is;
|
||||||
|
|||||||
@@ -21,15 +21,29 @@ namespace boost
|
|||||||
|
|
||||||
struct detach
|
struct detach
|
||||||
{
|
{
|
||||||
void operator()(thread& t)
|
template <class Thread>
|
||||||
|
void operator()(Thread& t)
|
||||||
{
|
{
|
||||||
t.detach();
|
t.detach();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct detach_if_joinable
|
||||||
|
{
|
||||||
|
template <class Thread>
|
||||||
|
void operator()(Thread& t)
|
||||||
|
{
|
||||||
|
if (t.joinable())
|
||||||
|
{
|
||||||
|
t.detach();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct join_if_joinable
|
struct join_if_joinable
|
||||||
{
|
{
|
||||||
void operator()(thread& t)
|
template <class Thread>
|
||||||
|
void operator()(Thread& t)
|
||||||
{
|
{
|
||||||
if (t.joinable())
|
if (t.joinable())
|
||||||
{
|
{
|
||||||
@@ -41,11 +55,12 @@ namespace boost
|
|||||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||||
struct interrupt_and_join_if_joinable
|
struct interrupt_and_join_if_joinable
|
||||||
{
|
{
|
||||||
void operator()(thread& t)
|
template <class Thread>
|
||||||
|
void operator()(Thread& t)
|
||||||
{
|
{
|
||||||
t.interrupt();
|
|
||||||
if (t.joinable())
|
if (t.joinable())
|
||||||
{
|
{
|
||||||
|
t.interrupt();
|
||||||
t.join();
|
t.join();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,14 +21,14 @@ namespace boost
|
|||||||
/**
|
/**
|
||||||
* Non-copyable RAII scoped thread guard joiner which join the thread if joinable when destroyed.
|
* 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
|
class thread_guard
|
||||||
{
|
{
|
||||||
thread& t_;
|
Thread& t_;
|
||||||
public:
|
public:
|
||||||
BOOST_THREAD_NO_COPYABLE( thread_guard)
|
BOOST_THREAD_NO_COPYABLE( thread_guard)
|
||||||
|
|
||||||
explicit thread_guard(thread& t) :
|
explicit thread_guard(Thread& t) :
|
||||||
t_(t)
|
t_(t)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
#include <boost/thread/detail/delete.hpp>
|
#include <boost/thread/detail/delete.hpp>
|
||||||
#include <boost/thread/detail/move.hpp>
|
#include <boost/thread/detail/move.hpp>
|
||||||
#include <boost/thread/concurrent_queues/sync_queue.hpp>
|
#include <boost/thread/concurrent_queues/sync_queue.hpp>
|
||||||
#include <boost/thread/detail/work.hpp>
|
#include <boost/thread/executors/work.hpp>
|
||||||
|
|
||||||
#include <boost/config/abi_prefix.hpp>
|
#include <boost/config/abi_prefix.hpp>
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ namespace boost
|
|||||||
class user_scheduler
|
class user_scheduler
|
||||||
{
|
{
|
||||||
/// type-erasure to store the works to do
|
/// type-erasure to store the works to do
|
||||||
typedef thread_detail::work work;
|
typedef executors::work work;
|
||||||
|
|
||||||
/// the thread safe work queue
|
/// the thread safe work queue
|
||||||
sync_queue<work > work_queue;
|
sync_queue<work > work_queue;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user