mirror of
https://github.com/boostorg/thread.git
synced 2026-02-03 09:42:16 +00:00
Compare commits
135 Commits
feature/sc
...
fix/blocki
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec770eeb6a | ||
|
|
b9ab307912 | ||
|
|
1ae96b3820 | ||
|
|
889c178173 | ||
|
|
7ba9591015 | ||
|
|
b07f18facf | ||
|
|
7b1b1b5daa | ||
|
|
63fb28c7d4 | ||
|
|
67e18ff039 | ||
|
|
e715d74a95 | ||
|
|
393d214ac9 | ||
|
|
0fa6038f6a | ||
|
|
cf1182ee99 | ||
|
|
a04497af24 | ||
|
|
821a93ca1a | ||
|
|
e0217424f3 | ||
|
|
cf76bc666c | ||
|
|
d00e39acc7 | ||
|
|
90ba3ae7c6 | ||
|
|
b68702b56d | ||
|
|
3b2322db96 | ||
|
|
6a427ac4b6 | ||
|
|
ffd856073f | ||
|
|
f1fafb117a | ||
|
|
e2cda49b0b | ||
|
|
d1aa2eec56 | ||
|
|
1db0ba4639 | ||
|
|
a4e7eba1d4 | ||
|
|
67778b3278 | ||
|
|
a5e6952a95 | ||
|
|
9cc1357c95 | ||
|
|
b571686e5d | ||
|
|
9c67be287e | ||
|
|
f599783444 | ||
|
|
d628b8d36c | ||
|
|
65c519c22c | ||
|
|
05e492c56c | ||
|
|
3c2321c37a | ||
|
|
6c72a2527f | ||
|
|
1bd09085db | ||
|
|
d6c3f15947 | ||
|
|
5960985355 | ||
|
|
84e2b7869d | ||
|
|
401f69f108 | ||
|
|
4f57e3fb61 | ||
|
|
fdf20f1adc | ||
|
|
990474ff47 | ||
|
|
786d842ad1 | ||
|
|
441c89d304 | ||
|
|
63098e84a2 | ||
|
|
71997bd9aa | ||
|
|
45510facc7 | ||
|
|
cf539064d6 | ||
|
|
3431736c88 | ||
|
|
095b53b2a2 | ||
|
|
7a63c40a01 | ||
|
|
c1148a66cc | ||
|
|
5fa0a5d4c5 | ||
|
|
75a8280701 | ||
|
|
2891aff469 | ||
|
|
e74fd82060 | ||
|
|
c16ec42941 | ||
|
|
b77eac3e37 | ||
|
|
5a141ccf99 | ||
|
|
35d7ae0d2e | ||
|
|
d9c7f95617 | ||
|
|
06b3f6a9d7 | ||
|
|
895b4a0ac5 | ||
|
|
eb14d3d958 | ||
|
|
9cb72849ee | ||
|
|
2c028aa014 | ||
|
|
ab026e239c | ||
|
|
3a48148462 | ||
|
|
9b9590730f | ||
|
|
8edc37930b | ||
|
|
ef48908f35 | ||
|
|
28ead512c1 | ||
|
|
6b60943f3e | ||
|
|
1fcaa47efa | ||
|
|
aac441392a | ||
|
|
6a34fc9c33 | ||
|
|
69d01b9bfd | ||
|
|
7b91ce7b64 | ||
|
|
978884ff0d | ||
|
|
ac8ca6eb04 | ||
|
|
1c16c52fe6 | ||
|
|
9299d26acf | ||
|
|
5577128bd8 | ||
|
|
e62c576944 | ||
|
|
ce8049f83f | ||
|
|
035217985c | ||
|
|
dfe95b3f2c | ||
|
|
e98447f974 | ||
|
|
deffa9aaf7 | ||
|
|
b87d26a900 | ||
|
|
6c9115fe39 | ||
|
|
b5b25eab1c | ||
|
|
803ba458ce | ||
|
|
c0470893d4 | ||
|
|
b2c445a030 | ||
|
|
6e37c55221 | ||
|
|
e1039e61f3 | ||
|
|
063b59e511 | ||
|
|
a342d1ccee | ||
|
|
811f3df98d | ||
|
|
8e1be55c6d | ||
|
|
421469686d | ||
|
|
72dfa02269 | ||
|
|
4c48b2276c | ||
|
|
8c7275cb9e | ||
|
|
14c5cff2ee | ||
|
|
83f38ea52c | ||
|
|
06a9f9ab6d | ||
|
|
e7f140cab6 | ||
|
|
1b99fe5587 | ||
|
|
b9a70f7aca | ||
|
|
ca87cbf57b | ||
|
|
929dc55a5a | ||
|
|
b29d9f850c | ||
|
|
1c81d8a4b1 | ||
|
|
7de29f4d45 | ||
|
|
9b0705cb6f | ||
|
|
3abdb869df | ||
|
|
f90e76a59c | ||
|
|
d4c8185cc9 | ||
|
|
e6501b5485 | ||
|
|
1ae3cb65f7 | ||
|
|
a8ad389bdd | ||
|
|
69c1d40750 | ||
|
|
c3b98129e4 | ||
|
|
3891eeef52 | ||
|
|
f1370b1255 | ||
|
|
69f2a1df72 | ||
|
|
700301e382 | ||
|
|
952aa44a98 |
133
README.md
133
README.md
@@ -6,3 +6,136 @@ Portable C++ multi-threading. C++11, C++14.
|
||||
### License
|
||||
|
||||
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>
|
||||
|
||||
@@ -63,6 +63,7 @@ project boost/thread
|
||||
<toolset>gcc:<cxxflags>-Wno-variadic-macros
|
||||
#<toolset>gcc:<cxxflags>-Wunused-local-typedefs
|
||||
<toolset>gcc:<cxxflags>-Wunused-function
|
||||
<toolset>gcc:<cxxflags>-Wno-unused-parameter
|
||||
|
||||
<toolset>darwin:<cxxflags>-Wextra
|
||||
<toolset>darwin:<cxxflags>-pedantic
|
||||
@@ -72,18 +73,20 @@ project boost/thread
|
||||
<toolset>darwin:<cxxflags>-Wno-variadic-macros
|
||||
#<toolset>darwin:<cxxflags>-Wunused-local-typedefs
|
||||
<toolset>darwin:<cxxflags>-Wunused-function
|
||||
<toolset>darwin:<cxxflags>-Wno-unused-parameter
|
||||
|
||||
#<toolset>pathscale:<cxxflags>-Wextra
|
||||
<toolset>pathscale:<cxxflags>-Wno-long-long
|
||||
<toolset>pathscale:<cxxflags>-pedantic
|
||||
|
||||
<toolset>clang:<warnings>on
|
||||
<toolset>clang:<cxxflags>-Wextra
|
||||
#<toolset>clang:<cxxflags>-ansi
|
||||
#<toolset>clang:<cxxflags>-fpermissive
|
||||
<toolset>clang:<cxxflags>-Wno-long-long
|
||||
<toolset>clang:<cxxflags>-Wunused-function
|
||||
<toolset>clang:<cxxflags>-Wno-variadic-macros
|
||||
<toolset>clang:<warnings>on
|
||||
<toolset>clang:<cxxflags>-Wno-unused-parameter
|
||||
|
||||
#<toolset>gcc-mingw-4.4.0:<cxxflags>-fdiagnostics-show-option
|
||||
#<toolset>gcc-mingw-4.5.0:<cxxflags>-fdiagnostics-show-option
|
||||
@@ -116,7 +119,9 @@ project boost/thread
|
||||
<toolset>intel:<cxxflags>-wd1418
|
||||
<toolset>intel:<cxxflags>-wd2415
|
||||
|
||||
<toolset>msvc:<cxxflags>/wd4100
|
||||
<toolset>msvc:<cxxflags>/wd4512
|
||||
<toolset>msvc:<cxxflags>/wd6246
|
||||
|
||||
|
||||
# : default-build <threading>multi
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
[warning These features are 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 :(]
|
||||
|
||||
[note These features are based on the [@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3785.pdf [*N3785 - Executors and Schedulers revision 3]] C++1y proposal from Chris Mysen, Niklas Gustafsson, Matt Austern, Jeffrey Yasskin. The text that follows has been adapted from tis paper to show the differences.]
|
||||
[note These features are based on the [@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3785.pdf [*N3785 - Executors and Schedulers revision 3]] C++1y proposal from Chris Mysen, Niklas Gustafsson, Matt Austern, Jeffrey Yasskin. The text that follows has been adapted from this paper to show the differences.]
|
||||
|
||||
Executors are objects that can execute units of work packaged as function objects. Boost.Thread differs from N3785 mainly in the an Executor doesn't needs to inherit from an abstract class Executor. Static polymorphism is used instead and type erasure is used internally.
|
||||
|
||||
@@ -142,6 +142,7 @@ The third one is related to performance. They assert that "any mechanism for sto
|
||||
|
||||
In addition `std::function<void()>` can not be constructed by moving the closure, so e.g. `std::packaged_task` could not be a Closure.
|
||||
|
||||
[/
|
||||
[heading Scheduled work]
|
||||
|
||||
The approach of this library respect to scheduled work of the N3785 proposal is quite different. Instead of adding the scheduled operations to a specific scheduled_executor polymorphic interface, we opt by adding two member template functions to a class scheduled_executor that wraps an existing executor. This has several advantages:
|
||||
@@ -155,6 +156,25 @@ In order to manage with all the clocks, there are two alternatives:
|
||||
* have a single instance of a `scheduled_executor<Clock>` for each `CLock`.
|
||||
|
||||
The library chose the first of those options, largely for simplicity.
|
||||
]
|
||||
|
||||
[heading Scheduled work]
|
||||
|
||||
The approach of this library respect to scheduled work of the N3785 proposal is quite different. Instead of adding the scheduled operations to a specific scheduled_executor polymorphic interface, we opt by adding a specific `scheduler` class that is not an executor and knows how to manage with the scheduling of timed tasks `submit_at`/`submit_after`.
|
||||
|
||||
|
||||
`scheduler` provides executor factories `at`/`after` given a specific `time_point` or a `duration`. The built executors wrap a reference to this scheduler and the time at which the submitted task will be executed.
|
||||
|
||||
If we want to schedule these operations on an existing executor (as `serial_executor` does), these classes provide a `on` factory taking another executor as parameter and wraps both instance on the returned executor.
|
||||
|
||||
sch.on(tp).after(seconds(i)).submit(boost::bind(fn,i));
|
||||
|
||||
This has several advantages:
|
||||
|
||||
* The scheduled operations are available for all the executors via wrappers.
|
||||
* The template functions could accept any chrono `time_point` and `duration` respectively as we are not working with virtual functions.
|
||||
|
||||
In order to manage with all the clocks, this library propose generic solution. `scheduler<Clock>` know how to manage with the `submit_at`/`submit_after` `Clock::time_point`/`Clock::duration` tasks. Note that the durations on different clocks differ.
|
||||
|
||||
[heading Not Handled Exceptions]
|
||||
As in N3785 and based on the same design decision than `std`/`boost::thread` if a user closure throws an exception, the executor must call the `std::terminate` function.
|
||||
@@ -401,7 +421,7 @@ If invoked closure throws an exception the executor will call std::terminate, as
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [close the executor `e` for submissions.]]
|
||||
[[Effects:] [close the scheduler/executor `e` for submissions.]]
|
||||
|
||||
[[Remark:] [The worker threads will work until there is no more closures to run.]]
|
||||
|
||||
@@ -421,7 +441,7 @@ If invoked closure throws an exception the executor will call std::terminate, as
|
||||
|
||||
[[Return type:] [`bool`.]]
|
||||
|
||||
[[Return:] [whether the pool is closed for submissions.]]
|
||||
[[Return:] [whether the scheduler/executor is closed for submissions.]]
|
||||
|
||||
[[Throws:] [Whatever exception that can be throw while ensuring the thread safety.]]
|
||||
|
||||
@@ -659,8 +679,532 @@ Executor abstract base class.
|
||||
|
||||
[endsect]
|
||||
|
||||
[//////////////////////////////////////////////////////////]
|
||||
[section: scheduler Template Class `scheduler `]
|
||||
|
||||
Scheduler providing time related functions. Note that `scheduler` is not an Executor.
|
||||
|
||||
#include <boost/thread/executors/scheduler.hpp>
|
||||
namespace boost {
|
||||
|
||||
template <class Clock=steady_clock>
|
||||
class scheduler
|
||||
{
|
||||
public:
|
||||
using work = boost::function<void()> ;
|
||||
using clock = Clock;
|
||||
|
||||
scheduler(scheduler const&) = delete;
|
||||
scheduler& operator=(scheduler const&) = delete;
|
||||
|
||||
scheduler();
|
||||
~scheduler();
|
||||
|
||||
void close();
|
||||
bool closed();
|
||||
|
||||
template <class Duration, typename Closure>
|
||||
void submit_at(chrono::time_point<clock,Duration> abs_time, Closure&& closure);
|
||||
template <class Rep, class Period, typename Closure>
|
||||
void submit_after(chrono::duration<Rep,Period> rel_time, Closure&& closure);
|
||||
|
||||
template <class Duration>
|
||||
at_executor<scheduler> submit_at(chrono::time_point<clock,Duration> abs_time);
|
||||
template <class Rep, class Period>
|
||||
at_executor<scheduler> submit_after(chrono::duration<Rep,Period> rel_time);
|
||||
|
||||
template <class Executor>
|
||||
scheduler_executor_wrapper<scheduler, Executor> on(Executor& ex);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
[/////////////////////////////////////]
|
||||
[section:constructor Constructor `scheduler()`]
|
||||
|
||||
scheduler();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Constructs a `scheduler`. ]]
|
||||
|
||||
[[Throws:] [Nothing. ]]
|
||||
|
||||
]
|
||||
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:destructor Destructor `~scheduler()`]
|
||||
|
||||
~scheduler();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Destroys the scheduler.]]
|
||||
|
||||
[[Synchronization:] [The completion of all the closures happen before the completion of the executor destructor.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:submit_at Template Function Member `submit_at()`]
|
||||
|
||||
template <class Clock, class Duration, typename Closure>
|
||||
void submit_at(chrono::time_point<Clock,Duration> abs_time, Closure&& closure);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Schedule a `closure` to be executed at `abs_time`. ]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:submit_after Template Function Member `submit_after()`]
|
||||
|
||||
template <class Rep, class Period, typename Closure>
|
||||
void submit_after(chrono::duration<Rep,Period> rel_time, Closure&& closure);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Schedule a `closure` to be executed after `rel_time`. ]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
||||
|
||||
[//////////////////////////////////////////////////////////]
|
||||
[section:at_executor Template Class `at_executor`]
|
||||
|
||||
|
||||
#include <boost/thread/executors/scheduler.hpp>
|
||||
namespace boost {
|
||||
|
||||
template <class Scheduler>
|
||||
class at_executor
|
||||
{
|
||||
public:
|
||||
using work = Scheduler::work;
|
||||
using clock = Scheduler::clock;
|
||||
|
||||
at_executor(at_executor const&) = default;
|
||||
at_executor(at_executor &&) = default;
|
||||
at_executor& operator=(at_executor const&) = default;
|
||||
at_executor& operator=(at_executor &&) = default;
|
||||
|
||||
at_executor(Scheduler& sch, clock::time_point const& tp);
|
||||
~at_executor();
|
||||
|
||||
void close();
|
||||
bool closed();
|
||||
|
||||
Scheduler& underlying_scheduler();
|
||||
|
||||
template <class Closure>
|
||||
void submit(Closure&& closure);
|
||||
template <class Duration, typename Work>
|
||||
void submit_at(chrono::time_point<clock,Duration> abs_time, Closure&& closure);
|
||||
template <class Rep, class Period, typename Work>
|
||||
void submit_after(chrono::duration<Rep,Period> rel_time, Closure&& closure);
|
||||
|
||||
template <class Executor>
|
||||
resubmit_at_executor<Scheduler, Executor> on(Executor& ex);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
[/////////////////////////////////////]
|
||||
[section:constructor Constructor `at_executor(Scheduler&)`]
|
||||
|
||||
at_executor(Scheduler& sch, clock::time_point const& tp);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Constructs a `at_executor`. ]]
|
||||
|
||||
[[Throws:] [Nothing. ]]
|
||||
|
||||
]
|
||||
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:destructor Destructor `~at_executor()`]
|
||||
|
||||
~at_executor();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Destroys the `at_executor`.]]
|
||||
|
||||
[[Synchronization:] [The completion of all the closures happen before the completion of the executor destructor.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:underlying_scheduler Function member `underlying_scheduler()`]
|
||||
|
||||
Scheduler& underlying_scheduler() noexcept;
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Return:] [The underlying scheduler instance. ]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:submit_at Template Function Member `submit()`]
|
||||
|
||||
template <typename Closure>
|
||||
void submit(Closure&& closure);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Schedule the `closure` to be executed at the `abs_time` given at construction time. ]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:submit_at Template Function Member `submit_at()`]
|
||||
|
||||
template <class Clock, class Duration, typename Closure>
|
||||
void submit_at(chrono::time_point<Clock,Duration> abs_time, Closure&& closure);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Schedule a `closure` to be executed at `abs_time`. ]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:submit_after Template Function Member `submit_after()`]
|
||||
|
||||
template <class Rep, class Period, typename Closure>
|
||||
void submit_after(chrono::duration<Rep,Period> rel_time, Closure&& closure);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Schedule a `closure` to be executed after `rel_time`. ]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[//////////////////////////////////////////////////////////]
|
||||
[section:scheduler_executor_wrapper Template Class `scheduler_executor_wrapper`]
|
||||
|
||||
#include <boost/thread/executors/scheduler.hpp>
|
||||
namespace boost {
|
||||
|
||||
template <class Scheduler, class Executor>
|
||||
class scheduler_executor_wrapper
|
||||
{
|
||||
public:
|
||||
using work = Scheduler::work;
|
||||
using clock = Scheduler::clock;
|
||||
|
||||
scheduler_executor_wrapper(scheduler_executor_wrapper const&) = default;
|
||||
scheduler_executor_wrapper(scheduler_executor_wrapper &&) = default;
|
||||
scheduler_executor_wrapper& operator=(scheduler_executor_wrapper const&) = default;
|
||||
scheduler_executor_wrapper& operator=(scheduler_executor_wrapper &&) = default;
|
||||
|
||||
scheduler_executor_wrapper(Scheduler& sch, Executor& ex);
|
||||
|
||||
~scheduler_executor_wrapper();
|
||||
|
||||
void close();
|
||||
bool closed();
|
||||
|
||||
Executor& underlying_executor();
|
||||
Scheduler& underlying_scheduler();
|
||||
|
||||
template <class Closure>
|
||||
void submit(Closure&& closure);
|
||||
template <class Duration, typename Work>
|
||||
void submit_at(chrono::time_point<clock,Duration> abs_time, Closure&& closure);
|
||||
template <class Rep, class Period, typename Work>
|
||||
void submit_after(chrono::duration<Rep,Period> rel_time, Closure&& closure);
|
||||
|
||||
template <class Duration>
|
||||
resubmit_at_executor<Scheduler, Executor> at(chrono::time_point<clock,Duration> abs_time);
|
||||
template <class Rep, class Period>
|
||||
resubmit_at_executor<Scheduler, Executor> after(chrono::duration<Rep,Period> rel_time);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
[/////////////////////////////////////]
|
||||
[section:constructor Constructor `scheduler_executor_wrapper(Scheduler&, Executor&)`]
|
||||
|
||||
scheduler_executor_wrapper(Scheduler& sch, Executor& ex);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Constructs a `scheduler_executor_wrapper`. ]]
|
||||
|
||||
[[Throws:] [Nothing. ]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:destructor Destructor `~scheduler_executor_wrapper()`]
|
||||
|
||||
~scheduler_executor_wrapper();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Destroys the `scheduler_executor_wrapper`.]]
|
||||
|
||||
[[Synchronization:] [The completion of all the closures happen before the completion of the executor destructor.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:underlying_scheduler Function member `underlying_scheduler()`]
|
||||
|
||||
Scheduler& underlying_scheduler() noexcept;
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Return:] [The underlying scheduler instance. ]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:underlying_executor Function member `underlying_executor()`]
|
||||
|
||||
Executor& underlying_executor() noexcept;
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Return:] [The underlying executor instance. ]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:submit_at Template Function Member `submit()`]
|
||||
|
||||
template <typename Closure>
|
||||
void submit(Closure&& closure);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Submit the `closure` on the underlying executor. ]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:submit_at Template Function Member `submit_at()`]
|
||||
|
||||
template <class Clock, class Duration, typename Closure>
|
||||
void submit_at(chrono::time_point<Clock,Duration> abs_time, Closure&& closure);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Resubmit the `closure` to be executed on the underlying executor at `abs_time`. ]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:submit_after Template Function Member `submit_after()`]
|
||||
|
||||
template <class Rep, class Period, typename Closure>
|
||||
void submit_after(chrono::duration<Rep,Period> rel_time, Closure&& closure);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Resubmit the `closure` to be executed on the underlying executor after `rel_time`. ]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[//////////////////////////////////////////////////////////]
|
||||
[section:resubmit_at_executor Template Class `resubmit_at_executor`]
|
||||
|
||||
`Executor` wrapping an `Scheduler`, an `Executor` and a `time_point` providing an `Executor` interface.
|
||||
|
||||
#include <boost/thread/executors/scheduler.hpp>
|
||||
namespace boost {
|
||||
|
||||
template <class Scheduler, class Executor>
|
||||
class resubmit_at_executor
|
||||
{
|
||||
public:
|
||||
using work = Scheduler::work;
|
||||
using clock = Scheduler::clock;
|
||||
|
||||
resubmit_at_executor(resubmit_at_executor const&) = default;
|
||||
resubmit_at_executor(resubmit_at_executor &&) = default;
|
||||
resubmit_at_executor& operator=(resubmit_at_executor const&) = default;
|
||||
resubmit_at_executor& operator=(resubmit_at_executor &&) = default;
|
||||
|
||||
template <class Duration>
|
||||
resubmit_at_executor(Scheduler& sch, Executor& ex, clock::time_point<Duration> const& tp);
|
||||
~resubmit_at_executor();
|
||||
|
||||
void close();
|
||||
bool closed();
|
||||
|
||||
Executor& underlying_executor();
|
||||
Scheduler& underlying_scheduler();
|
||||
|
||||
template <class Closure>
|
||||
void submit(Closure&& closure);
|
||||
template <class Duration, typename Work>
|
||||
void submit_at(chrono::time_point<clock,Duration> abs_time, Closure&& closure);
|
||||
template <class Rep, class Period, typename Work>
|
||||
void submit_after(chrono::duration<Rep,Period> rel_time, Closure&& closure);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
[/////////////////////////////////////]
|
||||
[section:constructor Constructor `resubmit_at_executor(Scheduler&, Executor&, clock::time_point<Duration>)`]
|
||||
|
||||
template <class Duration>
|
||||
resubmit_at_executor(Scheduler& sch, Executor& ex, clock::time_point<Duration> const& tp);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Constructs a `resubmit_at_executor`. ]]
|
||||
|
||||
[[Throws:] [Nothing. ]]
|
||||
|
||||
]
|
||||
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:destructor Destructor `~resubmit_at_executor()`]
|
||||
|
||||
~resubmit_at_executor();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Destroys the executor_adaptor.]]
|
||||
|
||||
[[Synchronization:] [The completion of all the closures happen before the completion of the executor destructor.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:underlying_executor Function member `underlying_executor()`]
|
||||
|
||||
Executor& underlying_executor() noexcept;
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Return:] [The underlying executor instance. ]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:underlying_scheduler Function member `underlying_scheduler()`]
|
||||
|
||||
Scheduler& underlying_scheduler() noexcept;
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Return:] [The underlying scheduler instance. ]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:submit_at Template Function Member `submit()`]
|
||||
|
||||
template <typename Closure>
|
||||
void submit(Closure&& closure);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Resubmit the `closure` to be executed on the underlying executor at the `abs_time` given at construction time. ]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:submit_at Template Function Member `submit_at()`]
|
||||
|
||||
template <class Clock, class Duration, typename Closure>
|
||||
void submit_at(chrono::time_point<Clock,Duration> abs_time, Closure&& closure);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Resubmit the `closure` to be executed on the underlying executor at `abs_time`. ]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:submit_after Template Function Member `submit_after()`]
|
||||
|
||||
template <class Rep, class Period, typename Closure>
|
||||
void submit_after(chrono::duration<Rep,Period> rel_time, Closure&& closure);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Resubmit the `closure` to be executed on the underlying executor after `rel_time`. ]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[//////////////////////////////////////////////////////////]
|
||||
[/
|
||||
[section:scheduled_executor_ref Template Class `scheduled_executor_ref`]
|
||||
|
||||
Executor providing time related functions.
|
||||
@@ -694,10 +1238,6 @@ Executor providing time related functions.
|
||||
template <typename Pred>
|
||||
bool reschedule_until(Pred const& pred);
|
||||
|
||||
template <class Clock, class Duration>
|
||||
void submit_at(chrono::time_point<Clock,Duration> abs_time, work&& closure);
|
||||
template <class Rep, class Period>
|
||||
void submit_after(chrono::duration<Rep,Period> rel_time, work&& closure);
|
||||
template <class Clock, class Duration, typename Closure>
|
||||
void submit_at(chrono::time_point<Clock,Duration> abs_time, Closure&& closure);
|
||||
template <class Rep, class Period, typename Closure>
|
||||
@@ -746,20 +1286,31 @@ Executor providing time related functions.
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:submit_at Template Function Member `submit()`]
|
||||
|
||||
template <typename Closure>
|
||||
void submit(Closure&& closure);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Resubmit the `closure` to be executed on the underlying executor. ]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[/////////////////////////////////////]
|
||||
[section:submit_at Template Function Member `submit_at()`]
|
||||
|
||||
template <class Clock, class Duration, typename Closure>
|
||||
void submit_at(chrono::time_point<Clock,Duration> abs_time, Closure&& closure);
|
||||
template <class Rep, class Period, typename Closure>
|
||||
void submit_after(chrono::duration<Rep,Period> rel_time, Closure&& closure);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [The underlying executor instance. ]]
|
||||
[[Effects:] [Schedule a `closure` to be executed at `abs_time`. ]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
@@ -767,11 +1318,26 @@ Executor providing time related functions.
|
||||
|
||||
|
||||
[endsect]
|
||||
[/////////////////////////////////////]
|
||||
[section:submit_after Template Function Member `submit_after()`]
|
||||
|
||||
template <class Rep, class Period, typename Closure>
|
||||
void submit_after(chrono::duration<Rep,Period> rel_time, Closure&& closure);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Schedule a `closure` to be executed after `rel_time`. ]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[endsect]
|
||||
]
|
||||
|
||||
[//////////////////////////////////////////////////////////]
|
||||
[section:serial_executor Template Class `serial_executor`]
|
||||
|
||||
|
||||
@@ -8,6 +8,58 @@
|
||||
|
||||
[section:changes History]
|
||||
|
||||
[heading Version 4.5.0 - boost 1.58]
|
||||
|
||||
[*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/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/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/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/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/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/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 [@http://www.boost.org/development/tests/master/developer/thread.html thread trunk regression test] to see the last snapshot.
|
||||
|
||||
[*Sever limitations:]
|
||||
|
||||
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], ),
|
||||
* 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:]
|
||||
|
||||
* [@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/10826 #10826] Add scheduled executor operations
|
||||
|
||||
[*Fixed Bugs:]
|
||||
|
||||
|
||||
* [@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/10737 #10737] In serial_executor we have infinite wait if task throw exception.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10822 #10822] Boost.Thread fails to compile on Android
|
||||
* [@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/10964 #10964] future<future<T>>::unwrap().then() Deadlocks
|
||||
* [@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/10979 #10979] Support T& type deduction when the make_ready_future parameter is reference_wrapper<T>
|
||||
|
||||
|
||||
[heading Version 4.4.0 - boost 1.57]
|
||||
|
||||
[*Know Bugs:]
|
||||
@@ -557,9 +609,6 @@ been moved to __thread_id__.
|
||||
|
||||
The following features will be included in next releases.
|
||||
|
||||
# Complete the C++11 missing features, in particular
|
||||
* [@http://svn.boost.org/trac/boost/ticket/6227 #6227] C++11 compliance: Use of variadic templates on Generic Locking Algorithms on compilers providing them.
|
||||
|
||||
# Add some minor features, in particular
|
||||
* [@http://svn.boost.org/trac/boost/ticket/7589 #7589] Synchro: Add polymorphic lockables.
|
||||
|
||||
@@ -567,9 +616,6 @@ The following features will be included in next releases.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8273 #8273] Synchro: Add externally locked streams.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8514 #8514] Async: Add a thread_pool executor with work stealing.
|
||||
|
||||
# Add extensions related to fork-join as:
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9600 #9600] Async: Add task_region/task_run.
|
||||
|
||||
# And some additional extensions related to futures as:
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8517 #8517] Async: Add a variadic shared_future::then.
|
||||
|
||||
@@ -1020,7 +1020,7 @@ There are not too much tests yet, so it is possible that you can find out some t
|
||||
void swap(shared_future& other);
|
||||
|
||||
// retrieving the value
|
||||
see below get();
|
||||
see below get() const;
|
||||
|
||||
exception_ptr get_exception_ptr(); // EXTENSION
|
||||
|
||||
@@ -1066,9 +1066,9 @@ There are not too much tests yet, so it is possible that you can find out some t
|
||||
[///////////////////////////////////]
|
||||
[section:get Member function `get()`]
|
||||
|
||||
const R& get();
|
||||
R& get();
|
||||
void get();
|
||||
const R& get() const;
|
||||
R& get() const;
|
||||
void get() const;
|
||||
|
||||
[variablelist
|
||||
|
||||
@@ -2362,7 +2362,7 @@ All `R` types must be the same. If any of the `future<R>` or `shared_future<R>`
|
||||
[section:make_ready_future Non-member function `make_ready_future()` EXTENSION]
|
||||
|
||||
template <typename T>
|
||||
future<typename decay<T>::type> make_ready_future(T&& value); // EXTENSION
|
||||
future<V> make_ready_future(T&& value); // EXTENSION
|
||||
future<void> make_ready_future(); // EXTENSION
|
||||
template <typename T>
|
||||
future<T> make_ready_future(exception_ptr ex); // DEPRECATED
|
||||
@@ -2371,11 +2371,15 @@ All `R` types must be the same. If any of the `future<R>` or `shared_future<R>`
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Remark:][
|
||||
where `V` is determined as follows: Let `U` be `decay_t<T>`. Then `V` is `X&`
|
||||
if `U` equals `reference_wrapper<X>`, otherwise `V` is `U`.
|
||||
]]
|
||||
[[Effects:] [
|
||||
- value prototype: The value that is passed into the function is moved to the shared state of the returned function if it is an rvalue.
|
||||
Otherwise the value is copied to the shared state of the returned function.
|
||||
- value prototype: The value that is passed into the function is moved to the shared state of the returned future if it is an rvalue.
|
||||
Otherwise the value is copied to the shared state of the returned future.
|
||||
|
||||
- exception: The exception that is passed into the function is copied to the shared state of the returned function.
|
||||
- exception: The exception that is passed into the function is copied to the shared state of the returned future.
|
||||
|
||||
.]]
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ the result is ready, it is returned from __unique_future_get__ by rvalue-referen
|
||||
appropriate for the type.
|
||||
|
||||
On the other hand, many instances of __shared_future__ may reference the same result. Instances can be freely copied and assigned,
|
||||
and __shared_future_get__ returns a non `const` reference so that multiple calls to __shared_future_get__ are safe. You can move an
|
||||
and __shared_future_get__ returns a `const` reference so that multiple calls to __shared_future_get__ are safe. You can move an
|
||||
instance of __unique_future__ into an instance of __shared_future__, thus transferring ownership of the associated asynchronous
|
||||
result, but not vice-versa.
|
||||
|
||||
|
||||
482
doc/parallel.qbk
Normal file
482
doc/parallel.qbk
Normal file
@@ -0,0 +1,482 @@
|
||||
[/
|
||||
/ Copyright (c) 2014 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)
|
||||
/]
|
||||
|
||||
[//////////////////////////////////////////////////////////]
|
||||
[section:parallel Parallel - Fork-Join -- EXPERIMENTAL]
|
||||
|
||||
[section:fork_join Fork-Join]
|
||||
|
||||
[warning These features are 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 :(]
|
||||
|
||||
[note These features are based on the [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4088.pdf [* n4088 - Task Region R3]] C++1y proposal from P. Halpern, A. Robison, A. Laksberg, H. Sutter, et al. The text that follows has been adapted from this paper to show the differences.]
|
||||
|
||||
The major difference respect to the standard proposal is that we are able to use a common executor for several task regions.
|
||||
|
||||
[note
|
||||
Up to now, Boost.Thread doesn't implement the parallel algorithms as defined in [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4105.pdf [* n4105 - Information technology – Programming languages, their environments and system software interfaces – Technical Specification for C++ Extensions for Parallelism]].
|
||||
]
|
||||
|
||||
[////////////////////]
|
||||
[section Introduction]
|
||||
|
||||
|
||||
This module introduces a C++11/c++14 library function template `task_region` and a library class `task_region_handle`
|
||||
with member functions `run` and `wait` that together enable developers to write expressive and portable fork-join
|
||||
parallel code.
|
||||
|
||||
The working draft for the Parallelism TS [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4105.pdf [*N4105]] augments the STL algorithms with the inclusion of parallel execution policies. Programmers use these as a basis to write additional high-level algorithms that can be implemented in terms of the provided parallel algorithms. However, the scope of n4105 does not include lower-level mechanisms to express arbitrary fork-join parallelism
|
||||
|
||||
The `task_region`, `run` and the `wait` functions provided by this library are based on the `task_group` concept that is a part of the common subset of the PPL and the TBB libraries.
|
||||
|
||||
[endsect] [/ Introduction]
|
||||
|
||||
|
||||
[/////////////////////////]
|
||||
[section:tutorial Tutorial]
|
||||
|
||||
Consider an example of a parallel traversal of a tree, where a user-provided function compute is applied to each node of the tree, returning the sum of the results:
|
||||
|
||||
template<typename Func>
|
||||
int traverse(node *n, Func&& compute)
|
||||
{
|
||||
int left = 0, right = 0;
|
||||
task_region([&](task_region_handle& tr) {
|
||||
if (n->left)
|
||||
tr.run([&] { left = traverse(n->left, compute); });
|
||||
if (n->right)
|
||||
tr.run([&] { right = traverse(n->right, compute); });
|
||||
});
|
||||
return compute(n) + left + right;
|
||||
}
|
||||
|
||||
The example above demonstrates the use of two of the functions proposed in this paper, `task_region` and
|
||||
`task_region_handle::run`.
|
||||
The `task_region` function delineates a region in a program code potentially containing invocations of tasks
|
||||
spawned by the `run` member function of the `task_region_handle` class.
|
||||
|
||||
The run function spawns a task, a unit of work that is allowed to execute in parallel with respect to the caller.
|
||||
Any parallel tasks spawned by `run` within the `task_region` are joined back to a single thread of execution at
|
||||
the end of the `task_region`.
|
||||
|
||||
`run` takes a user-provided function object `f` and starts it asynchronously - i.e. it may return before the
|
||||
execution of `f` completes. The implementation's scheduler may choose to run `f` immediately or delay running
|
||||
`f` until compute resources become available.
|
||||
|
||||
A `task_region_handle` can be constructed only by `task_region` because it has no public constructors.
|
||||
Thus, `run` can be invoked (directly or indirectly) only from a user-provided function passed to `task_region`:
|
||||
|
||||
void g();
|
||||
void f(task_region_handle& tr)
|
||||
{
|
||||
tr.run(g); // OK, invoked from within task_region in h
|
||||
}
|
||||
void h()
|
||||
{
|
||||
task_region(f);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
task_region_handle tr; // Error: no public constructor
|
||||
tr.run(g); // No way to call run outside of a task_region
|
||||
return 0;
|
||||
}
|
||||
|
||||
[endsect] [/ Tutorial]
|
||||
|
||||
[////////////////]
|
||||
[section:examples Examples]
|
||||
|
||||
[section:fib Parallel Fibonacci]
|
||||
|
||||
|
||||
This is surely the worst implementation of the Fibonacci function. Anyway, here it is, as it is simple and shows the fork-join structure clearly. `Fibonacci(n) = Fibonacci(n-1) + Fibonacci(n-2)`, so the task decomposition is trivial.
|
||||
|
||||
int fib_task_region(int n)
|
||||
{
|
||||
using boost::experimental::parallel::task_region;
|
||||
using boost::experimental::parallel::task_region_handle;
|
||||
|
||||
if (n == 0) return 0;
|
||||
if (n == 1) return 1;
|
||||
|
||||
int n1;
|
||||
int n2;
|
||||
|
||||
task_region([&](task_region_handle& trh)
|
||||
{
|
||||
trh.run([&]
|
||||
{
|
||||
n1 = fib_task_region(n - 1);
|
||||
});
|
||||
|
||||
n2 = fib_task_region(n - 2);
|
||||
});
|
||||
|
||||
return n1 + n2;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
for (int i = 0; i<10; ++i) {
|
||||
std::cout << fib_task_region(i) << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
[endsect] [/ Fib]
|
||||
[section:fibex Parallel Fibonacci - Specific executor]
|
||||
|
||||
The previous example make use of an implementation defined way to spawn the tasks. Often the user wants to master how the task must be spawned. There is an overload of `task_region` that accept an additional `Executor` parameter and a function that takes as parameter a `task_region_handle_gen<Executor>`. `task_region_handle_gen<Executor>` run uses this executor to spawn the tasks.
|
||||
|
||||
template <class Ex>
|
||||
int fib_task_region_gen( Ex& ex, int n)
|
||||
{
|
||||
using boost::experimental::parallel::task_region;
|
||||
using boost::experimental::parallel::task_region_handle_gen;
|
||||
|
||||
if (n == 0) return 0;
|
||||
if (n == 1) return 1;
|
||||
|
||||
int n1;
|
||||
int n2;
|
||||
|
||||
task_region(ex, [&](task_region_handle_gen<Ex>& trh) // (2)
|
||||
{
|
||||
trh.run([&]
|
||||
{
|
||||
n1 = fib_task_region(n - 1);
|
||||
});
|
||||
|
||||
n2 = fib_task_region(n - 2);
|
||||
});
|
||||
|
||||
return n1 + n2;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
boost::basic_thread_pool tp; // (1)
|
||||
for (int i = 0; i<10; ++i) {
|
||||
std::cout << fib_task_region_gen(tp,i) << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
The specific executor is declared in line (1) and it is used in line (2).
|
||||
|
||||
[endsect] [/ Fib ex]
|
||||
|
||||
|
||||
|
||||
|
||||
[section:quick_sort Parallel Accumulate]
|
||||
|
||||
|
||||
[endsect] [/ Accumulate]
|
||||
|
||||
[section:quick_sort Parallel Quick Sort]
|
||||
|
||||
|
||||
|
||||
[endsect] [/ QuickSort]
|
||||
[endsect] [/ Examples]
|
||||
|
||||
|
||||
[////////////////////////]
|
||||
[section:rationale Design Rationale]
|
||||
|
||||
|
||||
[endsect] [/ Design Rationale]
|
||||
[endsect] [/ Fork-Join]
|
||||
|
||||
[/////////////////////]
|
||||
[section:ref Reference -- EXPERIMENTAL]
|
||||
|
||||
[/////////////////////////]
|
||||
[section:v1 Parallel V1]
|
||||
|
||||
[section:exception_list Header `<experimental/exception_list.hpp>`]
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
namespace parallel
|
||||
{
|
||||
inline namespace v1
|
||||
{
|
||||
|
||||
class exception_list;
|
||||
|
||||
} // v1
|
||||
} // parallel
|
||||
} // experimental
|
||||
} // boost
|
||||
|
||||
|
||||
[/////////////////////////]
|
||||
[section:exception_list Class `exception_list`]
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
namespace parallel
|
||||
{
|
||||
inline namespace v1
|
||||
{
|
||||
|
||||
class exception_list: public std::exception
|
||||
{
|
||||
public:
|
||||
typedef 'implementation defined' const_iterator;
|
||||
|
||||
~exception_list() noexcept {}
|
||||
|
||||
void add(exception_ptr const& e);
|
||||
size_t size() const noexcept;
|
||||
const_iterator begin() const noexcept;
|
||||
const_iterator end() const noexcept;
|
||||
const char* what() const noexcept;
|
||||
|
||||
};
|
||||
|
||||
} // v1
|
||||
} // parallel
|
||||
} // experimental
|
||||
} // boost
|
||||
|
||||
|
||||
[endsect] [/ exception_list]
|
||||
|
||||
[endsect] [/ exception_list.hpp]
|
||||
|
||||
[endsect] [/ Parallel V1]
|
||||
|
||||
[////////////////////////////////////////////////////////////////////]
|
||||
[section:v2 Parallel V2]
|
||||
[////////////////////////////////////////////////////////////////////]
|
||||
[section:concepts Concepts]
|
||||
[////////////////////////////////////////////////////////////////////]
|
||||
[section:regionCallable Concept `Region_Callable`]
|
||||
|
||||
[endsect] [/ Region_Callable]
|
||||
[////////////////////////////////////////////////////////////////////]
|
||||
[section:taskCallable Concept `Task_Callable`]
|
||||
|
||||
|
||||
[endsect] [/ Task_Callable]
|
||||
[////////////////////////////////////////////////////////////////////]
|
||||
[endsect] [/ Concepts]
|
||||
[////////////////////////////////////////////////////////////////////]
|
||||
[section:task_region Header `<experimental/task_region.hpp>`]
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
namespace parallel
|
||||
{
|
||||
inline namespace v2
|
||||
{
|
||||
|
||||
class task_canceled_exception;
|
||||
|
||||
template <class Executor>
|
||||
class task_region_handle_gen;
|
||||
|
||||
using default_executor = 'implementation defined';
|
||||
|
||||
class task_region_handle;
|
||||
|
||||
template <typename Executor, typename F>
|
||||
void task_region_final(Executor& ex, F&& f);
|
||||
template <typename F>
|
||||
void task_region_final(F&& f);
|
||||
|
||||
template <typename Executor, typename F>
|
||||
void task_region(Executor& ex, F&& f);
|
||||
template <typename F>
|
||||
void task_region(F&& f);
|
||||
|
||||
} // v2
|
||||
} // parallel
|
||||
} // experimental
|
||||
} // boost
|
||||
|
||||
|
||||
[////////////////////////////////////////////////////////////////////]
|
||||
[section:task_canceled_exception Class `task_canceled_exception `]
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
namespace parallel
|
||||
{
|
||||
inline namespace v2
|
||||
{
|
||||
|
||||
class task_canceled_exception: public std::exception
|
||||
{
|
||||
public:
|
||||
task_canceled_exception() noexcept;
|
||||
task_canceled_exception(const task_canceled_exception&) noexcept;
|
||||
task_canceled_exception& operator=(const task_canceled_exception&) noexcept;
|
||||
virtual const char* what() const noexcept;
|
||||
};
|
||||
|
||||
} // v2
|
||||
} // parallel
|
||||
} // experimental
|
||||
} // boost
|
||||
|
||||
[endsect] [/ task_canceled_exception]
|
||||
[////////////////////////////////////////////////////////////////////]
|
||||
[section:task_region_handle_gen Template Class `task_region_handle_gen<>`]
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
namespace parallel
|
||||
{
|
||||
inline namespace v2
|
||||
{
|
||||
|
||||
template <class Executor>
|
||||
class task_region_handle_gen
|
||||
{
|
||||
protected:
|
||||
task_region_handle_gen(Executor& ex);
|
||||
|
||||
~task_region_handle_gen();
|
||||
|
||||
public:
|
||||
task_region_handle_gen(const task_region_handle_gen&) = delete;
|
||||
task_region_handle_gen& operator=(const task_region_handle_gen&) = delete;
|
||||
task_region_handle_gen* operator&() const = delete;
|
||||
|
||||
template<typename F>
|
||||
void run(F&& f);
|
||||
|
||||
void wait();
|
||||
};
|
||||
|
||||
} // v2
|
||||
} // parallel
|
||||
} // experimental
|
||||
} // boost
|
||||
|
||||
[endsect] [/ task_region_handle_gen]
|
||||
[////////////////////////////////////////////////////////////////////]
|
||||
[section:default_executor Class `default_executor `]
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
namespace parallel
|
||||
{
|
||||
inline namespace v2
|
||||
{
|
||||
|
||||
using default_executor = 'implementation defined';
|
||||
|
||||
} // v2
|
||||
} // parallel
|
||||
} // experimental
|
||||
} // boost
|
||||
|
||||
[endsect] [/ default_executor]
|
||||
[////////////////////////////////////////////////////////////////////]
|
||||
[section:task_region_handle Class `task_region_handle `]
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
namespace parallel
|
||||
{
|
||||
inline namespace v2
|
||||
{
|
||||
|
||||
class task_region_handle :
|
||||
public task_region_handle_gen<default_executor>
|
||||
{
|
||||
protected:
|
||||
task_region_handle();
|
||||
task_region_handle(const task_region_handle&) = delete;
|
||||
task_region_handle& operator=(const task_region_handle&) = delete;
|
||||
task_region_handle* operator&() const = delete;
|
||||
|
||||
};
|
||||
|
||||
} // v2
|
||||
} // parallel
|
||||
} // experimental
|
||||
} // boost
|
||||
|
||||
[endsect] [/ task_region_handle]
|
||||
[////////////////////////////////////////////////////////////////////]
|
||||
[section:task_region_final Template Function `task_region_final `]
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
namespace parallel
|
||||
{
|
||||
inline namespace v2
|
||||
{
|
||||
|
||||
template <typename Executor, typename F>
|
||||
void task_region_final(Executor& ex, F&& f);
|
||||
template <typename F>
|
||||
void task_region_final(F&& f);
|
||||
|
||||
} // v2
|
||||
} // parallel
|
||||
} // experimental
|
||||
} // boost
|
||||
|
||||
[endsect] [/ task_region_final]
|
||||
[////////////////////////////////////////////////////////////////////]
|
||||
[section:task_region Template Function `task_region `]
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
namespace parallel
|
||||
{
|
||||
inline namespace v2
|
||||
{
|
||||
|
||||
template <typename Executor, typename F>
|
||||
void task_region(Executor& ex, F&& f);
|
||||
template <typename F>
|
||||
void task_region(F&& f);
|
||||
|
||||
} // v2
|
||||
} // parallel
|
||||
} // experimental
|
||||
} // boost
|
||||
|
||||
[endsect] [/ task_region]
|
||||
|
||||
|
||||
|
||||
|
||||
[endsect] [/ task_region.hpp]
|
||||
[endsect] [/ Parallel V2]
|
||||
[endsect] [/ Reference]
|
||||
|
||||
[endsect] [/ Parallel]
|
||||
@@ -21,18 +21,18 @@
|
||||
class scoped_thread;
|
||||
void swap(scoped_thread& lhs,scoped_thread& rhs) noexcept;
|
||||
|
||||
[section:motovation 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.
|
||||
|
||||
While the scoped_thread class defined in C++ Concurrency in Action is closer to strict_scoped_thread class that doesn't allows any change in the wrapped thread, Boost.Thread provides a class scoped_thread that provides the same non-deprecated interface than __thread.
|
||||
While the scoped_thread class defined in C++ Concurrency in Action is closer to strict_scoped_thread class that doesn't allows any change in the wrapped thread, Boost.Thread provides a class scoped_thread that provides the same non-deprecated interface as __thread.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:tutorial Tutorial]
|
||||
|
||||
Scoped Threads are wrappers around a thread that allows the user to state what to do at destruction time. One of the common uses is to join the thread at destruction time so this is the default behavior. This is the single difference respect to a thread. While thread call std::terminate() on the destructor is the thread is joinable, strict_scoped_thread<> or scoped_thread<> join the thread if joinable.
|
||||
Scoped Threads are wrappers around a thread that allows the user to state what to do at destruction time. One of the common uses is to join the thread at destruction time so this is the default behavior. This is the single difference respect to a thread. While thread call std::terminate() on the destructor if the thread is joinable, strict_scoped_thread<> or scoped_thread<> join the thread if joinable.
|
||||
|
||||
The difference between strict_scoped_thread and scoped_thread is that the strict_scoped_thread hides completely the owned thread and so the user can do nothing with the owned thread other than the specific action given as parameter, while scoped_thread provide the same interface than __thread and forwards all the operations.
|
||||
The difference between strict_scoped_thread and scoped_thread is that the strict_scoped_thread hides completely the owned thread and so the user can do nothing with the owned thread other than the specific action given as parameter, while scoped_thread provide the same interface as __thread and forwards all the operations.
|
||||
|
||||
boost::strict_scoped_thread<> t1((boost::thread(f)));
|
||||
//t1.detach(); // compile fails
|
||||
@@ -114,15 +114,15 @@ The difference between strict_scoped_thread and scoped_thread is that the strict
|
||||
};
|
||||
|
||||
|
||||
RAI __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.
|
||||
|
||||
CallableThread: A callable `void(thread&)`.
|
||||
|
||||
The default is a `join_if_joinable`.
|
||||
|
||||
|
||||
`std/boost::thread` destructor terminates the program if the __thread is not joinable.
|
||||
This wrapper can be used to join the thread before destroying it seems a natural need.
|
||||
Thread destructor terminates the program if the __thread is joinable.
|
||||
This wrapper can be used to join the thread before destroying it.
|
||||
|
||||
[heading Example]
|
||||
|
||||
@@ -233,13 +233,13 @@ This wrapper can be used to join the thread before destroying it seems a natural
|
||||
void swap(scoped_thread& lhs,scoped_thread& rhs) noexcept;
|
||||
|
||||
|
||||
RAI __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.
|
||||
|
||||
CallableThread: A callable void(thread&).
|
||||
The default is join_if_joinable.
|
||||
|
||||
thread std::thread destructor terminates the program if the thread is not joinable.
|
||||
Having a wrapper that can join the thread before destroying it seems a natural need.
|
||||
Thread destructor terminates the program if the thread is joinable.
|
||||
This wrapper can be used to join the thread before destroying it.
|
||||
|
||||
Remark: `scoped_thread` is not a __thread as __thread is not designed to be derived from as a polymorphic type.
|
||||
|
||||
@@ -312,9 +312,9 @@ any) to `*this`.
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [move the thread to own `t_`.]]
|
||||
[[Effects:] [Transfers ownership of the thread managed by `other` (if any) to the newly constructed scoped_thread instance.]]
|
||||
|
||||
[[Postconditions:] [`*this.t_` refers to the newly created thread of execution and `this->get_id()!=thread::id()`.]]
|
||||
[[Postconditions:] [other.get_id()==thread::id() and get_id() returns the value of other.get_id() prior to the construction.]]
|
||||
|
||||
[[Throws:] [Nothing]]
|
||||
|
||||
@@ -329,7 +329,7 @@ any) to `*this`.
|
||||
|
||||
[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()`.]]
|
||||
|
||||
|
||||
@@ -244,7 +244,6 @@
|
||||
[include futures.qbk]
|
||||
[endsect]
|
||||
|
||||
|
||||
[include tss.qbk]
|
||||
|
||||
[section:sds Synchronized Data Structures]
|
||||
@@ -253,6 +252,8 @@
|
||||
[/include sync_streams.qbk]
|
||||
[endsect]
|
||||
|
||||
[include parallel.qbk]
|
||||
|
||||
[include time.qbk]
|
||||
|
||||
[include emulations.qbk]
|
||||
|
||||
@@ -125,7 +125,7 @@ the user to set the platform specific attributes. Boost.Thread stay in the middl
|
||||
thread::attributes which allows to set at least in a portable way the stack size as follows:
|
||||
|
||||
boost::thread::attributes attrs;
|
||||
attrs.set_size(4096*10);
|
||||
attrs.set_stack_size(4096*10);
|
||||
boost::thread deep_thought_2(attrs, find_the_question, 42);
|
||||
|
||||
Even for this simple attribute there could be portable issues as some platforms could require that the stack size
|
||||
@@ -147,7 +147,7 @@ Next follows how the user could set the stack size and the scheduling policy on
|
||||
// ... window version
|
||||
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
|
||||
// ... pthread version
|
||||
pthread_attr_setschedpolicy(attr.get_native_handle(), SCHED_RR);
|
||||
pthread_attr_setschedpolicy(attr.native_handle(), SCHED_RR);
|
||||
#else
|
||||
#error "Boost threads unavailable on this platform"
|
||||
#endif
|
||||
@@ -432,12 +432,14 @@ This behavior is incompatible with the current Boost.Thread design, so the use o
|
||||
class attributes; // EXTENSION
|
||||
|
||||
thread() noexcept;
|
||||
~thread();
|
||||
|
||||
thread(const thread&) = delete;
|
||||
thread& operator=(const thread&) = delete;
|
||||
|
||||
// move support
|
||||
thread(thread&&) noexcept;
|
||||
thread& operator=(thread&&) noexcept;
|
||||
~thread();
|
||||
|
||||
template <class F>
|
||||
explicit thread(F f);
|
||||
@@ -456,10 +458,6 @@ This behavior is incompatible with the current Boost.Thread design, so the use o
|
||||
template <class F, class ...Args>
|
||||
explicit thread(attributes& attrs, F&& f, Args&&... args);
|
||||
|
||||
// move support
|
||||
thread(thread && x) noexcept;
|
||||
thread& operator=(thread && x) noexcept;
|
||||
|
||||
void swap(thread& x) noexcept;
|
||||
|
||||
class id;
|
||||
|
||||
91
example/fib_task_region.cpp
Normal file
91
example/fib_task_region.cpp
Normal file
@@ -0,0 +1,91 @@
|
||||
// Copyright (C) 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)
|
||||
|
||||
#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
|
||||
|
||||
#include <boost/thread/experimental/task_region.hpp>
|
||||
#include <iostream>
|
||||
|
||||
#if ! defined BOOST_NO_CXX11_RANGE_BASED_FOR && ! defined BOOST_NO_CXX11_LAMBDAS
|
||||
|
||||
int fib_task_region(int n)
|
||||
{
|
||||
using boost::experimental::parallel::task_region;
|
||||
using boost::experimental::parallel::task_region_handle;
|
||||
|
||||
if (n == 0) return 0;
|
||||
if (n == 1) return 1;
|
||||
|
||||
int n1;
|
||||
int n2;
|
||||
|
||||
task_region([&](task_region_handle& trh)
|
||||
{
|
||||
trh.run([&]
|
||||
{
|
||||
n1 = fib_task_region(n - 1);
|
||||
});
|
||||
|
||||
n2 = fib_task_region(n - 2);
|
||||
});
|
||||
|
||||
return n1 + n2;
|
||||
}
|
||||
|
||||
#if defined BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
template <class Ex>
|
||||
int fib_task_region_gen( Ex& ex, int n)
|
||||
{
|
||||
using boost::experimental::parallel::task_region;
|
||||
using boost::experimental::parallel::task_region_handle_gen;
|
||||
|
||||
if (n == 0) return 0;
|
||||
if (n == 1) return 1;
|
||||
|
||||
int n1;
|
||||
int n2;
|
||||
|
||||
task_region(ex, [&](task_region_handle_gen<Ex>& trh)
|
||||
{
|
||||
trh.run([&]
|
||||
{
|
||||
n1 = fib_task_region(n - 1);
|
||||
});
|
||||
|
||||
n2 = fib_task_region(n - 2);
|
||||
});
|
||||
|
||||
return n1 + n2;
|
||||
}
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
for (int i = 0; i<10; ++i) {
|
||||
std::cout << fib_task_region(i) << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
#if defined BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
boost::basic_thread_pool tp;
|
||||
for (int i = 0; i<10; ++i) {
|
||||
std::cout << fib_task_region_gen(tp,i) << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -35,31 +35,83 @@ int p1()
|
||||
|
||||
int main()
|
||||
{
|
||||
const int number_of_tests = 100;
|
||||
const int number_of_tests = 200;
|
||||
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++)
|
||||
try
|
||||
{
|
||||
//boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
||||
boost::future<int> f1 = boost::async(&p1);
|
||||
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
||||
boost::future<int> f2 = f1.fallback_to(-1);
|
||||
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
||||
f2.wait();
|
||||
//std::cout << __FILE__ << "["<< __LINE__<<"] " << std::endl;
|
||||
BOOST_ASSERT(f2.get()==1);
|
||||
//std::cout << __FILE__ << "["<< __LINE__<<"] " << std::endl;
|
||||
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
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;
|
||||
return 1;
|
||||
}
|
||||
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;
|
||||
return 2;
|
||||
}
|
||||
@@ -75,18 +127,20 @@ int main()
|
||||
boost::future<int> f2 = f1.fallback_to(-1);
|
||||
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
||||
f2.wait();
|
||||
//std::cout << __FILE__ << "["<< __LINE__<<"] " << std::endl;
|
||||
BOOST_ASSERT(f2.get()==-1);
|
||||
//std::cout << __FILE__ << "["<< __LINE__<<"] " << std::endl;
|
||||
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
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;
|
||||
return 1;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -104,6 +104,26 @@ int main()
|
||||
boost::future<int&> f = compute_ref(0);
|
||||
std::cout << f.get() << std::endl;
|
||||
}
|
||||
#if __cplusplus > 201103L
|
||||
{
|
||||
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
|
||||
int i = 0;
|
||||
boost::future<int&> f = boost::make_ready_future(std::ref(i));
|
||||
std::cout << f.get() << std::endl;
|
||||
}
|
||||
#endif
|
||||
{
|
||||
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
|
||||
int i = 0;
|
||||
boost::future<int&> f = boost::make_ready_future(boost::ref(i));
|
||||
std::cout << f.get() << std::endl;
|
||||
}
|
||||
{
|
||||
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
|
||||
const int i = 0;
|
||||
boost::future<int const&> f = boost::make_ready_future(boost::cref(i));
|
||||
std::cout << f.get() << std::endl;
|
||||
}
|
||||
// {
|
||||
// std::cout << __FILE__ << " "<< __LINE__ << std::endl;
|
||||
// boost::future<int> f = compute(2);
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
typedef std::ostream the_ostream;
|
||||
typedef std::istream the_istream;
|
||||
#endif
|
||||
#include <boost/thread/sync_queue.hpp>
|
||||
#include <boost/thread/concurrent_queues/sync_queue.hpp>
|
||||
|
||||
void producer(the_ostream &mos, boost::sync_queue<int> & sbq)
|
||||
{
|
||||
@@ -30,9 +30,9 @@ void producer(the_ostream &mos, boost::sync_queue<int> & sbq)
|
||||
try {
|
||||
for(int i=0; ;++i)
|
||||
{
|
||||
sbq.push_back(i);
|
||||
sbq.push(i);
|
||||
//sbq << i;
|
||||
mos << "push_back(" << i << ") "<< sbq.size()<<"\n";
|
||||
mos << "push(" << i << ") "<< sbq.size()<<"\n";
|
||||
this_thread::sleep_for(chrono::milliseconds(200));
|
||||
}
|
||||
}
|
||||
@@ -55,7 +55,7 @@ void consumer(
|
||||
for(int i=0; ;++i)
|
||||
{
|
||||
int r;
|
||||
sbq.pull_front(r);
|
||||
sbq.pull(r);
|
||||
//sbq >> r;
|
||||
mos << i << " pull(" << r << ") "<< sbq.size()<<"\n";
|
||||
|
||||
@@ -78,7 +78,7 @@ void consumer2(the_ostream &mos, boost::sync_queue<int> & sbq)
|
||||
for(int i=0; ;++i)
|
||||
{
|
||||
int r;
|
||||
queue_op_status st = sbq.try_pull_front(r);
|
||||
queue_op_status st = sbq.try_pull(r);
|
||||
if (queue_op_status::closed == st) break;
|
||||
if (queue_op_status::success == st) {
|
||||
mos << i << " pull(" << r << ")\n";
|
||||
@@ -98,9 +98,9 @@ void consumer3(the_ostream &mos, boost::sync_queue<int> & sbq)
|
||||
for(int i=0; ;++i)
|
||||
{
|
||||
int r;
|
||||
queue_op_status res = sbq.wait_pull_front(r);
|
||||
queue_op_status res = sbq.wait_pull(r);
|
||||
if (res==queue_op_status::closed) break;
|
||||
mos << i << " wait_pull_front(" << r << ")\n";
|
||||
mos << i << " wait_pull(" << r << ")\n";
|
||||
this_thread::sleep_for(chrono::milliseconds(250));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
typedef std::ostream the_ostream;
|
||||
typedef std::istream the_istream;
|
||||
#endif
|
||||
#include <boost/thread/sync_queue.hpp>
|
||||
#include <boost/thread/concurrent_queues/sync_queue.hpp>
|
||||
#include <boost/thread/concurrent_queues/queue_adaptor.hpp>
|
||||
#include <boost/thread/concurrent_queues/queue_views.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
113
example/serial_executor.cpp
Normal file
113
example/serial_executor.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
// Copyright (C) 2015 Vicente J. Botet Escriba
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/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/serial_executor.hpp>
|
||||
#include <boost/thread/executors/executor.hpp>
|
||||
#include <boost/thread/executors/executor_adaptor.hpp>
|
||||
#include <boost/thread/executor.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
void p1()
|
||||
{
|
||||
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(30));
|
||||
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
}
|
||||
|
||||
void p2()
|
||||
{
|
||||
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(10));
|
||||
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
}
|
||||
|
||||
int f1()
|
||||
{
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
boost::this_thread::sleep_for(boost::chrono::seconds(1));
|
||||
return 1;
|
||||
}
|
||||
int f2(int i)
|
||||
{
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
boost::this_thread::sleep_for(boost::chrono::seconds(2));
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
void submit_some(boost::serial_executor& tp)
|
||||
{
|
||||
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
tp.submit(&p2);
|
||||
}
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
tp.submit(&p1);
|
||||
}
|
||||
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void at_th_entry(boost::basic_thread_pool& )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int test_executor_adaptor()
|
||||
{
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
{
|
||||
boost::basic_thread_pool ea1(4);
|
||||
boost::serial_executor ea2(ea1);
|
||||
submit_some(ea2);
|
||||
boost::this_thread::sleep_for(boost::chrono::seconds(10));
|
||||
}
|
||||
#endif
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
std::cout << "ERROR= " << ex.what() << "" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cout << " ERROR= exception thrown" << std::endl;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
return test_executor_adaptor();
|
||||
}
|
||||
113
example/serial_executor_cont.cpp
Normal file
113
example/serial_executor_cont.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
// Copyright (C) 2015 Vicente J. Botet Escriba
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/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/serial_executor_cont.hpp>
|
||||
#include <boost/thread/executors/executor.hpp>
|
||||
#include <boost/thread/executors/executor_adaptor.hpp>
|
||||
#include <boost/thread/executor.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
void p1()
|
||||
{
|
||||
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(30));
|
||||
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
}
|
||||
|
||||
void p2()
|
||||
{
|
||||
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(10));
|
||||
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
}
|
||||
|
||||
int f1()
|
||||
{
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
boost::this_thread::sleep_for(boost::chrono::seconds(1));
|
||||
return 1;
|
||||
}
|
||||
int f2(int i)
|
||||
{
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
boost::this_thread::sleep_for(boost::chrono::seconds(2));
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
void submit_some(boost::serial_executor_cont& tp)
|
||||
{
|
||||
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
tp.submit(&p2);
|
||||
}
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
tp.submit(&p1);
|
||||
}
|
||||
std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void at_th_entry(boost::basic_thread_pool& )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int test_executor_adaptor()
|
||||
{
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
{
|
||||
boost::basic_thread_pool ea1(4);
|
||||
boost::serial_executor_cont ea2(ea1);
|
||||
submit_some(ea2);
|
||||
boost::this_thread::sleep_for(boost::chrono::seconds(10));
|
||||
}
|
||||
#endif
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
std::cout << "ERROR= " << ex.what() << "" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cout << " ERROR= exception thrown" << std::endl;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
return test_executor_adaptor();
|
||||
}
|
||||
209
include/boost/thread/concurrent_queues/deque_adaptor.hpp
Normal file
209
include/boost/thread/concurrent_queues/deque_adaptor.hpp
Normal file
@@ -0,0 +1,209 @@
|
||||
#ifndef BOOST_THREAD_CONCURRENT_DEQUE_ADAPTOR_HPP
|
||||
#define BOOST_THREAD_CONCURRENT_DEQUE_ADAPTOR_HPP
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Vicente J. Botet Escriba 2014. 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)
|
||||
//
|
||||
// See http://www.boost.org/libs/thread for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
|
||||
#include <boost/thread/concurrent_queues/deque_base.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace concurrent
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename Queue>
|
||||
class deque_adaptor_copyable_only :
|
||||
public boost::deque_base<typename Queue::value_type>
|
||||
{
|
||||
Queue queue;
|
||||
public:
|
||||
typedef typename Queue::value_type value_type;
|
||||
typedef std::size_t size_type;
|
||||
|
||||
// Constructors/Assignment/Destructors
|
||||
deque_adaptor_copyable_only() {}
|
||||
|
||||
// Observers
|
||||
bool empty() const { return queue.empty(); }
|
||||
bool full() const { return queue.full(); }
|
||||
size_type size() const { return queue.size(); }
|
||||
bool closed() const { return queue.closed(); }
|
||||
|
||||
// Modifiers
|
||||
void close() { queue.close(); }
|
||||
|
||||
void push_back(const value_type& x) { queue.push_back(x); }
|
||||
|
||||
void pull_front(value_type& x) { queue.pull_front(x); };
|
||||
value_type pull_front() { return queue.pull_front(); }
|
||||
|
||||
queue_op_status try_push_back(const value_type& x) { return queue.try_push_back(x); }
|
||||
queue_op_status try_pull_front(value_type& x) { return queue.try_pull_front(x); }
|
||||
|
||||
queue_op_status nonblocking_push_back(const value_type& x) { return queue.nonblocking_push_back(x); }
|
||||
queue_op_status nonblocking_pull_front(value_type& x) { return queue.nonblocking_pull_front(x); }
|
||||
|
||||
queue_op_status wait_push_back(const value_type& x) { return queue.wait_push_back(x); }
|
||||
queue_op_status wait_pull_front(value_type& x) { return queue.wait_pull_front(x); }
|
||||
|
||||
};
|
||||
template <typename Queue>
|
||||
class deque_adaptor_movable_only :
|
||||
public boost::deque_base<typename Queue::value_type>
|
||||
{
|
||||
Queue queue;
|
||||
public:
|
||||
typedef typename Queue::value_type value_type;
|
||||
typedef std::size_t size_type;
|
||||
|
||||
// Constructors/Assignment/Destructors
|
||||
|
||||
deque_adaptor_movable_only() {}
|
||||
|
||||
// Observers
|
||||
bool empty() const { return queue.empty(); }
|
||||
bool full() const { return queue.full(); }
|
||||
size_type size() const { return queue.size(); }
|
||||
bool closed() const { return queue.closed(); }
|
||||
|
||||
// Modifiers
|
||||
void close() { queue.close(); }
|
||||
|
||||
|
||||
void pull_front(value_type& x) { queue.pull_front(x); };
|
||||
// enable_if is_nothrow_copy_movable<value_type>
|
||||
value_type pull_front() { return queue.pull_front(); }
|
||||
|
||||
queue_op_status try_pull_front(value_type& x) { return queue.try_pull_front(x); }
|
||||
|
||||
queue_op_status nonblocking_pull_front(value_type& x) { return queue.nonblocking_pull_front(x); }
|
||||
|
||||
queue_op_status wait_pull_front(value_type& x) { return queue.wait_pull_front(x); }
|
||||
|
||||
void push_back(BOOST_THREAD_RV_REF(value_type) x) { queue.push_back(boost::move(x)); }
|
||||
queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.try_push_back(boost::move(x)); }
|
||||
queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.nonblocking_push_back(boost::move(x)); }
|
||||
queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.wait_push_back(boost::move(x)); }
|
||||
};
|
||||
|
||||
template <typename Queue>
|
||||
class deque_adaptor_copyable_and_movable :
|
||||
public boost::deque_base<typename Queue::value_type>
|
||||
{
|
||||
Queue queue;
|
||||
public:
|
||||
typedef typename Queue::value_type value_type;
|
||||
typedef std::size_t size_type;
|
||||
|
||||
// Constructors/Assignment/Destructors
|
||||
|
||||
deque_adaptor_copyable_and_movable() {}
|
||||
|
||||
// Observers
|
||||
bool empty() const { return queue.empty(); }
|
||||
bool full() const { return queue.full(); }
|
||||
size_type size() const { return queue.size(); }
|
||||
bool closed() const { return queue.closed(); }
|
||||
|
||||
// Modifiers
|
||||
void close() { queue.close(); }
|
||||
|
||||
|
||||
void push_back(const value_type& x) { queue.push_back(x); }
|
||||
|
||||
void pull_front(value_type& x) { queue.pull_front(x); };
|
||||
// enable_if is_nothrow_copy_movable<value_type>
|
||||
value_type pull_front() { return queue.pull_front(); }
|
||||
|
||||
queue_op_status try_push_back(const value_type& x) { return queue.try_push_back(x); }
|
||||
queue_op_status try_pull_front(value_type& x) { return queue.try_pull_front(x); }
|
||||
|
||||
queue_op_status nonblocking_push_back(const value_type& x) { return queue.nonblocking_push_back(x); }
|
||||
queue_op_status nonblocking_pull_front(value_type& x) { return queue.nonblocking_pull_front(x); }
|
||||
|
||||
queue_op_status wait_push_back(const value_type& x) { return queue.wait_push_back(x); }
|
||||
queue_op_status wait_pull_front(value_type& x) { return queue.wait_pull_front(x); }
|
||||
|
||||
void push_back(BOOST_THREAD_RV_REF(value_type) x) { queue.push_back(boost::move(x)); }
|
||||
queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.try_push_back(boost::move(x)); }
|
||||
queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.nonblocking_push_back(boost::move(x)); }
|
||||
queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.wait_push_back(boost::move(x)); }
|
||||
};
|
||||
|
||||
|
||||
template <class Q, class T,
|
||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
#if defined __GNUC__ && ! defined __clang__
|
||||
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
bool Copyable = is_copy_constructible<T>::value,
|
||||
bool Movable = true
|
||||
#else
|
||||
bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
|
||||
bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
|
||||
#endif // __GNUC__
|
||||
#elif defined _MSC_VER
|
||||
#if _MSC_VER < 1700
|
||||
bool Copyable = is_copy_constructible<T>::value,
|
||||
bool Movable = true
|
||||
#else
|
||||
bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
|
||||
bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
|
||||
#endif // _MSC_VER
|
||||
#else
|
||||
bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
|
||||
bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
|
||||
#endif
|
||||
#else
|
||||
bool Copyable = is_copy_constructible<T>::value,
|
||||
bool Movable = has_move_emulation_enabled<T>::value
|
||||
#endif
|
||||
>
|
||||
struct deque_adaptor;
|
||||
|
||||
template <class Q, class T>
|
||||
struct deque_adaptor<Q, T, true, true> {
|
||||
typedef deque_adaptor_copyable_and_movable<Q> type;
|
||||
};
|
||||
template <class Q, class T>
|
||||
struct deque_adaptor<Q, T, true, false> {
|
||||
typedef deque_adaptor_copyable_only<Q> type;
|
||||
};
|
||||
template <class Q, class T>
|
||||
struct deque_adaptor<Q, T, false, true> {
|
||||
typedef deque_adaptor_movable_only<Q> type;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <typename Queue>
|
||||
class deque_adaptor :
|
||||
public detail::deque_adaptor<Queue, typename Queue::value_type>::type
|
||||
{
|
||||
public:
|
||||
typedef typename Queue::value_type value_type;
|
||||
typedef std::size_t size_type;
|
||||
// Constructors/Assignment/Destructors
|
||||
virtual ~deque_adaptor() {};
|
||||
};
|
||||
}
|
||||
using concurrent::deque_adaptor;
|
||||
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
202
include/boost/thread/concurrent_queues/deque_base.hpp
Normal file
202
include/boost/thread/concurrent_queues/deque_base.hpp
Normal file
@@ -0,0 +1,202 @@
|
||||
#ifndef BOOST_THREAD_CONCURRENT_DEQUE_BASE_HPP
|
||||
#define BOOST_THREAD_CONCURRENT_DEQUE_BASE_HPP
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Vicente J. Botet Escriba 2014. 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)
|
||||
//
|
||||
// See http://www.boost.org/libs/thread for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
|
||||
#include <boost/type_traits/conditional.hpp>
|
||||
#include <boost/type_traits/is_copy_constructible.hpp>
|
||||
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace concurrent
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename ValueType>
|
||||
class deque_base_copyable_only
|
||||
{
|
||||
public:
|
||||
typedef ValueType value_type;
|
||||
typedef std::size_t size_type;
|
||||
|
||||
// Constructors/Assignment/Destructors
|
||||
virtual ~deque_base_copyable_only() {};
|
||||
|
||||
// Observers
|
||||
virtual bool empty() const = 0;
|
||||
virtual bool full() const = 0;
|
||||
virtual size_type size() const = 0;
|
||||
virtual bool closed() const = 0;
|
||||
|
||||
// Modifiers
|
||||
virtual void close() = 0;
|
||||
|
||||
virtual void push_back(const value_type& x) = 0;
|
||||
|
||||
virtual void pull_front(value_type&) = 0;
|
||||
virtual value_type pull_front() = 0;
|
||||
|
||||
virtual queue_op_status try_push_back(const value_type& x) = 0;
|
||||
virtual queue_op_status try_pull_front(value_type&) = 0;
|
||||
|
||||
virtual queue_op_status nonblocking_push_back(const value_type& x) = 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_pull_front(ValueType& elem) = 0;
|
||||
|
||||
};
|
||||
|
||||
template <typename ValueType>
|
||||
class deque_base_movable_only
|
||||
{
|
||||
public:
|
||||
typedef ValueType value_type;
|
||||
typedef std::size_t size_type;
|
||||
// Constructors/Assignment/Destructors
|
||||
virtual ~deque_base_movable_only() {};
|
||||
|
||||
// Observers
|
||||
virtual bool empty() const = 0;
|
||||
virtual bool full() const = 0;
|
||||
virtual size_type size() const = 0;
|
||||
virtual bool closed() const = 0;
|
||||
|
||||
// Modifiers
|
||||
virtual void close() = 0;
|
||||
|
||||
virtual void pull_front(value_type&) = 0;
|
||||
// enable_if is_nothrow_movable<value_type>
|
||||
virtual value_type pull_front() = 0;
|
||||
|
||||
virtual queue_op_status try_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 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 nonblocking_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 <typename ValueType>
|
||||
class deque_base_copyable_and_movable
|
||||
{
|
||||
public:
|
||||
typedef ValueType value_type;
|
||||
typedef std::size_t size_type;
|
||||
// Constructors/Assignment/Destructors
|
||||
virtual ~deque_base_copyable_and_movable() {};
|
||||
|
||||
|
||||
// Observers
|
||||
virtual bool empty() const = 0;
|
||||
virtual bool full() const = 0;
|
||||
virtual size_type size() const = 0;
|
||||
virtual bool closed() const = 0;
|
||||
|
||||
// Modifiers
|
||||
virtual void close() = 0;
|
||||
|
||||
virtual void push_back(const value_type& x) = 0;
|
||||
|
||||
virtual void pull_front(value_type&) = 0;
|
||||
// enable_if is_nothrow_copy_movable<value_type>
|
||||
virtual value_type pull_front() = 0;
|
||||
|
||||
virtual queue_op_status try_push_back(const value_type& x) = 0;
|
||||
virtual queue_op_status try_pull_front(value_type&) = 0;
|
||||
|
||||
virtual queue_op_status nonblocking_push_back(const value_type& x) = 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_pull_front(ValueType& elem) = 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 nonblocking_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,
|
||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
#if defined __GNUC__ && ! defined __clang__
|
||||
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
bool Copyable = is_copy_constructible<T>::value,
|
||||
bool Movable = true
|
||||
#else
|
||||
bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
|
||||
bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
|
||||
#endif // __GNUC__
|
||||
#elif defined _MSC_VER
|
||||
#if _MSC_VER < 1700
|
||||
bool Copyable = is_copy_constructible<T>::value,
|
||||
bool Movable = true
|
||||
#else
|
||||
bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
|
||||
bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
|
||||
#endif // _MSC_VER
|
||||
#else
|
||||
bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
|
||||
bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
|
||||
#endif
|
||||
#else
|
||||
bool Copyable = is_copy_constructible<T>::value,
|
||||
bool Movable = has_move_emulation_enabled<T>::value
|
||||
#endif
|
||||
>
|
||||
struct deque_base;
|
||||
|
||||
template <class T>
|
||||
struct deque_base<T, true, true> {
|
||||
typedef deque_base_copyable_and_movable<T> type;
|
||||
};
|
||||
template <class T>
|
||||
struct deque_base<T, true, false> {
|
||||
typedef deque_base_copyable_only<T> type;
|
||||
};
|
||||
template <class T>
|
||||
struct deque_base<T, false, true> {
|
||||
typedef deque_base_movable_only<T> type;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <typename ValueType>
|
||||
class deque_base :
|
||||
public detail::deque_base<ValueType>::type
|
||||
{
|
||||
public:
|
||||
typedef ValueType value_type;
|
||||
typedef std::size_t size_type;
|
||||
// Constructors/Assignment/Destructors
|
||||
virtual ~deque_base() {};
|
||||
};
|
||||
|
||||
}
|
||||
using concurrent::deque_base;
|
||||
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
165
include/boost/thread/concurrent_queues/deque_views.hpp
Normal file
165
include/boost/thread/concurrent_queues/deque_views.hpp
Normal file
@@ -0,0 +1,165 @@
|
||||
#ifndef BOOST_THREAD_QUEUE_VIEWS_HPP
|
||||
#define BOOST_THREAD_QUEUE_VIEWS_HPP
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Vicente J. Botet Escriba 2014. 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)
|
||||
//
|
||||
// See http://www.boost.org/libs/thread for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
|
||||
#include <boost/thread/concurrent_queues/deque_base.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace concurrent
|
||||
{
|
||||
|
||||
template <typename Queue>
|
||||
class deque_back_view
|
||||
{
|
||||
Queue* queue;
|
||||
public:
|
||||
typedef typename Queue::value_type value_type;
|
||||
typedef typename Queue::size_type size_type;
|
||||
|
||||
// Constructors/Assignment/Destructors
|
||||
deque_back_view(Queue& q) BOOST_NOEXCEPT : queue(&q) {}
|
||||
|
||||
// Observers
|
||||
bool empty() const { return queue->empty(); }
|
||||
bool full() const { return queue->full(); }
|
||||
size_type size() const { return queue->size(); }
|
||||
bool closed() const { return queue->closed(); }
|
||||
|
||||
// Modifiers
|
||||
void close() { queue->close(); }
|
||||
|
||||
void push(const value_type& x) { queue->push_back(x); }
|
||||
|
||||
void pull(value_type& x) { queue->pull_back(x); }
|
||||
// enable_if is_nothrow_copy_movable<value_type>
|
||||
value_type pull() { return queue->pull_back(); }
|
||||
|
||||
queue_op_status try_push(const value_type& x) { return queue->try_push_back(x); }
|
||||
|
||||
queue_op_status try_pull(value_type& x) { return queue->try_pull_back(x); }
|
||||
|
||||
queue_op_status nonblocking_push(const value_type& x) { return queue->nonblocking_push_back(x); }
|
||||
|
||||
queue_op_status nonblocking_pull(value_type& x) { return queue->nonblocking_pull_back(x); }
|
||||
|
||||
queue_op_status wait_push(const value_type& x) { return queue->wait_push_back(x); }
|
||||
queue_op_status wait_pull(value_type& x) { return queue->wait_pull_back(x); }
|
||||
|
||||
void push(BOOST_THREAD_RV_REF(value_type) x) { queue->push_back(boost::move(x)); }
|
||||
queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->try_push_back(boost::move(x)); }
|
||||
queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->nonblocking_push_back(boost::move(x)); }
|
||||
queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->wait_push_back(boost::move(x)); }
|
||||
};
|
||||
|
||||
template <typename Queue>
|
||||
class deque_front_view
|
||||
{
|
||||
Queue* queue;
|
||||
public:
|
||||
typedef typename Queue::value_type value_type;
|
||||
typedef typename Queue::size_type size_type;
|
||||
|
||||
// Constructors/Assignment/Destructors
|
||||
deque_front_view(Queue& q) BOOST_NOEXCEPT : queue(&q) {}
|
||||
|
||||
// Observers
|
||||
bool empty() const { return queue->empty(); }
|
||||
bool full() const { return queue->full(); }
|
||||
size_type size() const { return queue->size(); }
|
||||
bool closed() const { return queue->closed(); }
|
||||
|
||||
// Modifiers
|
||||
void close() { queue->close(); }
|
||||
|
||||
void push(const value_type& x) { queue->push_front(x); }
|
||||
|
||||
void pull(value_type& x) { queue->pull_front(x); };
|
||||
// enable_if is_nothrow_copy_movable<value_type>
|
||||
value_type pull() { return queue->pull_front(); }
|
||||
|
||||
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_front(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_front(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_front(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)); }
|
||||
|
||||
};
|
||||
|
||||
#if ! defined BOOST_NO_CXX11_TEMPLATE_ALIASES
|
||||
|
||||
template <class T>
|
||||
using deque_back = deque_back_view<deque_base<T> > ;
|
||||
template <class T>
|
||||
using deque_front = deque_front_view<deque_base<T> > ;
|
||||
|
||||
#else
|
||||
|
||||
template <class T>
|
||||
struct deque_back : deque_back_view<deque_base<T> >
|
||||
{
|
||||
typedef deque_back_view<deque_base<T> > base_type;
|
||||
deque_back(deque_base<T>& q) BOOST_NOEXCEPT : base_type(q) {}
|
||||
};
|
||||
template <class T>
|
||||
struct deque_front : deque_front_view<deque_base<T> >
|
||||
{
|
||||
typedef deque_front_view<deque_base<T> > base_type;
|
||||
deque_front(deque_base<T>& q) BOOST_NOEXCEPT : base_type(q) {}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// template <class Queue>
|
||||
// deque_back_view<Queue> back(Queue & q) { return deque_back_view<Queue>(q); }
|
||||
// template <class Queue>
|
||||
// deque_front_view<Queue> front(Queue & q) { return deque_front_view<Queue>(q); }
|
||||
//#if 0
|
||||
// template <class T>
|
||||
// deque_back<T> back(deque_base<T> & q) { return deque_back<T>(q); }
|
||||
// template <class T>
|
||||
// deque_front<T> front(deque_base<T> & q) { return deque_front<T>(q); }
|
||||
//#else
|
||||
// template <class T>
|
||||
// typename deque_back<T>::type back(deque_base<T> & q) { return typename deque_back<T>::type(q); }
|
||||
// template <class T>
|
||||
// typename deque_front<T>::type front(deque_base<T> & q) { return typename deque_front<T>::type(q); }
|
||||
//#endif
|
||||
}
|
||||
|
||||
using concurrent::deque_back_view;
|
||||
using concurrent::deque_front_view;
|
||||
using concurrent::deque_back;
|
||||
using concurrent::deque_front;
|
||||
//using concurrent::back;
|
||||
//using concurrent::front;
|
||||
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,223 @@
|
||||
#ifndef BOOST_THREAD_CONCURRENT_QUEUES_DETAIL_SYNC_DEQUE_BASE_HPP
|
||||
#define BOOST_THREAD_CONCURRENT_QUEUES_DETAIL_SYNC_DEQUE_BASE_HPP
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Vicente J. Botet Escriba 2013-2014. 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)
|
||||
//
|
||||
// See http://www.boost.org/libs/thread for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
|
||||
|
||||
#include <boost/chrono/duration.hpp>
|
||||
#include <boost/chrono/time_point.hpp>
|
||||
#include <boost/chrono/system_clocks.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace concurrent
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <class ValueType, class Queue>
|
||||
class sync_deque_base
|
||||
{
|
||||
public:
|
||||
typedef ValueType value_type;
|
||||
typedef Queue underlying_queue_type;
|
||||
typedef std::size_t size_type;
|
||||
typedef queue_op_status op_status;
|
||||
|
||||
typedef typename chrono::steady_clock clock;
|
||||
typedef typename clock::duration duration;
|
||||
typedef typename clock::time_point time_point;
|
||||
|
||||
// Constructors/Assignment/Destructors
|
||||
BOOST_THREAD_NO_COPYABLE(sync_deque_base)
|
||||
inline sync_deque_base();
|
||||
//template <typename Range>
|
||||
//inline explicit sync_deque(Range range);
|
||||
inline ~sync_deque_base();
|
||||
|
||||
// Observers
|
||||
inline bool empty() const;
|
||||
inline bool full() const;
|
||||
inline size_type size() const;
|
||||
inline bool closed() const;
|
||||
|
||||
// Modifiers
|
||||
inline void close();
|
||||
|
||||
inline underlying_queue_type underlying_queue() {
|
||||
lock_guard<mutex> lk(mtx_);
|
||||
return boost::move(data_);
|
||||
}
|
||||
|
||||
protected:
|
||||
mutable mutex mtx_;
|
||||
condition_variable not_empty_;
|
||||
underlying_queue_type data_;
|
||||
bool closed_;
|
||||
|
||||
inline bool empty(unique_lock<mutex>& ) const BOOST_NOEXCEPT
|
||||
{
|
||||
return data_.empty();
|
||||
}
|
||||
inline bool empty(lock_guard<mutex>& ) const BOOST_NOEXCEPT
|
||||
{
|
||||
return data_.empty();
|
||||
}
|
||||
|
||||
inline size_type size(lock_guard<mutex>& ) const BOOST_NOEXCEPT
|
||||
{
|
||||
return data_.size();
|
||||
}
|
||||
inline bool closed(unique_lock<mutex>& lk) const;
|
||||
inline bool closed(lock_guard<mutex>& lk) const;
|
||||
|
||||
inline void throw_if_closed(unique_lock<mutex>&);
|
||||
inline void throw_if_closed(lock_guard<mutex>&);
|
||||
|
||||
inline void wait_until_not_empty(unique_lock<mutex>& lk);
|
||||
inline bool wait_until_not_empty_or_closed(unique_lock<mutex>& lk);
|
||||
inline queue_op_status wait_until_not_empty_until(unique_lock<mutex>& lk, time_point const&);
|
||||
|
||||
inline void notify_not_empty_if_needed(unique_lock<mutex>& )
|
||||
{
|
||||
not_empty_.notify_one();
|
||||
}
|
||||
inline void notify_not_empty_if_needed(lock_guard<mutex>& )
|
||||
{
|
||||
not_empty_.notify_one();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <class ValueType, class Queue>
|
||||
sync_deque_base<ValueType, Queue>::sync_deque_base() :
|
||||
data_(), closed_(false)
|
||||
{
|
||||
BOOST_ASSERT(data_.empty());
|
||||
}
|
||||
|
||||
template <class ValueType, class Queue>
|
||||
sync_deque_base<ValueType, Queue>::~sync_deque_base()
|
||||
{
|
||||
}
|
||||
|
||||
template <class ValueType, class Queue>
|
||||
void sync_deque_base<ValueType, Queue>::close()
|
||||
{
|
||||
{
|
||||
lock_guard<mutex> lk(mtx_);
|
||||
closed_ = true;
|
||||
}
|
||||
not_empty_.notify_all();
|
||||
}
|
||||
|
||||
template <class ValueType, class Queue>
|
||||
bool sync_deque_base<ValueType, Queue>::closed() const
|
||||
{
|
||||
lock_guard<mutex> lk(mtx_);
|
||||
return closed(lk);
|
||||
}
|
||||
template <class ValueType, class Queue>
|
||||
bool sync_deque_base<ValueType, Queue>::closed(unique_lock<mutex>&) const
|
||||
{
|
||||
return closed_;
|
||||
}
|
||||
template <class ValueType, class Queue>
|
||||
bool sync_deque_base<ValueType, Queue>::closed(lock_guard<mutex>&) const
|
||||
{
|
||||
return closed_;
|
||||
}
|
||||
|
||||
template <class ValueType, class Queue>
|
||||
bool sync_deque_base<ValueType, Queue>::empty() const
|
||||
{
|
||||
lock_guard<mutex> lk(mtx_);
|
||||
return empty(lk);
|
||||
}
|
||||
template <class ValueType, class Queue>
|
||||
bool sync_deque_base<ValueType, Queue>::full() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class ValueType, class Queue>
|
||||
typename sync_deque_base<ValueType, Queue>::size_type sync_deque_base<ValueType, Queue>::size() const
|
||||
{
|
||||
lock_guard<mutex> lk(mtx_);
|
||||
return size(lk);
|
||||
}
|
||||
|
||||
template <class ValueType, class Queue>
|
||||
void sync_deque_base<ValueType, Queue>::throw_if_closed(unique_lock<mutex>& lk)
|
||||
{
|
||||
if (closed(lk))
|
||||
{
|
||||
BOOST_THROW_EXCEPTION( sync_deque_is_closed() );
|
||||
}
|
||||
}
|
||||
template <class ValueType, class Queue>
|
||||
void sync_deque_base<ValueType, Queue>::throw_if_closed(lock_guard<mutex>& lk)
|
||||
{
|
||||
if (closed(lk))
|
||||
{
|
||||
BOOST_THROW_EXCEPTION( sync_deque_is_closed() );
|
||||
}
|
||||
}
|
||||
|
||||
template <class ValueType, class Queue>
|
||||
void sync_deque_base<ValueType, Queue>::wait_until_not_empty(unique_lock<mutex>& lk)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (! empty(lk)) break;
|
||||
throw_if_closed(lk);
|
||||
not_empty_.wait(lk);
|
||||
}
|
||||
}
|
||||
template <class ValueType, class Queue>
|
||||
bool sync_deque_base<ValueType, Queue>::wait_until_not_empty_or_closed(unique_lock<mutex>& lk)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (! empty(lk)) break;
|
||||
if (closed(lk)) return true;
|
||||
not_empty_.wait(lk);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class ValueType, class Queue>
|
||||
queue_op_status sync_deque_base<ValueType, Queue>::wait_until_not_empty_until(unique_lock<mutex>& lk, time_point const&tp)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (! empty(lk)) return queue_op_status::success;
|
||||
throw_if_closed(lk);
|
||||
if (not_empty_.wait_until(lk, tp) == cv_status::timeout ) return queue_op_status::timeout;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // detail
|
||||
} // concurrent
|
||||
} // boost
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
@@ -46,19 +46,19 @@ namespace detail
|
||||
// Modifiers
|
||||
void close() { queue.close(); }
|
||||
|
||||
void push_back(const value_type& x) { queue.push_back(x); }
|
||||
void push(const value_type& x) { queue.push(x); }
|
||||
|
||||
void pull_front(value_type& x) { queue.pull_front(x); };
|
||||
value_type pull_front() { return queue.pull_front(); }
|
||||
void pull(value_type& x) { queue.pull(x); };
|
||||
value_type pull() { return queue.pull(); }
|
||||
|
||||
queue_op_status try_push_back(const value_type& x) { return queue.try_push_back(x); }
|
||||
queue_op_status try_pull_front(value_type& x) { return queue.try_pull_front(x); }
|
||||
queue_op_status try_push(const value_type& x) { return queue.try_push(x); }
|
||||
queue_op_status try_pull(value_type& x) { return queue.try_pull(x); }
|
||||
|
||||
queue_op_status nonblocking_push_back(const value_type& x) { return queue.nonblocking_push_back(x); }
|
||||
queue_op_status nonblocking_pull_front(value_type& x) { return queue.nonblocking_pull_front(x); }
|
||||
queue_op_status nonblocking_push(const value_type& x) { return queue.nonblocking_push(x); }
|
||||
queue_op_status nonblocking_pull(value_type& x) { return queue.nonblocking_pull(x); }
|
||||
|
||||
queue_op_status wait_push_back(const value_type& x) { return queue.wait_push_back(x); }
|
||||
queue_op_status wait_pull_front(value_type& x) { return queue.wait_pull_front(x); }
|
||||
queue_op_status wait_push(const value_type& x) { return queue.wait_push(x); }
|
||||
queue_op_status wait_pull(value_type& x) { return queue.wait_pull(x); }
|
||||
|
||||
};
|
||||
template <typename Queue>
|
||||
@@ -84,20 +84,20 @@ namespace detail
|
||||
void close() { queue.close(); }
|
||||
|
||||
|
||||
void pull_front(value_type& x) { queue.pull_front(x); };
|
||||
void pull(value_type& x) { queue.pull(x); };
|
||||
// enable_if is_nothrow_copy_movable<value_type>
|
||||
value_type pull_front() { return queue.pull_front(); }
|
||||
value_type pull() { return queue.pull(); }
|
||||
|
||||
queue_op_status try_pull_front(value_type& x) { return queue.try_pull_front(x); }
|
||||
queue_op_status try_pull(value_type& x) { return queue.try_pull(x); }
|
||||
|
||||
queue_op_status nonblocking_pull_front(value_type& x) { return queue.nonblocking_pull_front(x); }
|
||||
queue_op_status nonblocking_pull(value_type& x) { return queue.nonblocking_pull(x); }
|
||||
|
||||
queue_op_status wait_pull_front(value_type& x) { return queue.wait_pull_front(x); }
|
||||
queue_op_status wait_pull(value_type& x) { return queue.wait_pull(x); }
|
||||
|
||||
void push_back(BOOST_THREAD_RV_REF(value_type) x) { queue.push_back(boost::move(x)); }
|
||||
queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.try_push_back(boost::move(x)); }
|
||||
queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.nonblocking_push_back(boost::move(x)); }
|
||||
queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.wait_push_back(boost::move(x)); }
|
||||
void push(BOOST_THREAD_RV_REF(value_type) x) { queue.push(boost::move(x)); }
|
||||
queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue.try_push(boost::move(x)); }
|
||||
queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue.nonblocking_push(boost::move(x)); }
|
||||
queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) { return queue.wait_push(boost::move(x)); }
|
||||
};
|
||||
|
||||
template <typename Queue>
|
||||
@@ -123,31 +123,31 @@ namespace detail
|
||||
void close() { queue.close(); }
|
||||
|
||||
|
||||
void push_back(const value_type& x) { queue.push_back(x); }
|
||||
void push(const value_type& x) { queue.push(x); }
|
||||
|
||||
void pull_front(value_type& x) { queue.pull_front(x); };
|
||||
void pull(value_type& x) { queue.pull(x); };
|
||||
// enable_if is_nothrow_copy_movable<value_type>
|
||||
value_type pull_front() { return queue.pull_front(); }
|
||||
value_type pull() { return queue.pull(); }
|
||||
|
||||
queue_op_status try_push_back(const value_type& x) { return queue.try_push_back(x); }
|
||||
queue_op_status try_pull_front(value_type& x) { return queue.try_pull_front(x); }
|
||||
queue_op_status try_push(const value_type& x) { return queue.try_push(x); }
|
||||
queue_op_status try_pull(value_type& x) { return queue.try_pull(x); }
|
||||
|
||||
queue_op_status nonblocking_push_back(const value_type& x) { return queue.nonblocking_push_back(x); }
|
||||
queue_op_status nonblocking_pull_front(value_type& x) { return queue.nonblocking_pull_front(x); }
|
||||
queue_op_status nonblocking_push(const value_type& x) { return queue.nonblocking_push(x); }
|
||||
queue_op_status nonblocking_pull(value_type& x) { return queue.nonblocking_pull(x); }
|
||||
|
||||
queue_op_status wait_push_back(const value_type& x) { return queue.wait_push_back(x); }
|
||||
queue_op_status wait_pull_front(value_type& x) { return queue.wait_pull_front(x); }
|
||||
queue_op_status wait_push(const value_type& x) { return queue.wait_push(x); }
|
||||
queue_op_status wait_pull(value_type& x) { return queue.wait_pull(x); }
|
||||
|
||||
void push_back(BOOST_THREAD_RV_REF(value_type) x) { queue.push_back(boost::move(x)); }
|
||||
queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.try_push_back(boost::move(x)); }
|
||||
queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.nonblocking_push_back(boost::move(x)); }
|
||||
queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.wait_push_back(boost::move(x)); }
|
||||
void push(BOOST_THREAD_RV_REF(value_type) x) { queue.push(boost::move(x)); }
|
||||
queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue.try_push(boost::move(x)); }
|
||||
queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue.nonblocking_push(boost::move(x)); }
|
||||
queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) { return queue.wait_push(boost::move(x)); }
|
||||
};
|
||||
|
||||
|
||||
template <class Q, class T,
|
||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
#if defined __GNUC__
|
||||
#if defined __GNUC__ && ! defined __clang__
|
||||
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
bool Copyable = is_copy_constructible<T>::value,
|
||||
bool Movable = true
|
||||
|
||||
@@ -46,19 +46,19 @@ namespace detail
|
||||
// Modifiers
|
||||
virtual void close() = 0;
|
||||
|
||||
virtual void push_back(const value_type& x) = 0;
|
||||
virtual void push(const value_type& x) = 0;
|
||||
|
||||
virtual void pull_front(value_type&) = 0;
|
||||
virtual value_type pull_front() = 0;
|
||||
virtual void pull(value_type&) = 0;
|
||||
virtual value_type pull() = 0;
|
||||
|
||||
virtual queue_op_status try_push_back(const value_type& x) = 0;
|
||||
virtual queue_op_status try_pull_front(value_type&) = 0;
|
||||
virtual queue_op_status try_push(const value_type& x) = 0;
|
||||
virtual queue_op_status try_pull(value_type&) = 0;
|
||||
|
||||
virtual queue_op_status nonblocking_push_back(const value_type& x) = 0;
|
||||
virtual queue_op_status nonblocking_pull_front(value_type&) = 0;
|
||||
virtual queue_op_status nonblocking_push(const value_type& x) = 0;
|
||||
virtual queue_op_status nonblocking_pull(value_type&) = 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_push(const value_type& x) = 0;
|
||||
virtual queue_op_status wait_pull(ValueType& elem) = 0;
|
||||
|
||||
};
|
||||
|
||||
@@ -80,20 +80,20 @@ namespace detail
|
||||
// Modifiers
|
||||
virtual void close() = 0;
|
||||
|
||||
virtual void pull_front(value_type&) = 0;
|
||||
virtual void pull(value_type&) = 0;
|
||||
// enable_if is_nothrow_movable<value_type>
|
||||
virtual value_type pull_front() = 0;
|
||||
virtual value_type pull() = 0;
|
||||
|
||||
virtual queue_op_status try_pull_front(value_type&) = 0;
|
||||
virtual queue_op_status try_pull(value_type&) = 0;
|
||||
|
||||
virtual queue_op_status nonblocking_pull_front(value_type&) = 0;
|
||||
virtual queue_op_status nonblocking_pull(value_type&) = 0;
|
||||
|
||||
virtual queue_op_status wait_pull_front(ValueType& elem) = 0;
|
||||
virtual queue_op_status wait_pull(ValueType& elem) = 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 nonblocking_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 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 nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
||||
virtual queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -116,30 +116,30 @@ namespace detail
|
||||
// Modifiers
|
||||
virtual void close() = 0;
|
||||
|
||||
virtual void push_back(const value_type& x) = 0;
|
||||
virtual void push(const value_type& x) = 0;
|
||||
|
||||
virtual void pull_front(value_type&) = 0;
|
||||
virtual void pull(value_type&) = 0;
|
||||
// enable_if is_nothrow_copy_movable<value_type>
|
||||
virtual value_type pull_front() = 0;
|
||||
virtual value_type pull() = 0;
|
||||
|
||||
virtual queue_op_status try_push_back(const value_type& x) = 0;
|
||||
virtual queue_op_status try_pull_front(value_type&) = 0;
|
||||
virtual queue_op_status try_push(const value_type& x) = 0;
|
||||
virtual queue_op_status try_pull(value_type&) = 0;
|
||||
|
||||
virtual queue_op_status nonblocking_push_back(const value_type& x) = 0;
|
||||
virtual queue_op_status nonblocking_pull_front(value_type&) = 0;
|
||||
virtual queue_op_status nonblocking_push(const value_type& x) = 0;
|
||||
virtual queue_op_status nonblocking_pull(value_type&) = 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_push(const value_type& x) = 0;
|
||||
virtual queue_op_status wait_pull(ValueType& elem) = 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 nonblocking_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 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 nonblocking_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,
|
||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
#if defined __GNUC__
|
||||
#if defined __GNUC__ && ! defined __clang__
|
||||
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
bool Copyable = is_copy_constructible<T>::value,
|
||||
bool Movable = true
|
||||
|
||||
@@ -43,27 +43,17 @@ namespace concurrent
|
||||
// Modifiers
|
||||
void close() { queue->close(); }
|
||||
|
||||
void push(const value_type& x) { queue->push_back(x); }
|
||||
void push(const value_type& x) { queue->push(x); }
|
||||
|
||||
void pull(value_type& x) { queue->pull_back(x); }
|
||||
// enable_if is_nothrow_copy_movable<value_type>
|
||||
value_type pull() { return queue->pull_back(); }
|
||||
queue_op_status try_push(const value_type& x) { return queue->try_push(x); }
|
||||
|
||||
queue_op_status try_push(const value_type& x) { return queue->try_push_back(x); }
|
||||
queue_op_status nonblocking_push(const value_type& x) { return queue->nonblocking_push(x); }
|
||||
queue_op_status wait_push(const value_type& x) { return queue->wait_push(x); }
|
||||
|
||||
queue_op_status try_pull(value_type& x) { return queue->try_pull_back(x); }
|
||||
|
||||
queue_op_status nonblocking_push(const value_type& x) { return queue->nonblocking_push_back(x); }
|
||||
|
||||
queue_op_status nonblocking_pull(value_type& x) { return queue->nonblocking_pull_back(x); }
|
||||
|
||||
queue_op_status wait_push(const value_type& x) { return queue->wait_push_back(x); }
|
||||
queue_op_status wait_pull(value_type& x) { return queue->wait_pull_back(x); }
|
||||
|
||||
void push(BOOST_THREAD_RV_REF(value_type) x) { queue->push_back(boost::move(x)); }
|
||||
queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->try_push_back(boost::move(x)); }
|
||||
queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->nonblocking_push_back(boost::move(x)); }
|
||||
queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->wait_push_back(boost::move(x)); }
|
||||
void push(BOOST_THREAD_RV_REF(value_type) x) { queue->push(boost::move(x)); }
|
||||
queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->try_push(boost::move(x)); }
|
||||
queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->nonblocking_push(boost::move(x)); }
|
||||
queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->wait_push(boost::move(x)); }
|
||||
};
|
||||
|
||||
template <typename Queue>
|
||||
@@ -88,20 +78,20 @@ namespace concurrent
|
||||
|
||||
void push(const value_type& x) { queue->push_front(x); }
|
||||
|
||||
void pull(value_type& x) { queue->pull_front(x); };
|
||||
void pull(value_type& x) { queue->pull(x); };
|
||||
// enable_if is_nothrow_copy_movable<value_type>
|
||||
value_type pull() { return queue->pull_front(); }
|
||||
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_front(x); }
|
||||
queue_op_status try_pull(value_type& x) { return queue->try_pull(x); }
|
||||
|
||||
queue_op_status nonblocking_push(const value_type& x) { return queue->nonblocking_push_front(x); }
|
||||
|
||||
queue_op_status nonblocking_pull(value_type& x) { return queue->nonblocking_pull_front(x); }
|
||||
queue_op_status nonblocking_pull(value_type& x) { return queue->nonblocking_pull(x); }
|
||||
|
||||
queue_op_status wait_push(const value_type& x) { return queue->wait_push_front(x); }
|
||||
queue_op_status wait_pull(value_type& x) { return queue->wait_pull_front(x); }
|
||||
queue_op_status wait_pull(value_type& x) { return queue->wait_pull(x); }
|
||||
void push(BOOST_THREAD_RV_REF(value_type) x) { queue->push_front(forward<value_type>(x)); }
|
||||
queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->try_push_front(forward<value_type>(x)); }
|
||||
queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->nonblocking_push_front(forward<value_type>(x)); }
|
||||
|
||||
327
include/boost/thread/concurrent_queues/sync_deque.hpp
Normal file
327
include/boost/thread/concurrent_queues/sync_deque.hpp
Normal file
@@ -0,0 +1,327 @@
|
||||
#ifndef BOOST_THREAD_CONCURRENT_QUEUES_SYNC_DEQUE_HPP
|
||||
#define BOOST_THREAD_CONCURRENT_QUEUES_SYNC_DEQUE_HPP
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Vicente J. Botet Escriba 2013-2014. 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)
|
||||
//
|
||||
// See http://www.boost.org/libs/thread for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/concurrent_queues/detail/sync_queue_base.hpp>
|
||||
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
#include <boost/thread/csbl/devector.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/smart_ptr/shared_ptr.hpp>
|
||||
#include <boost/smart_ptr/make_shared.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace concurrent
|
||||
{
|
||||
template <class ValueType, class Container = csbl::devector<ValueType> >
|
||||
class sync_deque
|
||||
: public detail::sync_queue_base<ValueType, Container >
|
||||
{
|
||||
typedef detail::sync_queue_base<ValueType, Container > super;
|
||||
|
||||
public:
|
||||
typedef ValueType value_type;
|
||||
//typedef typename super::value_type value_type; // fixme
|
||||
typedef typename super::underlying_queue_type underlying_queue_type;
|
||||
typedef typename super::size_type size_type;
|
||||
typedef typename super::op_status op_status;
|
||||
|
||||
// Constructors/Assignment/Destructors
|
||||
BOOST_THREAD_NO_COPYABLE(sync_deque)
|
||||
inline sync_deque();
|
||||
//template <typename Range>
|
||||
//inline explicit sync_deque(Range range);
|
||||
inline ~sync_deque();
|
||||
|
||||
// Modifiers
|
||||
inline void push_back(const value_type& x);
|
||||
inline queue_op_status try_push_back(const value_type& x);
|
||||
inline queue_op_status nonblocking_push_back(const value_type& x);
|
||||
inline queue_op_status wait_push_back(const value_type& x);
|
||||
inline void push_back(BOOST_THREAD_RV_REF(value_type) x);
|
||||
inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x);
|
||||
inline queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x);
|
||||
inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x);
|
||||
|
||||
// Observers/Modifiers
|
||||
inline void pull_front(value_type&);
|
||||
// enable_if is_nothrow_copy_movable<value_type>
|
||||
inline value_type pull_front();
|
||||
|
||||
inline queue_op_status try_pull_front(value_type&);
|
||||
inline queue_op_status nonblocking_pull_front(value_type&);
|
||||
inline queue_op_status wait_pull_front(ValueType& elem);
|
||||
|
||||
private:
|
||||
|
||||
inline queue_op_status try_pull_front(value_type& x, unique_lock<mutex>& lk);
|
||||
inline queue_op_status wait_pull_front(value_type& x, unique_lock<mutex>& lk);
|
||||
inline queue_op_status try_push_back(const value_type& x, unique_lock<mutex>& lk);
|
||||
inline queue_op_status wait_push_back(const value_type& x, unique_lock<mutex>& lk);
|
||||
inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
|
||||
inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
|
||||
|
||||
inline void pull_front(value_type& elem, unique_lock<mutex>& )
|
||||
{
|
||||
elem = boost::move(super::data_.front());
|
||||
super::data_.pop_front();
|
||||
}
|
||||
inline value_type pull_front(unique_lock<mutex>& )
|
||||
{
|
||||
value_type e = boost::move(super::data_.front());
|
||||
super::data_.pop_front();
|
||||
return boost::move(e);
|
||||
}
|
||||
|
||||
inline void push_back(const value_type& elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
super::data_.push_back(elem);
|
||||
super::notify_not_empty_if_needed(lk);
|
||||
}
|
||||
|
||||
inline void push_back(BOOST_THREAD_RV_REF(value_type) elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
super::data_.push_back(boost::move(elem));
|
||||
super::notify_not_empty_if_needed(lk);
|
||||
}
|
||||
};
|
||||
|
||||
template <class ValueType, class Container>
|
||||
sync_deque<ValueType, Container>::sync_deque() :
|
||||
super()
|
||||
{
|
||||
}
|
||||
|
||||
// template <class ValueType, class Container>
|
||||
// template <class Range>
|
||||
// explicit sync_deque<ValueType, Container>::sync_deque(Range range) :
|
||||
// data_(), closed_(false)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// typedef typename Range::iterator iterator_t;
|
||||
// iterator_t first = boost::begin(range);
|
||||
// iterator_t end = boost::end(range);
|
||||
// for (iterator_t cur = first; cur != end; ++cur)
|
||||
// {
|
||||
// data_.push(boost::move(*cur));;
|
||||
// }
|
||||
// notify_not_empty_if_needed(lk);
|
||||
// }
|
||||
// catch (...)
|
||||
// {
|
||||
// delete[] data_;
|
||||
// }
|
||||
// }
|
||||
|
||||
template <class ValueType, class Container>
|
||||
sync_deque<ValueType, Container>::~sync_deque()
|
||||
{
|
||||
}
|
||||
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_deque<ValueType, Container>::try_pull_front(ValueType& elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
if (super::empty(lk))
|
||||
{
|
||||
if (super::closed(lk)) return queue_op_status::closed;
|
||||
return queue_op_status::empty;
|
||||
}
|
||||
pull_front(elem, lk);
|
||||
return queue_op_status::success;
|
||||
}
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_deque<ValueType, Container>::wait_pull_front(ValueType& elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
if (super::empty(lk))
|
||||
{
|
||||
if (super::closed(lk)) return queue_op_status::closed;
|
||||
}
|
||||
bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
|
||||
if (has_been_closed) return queue_op_status::closed;
|
||||
pull_front(elem, lk);
|
||||
return queue_op_status::success;
|
||||
}
|
||||
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_deque<ValueType, Container>::try_pull_front(ValueType& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
return try_pull_front(elem, lk);
|
||||
}
|
||||
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_deque<ValueType, Container>::wait_pull_front(ValueType& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
return wait_pull_front(elem, lk);
|
||||
}
|
||||
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_deque<ValueType, Container>::nonblocking_pull_front(ValueType& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_, try_to_lock);
|
||||
if (!lk.owns_lock())
|
||||
{
|
||||
return queue_op_status::busy;
|
||||
}
|
||||
return try_pull_front(elem, lk);
|
||||
}
|
||||
|
||||
template <class ValueType, class Container>
|
||||
void sync_deque<ValueType, Container>::pull_front(ValueType& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
super::wait_until_not_empty(lk);
|
||||
pull_front(elem, lk);
|
||||
}
|
||||
|
||||
// enable if ValueType is nothrow movable
|
||||
template <class ValueType, class Container>
|
||||
ValueType sync_deque<ValueType, Container>::pull_front()
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
super::wait_until_not_empty(lk);
|
||||
return pull_front(lk);
|
||||
}
|
||||
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_deque<ValueType, Container>::try_push_back(const ValueType& elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
if (super::closed(lk)) return queue_op_status::closed;
|
||||
push_back(elem, lk);
|
||||
return queue_op_status::success;
|
||||
}
|
||||
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_deque<ValueType, Container>::try_push_back(const ValueType& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
return try_push_back(elem, lk);
|
||||
}
|
||||
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_deque<ValueType, Container>::wait_push_back(const ValueType& elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
if (super::closed(lk)) return queue_op_status::closed;
|
||||
push_back(elem, lk);
|
||||
return queue_op_status::success;
|
||||
}
|
||||
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_deque<ValueType, Container>::wait_push_back(const ValueType& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
return wait_push_back(elem, lk);
|
||||
}
|
||||
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_deque<ValueType, Container>::nonblocking_push_back(const ValueType& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_, try_to_lock);
|
||||
if (!lk.owns_lock()) return queue_op_status::busy;
|
||||
return try_push_back(elem, lk);
|
||||
}
|
||||
|
||||
template <class ValueType, class Container>
|
||||
void sync_deque<ValueType, Container>::push_back(const ValueType& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
super::throw_if_closed(lk);
|
||||
push_back(elem, lk);
|
||||
}
|
||||
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_deque<ValueType, Container>::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
if (super::closed(lk)) return queue_op_status::closed;
|
||||
push_back(boost::move(elem), lk);
|
||||
return queue_op_status::success;
|
||||
}
|
||||
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_deque<ValueType, Container>::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
return try_push_back(boost::move(elem), lk);
|
||||
}
|
||||
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_deque<ValueType, Container>::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
if (super::closed(lk)) return queue_op_status::closed;
|
||||
push_back(boost::move(elem), lk);
|
||||
return queue_op_status::success;
|
||||
}
|
||||
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_deque<ValueType, Container>::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
return wait_push_back(boost::move(elem), lk);
|
||||
}
|
||||
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_deque<ValueType, Container>::nonblocking_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_, try_to_lock);
|
||||
if (!lk.owns_lock())
|
||||
{
|
||||
return queue_op_status::busy;
|
||||
}
|
||||
return try_push_back(boost::move(elem), lk);
|
||||
}
|
||||
|
||||
template <class ValueType, class Container>
|
||||
void sync_deque<ValueType, Container>::push_back(BOOST_THREAD_RV_REF(ValueType) elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
super::throw_if_closed(lk);
|
||||
push_back(boost::move(elem), lk);
|
||||
}
|
||||
|
||||
template <class ValueType, class Container>
|
||||
sync_deque<ValueType, Container>& operator<<(sync_deque<ValueType, Container>& sbq, BOOST_THREAD_RV_REF(ValueType) elem)
|
||||
{
|
||||
sbq.push_back(boost::move(elem));
|
||||
return sbq;
|
||||
}
|
||||
|
||||
template <class ValueType, class Container>
|
||||
sync_deque<ValueType, Container>& operator<<(sync_deque<ValueType, Container>& sbq, ValueType const&elem)
|
||||
{
|
||||
sbq.push_back(elem);
|
||||
return sbq;
|
||||
}
|
||||
|
||||
template <class ValueType, class Container>
|
||||
sync_deque<ValueType, Container>& operator>>(sync_deque<ValueType, Container>& sbq, ValueType &elem)
|
||||
{
|
||||
sbq.pull_front(elem);
|
||||
return sbq;
|
||||
}
|
||||
|
||||
}
|
||||
using concurrent::sync_deque;
|
||||
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
@@ -39,9 +39,11 @@ namespace detail {
|
||||
class priority_queue
|
||||
{
|
||||
private:
|
||||
std::vector<Type> _elements;
|
||||
Container _elements;
|
||||
Compare _compare;
|
||||
public:
|
||||
typedef Type value_type;
|
||||
|
||||
explicit priority_queue(const Compare& compare = Compare())
|
||||
: _elements(), _compare(compare)
|
||||
{ }
|
||||
@@ -67,17 +69,21 @@ namespace detail {
|
||||
std::push_heap(_elements.begin(), _elements.end(), _compare);
|
||||
}
|
||||
|
||||
Type pull()
|
||||
void pop()
|
||||
{
|
||||
std::pop_heap(_elements.begin(), _elements.end(), _compare);
|
||||
Type result = boost::move(_elements.back());
|
||||
_elements.pop_back();
|
||||
}
|
||||
Type pull()
|
||||
{
|
||||
Type result = boost::move(_elements.front());
|
||||
pop();
|
||||
return boost::move(result);
|
||||
}
|
||||
|
||||
Type const& top()
|
||||
{
|
||||
return _elements.back();
|
||||
return _elements.front();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include <boost/thread/concurrent_queues/detail/sync_queue_base.hpp>
|
||||
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
#include <boost/thread/csbl/deque.hpp>
|
||||
#include <boost/thread/csbl/devector.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
|
||||
@@ -29,11 +29,11 @@ namespace boost
|
||||
{
|
||||
namespace concurrent
|
||||
{
|
||||
template <typename ValueType>
|
||||
template <class ValueType, class Container = csbl::devector<ValueType> >
|
||||
class sync_queue
|
||||
: public detail::sync_queue_base<ValueType, csbl::deque<ValueType> >
|
||||
: public detail::sync_queue_base<ValueType, Container >
|
||||
{
|
||||
typedef detail::sync_queue_base<ValueType, csbl::deque<ValueType> > super;
|
||||
typedef detail::sync_queue_base<ValueType, Container > super;
|
||||
|
||||
public:
|
||||
typedef ValueType value_type;
|
||||
@@ -45,65 +45,39 @@ namespace concurrent
|
||||
// Constructors/Assignment/Destructors
|
||||
BOOST_THREAD_NO_COPYABLE(sync_queue)
|
||||
inline sync_queue();
|
||||
//template <typename Range>
|
||||
//template <class Range>
|
||||
//inline explicit sync_queue(Range range);
|
||||
inline ~sync_queue();
|
||||
|
||||
// Modifiers
|
||||
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
|
||||
inline void push(const value_type& x);
|
||||
inline bool try_push(const value_type& x);
|
||||
inline bool try_push(no_block_tag, const value_type& x);
|
||||
inline queue_op_status try_push(const value_type& x);
|
||||
inline queue_op_status nonblocking_push(const value_type& x);
|
||||
inline queue_op_status wait_push(const value_type& x);
|
||||
inline void push(BOOST_THREAD_RV_REF(value_type) x);
|
||||
inline bool try_push(BOOST_THREAD_RV_REF(value_type) x);
|
||||
inline bool try_push(no_block_tag, BOOST_THREAD_RV_REF(value_type) x);
|
||||
#endif
|
||||
inline void push_back(const value_type& x);
|
||||
inline queue_op_status try_push_back(const value_type& x);
|
||||
inline queue_op_status nonblocking_push_back(const value_type& x);
|
||||
inline queue_op_status wait_push_back(const value_type& x);
|
||||
inline void push_back(BOOST_THREAD_RV_REF(value_type) x);
|
||||
inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x);
|
||||
inline queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x);
|
||||
inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x);
|
||||
inline queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x);
|
||||
inline queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x);
|
||||
inline queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x);
|
||||
|
||||
// Observers/Modifiers
|
||||
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
inline void pull(value_type&);
|
||||
inline void pull(ValueType& elem, bool & closed);
|
||||
// enable_if is_nothrow_copy_movable<value_type>
|
||||
inline value_type pull();
|
||||
inline shared_ptr<ValueType> ptr_pull();
|
||||
#endif
|
||||
inline void pull_front(value_type&);
|
||||
// enable_if is_nothrow_copy_movable<value_type>
|
||||
inline value_type pull_front();
|
||||
|
||||
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
inline bool try_pull(value_type&);
|
||||
inline bool try_pull(no_block_tag,value_type&);
|
||||
inline shared_ptr<ValueType> try_pull();
|
||||
#endif
|
||||
inline queue_op_status try_pull_front(value_type&);
|
||||
inline queue_op_status nonblocking_pull_front(value_type&);
|
||||
inline queue_op_status wait_pull_front(ValueType& elem);
|
||||
inline queue_op_status try_pull(value_type&);
|
||||
inline queue_op_status nonblocking_pull(value_type&);
|
||||
inline queue_op_status wait_pull(ValueType& elem);
|
||||
|
||||
private:
|
||||
|
||||
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
inline bool try_pull(value_type& x, unique_lock<mutex>& lk);
|
||||
inline bool try_push(const value_type& x, unique_lock<mutex>& lk);
|
||||
inline bool try_push(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
|
||||
inline shared_ptr<value_type> try_pull(unique_lock<mutex>& lk);
|
||||
#endif
|
||||
inline queue_op_status try_pull_front(value_type& x, unique_lock<mutex>& lk);
|
||||
inline queue_op_status wait_pull_front(value_type& x, unique_lock<mutex>& lk);
|
||||
inline queue_op_status try_push_back(const value_type& x, unique_lock<mutex>& lk);
|
||||
inline queue_op_status wait_push_back(const value_type& x, unique_lock<mutex>& lk);
|
||||
inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
|
||||
inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
|
||||
inline queue_op_status try_pull(value_type& x, unique_lock<mutex>& lk);
|
||||
inline queue_op_status wait_pull(value_type& x, unique_lock<mutex>& lk);
|
||||
inline queue_op_status try_push(const value_type& x, unique_lock<mutex>& lk);
|
||||
inline queue_op_status wait_push(const value_type& x, unique_lock<mutex>& lk);
|
||||
inline queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
|
||||
inline queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
|
||||
|
||||
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
inline void pull(value_type& elem, unique_lock<mutex>& )
|
||||
{
|
||||
elem = boost::move(super::data_.front());
|
||||
@@ -115,26 +89,7 @@ namespace concurrent
|
||||
super::data_.pop_front();
|
||||
return boost::move(e);
|
||||
}
|
||||
inline boost::shared_ptr<value_type> ptr_pull(unique_lock<mutex>& )
|
||||
{
|
||||
shared_ptr<value_type> res = make_shared<value_type>(boost::move(super::data_.front()));
|
||||
super::data_.pop_front();
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
inline void pull_front(value_type& elem, unique_lock<mutex>& )
|
||||
{
|
||||
elem = boost::move(super::data_.front());
|
||||
super::data_.pop_front();
|
||||
}
|
||||
inline value_type pull_front(unique_lock<mutex>& )
|
||||
{
|
||||
value_type e = boost::move(super::data_.front());
|
||||
super::data_.pop_front();
|
||||
return boost::move(e);
|
||||
}
|
||||
|
||||
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
inline void push(const value_type& elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
super::data_.push_back(elem);
|
||||
@@ -146,29 +101,17 @@ namespace concurrent
|
||||
super::data_.push_back(boost::move(elem));
|
||||
super::notify_not_empty_if_needed(lk);
|
||||
}
|
||||
#endif
|
||||
inline void push_back(const value_type& elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
super::data_.push_back(elem);
|
||||
super::notify_not_empty_if_needed(lk);
|
||||
}
|
||||
|
||||
inline void push_back(BOOST_THREAD_RV_REF(value_type) elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
super::data_.push_back(boost::move(elem));
|
||||
super::notify_not_empty_if_needed(lk);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ValueType>
|
||||
sync_queue<ValueType>::sync_queue() :
|
||||
template <class ValueType, class Container>
|
||||
sync_queue<ValueType, Container>::sync_queue() :
|
||||
super()
|
||||
{
|
||||
}
|
||||
|
||||
// template <typename ValueType>
|
||||
// template <typename Range>
|
||||
// explicit sync_queue<ValueType>::sync_queue(Range range) :
|
||||
// template <class ValueType, class Container>
|
||||
// template <class Range>
|
||||
// explicit sync_queue<ValueType, Container>::sync_queue(Range range) :
|
||||
// data_(), closed_(false)
|
||||
// {
|
||||
// try
|
||||
@@ -188,47 +131,24 @@ namespace concurrent
|
||||
// }
|
||||
// }
|
||||
|
||||
template <typename ValueType>
|
||||
sync_queue<ValueType>::~sync_queue()
|
||||
template <class ValueType, class Container>
|
||||
sync_queue<ValueType, Container>::~sync_queue()
|
||||
{
|
||||
}
|
||||
|
||||
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
template <typename ValueType>
|
||||
bool sync_queue<ValueType>::try_pull(ValueType& elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
if (super::empty(lk))
|
||||
{
|
||||
super::throw_if_closed(lk);
|
||||
return false;
|
||||
}
|
||||
pull(elem, lk);
|
||||
return true;
|
||||
}
|
||||
template <typename ValueType>
|
||||
shared_ptr<ValueType> sync_queue<ValueType>::try_pull(unique_lock<mutex>& lk)
|
||||
{
|
||||
if (super::empty(lk))
|
||||
{
|
||||
super::throw_if_closed(lk);
|
||||
return shared_ptr<ValueType>();
|
||||
}
|
||||
return ptr_pull(lk);
|
||||
}
|
||||
#endif
|
||||
template <typename ValueType>
|
||||
queue_op_status sync_queue<ValueType>::try_pull_front(ValueType& elem, unique_lock<mutex>& lk)
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_queue<ValueType, Container>::try_pull(ValueType& elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
if (super::empty(lk))
|
||||
{
|
||||
if (super::closed(lk)) return queue_op_status::closed;
|
||||
return queue_op_status::empty;
|
||||
}
|
||||
pull_front(elem, lk);
|
||||
pull(elem, lk);
|
||||
return queue_op_status::success;
|
||||
}
|
||||
template <typename ValueType>
|
||||
queue_op_status sync_queue<ValueType>::wait_pull_front(ValueType& elem, unique_lock<mutex>& lk)
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_queue<ValueType, Container>::wait_pull(ValueType& elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
if (super::empty(lk))
|
||||
{
|
||||
@@ -236,301 +156,165 @@ namespace concurrent
|
||||
}
|
||||
bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
|
||||
if (has_been_closed) return queue_op_status::closed;
|
||||
pull_front(elem, lk);
|
||||
pull(elem, lk);
|
||||
return queue_op_status::success;
|
||||
}
|
||||
|
||||
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
template <typename ValueType>
|
||||
bool sync_queue<ValueType>::try_pull(ValueType& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
return try_pull(elem, lk);
|
||||
}
|
||||
#endif
|
||||
template <typename ValueType>
|
||||
queue_op_status sync_queue<ValueType>::try_pull_front(ValueType& elem)
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_queue<ValueType, Container>::try_pull(ValueType& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
return try_pull_front(elem, lk);
|
||||
return try_pull(elem, lk);
|
||||
}
|
||||
|
||||
template <typename ValueType>
|
||||
queue_op_status sync_queue<ValueType>::wait_pull_front(ValueType& elem)
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_queue<ValueType, Container>::wait_pull(ValueType& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
return wait_pull_front(elem, lk);
|
||||
return wait_pull(elem, lk);
|
||||
}
|
||||
|
||||
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
template <typename ValueType>
|
||||
bool sync_queue<ValueType>::try_pull(no_block_tag,ValueType& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_, try_to_lock);
|
||||
if (!lk.owns_lock())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return try_pull(elem, lk);
|
||||
}
|
||||
template <typename ValueType>
|
||||
boost::shared_ptr<ValueType> sync_queue<ValueType>::try_pull()
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
return try_pull(lk);
|
||||
}
|
||||
#endif
|
||||
template <typename ValueType>
|
||||
queue_op_status sync_queue<ValueType>::nonblocking_pull_front(ValueType& elem)
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_queue<ValueType, Container>::nonblocking_pull(ValueType& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_, try_to_lock);
|
||||
if (!lk.owns_lock())
|
||||
{
|
||||
return queue_op_status::busy;
|
||||
}
|
||||
return try_pull_front(elem, lk);
|
||||
return try_pull(elem, lk);
|
||||
}
|
||||
|
||||
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
template <typename ValueType>
|
||||
void sync_queue<ValueType>::pull(ValueType& elem)
|
||||
template <class ValueType, class Container>
|
||||
void sync_queue<ValueType, Container>::pull(ValueType& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
super::wait_until_not_empty(lk);
|
||||
pull(elem, lk);
|
||||
}
|
||||
template <typename ValueType>
|
||||
void sync_queue<ValueType>::pull(ValueType& elem, bool & has_been_closed)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
has_been_closed = super::wait_until_not_empty_or_closed(lk);
|
||||
if (has_been_closed) {return;}
|
||||
pull(elem, lk);
|
||||
}
|
||||
|
||||
// enable if ValueType is nothrow movable
|
||||
template <typename ValueType>
|
||||
ValueType sync_queue<ValueType>::pull()
|
||||
template <class ValueType, class Container>
|
||||
ValueType sync_queue<ValueType, Container>::pull()
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
super::wait_until_not_empty(lk);
|
||||
return pull(lk);
|
||||
}
|
||||
template <typename ValueType>
|
||||
boost::shared_ptr<ValueType> sync_queue<ValueType>::ptr_pull()
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
super::wait_until_not_empty(lk);
|
||||
return ptr_pull(lk);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename ValueType>
|
||||
void sync_queue<ValueType>::pull_front(ValueType& elem)
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_queue<ValueType, Container>::try_push(const ValueType& elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
super::wait_until_not_empty(lk);
|
||||
pull_front(elem, lk);
|
||||
}
|
||||
|
||||
// enable if ValueType is nothrow movable
|
||||
template <typename ValueType>
|
||||
ValueType sync_queue<ValueType>::pull_front()
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
super::wait_until_not_empty(lk);
|
||||
return pull_front(lk);
|
||||
}
|
||||
|
||||
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
template <typename ValueType>
|
||||
bool sync_queue<ValueType>::try_push(const ValueType& elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
super::throw_if_closed(lk);
|
||||
if (super::closed(lk)) return queue_op_status::closed;
|
||||
push(elem, lk);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename ValueType>
|
||||
bool sync_queue<ValueType>::try_push(const ValueType& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
return try_push(elem, lk);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename ValueType>
|
||||
queue_op_status sync_queue<ValueType>::try_push_back(const ValueType& elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
if (super::closed(lk)) return queue_op_status::closed;
|
||||
push_back(elem, lk);
|
||||
return queue_op_status::success;
|
||||
}
|
||||
|
||||
template <typename ValueType>
|
||||
queue_op_status sync_queue<ValueType>::try_push_back(const ValueType& elem)
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_queue<ValueType, Container>::try_push(const ValueType& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
return try_push_back(elem, lk);
|
||||
return try_push(elem, lk);
|
||||
}
|
||||
|
||||
template <typename ValueType>
|
||||
queue_op_status sync_queue<ValueType>::wait_push_back(const ValueType& elem, unique_lock<mutex>& lk)
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_queue<ValueType, Container>::wait_push(const ValueType& elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
if (super::closed(lk)) return queue_op_status::closed;
|
||||
push_back(elem, lk);
|
||||
push(elem, lk);
|
||||
return queue_op_status::success;
|
||||
}
|
||||
|
||||
template <typename ValueType>
|
||||
queue_op_status sync_queue<ValueType>::wait_push_back(const ValueType& elem)
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_queue<ValueType, Container>::wait_push(const ValueType& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
return wait_push_back(elem, lk);
|
||||
return wait_push(elem, lk);
|
||||
}
|
||||
|
||||
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
template <typename ValueType>
|
||||
bool sync_queue<ValueType>::try_push(no_block_tag, const ValueType& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_, try_to_lock);
|
||||
if (!lk.owns_lock()) return false;
|
||||
return try_push(elem, lk);
|
||||
}
|
||||
#endif
|
||||
template <typename ValueType>
|
||||
queue_op_status sync_queue<ValueType>::nonblocking_push_back(const ValueType& elem)
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_queue<ValueType, Container>::nonblocking_push(const ValueType& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_, try_to_lock);
|
||||
if (!lk.owns_lock()) return queue_op_status::busy;
|
||||
return try_push_back(elem, lk);
|
||||
return try_push(elem, lk);
|
||||
}
|
||||
|
||||
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
template <typename ValueType>
|
||||
void sync_queue<ValueType>::push(const ValueType& elem)
|
||||
template <class ValueType, class Container>
|
||||
void sync_queue<ValueType, Container>::push(const ValueType& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
super::throw_if_closed(lk);
|
||||
push(elem, lk);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename ValueType>
|
||||
void sync_queue<ValueType>::push_back(const ValueType& elem)
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_queue<ValueType, Container>::try_push(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
super::throw_if_closed(lk);
|
||||
push_back(elem, lk);
|
||||
}
|
||||
|
||||
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
template <typename ValueType>
|
||||
bool sync_queue<ValueType>::try_push(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
super::throw_if_closed(lk);
|
||||
if (super::closed(lk)) return queue_op_status::closed;
|
||||
push(boost::move(elem), lk);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename ValueType>
|
||||
bool sync_queue<ValueType>::try_push(BOOST_THREAD_RV_REF(ValueType) elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
return try_push(boost::move(elem), lk);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename ValueType>
|
||||
queue_op_status sync_queue<ValueType>::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
if (super::closed(lk)) return queue_op_status::closed;
|
||||
push_back(boost::move(elem), lk);
|
||||
return queue_op_status::success;
|
||||
}
|
||||
|
||||
template <typename ValueType>
|
||||
queue_op_status sync_queue<ValueType>::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_queue<ValueType, Container>::try_push(BOOST_THREAD_RV_REF(ValueType) elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
return try_push_back(boost::move(elem), lk);
|
||||
return try_push(boost::move(elem), lk);
|
||||
}
|
||||
|
||||
template <typename ValueType>
|
||||
queue_op_status sync_queue<ValueType>::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_queue<ValueType, Container>::wait_push(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
|
||||
{
|
||||
if (super::closed(lk)) return queue_op_status::closed;
|
||||
push_back(boost::move(elem), lk);
|
||||
push(boost::move(elem), lk);
|
||||
return queue_op_status::success;
|
||||
}
|
||||
|
||||
template <typename ValueType>
|
||||
queue_op_status sync_queue<ValueType>::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_queue<ValueType, Container>::wait_push(BOOST_THREAD_RV_REF(ValueType) elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
return wait_push_back(boost::move(elem), lk);
|
||||
return wait_push(boost::move(elem), lk);
|
||||
}
|
||||
|
||||
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
template <typename ValueType>
|
||||
bool sync_queue<ValueType>::try_push(no_block_tag, BOOST_THREAD_RV_REF(ValueType) elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_, try_to_lock);
|
||||
if (!lk.owns_lock())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return try_push(boost::move(elem), lk);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename ValueType>
|
||||
queue_op_status sync_queue<ValueType>::nonblocking_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
|
||||
template <class ValueType, class Container>
|
||||
queue_op_status sync_queue<ValueType, Container>::nonblocking_push(BOOST_THREAD_RV_REF(ValueType) elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_, try_to_lock);
|
||||
if (!lk.owns_lock())
|
||||
{
|
||||
return queue_op_status::busy;
|
||||
}
|
||||
return try_push_back(boost::move(elem), lk);
|
||||
return try_push(boost::move(elem), lk);
|
||||
}
|
||||
|
||||
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
template <typename ValueType>
|
||||
void sync_queue<ValueType>::push(BOOST_THREAD_RV_REF(ValueType) elem)
|
||||
template <class ValueType, class Container>
|
||||
void sync_queue<ValueType, Container>::push(BOOST_THREAD_RV_REF(ValueType) elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
super::throw_if_closed(lk);
|
||||
push(boost::move(elem), lk);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename ValueType>
|
||||
void sync_queue<ValueType>::push_back(BOOST_THREAD_RV_REF(ValueType) elem)
|
||||
template <class ValueType, class Container>
|
||||
sync_queue<ValueType, Container>& operator<<(sync_queue<ValueType, Container>& sbq, BOOST_THREAD_RV_REF(ValueType) elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
super::throw_if_closed(lk);
|
||||
push_back(boost::move(elem), lk);
|
||||
}
|
||||
|
||||
template <typename ValueType>
|
||||
sync_queue<ValueType>& operator<<(sync_queue<ValueType>& sbq, BOOST_THREAD_RV_REF(ValueType) elem)
|
||||
{
|
||||
sbq.push_back(boost::move(elem));
|
||||
sbq.push(boost::move(elem));
|
||||
return sbq;
|
||||
}
|
||||
|
||||
template <typename ValueType>
|
||||
sync_queue<ValueType>& operator<<(sync_queue<ValueType>& sbq, ValueType const&elem)
|
||||
template <class ValueType, class Container>
|
||||
sync_queue<ValueType, Container>& operator<<(sync_queue<ValueType, Container>& sbq, ValueType const&elem)
|
||||
{
|
||||
sbq.push_back(elem);
|
||||
sbq.push(elem);
|
||||
return sbq;
|
||||
}
|
||||
|
||||
template <typename ValueType>
|
||||
sync_queue<ValueType>& operator>>(sync_queue<ValueType>& sbq, ValueType &elem)
|
||||
template <class ValueType, class Container>
|
||||
sync_queue<ValueType, Container>& operator>>(sync_queue<ValueType, Container>& sbq, ValueType &elem)
|
||||
{
|
||||
sbq.pull_front(elem);
|
||||
sbq.pull(elem);
|
||||
return sbq;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,11 +24,12 @@ namespace concurrent
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <class T>
|
||||
template <class T, class Clock = chrono::steady_clock>
|
||||
struct scheduled_type
|
||||
{
|
||||
typedef typename chrono::steady_clock clock;
|
||||
typedef chrono::steady_clock::time_point time_point;
|
||||
typedef T value_type;
|
||||
typedef Clock clock;
|
||||
typedef typename clock::time_point time_point;
|
||||
T data;
|
||||
time_point time;
|
||||
|
||||
@@ -64,20 +65,17 @@ namespace detail
|
||||
|
||||
} //end detail namespace
|
||||
|
||||
template <class T>
|
||||
template <class T, class Clock = chrono::steady_clock>
|
||||
class sync_timed_queue
|
||||
: private sync_priority_queue<detail::scheduled_type<T> >
|
||||
: private sync_priority_queue<detail::scheduled_type<T, Clock> >
|
||||
{
|
||||
typedef detail::scheduled_type<T> stype;
|
||||
typedef sync_priority_queue<stype> super;
|
||||
public:
|
||||
//typedef typename stype::clock clock; // fixme
|
||||
typedef typename chrono::steady_clock clock;
|
||||
|
||||
typedef T value_type;
|
||||
typedef Clock clock;
|
||||
typedef typename clock::duration duration;
|
||||
typedef typename clock::time_point time_point;
|
||||
typedef T value_type;
|
||||
//typedef typename super::value_type value_type; // fixme
|
||||
typedef typename super::underlying_queue_type underlying_queue_type;
|
||||
typedef typename super::size_type size_type;
|
||||
typedef typename super::op_status op_status;
|
||||
@@ -94,21 +92,29 @@ namespace detail
|
||||
T pull();
|
||||
void pull(T& elem);
|
||||
|
||||
queue_op_status pull_until(const clock::time_point& tp, T& elem);
|
||||
queue_op_status pull_for(const clock::duration& dura, T& elem);
|
||||
template <class Duration>
|
||||
queue_op_status pull_until(chrono::time_point<clock,Duration> const& tp, T& elem);
|
||||
template <class Rep, class Period>
|
||||
queue_op_status pull_for(chrono::duration<Rep,Period> const& dura, T& elem);
|
||||
|
||||
queue_op_status try_pull(T& elem);
|
||||
queue_op_status wait_pull(T& elem);
|
||||
queue_op_status nonblocking_pull(T& elem);
|
||||
|
||||
void push(const T& elem, const time_point& tp);
|
||||
void push(const T& elem, const duration& dura);
|
||||
template <class Duration>
|
||||
void push(const T& elem, chrono::time_point<clock,Duration> const& tp);
|
||||
template <class Rep, class Period>
|
||||
void push(const T& elem, chrono::duration<Rep,Period> const& dura);
|
||||
|
||||
queue_op_status try_push(const T& elem, const time_point& tp);
|
||||
queue_op_status try_push(const T& elem, const duration& dura);
|
||||
template <class Duration>
|
||||
queue_op_status try_push(const T& elem, chrono::time_point<clock,Duration> const& tp);
|
||||
template <class Rep, class Period>
|
||||
queue_op_status try_push(const T& elem, chrono::duration<Rep,Period> const& dura);
|
||||
|
||||
queue_op_status try_push(BOOST_THREAD_RV_REF(T) elem, const time_point& tp);
|
||||
queue_op_status try_push(BOOST_THREAD_RV_REF(T) elem, const duration& dura);
|
||||
template <class Duration>
|
||||
queue_op_status try_push(BOOST_THREAD_RV_REF(T) elem, chrono::time_point<clock,Duration> const& tp);
|
||||
template <class Rep, class Period>
|
||||
queue_op_status try_push(BOOST_THREAD_RV_REF(T) elem, chrono::duration<Rep,Period> const& dura);
|
||||
|
||||
private:
|
||||
T pull(unique_lock<mutex>&);
|
||||
@@ -122,11 +128,10 @@ namespace detail
|
||||
|
||||
queue_op_status wait_pull(unique_lock<mutex>& lk, T& elem);
|
||||
|
||||
//queue_op_status nonblocking_pull(unique_lock<mutex>& lk, T& elem);
|
||||
|
||||
bool wait_until_not_empty_time_reached_or_closed(unique_lock<mutex>&);
|
||||
T pull_when_time_reached(unique_lock<mutex>&);
|
||||
queue_op_status pull_when_time_reached_until(unique_lock<mutex>&, const clock::time_point& tp, T& elem);
|
||||
template <class Duration>
|
||||
queue_op_status pull_when_time_reached_until(unique_lock<mutex>&, chrono::time_point<clock,Duration> const& tp, T& elem);
|
||||
bool time_not_reached(unique_lock<mutex>&);
|
||||
bool time_not_reached(lock_guard<mutex>&);
|
||||
bool empty_or_time_not_reached(unique_lock<mutex>&);
|
||||
@@ -139,58 +144,64 @@ namespace detail
|
||||
}; //end class
|
||||
|
||||
|
||||
template <class T>
|
||||
void sync_timed_queue<T>::push(const T& elem, const time_point& tp)
|
||||
template <class T, class Clock>
|
||||
template <class Duration>
|
||||
void sync_timed_queue<T, Clock>::push(const T& elem, chrono::time_point<clock,Duration> const& tp)
|
||||
{
|
||||
super::push(stype(elem,tp));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void sync_timed_queue<T>::push(const T& elem, const duration& dura)
|
||||
template <class T, class Clock>
|
||||
template <class Rep, class Period>
|
||||
void sync_timed_queue<T, Clock>::push(const T& elem, chrono::duration<Rep,Period> const& dura)
|
||||
{
|
||||
push(elem, clock::now() + dura);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
queue_op_status sync_timed_queue<T>::try_push(const T& elem, const time_point& tp)
|
||||
template <class T, class Clock>
|
||||
template <class Duration>
|
||||
queue_op_status sync_timed_queue<T, Clock>::try_push(const T& elem, chrono::time_point<clock,Duration> const& tp)
|
||||
{
|
||||
return super::try_push(stype(elem,tp));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
queue_op_status sync_timed_queue<T>::try_push(const T& elem, const duration& dura)
|
||||
template <class T, class Clock>
|
||||
template <class Rep, class Period>
|
||||
queue_op_status sync_timed_queue<T, Clock>::try_push(const T& elem, chrono::duration<Rep,Period> const& dura)
|
||||
{
|
||||
return try_push(elem,clock::now() + dura);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
queue_op_status sync_timed_queue<T>::try_push(BOOST_THREAD_RV_REF(T) elem, const time_point& tp)
|
||||
template <class T, class Clock>
|
||||
template <class Duration>
|
||||
queue_op_status sync_timed_queue<T, Clock>::try_push(BOOST_THREAD_RV_REF(T) elem, chrono::time_point<clock,Duration> const& tp)
|
||||
{
|
||||
return super::try_push(stype(boost::move(elem), tp));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
queue_op_status sync_timed_queue<T>::try_push(BOOST_THREAD_RV_REF(T) elem, const duration& dura)
|
||||
template <class T, class Clock>
|
||||
template <class Rep, class Period>
|
||||
queue_op_status sync_timed_queue<T, Clock>::try_push(BOOST_THREAD_RV_REF(T) elem, chrono::duration<Rep,Period> const& dura)
|
||||
{
|
||||
return try_push(boost::move(elem), clock::now() + dura);
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
template <class T>
|
||||
bool sync_timed_queue<T>::time_not_reached(unique_lock<mutex>&)
|
||||
template <class T, class Clock>
|
||||
bool sync_timed_queue<T, Clock>::time_not_reached(unique_lock<mutex>&)
|
||||
{
|
||||
return super::data_.top().time_not_reached();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool sync_timed_queue<T>::time_not_reached(lock_guard<mutex>&)
|
||||
template <class T, class Clock>
|
||||
bool sync_timed_queue<T, Clock>::time_not_reached(lock_guard<mutex>&)
|
||||
{
|
||||
return super::data_.top().time_not_reached();
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
template <class T>
|
||||
bool sync_timed_queue<T>::wait_until_not_empty_time_reached_or_closed(unique_lock<mutex>& lk)
|
||||
template <class T, class Clock>
|
||||
bool sync_timed_queue<T, Clock>::wait_until_not_empty_time_reached_or_closed(unique_lock<mutex>& lk)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
@@ -207,8 +218,8 @@ namespace detail
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
template <class T>
|
||||
T sync_timed_queue<T>::pull_when_time_reached(unique_lock<mutex>& lk)
|
||||
template <class T, class Clock>
|
||||
T sync_timed_queue<T, Clock>::pull_when_time_reached(unique_lock<mutex>& lk)
|
||||
{
|
||||
while (time_not_reached(lk))
|
||||
{
|
||||
@@ -219,11 +230,12 @@ namespace detail
|
||||
return pull(lk);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <class T, class Clock>
|
||||
template <class Duration>
|
||||
queue_op_status
|
||||
sync_timed_queue<T>::pull_when_time_reached_until(unique_lock<mutex>& lk, const clock::time_point& tp, T& elem)
|
||||
sync_timed_queue<T, Clock>::pull_when_time_reached_until(unique_lock<mutex>& lk, chrono::time_point<clock,Duration> const& tp, T& elem)
|
||||
{
|
||||
clock::time_point tpmin = (tp < super::data_.top().time) ? tp : super::data_.top().time;
|
||||
chrono::time_point<clock,Duration> tpmin = (tp < super::data_.top().time) ? tp : super::data_.top().time;
|
||||
while (time_not_reached(lk))
|
||||
{
|
||||
super::throw_if_closed(lk);
|
||||
@@ -237,15 +249,15 @@ namespace detail
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
template <class T>
|
||||
bool sync_timed_queue<T>::empty_or_time_not_reached(unique_lock<mutex>& lk)
|
||||
template <class T, class Clock>
|
||||
bool sync_timed_queue<T, Clock>::empty_or_time_not_reached(unique_lock<mutex>& lk)
|
||||
{
|
||||
if ( super::empty(lk) ) return true;
|
||||
if ( time_not_reached(lk) ) return true;
|
||||
return false;
|
||||
}
|
||||
template <class T>
|
||||
bool sync_timed_queue<T>::empty_or_time_not_reached(lock_guard<mutex>& lk)
|
||||
template <class T, class Clock>
|
||||
bool sync_timed_queue<T, Clock>::empty_or_time_not_reached(lock_guard<mutex>& lk)
|
||||
{
|
||||
if ( super::empty(lk) ) return true;
|
||||
if ( time_not_reached(lk) ) return true;
|
||||
@@ -253,8 +265,8 @@ namespace detail
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
template <class T>
|
||||
T sync_timed_queue<T>::pull(unique_lock<mutex>&)
|
||||
template <class T, class Clock>
|
||||
T sync_timed_queue<T, Clock>::pull(unique_lock<mutex>&)
|
||||
{
|
||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
return boost::move(super::data_.pull().data);
|
||||
@@ -263,8 +275,8 @@ namespace detail
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T sync_timed_queue<T>::pull(lock_guard<mutex>&)
|
||||
template <class T, class Clock>
|
||||
T sync_timed_queue<T, Clock>::pull(lock_guard<mutex>&)
|
||||
{
|
||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
return boost::move(super::data_.pull().data);
|
||||
@@ -272,8 +284,8 @@ namespace detail
|
||||
return super::data_.pull().data;
|
||||
#endif
|
||||
}
|
||||
template <class T>
|
||||
T sync_timed_queue<T>::pull()
|
||||
template <class T, class Clock>
|
||||
T sync_timed_queue<T, Clock>::pull()
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
super::wait_until_not_empty(lk);
|
||||
@@ -281,8 +293,8 @@ namespace detail
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
template <class T>
|
||||
void sync_timed_queue<T>::pull(unique_lock<mutex>&, T& elem)
|
||||
template <class T, class Clock>
|
||||
void sync_timed_queue<T, Clock>::pull(unique_lock<mutex>&, T& elem)
|
||||
{
|
||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
elem = boost::move(super::data_.pull().data);
|
||||
@@ -291,8 +303,8 @@ namespace detail
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void sync_timed_queue<T>::pull(lock_guard<mutex>&, T& elem)
|
||||
template <class T, class Clock>
|
||||
void sync_timed_queue<T, Clock>::pull(lock_guard<mutex>&, T& elem)
|
||||
{
|
||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
elem = boost::move(super::data_.pull().data);
|
||||
@@ -301,8 +313,8 @@ namespace detail
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void sync_timed_queue<T>::pull(T& elem)
|
||||
template <class T, class Clock>
|
||||
void sync_timed_queue<T, Clock>::pull(T& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
super::wait_until_not_empty(lk);
|
||||
@@ -310,9 +322,10 @@ namespace detail
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
template <class T>
|
||||
template <class T, class Clock>
|
||||
template <class Duration>
|
||||
queue_op_status
|
||||
sync_timed_queue<T>::pull_until(const clock::time_point& tp, T& elem)
|
||||
sync_timed_queue<T, Clock>::pull_until(chrono::time_point<clock,Duration> const& tp, T& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
|
||||
@@ -322,16 +335,17 @@ namespace detail
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
template <class T>
|
||||
template <class T, class Clock>
|
||||
template <class Rep, class Period>
|
||||
queue_op_status
|
||||
sync_timed_queue<T>::pull_for(const clock::duration& dura, T& elem)
|
||||
sync_timed_queue<T, Clock>::pull_for(chrono::duration<Rep,Period> const& dura, T& elem)
|
||||
{
|
||||
return pull_until(clock::now() + dura, elem);
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
template <class T>
|
||||
queue_op_status sync_timed_queue<T>::try_pull(unique_lock<mutex>& lk, T& elem)
|
||||
template <class T, class Clock>
|
||||
queue_op_status sync_timed_queue<T, Clock>::try_pull(unique_lock<mutex>& lk, T& elem)
|
||||
{
|
||||
if ( super::empty(lk) )
|
||||
{
|
||||
@@ -347,8 +361,8 @@ namespace detail
|
||||
pull(lk, elem);
|
||||
return queue_op_status::success;
|
||||
}
|
||||
template <class T>
|
||||
queue_op_status sync_timed_queue<T>::try_pull(lock_guard<mutex>& lk, T& elem)
|
||||
template <class T, class Clock>
|
||||
queue_op_status sync_timed_queue<T, Clock>::try_pull(lock_guard<mutex>& lk, T& elem)
|
||||
{
|
||||
if ( super::empty(lk) )
|
||||
{
|
||||
@@ -364,16 +378,16 @@ namespace detail
|
||||
return queue_op_status::success;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
queue_op_status sync_timed_queue<T>::try_pull(T& elem)
|
||||
template <class T, class Clock>
|
||||
queue_op_status sync_timed_queue<T, Clock>::try_pull(T& elem)
|
||||
{
|
||||
lock_guard<mutex> lk(super::mtx_);
|
||||
return try_pull(lk, elem);
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
template <class T>
|
||||
queue_op_status sync_timed_queue<T>::wait_pull(unique_lock<mutex>& lk, T& elem)
|
||||
template <class T, class Clock>
|
||||
queue_op_status sync_timed_queue<T, Clock>::wait_pull(unique_lock<mutex>& lk, T& elem)
|
||||
{
|
||||
if (super::empty(lk))
|
||||
{
|
||||
@@ -385,16 +399,16 @@ namespace detail
|
||||
return queue_op_status::success;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
queue_op_status sync_timed_queue<T>::wait_pull(T& elem)
|
||||
template <class T, class Clock>
|
||||
queue_op_status sync_timed_queue<T, Clock>::wait_pull(T& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_);
|
||||
return wait_pull(lk, elem);
|
||||
}
|
||||
|
||||
// ///////////////////////////
|
||||
// template <class T>
|
||||
// queue_op_status sync_timed_queue<T>::wait_pull(unique_lock<mutex> &lk, T& elem)
|
||||
// template <class T, class Clock>
|
||||
// queue_op_status sync_timed_queue<T, Clock>::wait_pull(unique_lock<mutex> &lk, T& elem)
|
||||
// {
|
||||
// if (super::empty(lk))
|
||||
// {
|
||||
@@ -406,15 +420,15 @@ namespace detail
|
||||
// return queue_op_status::success;
|
||||
// }
|
||||
// template <class T>
|
||||
// queue_op_status sync_timed_queue<T>::wait_pull(T& elem)
|
||||
// queue_op_status sync_timed_queue<T, Clock>::wait_pull(T& elem)
|
||||
// {
|
||||
// unique_lock<mutex> lk(super::mtx_);
|
||||
// return wait_pull(lk, elem);
|
||||
// }
|
||||
|
||||
///////////////////////////
|
||||
template <class T>
|
||||
queue_op_status sync_timed_queue<T>::nonblocking_pull(T& elem)
|
||||
template <class T, class Clock>
|
||||
queue_op_status sync_timed_queue<T, Clock>::nonblocking_pull(T& elem)
|
||||
{
|
||||
unique_lock<mutex> lk(super::mtx_, try_to_lock);
|
||||
if (! lk.owns_lock()) return queue_op_status::busy;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
// [
|
||||
// _Ty=non_copyable
|
||||
// ]
|
||||
#if defined BOOST_THREAD_USES_BOOST_DEQUE || defined BOOST_NO_CXX11_HDR_DEQUE || defined BOOST_NO_CXX11_RVALUE_REFERENCES || (defined _MSC_VER && _MSC_FULL_VER < 180020827)
|
||||
#if defined BOOST_THREAD_USES_BOOST_DEQUE || defined BOOST_NO_CXX11_RVALUE_REFERENCES || (defined _MSC_VER && _MSC_FULL_VER < 180020827)
|
||||
#ifndef BOOST_THREAD_USES_BOOST_DEQUE
|
||||
#define BOOST_THREAD_USES_BOOST_DEQUE
|
||||
#endif
|
||||
|
||||
100
include/boost/thread/csbl/devector.hpp
Normal file
100
include/boost/thread/csbl/devector.hpp
Normal file
@@ -0,0 +1,100 @@
|
||||
// Copyright (C) 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)
|
||||
//
|
||||
// 2013/10 Vicente J. Botet Escriba
|
||||
// Creation.
|
||||
|
||||
#ifndef BOOST_CSBL_DEVECTOR_HPP
|
||||
#define BOOST_CSBL_DEVECTOR_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <boost/thread/csbl/vector.hpp>
|
||||
#include <boost/move/detail/move_helpers.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace csbl
|
||||
{
|
||||
template <class T>
|
||||
class devector
|
||||
{
|
||||
typedef vector<T> vector_type;
|
||||
vector<T> data_;
|
||||
std::size_t front_index_;
|
||||
|
||||
BOOST_COPYABLE_AND_MOVABLE(devector)
|
||||
|
||||
template <class U>
|
||||
void priv_push_back(BOOST_FWD_REF(U) x)
|
||||
{ data_.push_back(boost::forward<U>(x)); }
|
||||
|
||||
public:
|
||||
typedef typename vector_type::size_type size_type;
|
||||
typedef typename vector_type::reference reference;
|
||||
typedef typename vector_type::const_reference const_reference;
|
||||
|
||||
|
||||
devector() : front_index_(0) {}
|
||||
devector(devector const& x) BOOST_NOEXCEPT
|
||||
: data_(x.data_),
|
||||
front_index_(x.front_index_)
|
||||
{}
|
||||
devector(BOOST_RV_REF(devector) x) BOOST_NOEXCEPT
|
||||
: data_(boost::move(x.data_)),
|
||||
front_index_(x.front_index_)
|
||||
{}
|
||||
|
||||
devector& operator=(BOOST_COPY_ASSIGN_REF(devector) x)
|
||||
{
|
||||
if (&x != this)
|
||||
{
|
||||
data_ = x.data_;
|
||||
front_index_ = x.front_index_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
devector& operator=(BOOST_RV_REF(devector) x)
|
||||
BOOST_NOEXCEPT_IF(vector<T>::allocator_traits_type::propagate_on_container_move_assignment::value)
|
||||
{
|
||||
data_ = boost::move(x.data_);
|
||||
front_index_ = x.front_index_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool empty() const BOOST_NOEXCEPT
|
||||
{ return data_.size() == front_index_; }
|
||||
|
||||
size_type size() const BOOST_NOEXCEPT
|
||||
{ return data_.size() - front_index_; }
|
||||
|
||||
reference front() BOOST_NOEXCEPT
|
||||
{ return data_[front_index_]; }
|
||||
|
||||
const_reference front() const BOOST_NOEXCEPT
|
||||
{ return data_[front_index_]; }
|
||||
|
||||
reference back() BOOST_NOEXCEPT
|
||||
{ return data_.back(); }
|
||||
|
||||
const_reference back() const BOOST_NOEXCEPT
|
||||
{ return data_.back(); }
|
||||
|
||||
BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
|
||||
|
||||
void pop_front()
|
||||
{
|
||||
++front_index_;
|
||||
if (empty()) {
|
||||
data_.clear();
|
||||
front_index_=0;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif // header
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if defined BOOST_THREAD_USES_BOOST_LIST || defined BOOST_NO_CXX11_HDR_LIST || defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
#if defined BOOST_THREAD_USES_BOOST_LIST || defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
#ifndef BOOST_THREAD_USES_BOOST_LIST
|
||||
#define BOOST_THREAD_USES_BOOST_LIST
|
||||
#endif
|
||||
|
||||
45
include/boost/thread/csbl/queue.hpp
Normal file
45
include/boost/thread/csbl/queue.hpp
Normal file
@@ -0,0 +1,45 @@
|
||||
// Copyright (C) 2015 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)
|
||||
//
|
||||
// 2013/10 Vicente J. Botet Escriba
|
||||
// Creation.
|
||||
|
||||
#ifndef BOOST_CSBL_QUEUE_HPP
|
||||
#define BOOST_CSBL_QUEUE_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
// MSVC has some trouble instantiating a non_copyable type
|
||||
//C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xmemory0(606) : error C2248: 'non_copyable::non_copyable' : cannot access private member declared in class 'non_copyable'
|
||||
// ..\libs\thread\test\sync\mutual_exclusion\queue_views\single_thread_pass.cpp(24) : see declaration of 'non_copyable::non_copyable'
|
||||
// ..\libs\thread\test\sync\mutual_exclusion\queue_views\single_thread_pass.cpp(23) : see declaration of 'non_copyable'
|
||||
// C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xmemory0(605) : while compiling class template member function 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)'
|
||||
// with
|
||||
// [
|
||||
// _Ty=non_copyable
|
||||
// ]
|
||||
#if defined BOOST_THREAD_USES_BOOST_QUEUE || defined BOOST_NO_CXX11_RVALUE_REFERENCES || (defined _MSC_VER && _MSC_FULL_VER < 180020827)
|
||||
#ifndef BOOST_THREAD_USES_BOOST_QUEUE
|
||||
#define BOOST_THREAD_USES_BOOST_QUEUE
|
||||
#endif
|
||||
#include <boost/container/queue.hpp>
|
||||
#else
|
||||
#include <queue>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace csbl
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_BOOST_QUEUE
|
||||
using ::boost::container::queue;
|
||||
|
||||
#else
|
||||
using ::std::queue;
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
#endif // header
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if defined BOOST_THREAD_USES_BOOST_VECTOR || defined BOOST_NO_CXX11_HDR_VECTOR || defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
#if defined BOOST_THREAD_USES_BOOST_VECTOR || defined BOOST_NO_CXX11_RVALUE_REFERENCES || defined BOOST_MSVC
|
||||
#ifndef BOOST_THREAD_USES_BOOST_VECTOR
|
||||
#define BOOST_THREAD_USES_BOOST_VECTOR
|
||||
#endif
|
||||
|
||||
@@ -134,7 +134,7 @@ namespace boost
|
||||
//BOOST_THREAD_DCL_MOVABLE_BEG(X) invoker<Fp> BOOST_THREAD_DCL_MOVABLE_END
|
||||
#else
|
||||
|
||||
#if ! defined BOOST_MSVC
|
||||
#if ! defined BOOST_MSVC && defined(BOOST_THREAD_PROVIDES_INVOKE)
|
||||
|
||||
#define BOOST_THREAD_RV_REF_ARG_T(z, n, unused) BOOST_PP_COMMA_IF(n) BOOST_THREAD_RV_REF(Arg##n)
|
||||
#define BOOST_THREAD_RV_REF_A_T(z, n, unused) BOOST_PP_COMMA_IF(n) BOOST_THREAD_RV_REF(A##n)
|
||||
|
||||
@@ -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
|
||||
@@ -14,7 +14,7 @@
|
||||
#include <boost/thread/detail/delete.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/scoped_thread.hpp>
|
||||
#include <boost/thread/sync_queue.hpp>
|
||||
#include <boost/thread/concurrent_queues/sync_queue.hpp>
|
||||
#include <boost/thread/executors/work.hpp>
|
||||
#include <boost/thread/csbl/vector.hpp>
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace executors
|
||||
try
|
||||
{
|
||||
work task;
|
||||
if (work_queue.try_pull_front(task) == queue_op_status::success)
|
||||
if (work_queue.try_pull(task) == queue_op_status::success)
|
||||
{
|
||||
task();
|
||||
return true;
|
||||
@@ -87,7 +87,7 @@ namespace executors
|
||||
for(;;)
|
||||
{
|
||||
work task;
|
||||
queue_op_status st = work_queue.wait_pull_front(task);
|
||||
queue_op_status st = work_queue.wait_pull(task);
|
||||
if (st == queue_op_status::closed) return;
|
||||
task();
|
||||
}
|
||||
@@ -269,18 +269,18 @@ namespace executors
|
||||
template <typename Closure>
|
||||
void submit(Closure & closure)
|
||||
{
|
||||
work_queue.push_back(work(closure));
|
||||
work_queue.push(work(closure));
|
||||
}
|
||||
#endif
|
||||
void submit(void (*closure)())
|
||||
{
|
||||
work_queue.push_back(work(closure));
|
||||
work_queue.push(work(closure));
|
||||
}
|
||||
|
||||
template <typename Closure>
|
||||
void submit(BOOST_THREAD_RV_REF(Closure) closure)
|
||||
{
|
||||
work_queue.push_back(work(boost::forward<Closure>(closure)));
|
||||
work_queue.push(work(boost::forward<Closure>(closure)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
// Copyright (C) 2014 Ian Forbed
|
||||
// Copyright (C) 2014 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_EXECUTORS_DETAIL_PRIORITY_EXECUTOR_BASE_HPP
|
||||
#define BOOST_THREAD_EXECUTORS_DETAIL_PRIORITY_EXECUTOR_BASE_HPP
|
||||
|
||||
#include <boost/atomic.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/concurrent_queues/sync_timed_queue.hpp>
|
||||
#include <boost/thread/executors/work.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace executors
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <class Queue>
|
||||
class priority_executor_base
|
||||
{
|
||||
public:
|
||||
typedef boost::function<void()> work;
|
||||
//typedef executors::work work;
|
||||
protected:
|
||||
typedef Queue queue_type;
|
||||
queue_type _workq;
|
||||
|
||||
priority_executor_base() {}
|
||||
public:
|
||||
|
||||
~priority_executor_base()
|
||||
{
|
||||
if(!closed())
|
||||
{
|
||||
this->close();
|
||||
}
|
||||
}
|
||||
|
||||
void close()
|
||||
{
|
||||
_workq.close();
|
||||
}
|
||||
|
||||
bool closed()
|
||||
{
|
||||
return _workq.closed();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
try
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
work task;
|
||||
queue_op_status st = _workq.wait_pull(task);
|
||||
if (st == queue_op_status::closed) return;
|
||||
task();
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::terminate();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}; //end class
|
||||
|
||||
} //end detail namespace
|
||||
} //end executors namespace
|
||||
} //end boost namespace
|
||||
#endif
|
||||
@@ -5,14 +5,16 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef SCHEDULED_EXECUTOR_HPP
|
||||
#define SCHEDULED_EXECUTOR_HPP
|
||||
#ifndef BOOST_THREAD_EXECUTORS_DETAIL_SCHEDULED_EXECUTOR_BASE_HPP
|
||||
#define BOOST_THREAD_EXECUTORS_DETAIL_SCHEDULED_EXECUTOR_BASE_HPP
|
||||
|
||||
#include <boost/thread/concurrent_queues/sync_timed_queue.hpp>
|
||||
#include <boost/thread/executors/detail/priority_executor_base.hpp>
|
||||
#include <boost/thread/executors/work.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
|
||||
#include <boost/atomic.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/concurrent_queues/sync_timed_queue.hpp>
|
||||
#include <boost/thread/executors/work.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
@@ -20,71 +22,38 @@ namespace executors
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
class scheduled_executor_base
|
||||
template <class Clock=chrono::steady_clock>
|
||||
class scheduled_executor_base : public priority_executor_base<concurrent::sync_timed_queue<boost::function<void()>, Clock > >
|
||||
{
|
||||
public:
|
||||
typedef boost::function<void()> work;
|
||||
//typedef executors::work work;
|
||||
typedef chrono::steady_clock clock;
|
||||
typedef clock::duration duration;
|
||||
typedef clock::time_point time_point;
|
||||
typedef Clock clock;
|
||||
typedef typename clock::duration duration;
|
||||
typedef typename clock::time_point time_point;
|
||||
protected:
|
||||
concurrent::sync_timed_queue<work> _workq;
|
||||
|
||||
scheduled_executor_base() {}
|
||||
public:
|
||||
|
||||
~scheduled_executor_base()
|
||||
{
|
||||
if(!closed())
|
||||
if(! this->closed())
|
||||
{
|
||||
this->close();
|
||||
}
|
||||
}
|
||||
|
||||
void close()
|
||||
{
|
||||
_workq.close();
|
||||
}
|
||||
|
||||
bool closed()
|
||||
{
|
||||
return _workq.closed();
|
||||
}
|
||||
|
||||
void submit(work w)
|
||||
{
|
||||
_workq.push(w, clock::now());
|
||||
}
|
||||
|
||||
void submit_at(work w, const time_point& tp)
|
||||
{
|
||||
_workq.push(w, tp);
|
||||
this->_workq.push(w, tp);
|
||||
}
|
||||
|
||||
void submit_after(work w, const duration& dura)
|
||||
{
|
||||
_workq.push(w, dura);
|
||||
this->_workq.push(w, dura+clock::now());
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
try
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
work task;
|
||||
queue_op_status st = _workq.wait_pull(task);
|
||||
if (st == queue_op_status::closed) return;
|
||||
task();
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::terminate();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}; //end class
|
||||
|
||||
} //end detail namespace
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/detail/delete.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/sync_queue.hpp>
|
||||
#include <boost/thread/concurrent_queues/sync_queue.hpp>
|
||||
#include <boost/thread/executors/work.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
@@ -44,7 +44,7 @@ namespace executors
|
||||
work task;
|
||||
try
|
||||
{
|
||||
if (work_queue.try_pull_front(task) == queue_op_status::success)
|
||||
if (work_queue.try_pull(task) == queue_op_status::success)
|
||||
{
|
||||
task();
|
||||
return true;
|
||||
@@ -143,18 +143,18 @@ namespace executors
|
||||
template <typename Closure>
|
||||
void submit(Closure & closure)
|
||||
{
|
||||
work_queue.push_back(work(closure));
|
||||
work_queue.push(work(closure));
|
||||
}
|
||||
#endif
|
||||
void submit(void (*closure)())
|
||||
{
|
||||
work_queue.push_back(work(closure));
|
||||
work_queue.push(work(closure));
|
||||
}
|
||||
|
||||
template <typename Closure>
|
||||
void submit(BOOST_THREAD_RV_REF(Closure) closure)
|
||||
{
|
||||
work_queue.push_back(work(boost::forward<Closure>(closure)));
|
||||
work_queue.push(work(boost::forward<Closure>(closure)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace boost
|
||||
namespace executors
|
||||
{
|
||||
|
||||
class scheduled_thread_pool : public detail::scheduled_executor_base
|
||||
class scheduled_thread_pool : public detail::scheduled_executor_base<>
|
||||
{
|
||||
private:
|
||||
thread_group _workers;
|
||||
@@ -36,29 +36,9 @@ namespace executors
|
||||
}
|
||||
|
||||
private:
|
||||
typedef detail::scheduled_executor_base super;
|
||||
inline void loop();
|
||||
typedef detail::scheduled_executor_base<> super;
|
||||
}; //end class
|
||||
|
||||
void scheduled_thread_pool::loop()
|
||||
{
|
||||
try
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
super::work task;
|
||||
queue_op_status st = super::_workq.wait_pull(task);
|
||||
if (st == queue_op_status::closed) return;
|
||||
task();
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::terminate();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
} //end executors namespace
|
||||
|
||||
using executors::scheduled_thread_pool;
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/executors/detail/scheduled_executor_base.hpp>
|
||||
|
||||
#include <boost/chrono/time_point.hpp>
|
||||
#include <boost/chrono/duration.hpp>
|
||||
#include <boost/chrono/system_clocks.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
@@ -51,9 +53,11 @@ namespace boost
|
||||
class resubmit_at_executor
|
||||
{
|
||||
public:
|
||||
typedef chrono::steady_clock clock;
|
||||
typedef typename Scheduler::clock clock;
|
||||
typedef typename Scheduler::work work;
|
||||
|
||||
resubmit_at_executor(Scheduler& sch, Executor& ex, clock::time_point const& tp) :
|
||||
template <class Duration>
|
||||
resubmit_at_executor(Scheduler& sch, Executor& ex, chrono::time_point<clock, Duration> const& tp) :
|
||||
sch(sch),
|
||||
ex(ex),
|
||||
tp(tp),
|
||||
@@ -98,7 +102,7 @@ namespace boost
|
||||
private:
|
||||
Scheduler& sch;
|
||||
Executor& ex;
|
||||
clock::time_point tp;
|
||||
typename clock::time_point tp;
|
||||
bool is_closed;
|
||||
};
|
||||
|
||||
@@ -111,7 +115,8 @@ namespace boost
|
||||
class scheduler_executor_wrapper
|
||||
{
|
||||
public:
|
||||
typedef chrono::steady_clock clock;
|
||||
typedef typename Scheduler::clock clock;
|
||||
typedef typename Scheduler::work work;
|
||||
typedef resubmit_at_executor<Scheduler, Executor> the_executor;
|
||||
|
||||
scheduler_executor_wrapper(Scheduler& sch, Executor& ex) :
|
||||
@@ -132,13 +137,14 @@ namespace boost
|
||||
return sch;
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
the_executor after(Duration const& rel_time)
|
||||
template <class Rep, class Period>
|
||||
the_executor after(chrono::duration<Rep,Period> const& rel_time)
|
||||
{
|
||||
return at(clock::now() + rel_time );
|
||||
}
|
||||
|
||||
the_executor at(clock::time_point const& abs_time)
|
||||
template <class Duration>
|
||||
the_executor at(chrono::time_point<clock,Duration> const& abs_time)
|
||||
{
|
||||
return the_executor(sch, ex, abs_time);
|
||||
}
|
||||
@@ -154,9 +160,12 @@ namespace boost
|
||||
class at_executor
|
||||
{
|
||||
public:
|
||||
typedef chrono::steady_clock clock;
|
||||
typedef typename Scheduler::clock clock;
|
||||
typedef typename Scheduler::work work;
|
||||
typedef typename clock::time_point time_point;
|
||||
|
||||
at_executor(Scheduler& sch, clock::time_point const& tp) :
|
||||
template <class Duration>
|
||||
at_executor(Scheduler& sch, chrono::time_point<clock,Duration> const& tp) :
|
||||
sch(sch),
|
||||
tp(tp),
|
||||
is_closed(false)
|
||||
@@ -200,18 +209,20 @@ namespace boost
|
||||
|
||||
private:
|
||||
Scheduler& sch;
|
||||
clock::time_point tp;
|
||||
time_point tp;
|
||||
bool is_closed;
|
||||
}; //end class
|
||||
|
||||
/// A @c Scheduler using a specific thread. Note that a Scheduler is not an Executor.
|
||||
/// It provides factory helper functions such as at/after that convert a @c Scheduler into an @c Executor
|
||||
/// that submit the work at/after a specific time/duration respectively.
|
||||
class scheduler : public detail::scheduled_executor_base
|
||||
template <class Clock = chrono::steady_clock>
|
||||
class scheduler : public detail::scheduled_executor_base<Clock>
|
||||
{
|
||||
public:
|
||||
typedef chrono::steady_clock clock;
|
||||
typedef clock::time_point time_point;
|
||||
typedef typename detail::scheduled_executor_base<Clock>::work work;
|
||||
|
||||
typedef Clock clock;
|
||||
|
||||
scheduler()
|
||||
: super(),
|
||||
@@ -228,19 +239,20 @@ namespace boost
|
||||
return scheduler_executor_wrapper<scheduler, Ex>(*this, ex);
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
at_executor<scheduler> after(Duration const& rel_time)
|
||||
template <class Rep, class Period>
|
||||
at_executor<scheduler> after(chrono::duration<Rep,Period> const& rel_time)
|
||||
{
|
||||
return at(rel_time + clock::now());
|
||||
}
|
||||
|
||||
at_executor<scheduler> at(time_point const& tp)
|
||||
template <class Duration>
|
||||
at_executor<scheduler> at(chrono::time_point<clock,Duration> const& tp)
|
||||
{
|
||||
return at_executor<scheduler>(*this, tp);
|
||||
}
|
||||
|
||||
private:
|
||||
typedef detail::scheduled_executor_base super;
|
||||
typedef detail::scheduled_executor_base<Clock> super;
|
||||
thread thr;
|
||||
};
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace executors
|
||||
{
|
||||
|
||||
template <typename Executor>
|
||||
class scheduling_adpator : public detail::scheduled_executor_base
|
||||
class scheduling_adpator : public detail::scheduled_executor_base<>
|
||||
{
|
||||
private:
|
||||
Executor& _exec;
|
||||
@@ -26,7 +26,7 @@ namespace executors
|
||||
scheduling_adpator(Executor& ex)
|
||||
: super(),
|
||||
_exec(ex),
|
||||
_scheduler(&scheduling_adpator::loop, this) {}
|
||||
_scheduler(&super::loop, this) {}
|
||||
|
||||
~scheduling_adpator()
|
||||
{
|
||||
@@ -40,30 +40,9 @@ namespace executors
|
||||
}
|
||||
|
||||
private:
|
||||
typedef detail::scheduled_executor_base super;
|
||||
void loop();
|
||||
typedef detail::scheduled_executor_base<> super;
|
||||
}; //end class
|
||||
|
||||
template<typename Executor>
|
||||
void scheduling_adpator<Executor>::loop()
|
||||
{
|
||||
try
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
super::work task;
|
||||
queue_op_status st = super::_workq.wait_pull(task);
|
||||
if (st == queue_op_status::closed) return;
|
||||
_exec.submit(task);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::terminate();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
} //end executors
|
||||
|
||||
using executors::scheduling_adpator;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/detail/delete.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/sync_queue.hpp>
|
||||
#include <boost/thread/concurrent_queues/sync_queue.hpp>
|
||||
#include <boost/thread/executors/work.hpp>
|
||||
#include <boost/thread/executors/generic_executor_ref.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
@@ -43,8 +43,13 @@ namespace executors
|
||||
try_executing_one_task(work& task, boost::promise<void> &p)
|
||||
: task(task), p(p) {}
|
||||
void operator()() {
|
||||
task();
|
||||
p.set_value();
|
||||
try {
|
||||
task();
|
||||
p.set_value();
|
||||
} catch (...)
|
||||
{
|
||||
p.set_exception(current_exception());
|
||||
}
|
||||
}
|
||||
};
|
||||
public:
|
||||
@@ -64,7 +69,7 @@ namespace executors
|
||||
work task;
|
||||
try
|
||||
{
|
||||
if (work_queue.try_pull_front(task) == queue_op_status::success)
|
||||
if (work_queue.try_pull(task) == queue_op_status::success)
|
||||
{
|
||||
boost::promise<void> p;
|
||||
try_executing_one_task tmp(task,p);
|
||||
@@ -165,18 +170,18 @@ namespace executors
|
||||
template <typename Closure>
|
||||
void submit(Closure & closure)
|
||||
{
|
||||
work_queue.push_back(work(closure));
|
||||
work_queue.push(work(closure));
|
||||
}
|
||||
#endif
|
||||
void submit(void (*closure)())
|
||||
{
|
||||
work_queue.push_back(work(closure));
|
||||
work_queue.push(work(closure));
|
||||
}
|
||||
|
||||
template <typename Closure>
|
||||
void submit(BOOST_THREAD_RV_REF(Closure) closure)
|
||||
{
|
||||
work_queue.push_back(work(boost::forward<Closure>(closure)));
|
||||
work_queue.push(work(boost::forward<Closure>(closure)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
170
include/boost/thread/executors/serial_executor_cont.hpp
Normal file
170
include/boost/thread/executors/serial_executor_cont.hpp
Normal file
@@ -0,0 +1,170 @@
|
||||
// Copyright (C) 2015 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)
|
||||
//
|
||||
// 2013/11 Vicente J. Botet Escriba
|
||||
// first implementation of a simple serial scheduler.
|
||||
|
||||
#ifndef BOOST_THREAD_SERIAL_EXECUTOR_CONT_HPP
|
||||
#define BOOST_THREAD_SERIAL_EXECUTOR_CONT_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/detail/delete.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/concurrent_queues/sync_queue.hpp>
|
||||
#include <boost/thread/executors/work.hpp>
|
||||
#include <boost/thread/executors/generic_executor_ref.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/thread/scoped_thread.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace executors
|
||||
{
|
||||
class serial_executor_cont
|
||||
{
|
||||
public:
|
||||
/// type-erasure to store the works to do
|
||||
typedef executors::work work;
|
||||
private:
|
||||
|
||||
generic_executor_ref ex_;
|
||||
future<void> fut_; // protected by mtx_
|
||||
bool closed_; // protected by mtx_
|
||||
mutex mtx_;
|
||||
|
||||
struct continuation {
|
||||
work task;
|
||||
template <class X>
|
||||
struct result {
|
||||
typedef void type;
|
||||
};
|
||||
continuation(BOOST_THREAD_RV_REF(work) tsk)
|
||||
: task(boost::move(tsk)) {}
|
||||
void operator()(future<void> f)
|
||||
{
|
||||
try {
|
||||
task();
|
||||
} catch (...) {
|
||||
std::terminate();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
bool closed(lock_guard<mutex>&) const
|
||||
{
|
||||
return closed_;
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* \par Returns
|
||||
* The underlying executor wrapped on a generic executor reference.
|
||||
*/
|
||||
generic_executor_ref& underlying_executor() BOOST_NOEXCEPT { return ex_; }
|
||||
|
||||
/// serial_executor_cont is not copyable.
|
||||
BOOST_THREAD_NO_COPYABLE(serial_executor_cont)
|
||||
|
||||
/**
|
||||
* \b Effects: creates a serial executor that runs closures in fifo order using one the associated executor.
|
||||
*
|
||||
* \b Throws: Whatever exception is thrown while initializing the needed resources.
|
||||
*
|
||||
* \b Notes:
|
||||
* * The lifetime of the associated executor must outlive the serial executor.
|
||||
* * The current implementation doesn't support submission from synchronous continuation, that is,
|
||||
* - the executor must execute the continuation asynchronously or
|
||||
* - the continuation can not submit to this serial executor.
|
||||
*/
|
||||
template <class Executor>
|
||||
serial_executor_cont(Executor& ex)
|
||||
: ex_(ex), fut_(make_ready_future()), closed_(false)
|
||||
{
|
||||
}
|
||||
/**
|
||||
* \b Effects: Destroys the thread pool.
|
||||
*
|
||||
* \b Synchronization: The completion of all the closures happen before the completion of the \c serial_executor_cont destructor.
|
||||
*/
|
||||
~serial_executor_cont()
|
||||
{
|
||||
// signal to the worker thread that there will be no more submissions.
|
||||
close();
|
||||
}
|
||||
|
||||
/**
|
||||
* \b Effects: close the \c serial_executor_cont for submissions.
|
||||
* The loop will work until there is no more closures to run.
|
||||
*/
|
||||
void close()
|
||||
{
|
||||
lock_guard<mutex> lk(mtx_);
|
||||
closed_ = true;;
|
||||
}
|
||||
|
||||
/**
|
||||
* \b Returns: whether the pool is closed for submissions.
|
||||
*/
|
||||
bool closed()
|
||||
{
|
||||
lock_guard<mutex> lk(mtx_);
|
||||
return closed(lk);
|
||||
}
|
||||
|
||||
/**
|
||||
* Effects: none.
|
||||
* Returns: always false.
|
||||
* Throws: No.
|
||||
* Remark: A serial executor can not execute one of its pending tasks as the tasks depends on the other tasks.
|
||||
*/
|
||||
bool try_executing_one()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible.
|
||||
*
|
||||
* \b Effects: The specified \c closure will be scheduled for execution after the last submitted closure finish.
|
||||
* If the invoked closure throws an exception the \c serial_executor_cont will call \c std::terminate, as is the case with threads.
|
||||
*
|
||||
* \b Throws: \c sync_queue_is_closed if the executor is closed.
|
||||
* Whatever exception that can be throw while storing the closure.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
template <typename Closure>
|
||||
void submit(Closure & closure)
|
||||
{
|
||||
lock_guard<mutex> lk(mtx_);
|
||||
if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
|
||||
fut_ = fut_.then(ex_, continuation(work(closure)));
|
||||
}
|
||||
#endif
|
||||
void submit(void (*closure)())
|
||||
{
|
||||
lock_guard<mutex> lk(mtx_);
|
||||
if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
|
||||
fut_ = fut_.then(ex_, continuation(work(closure)));
|
||||
}
|
||||
|
||||
template <typename Closure>
|
||||
void submit(BOOST_THREAD_RV_REF(Closure) closure)
|
||||
{
|
||||
lock_guard<mutex> lk(mtx_);
|
||||
if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
|
||||
fut_ = fut_.then(ex_, continuation(work(boost::forward<Closure>(closure))));
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
using executors::serial_executor_cont;
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef BOOST_THREAD_EXPERIMENTAL_CONFIG_INLINE_NAMESPACE_HPP
|
||||
#define BOOST_THREAD_EXPERIMENTAL_CONFIG_INLINE_NAMESPACE_HPP
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Vicente J. Botet Escriba 2014. 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)
|
||||
//
|
||||
// See http://www.boost.org/libs/thread for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_INLINE_NAMESPACES)
|
||||
# define BOOST_THREAD_INLINE_NAMESPACE(name) inline namespace name
|
||||
#else
|
||||
# define BOOST_THREAD_INLINE_NAMESPACE(name) namespace name
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
16
include/boost/thread/experimental/exception_list.hpp
Normal file
16
include/boost/thread/experimental/exception_list.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef BOOST_THREAD_EXPERIMENTAL_EXCEPTION_LIST_HPP
|
||||
#define BOOST_THREAD_EXPERIMENTAL_EXCEPTION_LIST_HPP
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Vicente J. Botet Escriba 2014. 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)
|
||||
//
|
||||
// See http://www.boost.org/libs/thread for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/thread/experimental/parallel/v1/exception_list.hpp>
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,70 @@
|
||||
#ifndef BOOST_THREAD_EXPERIMENTAL_PARALLEL_V1_EXCEPTION_LIST_HPP
|
||||
#define BOOST_THREAD_EXPERIMENTAL_PARALLEL_V1_EXCEPTION_LIST_HPP
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Vicente J. Botet Escriba 2014. 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)
|
||||
//
|
||||
// See http://www.boost.org/libs/thread for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/experimental/parallel/v1/inline_namespace.hpp>
|
||||
|
||||
#include <boost/exception_ptr.hpp>
|
||||
#include <exception>
|
||||
#include <list>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
namespace parallel
|
||||
{
|
||||
BOOST_THREAD_INLINE_NAMESPACE(v1)
|
||||
{
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE exception_list: public std::exception
|
||||
{
|
||||
typedef std::list<exception_ptr> exception_ptr_list;
|
||||
exception_ptr_list list_;
|
||||
public:
|
||||
typedef exception_ptr_list::const_iterator const_iterator;
|
||||
|
||||
~exception_list() BOOST_NOEXCEPT_OR_NOTHROW {}
|
||||
|
||||
void add(exception_ptr const& e)
|
||||
{
|
||||
list_.push_back(e);
|
||||
}
|
||||
size_t size() const BOOST_NOEXCEPT
|
||||
{
|
||||
return list_.size();
|
||||
}
|
||||
const_iterator begin() const BOOST_NOEXCEPT
|
||||
{
|
||||
return list_.begin();
|
||||
}
|
||||
const_iterator end() const BOOST_NOEXCEPT
|
||||
{
|
||||
return list_.end();
|
||||
}
|
||||
const char* what() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
return "exception_list";
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
} // parallel
|
||||
} // experimental
|
||||
} // boost
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef BOOST_THREAD_EXPERIMENTAL_PARALLEL_V1_INLINE_NAMESPACE_HPP
|
||||
#define BOOST_THREAD_EXPERIMENTAL_PARALLEL_V1_INLINE_NAMESPACE_HPP
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Vicente J. Botet Escriba 2014. 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)
|
||||
//
|
||||
// See http://www.boost.org/libs/thread for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/thread/experimental/config/inline_namespace.hpp>
|
||||
namespace boost {
|
||||
namespace experimental {
|
||||
namespace parallel {
|
||||
|
||||
BOOST_THREAD_INLINE_NAMESPACE(v1) {}
|
||||
|
||||
#if defined(BOOST_NO_CXX11_INLINE_NAMESPACES)
|
||||
using namespace v1;
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef BOOST_THREAD_EXPERIMENTAL_PARALLEL_V2_INLINE_NAMESPACE_HPP
|
||||
#define BOOST_THREAD_EXPERIMENTAL_PARALLEL_V2_INLINE_NAMESPACE_HPP
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Vicente J. Botet Escriba 2014. 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)
|
||||
//
|
||||
// See http://www.boost.org/libs/thread for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/thread/experimental/config/inline_namespace.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace experimental {
|
||||
namespace parallel {
|
||||
|
||||
BOOST_THREAD_INLINE_NAMESPACE(v2) {}
|
||||
|
||||
#if defined(BOOST_NO_CXX11_INLINE_NAMESPACES)
|
||||
using namespace v2;
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
320
include/boost/thread/experimental/parallel/v2/task_region.hpp
Executable file
320
include/boost/thread/experimental/parallel/v2/task_region.hpp
Executable file
@@ -0,0 +1,320 @@
|
||||
#ifndef BOOST_THREAD_EXPERIMENTAL_PARALLEL_V2_TASK_REGION_HPP
|
||||
#define BOOST_THREAD_EXPERIMENTAL_PARALLEL_V2_TASK_REGION_HPP
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Vicente J. Botet Escriba 2014. 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)
|
||||
//
|
||||
// See http://www.boost.org/libs/thread for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/thread/future.hpp>
|
||||
#if defined BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
#include <boost/thread/executors/basic_thread_pool.hpp>
|
||||
#endif
|
||||
#include <boost/thread/experimental/exception_list.hpp>
|
||||
#include <boost/thread/experimental/parallel/v2/inline_namespace.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
#define BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
namespace parallel
|
||||
{
|
||||
BOOST_THREAD_INLINE_NAMESPACE(v2)
|
||||
{
|
||||
class BOOST_SYMBOL_VISIBLE task_canceled_exception: public std::exception
|
||||
{
|
||||
public:
|
||||
//task_canceled_exception() BOOST_NOEXCEPT {}
|
||||
//task_canceled_exception(const task_canceled_exception&) BOOST_NOEXCEPT {}
|
||||
//task_canceled_exception& operator=(const task_canceled_exception&) BOOST_NOEXCEPT {}
|
||||
virtual const char* what() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return "task_canceled_exception";}
|
||||
};
|
||||
|
||||
template <class Executor>
|
||||
class task_region_handle_gen;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
void handle_task_region_exceptions(exception_list& errors)
|
||||
{
|
||||
try {
|
||||
boost::rethrow_exception(boost::current_exception());
|
||||
//throw boost::current_exception();
|
||||
}
|
||||
catch (task_canceled_exception& ex)
|
||||
{
|
||||
}
|
||||
catch (exception_list const& el)
|
||||
{
|
||||
for (exception_list::const_iterator it = el.begin(); it != el.end(); ++it)
|
||||
{
|
||||
boost::exception_ptr const& e = *it;
|
||||
try {
|
||||
rethrow_exception(e);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
handle_task_region_exceptions(errors);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
errors.add(boost::current_exception());
|
||||
}
|
||||
}
|
||||
|
||||
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
|
||||
template <class TRH, class F>
|
||||
struct wrapped
|
||||
{
|
||||
TRH& tr;
|
||||
F f;
|
||||
wrapped(TRH& tr, BOOST_THREAD_RV_REF(F) f) : tr(tr), f(move(f))
|
||||
{}
|
||||
void operator()()
|
||||
{
|
||||
try
|
||||
{
|
||||
f();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
lock_guard<mutex> lk(tr.mtx);
|
||||
tr.canceled = true;
|
||||
handle_task_region_exceptions(tr.exs);
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class Executor>
|
||||
class task_region_handle_gen
|
||||
{
|
||||
private:
|
||||
// Private members and friends
|
||||
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
|
||||
template <class TRH, class F>
|
||||
friend struct detail::wrapped;
|
||||
#endif
|
||||
template <typename F>
|
||||
friend void task_region(BOOST_THREAD_FWD_REF(F) f);
|
||||
template<typename F>
|
||||
friend void task_region_final(BOOST_THREAD_FWD_REF(F) f);
|
||||
template <class Ex, typename F>
|
||||
friend void task_region(Ex&, BOOST_THREAD_FWD_REF(F) f);
|
||||
template<class Ex, typename F>
|
||||
friend void task_region_final(Ex&, BOOST_THREAD_FWD_REF(F) f);
|
||||
|
||||
void wait_all()
|
||||
{
|
||||
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)
|
||||
{
|
||||
future<void>& f = *it;
|
||||
if (f.has_exception())
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::rethrow_exception(f.get_exception_ptr());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
detail::handle_task_region_exceptions(exs);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (exs.size() != 0)
|
||||
{
|
||||
boost::throw_exception(exs);
|
||||
//throw exs;
|
||||
}
|
||||
}
|
||||
protected:
|
||||
#if ! defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED && ! defined BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
task_region_handle_gen()
|
||||
{}
|
||||
#endif
|
||||
|
||||
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED && defined BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
task_region_handle_gen()
|
||||
: canceled(false)
|
||||
, ex(0)
|
||||
{}
|
||||
task_region_handle_gen(Executor& ex)
|
||||
: canceled(false)
|
||||
, ex(&ex)
|
||||
{}
|
||||
|
||||
#endif
|
||||
|
||||
#if ! defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED && defined BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
task_region_handle_gen()
|
||||
: ex(0)
|
||||
{}
|
||||
task_region_handle_gen(Executor& ex)
|
||||
: ex(&ex)
|
||||
{}
|
||||
#endif
|
||||
|
||||
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED && ! defined BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
task_region_handle_gen()
|
||||
: canceled(false)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
~task_region_handle_gen()
|
||||
{
|
||||
//wait_all();
|
||||
}
|
||||
|
||||
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
|
||||
bool canceled;
|
||||
#endif
|
||||
#if defined BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
Executor* ex;
|
||||
#endif
|
||||
exception_list exs;
|
||||
typedef csbl::vector<future<void> > group_type;
|
||||
group_type group;
|
||||
mutable mutex mtx;
|
||||
|
||||
|
||||
public:
|
||||
BOOST_DELETED_FUNCTION(task_region_handle_gen(const task_region_handle_gen&))
|
||||
BOOST_DELETED_FUNCTION(task_region_handle_gen& operator=(const task_region_handle_gen&))
|
||||
BOOST_DELETED_FUNCTION(task_region_handle_gen* operator&() const)
|
||||
|
||||
public:
|
||||
template<typename F>
|
||||
void run(BOOST_THREAD_FWD_REF(F) f)
|
||||
{
|
||||
lock_guard<mutex> lk(mtx);
|
||||
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
|
||||
if (canceled) {
|
||||
boost::throw_exception(task_canceled_exception());
|
||||
//throw task_canceled_exception();
|
||||
}
|
||||
#if defined BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
group.push_back(async(*ex, detail::wrapped<task_region_handle_gen<Executor>, F>(*this, forward<F>(f))));
|
||||
#else
|
||||
group.push_back(async(detail::wrapped<task_region_handle_gen<Executor>, F>(*this, forward<F>(f))));
|
||||
#endif
|
||||
#else
|
||||
#if defined BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
group.push_back(async(*ex, forward<F>(f)));
|
||||
#else
|
||||
group.push_back(async(forward<F>(f)));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void wait()
|
||||
{
|
||||
lock_guard<mutex> lk(mtx);
|
||||
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
|
||||
if (canceled) {
|
||||
boost::throw_exception(task_canceled_exception());
|
||||
//throw task_canceled_exception{};
|
||||
}
|
||||
#endif
|
||||
wait_all();
|
||||
}
|
||||
};
|
||||
#if defined BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
typedef basic_thread_pool default_executor;
|
||||
#else
|
||||
typedef int default_executor;
|
||||
#endif
|
||||
class task_region_handle :
|
||||
public task_region_handle_gen<default_executor>
|
||||
{
|
||||
default_executor tp;
|
||||
template <typename F>
|
||||
friend void task_region(BOOST_THREAD_FWD_REF(F) f);
|
||||
template<typename F>
|
||||
friend void task_region_final(BOOST_THREAD_FWD_REF(F) f);
|
||||
|
||||
protected:
|
||||
task_region_handle() : task_region_handle_gen<default_executor>()
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
ex = &tp;
|
||||
#endif
|
||||
}
|
||||
BOOST_DELETED_FUNCTION(task_region_handle(const task_region_handle&))
|
||||
BOOST_DELETED_FUNCTION(task_region_handle& operator=(const task_region_handle&))
|
||||
BOOST_DELETED_FUNCTION(task_region_handle* operator&() const)
|
||||
|
||||
};
|
||||
|
||||
template <typename Executor, typename F>
|
||||
void task_region_final(Executor& ex, BOOST_THREAD_FWD_REF(F) f)
|
||||
{
|
||||
task_region_handle_gen<Executor> tr(ex);
|
||||
try
|
||||
{
|
||||
f(tr);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
lock_guard<mutex> lk(tr.mtx);
|
||||
detail::handle_task_region_exceptions(tr.exs);
|
||||
}
|
||||
tr.wait_all();
|
||||
}
|
||||
|
||||
template <typename Executor, typename F>
|
||||
void task_region(Executor& ex, BOOST_THREAD_FWD_REF(F) f)
|
||||
{
|
||||
task_region_final(ex, forward<F>(f));
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
void task_region_final(BOOST_THREAD_FWD_REF(F) f)
|
||||
{
|
||||
task_region_handle tr;
|
||||
try
|
||||
{
|
||||
f(tr);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
lock_guard<mutex> lk(tr.mtx);
|
||||
detail::handle_task_region_exceptions(tr.exs);
|
||||
}
|
||||
tr.wait_all();
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
void task_region(BOOST_THREAD_FWD_REF(F) f)
|
||||
{
|
||||
task_region_final(forward<F>(f));
|
||||
}
|
||||
|
||||
} // v2
|
||||
} // parallel
|
||||
} // experimental
|
||||
} // boost
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif // header
|
||||
16
include/boost/thread/experimental/task_region.hpp
Normal file
16
include/boost/thread/experimental/task_region.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef BOOST_THREAD_EXPERIMENTAL_TASK_REGION_HPP
|
||||
#define BOOST_THREAD_EXPERIMENTAL_TASK_REGION_HPP
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Vicente J. Botet Escriba 2014. 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)
|
||||
//
|
||||
// See http://www.boost.org/libs/thread for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/thread/experimental/parallel/v2/task_region.hpp>
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
98
include/boost/thread/futures/future_error.hpp
Normal file
98
include/boost/thread/futures/future_error.hpp
Normal file
@@ -0,0 +1,98 @@
|
||||
// (C) Copyright 2008-10 Anthony Williams
|
||||
// (C) Copyright 2011-2015 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_FUTURES_FUTURE_ERROR_HPP
|
||||
#define BOOST_THREAD_FUTURES_FUTURE_ERROR_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/thread/futures/future_error_code.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class BOOST_SYMBOL_VISIBLE future_error
|
||||
: public std::logic_error
|
||||
{
|
||||
system::error_code ec_;
|
||||
public:
|
||||
future_error(system::error_code ec)
|
||||
: logic_error(ec.message()),
|
||||
ec_(ec)
|
||||
{
|
||||
}
|
||||
|
||||
const system::error_code& code() const BOOST_NOEXCEPT
|
||||
{
|
||||
return ec_;
|
||||
}
|
||||
};
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE future_uninitialized:
|
||||
public future_error
|
||||
{
|
||||
public:
|
||||
future_uninitialized() :
|
||||
future_error(system::make_error_code(future_errc::no_state))
|
||||
{}
|
||||
};
|
||||
class BOOST_SYMBOL_VISIBLE broken_promise:
|
||||
public future_error
|
||||
{
|
||||
public:
|
||||
broken_promise():
|
||||
future_error(system::make_error_code(future_errc::broken_promise))
|
||||
{}
|
||||
};
|
||||
class BOOST_SYMBOL_VISIBLE future_already_retrieved:
|
||||
public future_error
|
||||
{
|
||||
public:
|
||||
future_already_retrieved():
|
||||
future_error(system::make_error_code(future_errc::future_already_retrieved))
|
||||
{}
|
||||
};
|
||||
class BOOST_SYMBOL_VISIBLE promise_already_satisfied:
|
||||
public future_error
|
||||
{
|
||||
public:
|
||||
promise_already_satisfied():
|
||||
future_error(system::make_error_code(future_errc::promise_already_satisfied))
|
||||
{}
|
||||
};
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE task_already_started:
|
||||
public future_error
|
||||
{
|
||||
public:
|
||||
task_already_started():
|
||||
future_error(system::make_error_code(future_errc::promise_already_satisfied))
|
||||
{}
|
||||
};
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE task_moved:
|
||||
public future_error
|
||||
{
|
||||
public:
|
||||
task_moved():
|
||||
future_error(system::make_error_code(future_errc::no_state))
|
||||
{}
|
||||
};
|
||||
|
||||
class promise_moved:
|
||||
public future_error
|
||||
{
|
||||
public:
|
||||
promise_moved():
|
||||
future_error(system::make_error_code(future_errc::no_state))
|
||||
{}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // header
|
||||
@@ -1,12 +1,12 @@
|
||||
// (C) Copyright 2008-10 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
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_THREAD_FUTURE_ERROR_CODE_HPP
|
||||
#define BOOST_THREAD_FUTURE_ERROR_CODE_HPP
|
||||
#ifndef BOOST_THREAD_FUTURES_FUTURE_ERROR_CODE_HPP
|
||||
#define BOOST_THREAD_FUTURES_FUTURE_ERROR_CODE_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/core/scoped_enum.hpp>
|
||||
30
include/boost/thread/futures/future_status.hpp
Normal file
30
include/boost/thread/futures/future_status.hpp
Normal file
@@ -0,0 +1,30 @@
|
||||
// (C) Copyright 2008-10 Anthony Williams
|
||||
// (C) Copyright 2011-2015 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_FUTURES_FUTURE_STATUS_HPP
|
||||
#define BOOST_THREAD_FUTURES_FUTURE_STATUS_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/core/scoped_enum.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
//enum class future_status
|
||||
BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_status)
|
||||
{
|
||||
ready,
|
||||
timeout,
|
||||
deferred
|
||||
}
|
||||
BOOST_SCOPED_ENUM_DECLARE_END(future_status)
|
||||
namespace future_state
|
||||
{
|
||||
enum state { uninitialized, waiting, ready, moved, deferred };
|
||||
}
|
||||
}
|
||||
|
||||
#endif // header
|
||||
21
include/boost/thread/futures/is_future_type.hpp
Normal file
21
include/boost/thread/futures/is_future_type.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
// (C) Copyright 2008-10 Anthony Williams
|
||||
// (C) Copyright 2011-2015 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_FUTURES_IS_FUTURE_TYPE_HPP
|
||||
#define BOOST_THREAD_FUTURES_IS_FUTURE_TYPE_HPP
|
||||
|
||||
#include <boost/type_traits/integral_constant.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template<typename T>
|
||||
struct is_future_type : false_type
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
#endif // header
|
||||
30
include/boost/thread/futures/launch.hpp
Normal file
30
include/boost/thread/futures/launch.hpp
Normal file
@@ -0,0 +1,30 @@
|
||||
// (C) Copyright 2008-10 Anthony Williams
|
||||
// (C) Copyright 2011-2015 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_FUTURES_LAUNCH_HPP
|
||||
#define BOOST_THREAD_FUTURES_LAUNCH_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/core/scoped_enum.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
//enum class launch
|
||||
BOOST_SCOPED_ENUM_DECLARE_BEGIN(launch)
|
||||
{
|
||||
none = 0,
|
||||
async = 1,
|
||||
deferred = 2,
|
||||
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
executor = 4,
|
||||
#endif
|
||||
any = async | deferred
|
||||
}
|
||||
BOOST_SCOPED_ENUM_DECLARE_END(launch)
|
||||
}
|
||||
|
||||
#endif // header
|
||||
74
include/boost/thread/futures/wait_for_all.hpp
Normal file
74
include/boost/thread/futures/wait_for_all.hpp
Normal file
@@ -0,0 +1,74 @@
|
||||
// (C) Copyright 2008-10 Anthony Williams
|
||||
// (C) Copyright 2011-2015 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_FUTURES_WAIT_FOR_ALL_HPP
|
||||
#define BOOST_THREAD_FUTURES_WAIT_FOR_ALL_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/futures/is_future_type.hpp>
|
||||
|
||||
#include <boost/core/enable_if.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template<typename Iterator>
|
||||
typename boost::disable_if<is_future_type<Iterator>,void>::type wait_for_all(Iterator begin,Iterator end)
|
||||
{
|
||||
for(Iterator current=begin;current!=end;++current)
|
||||
{
|
||||
current->wait();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
|
||||
template<typename F1,typename F2>
|
||||
typename boost::enable_if<is_future_type<F1>,void>::type wait_for_all(F1& f1,F2& f2)
|
||||
{
|
||||
f1.wait();
|
||||
f2.wait();
|
||||
}
|
||||
|
||||
template<typename F1,typename F2,typename F3>
|
||||
void wait_for_all(F1& f1,F2& f2,F3& f3)
|
||||
{
|
||||
f1.wait();
|
||||
f2.wait();
|
||||
f3.wait();
|
||||
}
|
||||
|
||||
template<typename F1,typename F2,typename F3,typename F4>
|
||||
void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4)
|
||||
{
|
||||
f1.wait();
|
||||
f2.wait();
|
||||
f3.wait();
|
||||
f4.wait();
|
||||
}
|
||||
|
||||
template<typename F1,typename F2,typename F3,typename F4,typename F5>
|
||||
void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5)
|
||||
{
|
||||
f1.wait();
|
||||
f2.wait();
|
||||
f3.wait();
|
||||
f4.wait();
|
||||
f5.wait();
|
||||
}
|
||||
#else
|
||||
template<typename F1, typename... Fs>
|
||||
void wait_for_all(F1& f1, Fs&... fs)
|
||||
{
|
||||
bool dummy[] = { (f1.wait(), true), (fs.wait(), true)... };
|
||||
|
||||
// prevent unused parameter warning
|
||||
(void) dummy;
|
||||
}
|
||||
#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)}
|
||||
|
||||
}
|
||||
|
||||
#endif // header
|
||||
161
include/boost/thread/futures/wait_for_any.hpp
Normal file
161
include/boost/thread/futures/wait_for_any.hpp
Normal file
@@ -0,0 +1,161 @@
|
||||
// (C) Copyright 2008-10 Anthony Williams
|
||||
// (C) Copyright 2011-2015 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_FUTURES_WAIT_FOR_ANY_HPP
|
||||
#define BOOST_THREAD_FUTURES_WAIT_FOR_ANY_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/futures/is_future_type.hpp>
|
||||
#include <boost/thread/lock_algorithms.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
|
||||
#include <boost/core/enable_if.hpp>
|
||||
#include <boost/next_prior.hpp>
|
||||
#include <boost/scoped_array.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <class Future>
|
||||
class waiter_for_any_in_seq
|
||||
{
|
||||
struct registered_waiter;
|
||||
typedef std::vector<int>::size_type count_type;
|
||||
|
||||
struct registered_waiter
|
||||
{
|
||||
typedef Future future_type;
|
||||
future_type* future_;
|
||||
typedef typename Future::notify_when_ready_handle notify_when_ready_handle;
|
||||
notify_when_ready_handle handle;
|
||||
count_type index;
|
||||
|
||||
registered_waiter(future_type & a_future,
|
||||
notify_when_ready_handle handle_, count_type index_) :
|
||||
future_(&a_future), handle(handle_), index(index_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct all_futures_lock
|
||||
{
|
||||
#ifdef _MANAGED
|
||||
typedef std::ptrdiff_t count_type_portable;
|
||||
#else
|
||||
typedef count_type count_type_portable;
|
||||
#endif
|
||||
count_type_portable count;
|
||||
boost::scoped_array<boost::unique_lock<boost::mutex> > locks;
|
||||
|
||||
all_futures_lock(std::vector<registered_waiter>& waiters) :
|
||||
count(waiters.size()), locks(new boost::unique_lock<boost::mutex>[count])
|
||||
{
|
||||
for (count_type_portable i = 0; i < count; ++i)
|
||||
{
|
||||
locks[i] = BOOST_THREAD_MAKE_RV_REF(boost::unique_lock<boost::mutex>(waiters[i].future_->mutex()));
|
||||
}
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
boost::lock(locks.get(), locks.get() + count);
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
for (count_type_portable i = 0; i < count; ++i)
|
||||
{
|
||||
locks[i].unlock();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
boost::condition_variable_any cv;
|
||||
std::vector<registered_waiter> waiters_;
|
||||
count_type future_count;
|
||||
|
||||
public:
|
||||
waiter_for_any_in_seq() :
|
||||
future_count(0)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
void add(F& f)
|
||||
{
|
||||
if (f.valid())
|
||||
{
|
||||
registered_waiter waiter(f, f.notify_when_ready(cv), future_count);
|
||||
try
|
||||
{
|
||||
waiters_.push_back(waiter);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
f.future_->unnotify_when_ready(waiter.handle);
|
||||
throw;
|
||||
}
|
||||
++future_count;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES
|
||||
template <typename F1, typename ... Fs>
|
||||
void add(F1& f1, Fs&... fs)
|
||||
{
|
||||
add(f1);
|
||||
add(fs...);
|
||||
}
|
||||
#endif
|
||||
|
||||
count_type wait()
|
||||
{
|
||||
all_futures_lock lk(waiters_);
|
||||
for (;;)
|
||||
{
|
||||
for (count_type i = 0; i < waiters_.size(); ++i)
|
||||
{
|
||||
if (waiters_[i].future_->is_ready(lk.locks[i]))
|
||||
{
|
||||
return waiters_[i].index;
|
||||
}
|
||||
}
|
||||
cv.wait(lk);
|
||||
}
|
||||
}
|
||||
|
||||
~waiter_for_any_in_seq()
|
||||
{
|
||||
for (count_type i = 0; i < waiters_.size(); ++i)
|
||||
{
|
||||
waiters_[i].future_->unnotify_when_ready(waiters_[i].handle);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
typename boost::disable_if<is_future_type<Iterator> , Iterator>::type wait_for_any(Iterator begin, Iterator end)
|
||||
{
|
||||
if (begin == end) return end;
|
||||
|
||||
detail::waiter_for_any_in_seq<typename std::iterator_traits<Iterator>::value_type> waiter;
|
||||
for (Iterator current = begin; current != end; ++current)
|
||||
{
|
||||
waiter.add(*current);
|
||||
}
|
||||
return boost::next(begin, waiter.wait());
|
||||
}
|
||||
}
|
||||
|
||||
#endif // header
|
||||
@@ -27,7 +27,7 @@ namespace boost
|
||||
/// Effect: Decrement the count. Unlocks the lock and notify anyone waiting if we reached zero.
|
||||
/// Returns: true if count_ reached the value 0.
|
||||
/// @ThreadSafe ensured by the @c lk parameter
|
||||
bool count_down(unique_lock<mutex> &lk)
|
||||
bool count_down(unique_lock<mutex> &)
|
||||
/// pre_condition (count_ > 0)
|
||||
{
|
||||
BOOST_ASSERT(count_ > 0);
|
||||
|
||||
@@ -25,7 +25,9 @@
|
||||
#include <utility>
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
#include <asm/page.h> // http://code.google.com/p/android/issues/detail?id=39983
|
||||
# ifndef PAGE_SIZE
|
||||
# define PAGE_SIZE 4096
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <pthread.h>
|
||||
@@ -250,7 +252,7 @@ namespace boost
|
||||
inline
|
||||
void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns)
|
||||
{
|
||||
return boost::this_thread::hiden::sleep_for(boost::detail::to_timespec(ns));
|
||||
return boost::this_thread::no_interruption_point::hiden::sleep_for(boost::detail::to_timespec(ns));
|
||||
}
|
||||
#endif
|
||||
#endif // BOOST_THREAD_USES_CHRONO
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/detail/delete.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/sync_queue.hpp>
|
||||
#include <boost/thread/detail/work.hpp>
|
||||
#include <boost/thread/concurrent_queues/sync_queue.hpp>
|
||||
#include <boost/thread/executors/work.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace boost
|
||||
work task;
|
||||
try
|
||||
{
|
||||
if (work_queue.try_pull_front(task) == queue_op_status::success)
|
||||
if (work_queue.try_pull(task) == queue_op_status::success)
|
||||
{
|
||||
task();
|
||||
return true;
|
||||
@@ -144,23 +144,23 @@ namespace boost
|
||||
void submit(Closure & closure)
|
||||
{
|
||||
work w ((closure));
|
||||
work_queue.push_back(boost::move(w));
|
||||
work_queue.push(boost::move(w));
|
||||
//work_queue.push(work(closure)); // todo check why this doesn't work
|
||||
}
|
||||
#endif
|
||||
void submit(void (*closure)())
|
||||
{
|
||||
work w ((closure));
|
||||
work_queue.push_back(boost::move(w));
|
||||
//work_queue.push_back(work(closure)); // todo check why this doesn't work
|
||||
work_queue.push(boost::move(w));
|
||||
//work_queue.push(work(closure)); // todo check why this doesn't work
|
||||
}
|
||||
|
||||
template <typename Closure>
|
||||
void submit(BOOST_THREAD_RV_REF(Closure) closure)
|
||||
{
|
||||
work w =boost::move(closure);
|
||||
work_queue.push_back(boost::move(w));
|
||||
//work_queue.push_back(work(boost::move(closure))); // todo check why this doesn't work
|
||||
work_queue.push(boost::move(w));
|
||||
//work_queue.push(work(boost::move(closure))); // todo check why this doesn't work
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -285,7 +285,6 @@ namespace boost
|
||||
// Oops, we weren't called often enough, we're stuck
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
inline detail::gettickcount64_t GetTickCount64_()
|
||||
{
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
|
||||
|
||||
#include <boost/thread/future_error_code.hpp>
|
||||
#include <boost/thread/futures/future_error_code.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace boost
|
||||
|
||||
@@ -36,8 +36,6 @@
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include "./timeconv.inl"
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
|
||||
@@ -1,151 +0,0 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
// Copyright (C) 2009 Anthony Williams
|
||||
//
|
||||
// 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)
|
||||
|
||||
// boostinspect:nounnamed
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace {
|
||||
const int MILLISECONDS_PER_SECOND = 1000;
|
||||
const int NANOSECONDS_PER_SECOND = 1000000000;
|
||||
const int NANOSECONDS_PER_MILLISECOND = 1000000;
|
||||
|
||||
const int MICROSECONDS_PER_SECOND = 1000000;
|
||||
const int NANOSECONDS_PER_MICROSECOND = 1000;
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
inline void to_time(int milliseconds, boost::xtime& xt)
|
||||
{
|
||||
int res = 0;
|
||||
res = boost::xtime_get(&xt, boost::TIME_UTC_);
|
||||
BOOST_ASSERT(res == boost::TIME_UTC_); (void)res;
|
||||
|
||||
xt.sec += (milliseconds / MILLISECONDS_PER_SECOND);
|
||||
xt.nsec += ((milliseconds % MILLISECONDS_PER_SECOND) *
|
||||
NANOSECONDS_PER_MILLISECOND);
|
||||
|
||||
if (xt.nsec >= NANOSECONDS_PER_SECOND)
|
||||
{
|
||||
++xt.sec;
|
||||
xt.nsec -= NANOSECONDS_PER_SECOND;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
inline void to_timespec(const boost::xtime& xt, timespec& ts)
|
||||
{
|
||||
ts.tv_sec = static_cast<int>(xt.sec);
|
||||
ts.tv_nsec = static_cast<int>(xt.nsec);
|
||||
if(ts.tv_nsec >= NANOSECONDS_PER_SECOND)
|
||||
{
|
||||
ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND;
|
||||
ts.tv_nsec %= NANOSECONDS_PER_SECOND;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
inline void to_time(int milliseconds, timespec& ts)
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
boost::xtime xt;
|
||||
to_time(milliseconds, xt);
|
||||
to_timespec(xt, ts);
|
||||
#else
|
||||
ts.tv_sec += (milliseconds / MILLISECONDS_PER_SECOND);
|
||||
ts.tv_nsec += ((milliseconds % MILLISECONDS_PER_SECOND) *
|
||||
NANOSECONDS_PER_MILLISECOND);
|
||||
|
||||
if (ts.tv_nsec >= NANOSECONDS_PER_SECOND)
|
||||
{
|
||||
++ts.tv_sec;
|
||||
ts.tv_nsec -= NANOSECONDS_PER_SECOND;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
inline void to_timespec_duration(const boost::xtime& xt, timespec& ts)
|
||||
{
|
||||
boost::xtime cur;
|
||||
int res = 0;
|
||||
res = boost::xtime_get(&cur, boost::TIME_UTC_);
|
||||
BOOST_ASSERT(res == boost::TIME_UTC_); (void)res;
|
||||
|
||||
if (boost::xtime_cmp(xt, cur) <= 0)
|
||||
{
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ts.tv_sec = xt.sec - cur.sec;
|
||||
ts.tv_nsec = xt.nsec - cur.nsec;
|
||||
|
||||
if( ts.tv_nsec < 0 )
|
||||
{
|
||||
ts.tv_sec -= 1;
|
||||
ts.tv_nsec += NANOSECONDS_PER_SECOND;
|
||||
}
|
||||
if(ts.tv_nsec >= NANOSECONDS_PER_SECOND)
|
||||
{
|
||||
ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND;
|
||||
ts.tv_nsec %= NANOSECONDS_PER_SECOND;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
inline void to_duration(boost::xtime xt, int& milliseconds)
|
||||
{
|
||||
boost::xtime cur;
|
||||
int res = 0;
|
||||
res = boost::xtime_get(&cur, boost::TIME_UTC_);
|
||||
BOOST_ASSERT(res == boost::TIME_UTC_); (void)res;
|
||||
|
||||
if (boost::xtime_cmp(xt, cur) <= 0)
|
||||
milliseconds = 0;
|
||||
else
|
||||
{
|
||||
if (cur.nsec > xt.nsec)
|
||||
{
|
||||
xt.nsec += NANOSECONDS_PER_SECOND;
|
||||
--xt.sec;
|
||||
}
|
||||
milliseconds = (int)((xt.sec - cur.sec) * MILLISECONDS_PER_SECOND) +
|
||||
(((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MILLISECOND/2)) /
|
||||
NANOSECONDS_PER_MILLISECOND);
|
||||
}
|
||||
}
|
||||
|
||||
inline void to_microduration(boost::xtime xt, int& microseconds)
|
||||
{
|
||||
boost::xtime cur;
|
||||
int res = 0;
|
||||
res = boost::xtime_get(&cur, boost::TIME_UTC_);
|
||||
BOOST_ASSERT(res == boost::TIME_UTC_); (void)res;
|
||||
|
||||
if (boost::xtime_cmp(xt, cur) <= 0)
|
||||
microseconds = 0;
|
||||
else
|
||||
{
|
||||
if (cur.nsec > xt.nsec)
|
||||
{
|
||||
xt.nsec += NANOSECONDS_PER_SECOND;
|
||||
--xt.sec;
|
||||
}
|
||||
microseconds = (int)((xt.sec - cur.sec) * MICROSECONDS_PER_SECOND) +
|
||||
(((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MICROSECOND/2)) /
|
||||
NANOSECONDS_PER_MICROSECOND);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Change Log:
|
||||
// 1 Jun 01 Initial creation.
|
||||
@@ -529,11 +529,10 @@ namespace boost
|
||||
|
||||
unsigned thread::physical_concurrency() BOOST_NOEXCEPT
|
||||
{
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME || (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
|
||||
return hardware_concurrency();
|
||||
#else
|
||||
unsigned cores = 0;
|
||||
#if !(defined(__MINGW32__) || defined (__MINGW64__))
|
||||
DWORD size = 0;
|
||||
|
||||
GetLogicalProcessorInformation(NULL, &size);
|
||||
@@ -550,7 +549,6 @@ namespace boost
|
||||
if (buffer[i].Relationship == RelationProcessorCore)
|
||||
++cores;
|
||||
}
|
||||
#endif
|
||||
return cores;
|
||||
#endif
|
||||
}
|
||||
@@ -633,10 +631,60 @@ namespace boost
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef UNDER_CE
|
||||
#if !BOOST_PLAT_WINDOWS_RUNTIME
|
||||
namespace detail_
|
||||
{
|
||||
typedef struct _REASON_CONTEXT {
|
||||
ULONG Version;
|
||||
DWORD Flags;
|
||||
union {
|
||||
LPWSTR SimpleReasonString;
|
||||
struct {
|
||||
HMODULE LocalizedReasonModule;
|
||||
ULONG LocalizedReasonId;
|
||||
ULONG ReasonStringCount;
|
||||
LPWSTR *ReasonStrings;
|
||||
} Detailed;
|
||||
} Reason;
|
||||
} REASON_CONTEXT, *PREASON_CONTEXT;
|
||||
static REASON_CONTEXT default_reason_context={0/*POWER_REQUEST_CONTEXT_VERSION*/, 0x00000001/*POWER_REQUEST_CONTEXT_SIMPLE_STRING*/, (LPWSTR)L"generic"};
|
||||
typedef BOOL (WINAPI *setwaitabletimerex_t)(HANDLE, const LARGE_INTEGER *, LONG, PTIMERAPCROUTINE, LPVOID, PREASON_CONTEXT, ULONG);
|
||||
static inline BOOL WINAPI SetWaitableTimerEx_emulation(HANDLE hTimer, const LARGE_INTEGER *lpDueTime, LONG lPeriod, PTIMERAPCROUTINE pfnCompletionRoutine, LPVOID lpArgToCompletionRoutine, PREASON_CONTEXT WakeContext, ULONG TolerableDelay)
|
||||
{
|
||||
return SetWaitableTimer(hTimer, lpDueTime, lPeriod, pfnCompletionRoutine, lpArgToCompletionRoutine, FALSE);
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 6387) // MSVC sanitiser warns that GetModuleHandleA() might fail
|
||||
#endif
|
||||
static inline setwaitabletimerex_t SetWaitableTimerEx()
|
||||
{
|
||||
static setwaitabletimerex_t setwaitabletimerex_impl;
|
||||
if(setwaitabletimerex_impl)
|
||||
return setwaitabletimerex_impl;
|
||||
void (*addr)()=(void (*)()) GetProcAddress(
|
||||
#if !defined(BOOST_NO_ANSI_APIS)
|
||||
GetModuleHandleA("KERNEL32.DLL"),
|
||||
#else
|
||||
GetModuleHandleW(L"KERNEL32.DLL"),
|
||||
#endif
|
||||
"SetWaitableTimerEx");
|
||||
if(addr)
|
||||
setwaitabletimerex_impl=(setwaitabletimerex_t) addr;
|
||||
else
|
||||
setwaitabletimerex_impl=&SetWaitableTimerEx_emulation;
|
||||
return setwaitabletimerex_impl;
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
bool interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time)
|
||||
{
|
||||
detail::win32::handle handles[3]={0};
|
||||
detail::win32::handle handles[4]={0};
|
||||
unsigned handle_count=0;
|
||||
unsigned wait_handle_index=~0U;
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
@@ -659,32 +707,24 @@ namespace boost
|
||||
|
||||
#ifndef UNDER_CE
|
||||
#if !BOOST_PLAT_WINDOWS_RUNTIME
|
||||
unsigned const min_timer_wait_period=20;
|
||||
|
||||
// Preferentially use coalescing timers for better power consumption and timer accuracy
|
||||
if(!target_time.is_sentinel())
|
||||
{
|
||||
detail::timeout::remaining_time const time_left=target_time.remaining_milliseconds();
|
||||
if(time_left.milliseconds > min_timer_wait_period)
|
||||
timer_handle=CreateWaitableTimer(NULL,false,NULL);
|
||||
if(timer_handle!=0)
|
||||
{
|
||||
// for a long-enough timeout, use a waitable timer (which tracks clock changes)
|
||||
timer_handle=CreateWaitableTimer(NULL,false,NULL);
|
||||
if(timer_handle!=0)
|
||||
ULONG tolerable=32; // Empirical testing shows Windows ignores this when <= 26
|
||||
if(time_left.milliseconds/20>tolerable) // 5%
|
||||
tolerable=time_left.milliseconds/20;
|
||||
LARGE_INTEGER due_time=get_due_time(target_time);
|
||||
bool const set_time_succeeded=detail_::SetWaitableTimerEx()(timer_handle,&due_time,0,0,0,&detail_::default_reason_context,tolerable)!=0;
|
||||
if(set_time_succeeded)
|
||||
{
|
||||
LARGE_INTEGER due_time=get_due_time(target_time);
|
||||
|
||||
bool const set_time_succeeded=SetWaitableTimer(timer_handle,&due_time,0,0,0,false)!=0;
|
||||
if(set_time_succeeded)
|
||||
{
|
||||
timeout_index=handle_count;
|
||||
handles[handle_count++]=timer_handle;
|
||||
}
|
||||
timeout_index=handle_count;
|
||||
handles[handle_count++]=timer_handle;
|
||||
}
|
||||
}
|
||||
else if(!target_time.relative)
|
||||
{
|
||||
// convert short absolute-time timeouts into relative ones, so we don't race against clock changes
|
||||
target_time=detail::timeout(time_left.milliseconds);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -751,32 +791,24 @@ namespace boost
|
||||
|
||||
#ifndef UNDER_CE
|
||||
#if !BOOST_PLAT_WINDOWS_RUNTIME
|
||||
unsigned const min_timer_wait_period=20;
|
||||
|
||||
// Preferentially use coalescing timers for better power consumption and timer accuracy
|
||||
if(!target_time.is_sentinel())
|
||||
{
|
||||
detail::timeout::remaining_time const time_left=target_time.remaining_milliseconds();
|
||||
if(time_left.milliseconds > min_timer_wait_period)
|
||||
timer_handle=CreateWaitableTimer(NULL,false,NULL);
|
||||
if(timer_handle!=0)
|
||||
{
|
||||
// for a long-enough timeout, use a waitable timer (which tracks clock changes)
|
||||
timer_handle=CreateWaitableTimer(NULL,false,NULL);
|
||||
if(timer_handle!=0)
|
||||
ULONG tolerable=32; // Empirical testing shows Windows ignores this when <= 26
|
||||
if(time_left.milliseconds/20>tolerable) // 5%
|
||||
tolerable=time_left.milliseconds/20;
|
||||
LARGE_INTEGER due_time=get_due_time(target_time);
|
||||
bool const set_time_succeeded=detail_::SetWaitableTimerEx()(timer_handle,&due_time,0,0,0,&detail_::default_reason_context,tolerable)!=0;
|
||||
if(set_time_succeeded)
|
||||
{
|
||||
LARGE_INTEGER due_time=get_due_time(target_time);
|
||||
|
||||
bool const set_time_succeeded=SetWaitableTimer(timer_handle,&due_time,0,0,0,false)!=0;
|
||||
if(set_time_succeeded)
|
||||
{
|
||||
timeout_index=handle_count;
|
||||
handles[handle_count++]=timer_handle;
|
||||
}
|
||||
timeout_index=handle_count;
|
||||
handles[handle_count++]=timer_handle;
|
||||
}
|
||||
}
|
||||
else if(!target_time.relative)
|
||||
{
|
||||
// convert short absolute-time timeouts into relative ones, so we don't race against clock changes
|
||||
target_time=detail::timeout(time_left.milliseconds);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
//
|
||||
// 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)
|
||||
|
||||
// boostinspect:nounnamed
|
||||
|
||||
namespace {
|
||||
const int MILLISECONDS_PER_SECOND = 1000;
|
||||
const int NANOSECONDS_PER_SECOND = 1000000000;
|
||||
const int NANOSECONDS_PER_MILLISECOND = 1000000;
|
||||
|
||||
const int MICROSECONDS_PER_SECOND = 1000000;
|
||||
const int NANOSECONDS_PER_MICROSECOND = 1000;
|
||||
|
||||
inline void to_time(int milliseconds, boost::xtime& xt)
|
||||
{
|
||||
int res = 0;
|
||||
res = boost::xtime_get(&xt, boost::TIME_UTC_);
|
||||
assert(res == boost::TIME_UTC_);
|
||||
|
||||
xt.sec += (milliseconds / MILLISECONDS_PER_SECOND);
|
||||
xt.nsec += ((milliseconds % MILLISECONDS_PER_SECOND) *
|
||||
NANOSECONDS_PER_MILLISECOND);
|
||||
|
||||
if (xt.nsec >= NANOSECONDS_PER_SECOND)
|
||||
{
|
||||
++xt.sec;
|
||||
xt.nsec -= NANOSECONDS_PER_SECOND;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
inline void to_timespec(const boost::xtime& xt, timespec& ts)
|
||||
{
|
||||
ts.tv_sec = static_cast<int>(xt.sec);
|
||||
ts.tv_nsec = static_cast<int>(xt.nsec);
|
||||
if(ts.tv_nsec >= NANOSECONDS_PER_SECOND)
|
||||
{
|
||||
ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND;
|
||||
ts.tv_nsec %= NANOSECONDS_PER_SECOND;
|
||||
}
|
||||
}
|
||||
|
||||
inline void to_time(int milliseconds, timespec& ts)
|
||||
{
|
||||
boost::xtime xt;
|
||||
to_time(milliseconds, xt);
|
||||
to_timespec(xt, ts);
|
||||
}
|
||||
|
||||
inline void to_timespec_duration(const boost::xtime& xt, timespec& ts)
|
||||
{
|
||||
boost::xtime cur;
|
||||
int res = 0;
|
||||
res = boost::xtime_get(&cur, boost::TIME_UTC_);
|
||||
assert(res == boost::TIME_UTC_);
|
||||
|
||||
if (boost::xtime_cmp(xt, cur) <= 0)
|
||||
{
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ts.tv_sec = xt.sec - cur.sec;
|
||||
ts.tv_nsec = xt.nsec - cur.nsec;
|
||||
|
||||
if( ts.tv_nsec < 0 )
|
||||
{
|
||||
ts.tv_sec -= 1;
|
||||
ts.tv_nsec += NANOSECONDS_PER_SECOND;
|
||||
}
|
||||
if(ts.tv_nsec >= NANOSECONDS_PER_SECOND)
|
||||
{
|
||||
ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND;
|
||||
ts.tv_nsec %= NANOSECONDS_PER_SECOND;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
inline void to_duration(boost::xtime xt, int& milliseconds)
|
||||
{
|
||||
boost::xtime cur;
|
||||
int res = 0;
|
||||
res = boost::xtime_get(&cur, boost::TIME_UTC_);
|
||||
assert(res == boost::TIME_UTC_);
|
||||
|
||||
if (boost::xtime_cmp(xt, cur) <= 0)
|
||||
milliseconds = 0;
|
||||
else
|
||||
{
|
||||
if (cur.nsec > xt.nsec)
|
||||
{
|
||||
xt.nsec += NANOSECONDS_PER_SECOND;
|
||||
--xt.sec;
|
||||
}
|
||||
milliseconds = (int)((xt.sec - cur.sec) * MILLISECONDS_PER_SECOND) +
|
||||
(((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MILLISECOND/2)) /
|
||||
NANOSECONDS_PER_MILLISECOND);
|
||||
}
|
||||
}
|
||||
|
||||
inline void to_microduration(boost::xtime xt, int& microseconds)
|
||||
{
|
||||
boost::xtime cur;
|
||||
int res = 0;
|
||||
res = boost::xtime_get(&cur, boost::TIME_UTC_);
|
||||
assert(res == boost::TIME_UTC_);
|
||||
|
||||
if (boost::xtime_cmp(xt, cur) <= 0)
|
||||
microseconds = 0;
|
||||
else
|
||||
{
|
||||
if (cur.nsec > xt.nsec)
|
||||
{
|
||||
xt.nsec += NANOSECONDS_PER_SECOND;
|
||||
--xt.sec;
|
||||
}
|
||||
microseconds = (int)((xt.sec - cur.sec) * MICROSECONDS_PER_SECOND) +
|
||||
(((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MICROSECOND/2)) /
|
||||
NANOSECONDS_PER_MICROSECOND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Change Log:
|
||||
// 1 Jun 01 Initial creation.
|
||||
@@ -73,5 +73,13 @@ namespace boost
|
||||
}
|
||||
}
|
||||
|
||||
#else //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_DLL)
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Prevent LNK4221 warning with link=static
|
||||
namespace boost { namespace link_static_warning_inhibit {
|
||||
extern __declspec(dllexport) void foo() { }
|
||||
} }
|
||||
#endif
|
||||
|
||||
#endif //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_DLL)
|
||||
|
||||
@@ -34,6 +34,7 @@ project
|
||||
<toolset>gcc:<cxxflags>-Wno-variadic-macros
|
||||
#<toolset>gcc:<cxxflags>-Wunused-local-typedefs
|
||||
<toolset>gcc:<cxxflags>-Wunused-function
|
||||
<toolset>gcc:<cxxflags>-Wno-unused-parameter
|
||||
|
||||
<toolset>darwin:<cxxflags>-Wextra
|
||||
<toolset>darwin:<cxxflags>-pedantic
|
||||
@@ -43,18 +44,20 @@ project
|
||||
<toolset>darwin:<cxxflags>-Wno-variadic-macros
|
||||
#<toolset>darwin:<cxxflags>-Wunused-local-typedefs
|
||||
<toolset>darwin:<cxxflags>-Wunused-function
|
||||
<toolset>darwin:<cxxflags>-Wno-unused-parameter
|
||||
|
||||
#<toolset>pathscale:<cxxflags>-Wextra
|
||||
<toolset>pathscale:<cxxflags>-Wno-long-long
|
||||
<toolset>pathscale:<cxxflags>-pedantic
|
||||
|
||||
<toolset>clang:<warnings>on
|
||||
<toolset>clang:<cxxflags>-Wextra
|
||||
#<toolset>clang:<cxxflags>-pedantic
|
||||
<toolset>clang:<warnings>on
|
||||
<toolset>clang:<cxxflags>-Wno-long-long
|
||||
#<toolset>clang:<cxxflags>-ansi
|
||||
#<toolset>clang:<cxxflags>-fpermissive # doesn't work
|
||||
<toolset>clang:<cxxflags>-Wunused-function
|
||||
<toolset>clang:<cxxflags>-Wno-unused-parameter
|
||||
|
||||
#<toolset>gcc-mingw-4.4.0:<cxxflags>-fdiagnostics-show-option
|
||||
#<toolset>gcc-mingw-4.5.0:<cxxflags>-fdiagnostics-show-option
|
||||
@@ -97,6 +100,10 @@ project
|
||||
<toolset>intel:<cxxflags>-wd593,981
|
||||
<toolset>intel:<cxxflags>-wd1418
|
||||
<toolset>intel:<cxxflags>-wd2415
|
||||
|
||||
<toolset>msvc:<cxxflags>/wd4100
|
||||
<toolset>msvc:<cxxflags>/wd4512
|
||||
<toolset>msvc:<cxxflags>/wd6246
|
||||
;
|
||||
|
||||
rule thread-run ( sources )
|
||||
@@ -115,7 +122,7 @@ rule thread-test ( sources )
|
||||
sources = $(sources) winrt_init.cpp ;
|
||||
return
|
||||
[ run $(sources) ../build//boost_thread : : :
|
||||
<library>/boost/test//boost_unit_test_framework/<link>static
|
||||
<library>/boost/test//boost_unit_test_framework
|
||||
]
|
||||
[ run $(sources) ../src/tss_null.cpp ../build//boost_thread/<link>static
|
||||
: : :
|
||||
@@ -286,8 +293,10 @@ rule thread-compile ( sources : reqs * : name )
|
||||
[ thread-run test_7328.cpp ]
|
||||
[ thread-run test_7571.cpp ]
|
||||
[ thread-run test_9319.cpp ]
|
||||
[ thread-run test_9711.cpp ]
|
||||
|
||||
#[ thread-run test_9711.cpp ] This is an invalid use of ::then deferred.
|
||||
[ thread-run test_9856.cpp ]
|
||||
[ thread-compile test_10963.cpp : : test_10963_c ]
|
||||
[ thread-run test_10964.cpp ]
|
||||
;
|
||||
|
||||
|
||||
@@ -349,6 +358,7 @@ rule thread-compile ( sources : reqs * : name )
|
||||
[ thread-run2-noit ./sync/futures/promise/set_rvalue_pass.cpp : promise__set_rvalue_p ]
|
||||
[ thread-run2-noit ./sync/futures/promise/set_value_const_pass.cpp : promise__set_value_const_p ]
|
||||
[ thread-run2-noit ./sync/futures/promise/set_value_void_pass.cpp : promise__set_value_void_p ]
|
||||
[ thread-run2-noit ./sync/futures/promise/emplace_pass.cpp : promise__emplace_p ]
|
||||
[ thread-run2-noit ./sync/futures/promise/use_allocator_pass.cpp : promise__use_allocator_p ]
|
||||
[ thread-run2-noit ./sync/futures/promise/set_exception_at_thread_exit_pass.cpp : promise__set_exception_at_thread_exit_p ]
|
||||
[ thread-run2-noit ./sync/futures/promise/set_lvalue_at_thread_exit_pass.cpp : promise__set_lvalue_at_thread_exit_p ]
|
||||
@@ -357,6 +367,12 @@ rule thread-compile ( sources : reqs * : name )
|
||||
[ thread-run2-noit ./sync/futures/promise/set_value_at_thread_exit_void_pass.cpp : promise__set_value_at_thread_exit_void_p ]
|
||||
;
|
||||
|
||||
#explicit ts_make_ready_future ;
|
||||
test-suite ts_make_ready_future
|
||||
:
|
||||
[ thread-run2-noit ./sync/futures/make_ready_future_pass.cpp : make_ready_future_p ]
|
||||
;
|
||||
|
||||
#explicit ts_future ;
|
||||
test-suite ts_future
|
||||
:
|
||||
@@ -669,6 +685,12 @@ rule thread-compile ( sources : reqs * : name )
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/sync_queue/multi_thread_pass.cpp : sync_queue__multi_thread_p ]
|
||||
;
|
||||
|
||||
test-suite ts_sync_deque
|
||||
:
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/sync_deque/single_thread_pass.cpp : sync_deque__single_thread_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/sync_deque/multi_thread_pass.cpp : sync_deque__multi_thread_p ]
|
||||
;
|
||||
|
||||
test-suite ts_sync_bounded_queue
|
||||
:
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/sync_bounded_queue/single_thread_pass.cpp : sync_bounded_q_single_thread_p ]
|
||||
@@ -700,6 +722,12 @@ rule thread-compile ( sources : reqs * : name )
|
||||
#[ thread-run2-noit ./sync/mutual_exclusion/queue_views/multi_thread_pass.cpp : queue_views__multi_thread_p ]
|
||||
;
|
||||
|
||||
test-suite ts_deque_views
|
||||
:
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/deque_views/single_thread_pass.cpp : deque_views__single_thread_p ]
|
||||
#[ thread-run2-noit ./sync/mutual_exclusion/deque_views/multi_thread_pass.cpp : deque_views__multi_thread_p ]
|
||||
;
|
||||
|
||||
#explicit ts_this_thread ;
|
||||
test-suite ts_this_thread
|
||||
:
|
||||
@@ -780,11 +808,13 @@ rule thread-compile ( sources : reqs * : name )
|
||||
[ thread-run2 ../example/user_scheduler.cpp : ex_user_scheduler ]
|
||||
[ thread-run2 ../example/executor.cpp : ex_executor ]
|
||||
[ thread-run2 ../example/generic_executor_ref.cpp : ex_generic_executor_ref ]
|
||||
[ thread-run2 ../example/serial_executor.cpp : ex_serial_executor ]
|
||||
[ thread-run2 ../example/serial_executor_cont.cpp : ex_serial_executor_cont ]
|
||||
[ thread-run2 ../example/future_when_all.cpp : ex_future_when_all ]
|
||||
[ thread-run2 ../example/parallel_accumulate.cpp : ex_parallel_accumulate ]
|
||||
[ thread-run2 ../example/parallel_quick_sort.cpp : ex_parallel_quick_sort ]
|
||||
[ thread-run2 ../example/with_lock_guard.cpp : ex_with_lock_guard ]
|
||||
|
||||
[ thread-run2 ../example/fib_task_region.cpp : ex_fib_task_region ]
|
||||
;
|
||||
|
||||
#explicit ts_shared_upwards ;
|
||||
@@ -902,6 +932,19 @@ rule thread-compile ( sources : reqs * : name )
|
||||
#[ thread-run ../example/perf_condition_variable.cpp ]
|
||||
#[ thread-run ../example/perf_shared_mutex.cpp ]
|
||||
;
|
||||
|
||||
|
||||
#explicit ts_exception_list ;
|
||||
test-suite ts_exception_list
|
||||
:
|
||||
[ thread-run2-noit ./experimental/parallel/v1/exception_list_pass.cpp : exception_list_p ]
|
||||
;
|
||||
|
||||
#explicit ts_task_region ;
|
||||
test-suite ts_task_region
|
||||
:
|
||||
[ thread-run2-noit ./experimental/parallel/v2/task_region_pass.cpp : task_region_p ]
|
||||
;
|
||||
|
||||
explicit ts_ ;
|
||||
test-suite ts_
|
||||
|
||||
23
test/experimental/parallel/v1/exception_list_pass.cpp
Normal file
23
test/experimental/parallel/v1/exception_list_pass.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
// Copyright (C) 2014 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)
|
||||
|
||||
// <boost/thread/experimental/parallel/v1/exception_list.hpp>
|
||||
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#include <boost/config.hpp>
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
|
||||
#include <boost/thread/experimental/parallel/v1/exception_list.hpp>
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
return boost::report_errors();
|
||||
}
|
||||
293
test/experimental/parallel/v2/task_region_pass.cpp
Normal file
293
test/experimental/parallel/v2/task_region_pass.cpp
Normal file
@@ -0,0 +1,293 @@
|
||||
// Copyright (C) 2014 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)
|
||||
|
||||
// <boost/thread/experimental/parallel/v1/exception_list.hpp>
|
||||
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
#include <boost/config.hpp>
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
|
||||
#include <boost/thread/experimental/parallel/v2/task_region.hpp>
|
||||
#include <string>
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
#if ! defined BOOST_NO_CXX11_LAMBDAS && defined(BOOST_THREAD_PROVIDES_INVOKE)
|
||||
using boost::experimental::parallel::v2::task_region;
|
||||
using boost::experimental::parallel::v2::task_region_handle;
|
||||
using boost::experimental::parallel::v1::exception_list;
|
||||
|
||||
void run_no_exception()
|
||||
{
|
||||
std::string s("test");
|
||||
bool parent_flag = false;
|
||||
bool task1_flag = false;
|
||||
bool task2_flag = false;
|
||||
bool task21_flag = false;
|
||||
bool task3_flag = false;
|
||||
task_region([&](task_region_handle& trh)
|
||||
{
|
||||
parent_flag = true;
|
||||
trh.run([&]()
|
||||
{
|
||||
task1_flag = true;
|
||||
std::cout << "task1: " << s << std::endl;
|
||||
});
|
||||
trh.run([&]()
|
||||
{
|
||||
task2_flag = true;
|
||||
std::cout << "task2" << std::endl;
|
||||
task_region([&](task_region_handle& trh)
|
||||
{
|
||||
trh.run([&]()
|
||||
{
|
||||
task21_flag = true;
|
||||
std::cout << "task2.1" << std::endl;
|
||||
});
|
||||
});
|
||||
});
|
||||
int i = 0, j = 10, k = 20;
|
||||
trh.run([=, &task3_flag]()
|
||||
{
|
||||
task3_flag = true;
|
||||
std::cout << "task3: " << i << " " << j << " " << k << std::endl;
|
||||
});
|
||||
std::cout << "parent" << std::endl;
|
||||
});
|
||||
BOOST_TEST(parent_flag);
|
||||
BOOST_TEST(task1_flag);
|
||||
BOOST_TEST(task2_flag);
|
||||
BOOST_TEST(task21_flag);
|
||||
BOOST_TEST(task3_flag);
|
||||
}
|
||||
|
||||
void run_no_exception_wait()
|
||||
{
|
||||
std::string s("test");
|
||||
bool parent_flag = false;
|
||||
bool wait_flag = false;
|
||||
bool task1_flag = false;
|
||||
bool task2_flag = false;
|
||||
bool task21_flag = false;
|
||||
bool task3_flag = false;
|
||||
task_region([&](task_region_handle& trh)
|
||||
{
|
||||
parent_flag = true;
|
||||
trh.run([&]()
|
||||
{
|
||||
task1_flag = true;
|
||||
std::cout << "task1: " << s << std::endl;
|
||||
});
|
||||
trh.run([&]()
|
||||
{
|
||||
task2_flag = true;
|
||||
std::cout << "task2" << std::endl;
|
||||
task_region([&](task_region_handle& trh)
|
||||
{
|
||||
trh.run([&]()
|
||||
{
|
||||
task21_flag = true;
|
||||
std::cout << "task2.1" << std::endl;
|
||||
});
|
||||
});
|
||||
});
|
||||
int i = 0, j = 10, k = 20;
|
||||
trh.run([=, &task3_flag]()
|
||||
{
|
||||
task3_flag = true;
|
||||
std::cout << "task3: " << i << " " << j << " " << k << std::endl;
|
||||
});
|
||||
std::cout << "before" << std::endl;
|
||||
trh.wait();
|
||||
wait_flag = true;
|
||||
std::cout << "parent" << std::endl;
|
||||
});
|
||||
BOOST_TEST(parent_flag);
|
||||
BOOST_TEST(wait_flag);
|
||||
BOOST_TEST(task1_flag);
|
||||
BOOST_TEST(task2_flag);
|
||||
BOOST_TEST(task21_flag);
|
||||
BOOST_TEST(task3_flag);
|
||||
}
|
||||
|
||||
void run_exception_1()
|
||||
{
|
||||
try
|
||||
{
|
||||
task_region([](task_region_handle& trh)
|
||||
{
|
||||
trh.run([]()
|
||||
{
|
||||
std::cout << "task1" << std::endl;
|
||||
throw 1;
|
||||
});
|
||||
boost::this_thread::sleep_for(boost::chrono::seconds(1));
|
||||
trh.run([]()
|
||||
{
|
||||
std::cout << "task3" << std::endl;
|
||||
});
|
||||
BOOST_TEST(false);
|
||||
});
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
catch (exception_list const& e)
|
||||
{
|
||||
BOOST_TEST_EQ(e.size(), 1u);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
|
||||
void run_exception()
|
||||
{
|
||||
try
|
||||
{
|
||||
task_region([](task_region_handle& trh)
|
||||
{
|
||||
trh.run([]()
|
||||
{
|
||||
std::cout << "task1" << std::endl;
|
||||
throw 1;
|
||||
});
|
||||
trh.run([]()
|
||||
{
|
||||
std::cout << "task2" << std::endl;
|
||||
throw 2;
|
||||
});
|
||||
boost::this_thread::sleep_for(boost::chrono::seconds(1));
|
||||
trh.run([]()
|
||||
{
|
||||
std::cout << "task3" << std::endl;
|
||||
throw 3;
|
||||
});
|
||||
std::cout << "parent" << std::endl;
|
||||
throw 100;
|
||||
});
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
catch (exception_list const& el)
|
||||
{
|
||||
BOOST_TEST(el.size() >= 1u);
|
||||
for (boost::exception_ptr const& e: el)
|
||||
{
|
||||
try {
|
||||
boost::rethrow_exception(e);
|
||||
}
|
||||
catch (boost::exception&)
|
||||
{
|
||||
BOOST_TEST(true);
|
||||
}
|
||||
catch (int i) // this doesn't works yet
|
||||
{
|
||||
BOOST_TEST((i == 1) || (i == 2) || (i == 3));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void run_nested_exception()
|
||||
{
|
||||
std::string s("test");
|
||||
bool parent_flag = false;
|
||||
bool task1_flag = false;
|
||||
bool task2_flag = false;
|
||||
bool task21_flag = false;
|
||||
bool task3_flag = false;
|
||||
try
|
||||
{
|
||||
task_region([&](task_region_handle& trh)
|
||||
{
|
||||
parent_flag = true;
|
||||
trh.run([&]()
|
||||
{
|
||||
task1_flag = true;
|
||||
std::cout << "task1: " << s << std::endl;
|
||||
});
|
||||
trh.run([&]()
|
||||
{
|
||||
task2_flag = true;
|
||||
std::cout << "task2" << std::endl;
|
||||
task_region([&](task_region_handle& trh)
|
||||
{
|
||||
trh.run([&]()
|
||||
{
|
||||
task21_flag = true;
|
||||
std::cout << "task2.1" << std::endl;
|
||||
throw 21;
|
||||
});
|
||||
});
|
||||
});
|
||||
int i = 0, j = 10, k = 20;
|
||||
trh.run([=, &task3_flag]()
|
||||
{
|
||||
task3_flag = true;
|
||||
std::cout << "task3: " << i << " " << j << " " << k << std::endl;
|
||||
});
|
||||
std::cout << "parent" << std::endl;
|
||||
});
|
||||
}
|
||||
catch (exception_list const& el)
|
||||
{
|
||||
BOOST_TEST(el.size() == 1u);
|
||||
for (boost::exception_ptr const& e: el)
|
||||
{
|
||||
try {
|
||||
boost::rethrow_exception(e);
|
||||
}
|
||||
catch (int i) // this doesn't works yet
|
||||
{
|
||||
BOOST_TEST_EQ(i, 21);
|
||||
}
|
||||
catch (boost::exception&)
|
||||
{
|
||||
BOOST_TEST(true);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
BOOST_TEST(parent_flag);
|
||||
BOOST_TEST(task1_flag);
|
||||
BOOST_TEST(task2_flag);
|
||||
BOOST_TEST(task21_flag);
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
run_no_exception();
|
||||
run_no_exception_wait();
|
||||
run_exception();
|
||||
run_exception_1();
|
||||
run_nested_exception();
|
||||
return boost::report_errors();
|
||||
}
|
||||
#else
|
||||
int main()
|
||||
{
|
||||
return boost::report_errors();
|
||||
}
|
||||
#endif
|
||||
@@ -85,7 +85,7 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
int operator()()
|
||||
int operator()() const
|
||||
{
|
||||
boost::this_thread::sleep_for(ms(200));
|
||||
return 3;
|
||||
@@ -167,6 +167,48 @@ struct check_timer {
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
try {
|
||||
boost::async(f0);
|
||||
} catch (std::exception& ex)
|
||||
{
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl;
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
}
|
||||
{
|
||||
try {
|
||||
boost::async(boost::launch::async, f0);
|
||||
} catch (std::exception& ex)
|
||||
{
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl;
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
}
|
||||
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
{
|
||||
try {
|
||||
boost::async(boost::launch::deferred, f0);
|
||||
} catch (std::exception& ex)
|
||||
{
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl;
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false && "exception thrown");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
{
|
||||
try
|
||||
|
||||
@@ -51,6 +51,29 @@ void p3(boost::future<int> f)
|
||||
|
||||
int main()
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);
|
||||
BOOST_TEST(f1.valid());
|
||||
{
|
||||
boost::future<int> f2 = f1.then(&p2);
|
||||
BOOST_TEST(f2.valid());
|
||||
}
|
||||
BOOST_TEST(! f1.valid());
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);
|
||||
|
||||
157
test/sync/futures/make_ready_future_pass.cpp
Normal file
157
test/sync/futures/make_ready_future_pass.cpp
Normal file
@@ -0,0 +1,157 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Copyright (C) 2011,2014 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)
|
||||
|
||||
// <boost/thread/future.hpp>
|
||||
|
||||
// class promise<R>
|
||||
|
||||
// future<void> make_ready_future();
|
||||
// template <class T>
|
||||
// future<decay_t<T>> make_ready_future(T&&);
|
||||
// template <class T>
|
||||
// future<T> make_ready_future(remove_reference_t<T>&);
|
||||
// template <class T>
|
||||
// future<T> make_ready_future(remove_reference_t<T>&&);
|
||||
// template <class T, class ...Args>
|
||||
// future<T> make_ready_future(Args&& ... args);
|
||||
|
||||
#define BOOST_THREAD_VERSION 3
|
||||
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
struct A
|
||||
{
|
||||
A() :
|
||||
value(0)
|
||||
{
|
||||
}
|
||||
A(int i) :
|
||||
value(i)
|
||||
{
|
||||
}
|
||||
A(int i, int j) :
|
||||
value(i+j)
|
||||
{
|
||||
}
|
||||
int value;
|
||||
};
|
||||
|
||||
A make(int i) {
|
||||
return A(i);
|
||||
}
|
||||
A make(int i, int j) {
|
||||
return A(i, j);
|
||||
}
|
||||
|
||||
struct movable2
|
||||
{
|
||||
int value_;
|
||||
BOOST_THREAD_MOVABLE_ONLY(movable2)
|
||||
movable2() : value_(1){}
|
||||
movable2(int i) : value_(i){}
|
||||
movable2(int i, int j) : value_(i+j){}
|
||||
|
||||
//Move constructor and assignment
|
||||
movable2(BOOST_RV_REF(movable2) m)
|
||||
{ value_ = m.value_; m.value_ = 0; }
|
||||
|
||||
movable2 & operator=(BOOST_THREAD_RV_REF(movable2) m)
|
||||
{ value_ = m.value_; m.value_ = 0; return *this; }
|
||||
|
||||
bool moved() const //Observer
|
||||
{ return !value_; }
|
||||
|
||||
int value() const //Observer
|
||||
{ return value_; }
|
||||
};
|
||||
|
||||
|
||||
movable2 move_return_function2(int i) {
|
||||
return movable2(i);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
#if defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
BOOST_STATIC_ASSERT((boost::is_copy_constructible<movable2>::value == false));
|
||||
BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<movable2>::value == true));
|
||||
BOOST_STATIC_ASSERT((boost::is_copy_constructible<A>::value == true));
|
||||
BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<A>::value == false));
|
||||
#endif
|
||||
|
||||
{
|
||||
boost::future<void> f = boost::make_ready_future();
|
||||
f.wait();
|
||||
}
|
||||
{
|
||||
typedef A T;
|
||||
T i;
|
||||
boost::future<T> f = boost::make_ready_future(i);
|
||||
BOOST_TEST(f.get().value==0);
|
||||
}
|
||||
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
{
|
||||
typedef A T;
|
||||
boost::future<T> f = boost::make_ready_future<T>();
|
||||
BOOST_TEST(f.get().value==0);
|
||||
}
|
||||
{
|
||||
typedef A T;
|
||||
boost::future<T> f = boost::make_ready_future<T>(1);
|
||||
BOOST_TEST(f.get().value==1);
|
||||
}
|
||||
{
|
||||
typedef A T;
|
||||
boost::future<T> f = boost::make_ready_future<T>(1,2);
|
||||
BOOST_TEST(f.get().value==3);
|
||||
}
|
||||
{
|
||||
typedef A T;
|
||||
T i;
|
||||
boost::future<T&> f = boost::make_ready_future<T&>(i);
|
||||
BOOST_TEST(f.get().value==0);
|
||||
}
|
||||
#endif
|
||||
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
// sync/futures/make_ready_future_pass.cpp:125:65: erreur: conversion from Ôboost::future<boost::rv<movable2> >Õ to non-scalar type Ôboost::future<movable2>Õ requested
|
||||
{
|
||||
typedef movable2 T;
|
||||
T i;
|
||||
boost::future<T> f = boost::make_ready_future(boost::move(i));
|
||||
BOOST_TEST_EQ(f.get().value(),1);
|
||||
}
|
||||
#endif
|
||||
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
{
|
||||
typedef movable2 T;
|
||||
boost::future<T> f = boost::make_ready_future<T>();
|
||||
BOOST_TEST(f.get().value()==1);
|
||||
}
|
||||
{
|
||||
typedef movable2 T;
|
||||
boost::future<T> f = boost::make_ready_future<T>(1);
|
||||
BOOST_TEST(f.get().value()==1);
|
||||
}
|
||||
{
|
||||
typedef movable2 T;
|
||||
boost::future<T> f = boost::make_ready_future<T>(1,2);
|
||||
BOOST_TEST(f.get().value()==3);
|
||||
}
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
207
test/sync/futures/promise/emplace_pass.cpp
Normal file
207
test/sync/futures/promise/emplace_pass.cpp
Normal file
@@ -0,0 +1,207 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Copyright (C) 2011,2014 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)
|
||||
|
||||
// <boost/thread/future.hpp>
|
||||
|
||||
// class promise<R>
|
||||
|
||||
// template <class ...Args>
|
||||
// void promise::emplace(Args&& ... args);
|
||||
|
||||
#define BOOST_THREAD_VERSION 3
|
||||
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
struct A
|
||||
{
|
||||
A() :
|
||||
value(0)
|
||||
{
|
||||
}
|
||||
A(int i) :
|
||||
value(i)
|
||||
{
|
||||
}
|
||||
A(int i, int j) :
|
||||
value(i+j)
|
||||
{
|
||||
}
|
||||
BOOST_THREAD_MOVABLE_ONLY(A)
|
||||
|
||||
A(BOOST_THREAD_RV_REF(A) rhs)
|
||||
{
|
||||
if(rhs.value==0)
|
||||
throw 9;
|
||||
else
|
||||
{
|
||||
value=rhs.value;
|
||||
rhs.value=0;
|
||||
}
|
||||
}
|
||||
A& operator=(BOOST_THREAD_RV_REF(A) rhs)
|
||||
{
|
||||
if(rhs.value==0)
|
||||
throw 9;
|
||||
else
|
||||
{
|
||||
value=rhs.value;
|
||||
rhs.value=0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
int value;
|
||||
};
|
||||
|
||||
A make(int i) {
|
||||
return A(i);
|
||||
}
|
||||
A make(int i, int j) {
|
||||
return A(i, j);
|
||||
}
|
||||
|
||||
struct movable2
|
||||
{
|
||||
int value_;
|
||||
BOOST_THREAD_MOVABLE_ONLY(movable2)
|
||||
movable2() : value_(1){}
|
||||
movable2(int i) : value_(i){}
|
||||
movable2(int i, int j) : value_(i+j){}
|
||||
|
||||
//Move constructor and assignment
|
||||
movable2(BOOST_RV_REF(movable2) m)
|
||||
{ value_ = m.value_; m.value_ = 0; }
|
||||
|
||||
movable2 & operator=(BOOST_THREAD_RV_REF(movable2) m)
|
||||
{ value_ = m.value_; m.value_ = 0; return *this; }
|
||||
|
||||
bool moved() const //Observer
|
||||
{ return !value_; }
|
||||
|
||||
int value() const //Observer
|
||||
{ return value_; }
|
||||
};
|
||||
|
||||
|
||||
movable2 move_return_function2(int i) {
|
||||
return movable2(i);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
#if defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
BOOST_STATIC_ASSERT((boost::is_copy_constructible<movable2>::value == false));
|
||||
BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<movable2>::value == true));
|
||||
BOOST_STATIC_ASSERT((boost::is_copy_constructible<A>::value == false));
|
||||
BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<A>::value == true));
|
||||
#endif
|
||||
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
{
|
||||
typedef A T;
|
||||
T i;
|
||||
boost::promise<T> p;
|
||||
boost::future<T> f = p.get_future();
|
||||
p.emplace();
|
||||
try
|
||||
{
|
||||
T a = f.get(); (void)a;
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
catch (int j)
|
||||
{
|
||||
BOOST_TEST(j == 9);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
{
|
||||
typedef A T;
|
||||
boost::promise<T> p;
|
||||
boost::future<T> f = p.get_future();
|
||||
p.emplace(3);
|
||||
BOOST_TEST(f.get().value == 3);
|
||||
try
|
||||
{
|
||||
T j(3);
|
||||
p.set_value(boost::move(j));
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
catch (const boost::future_error& e)
|
||||
{
|
||||
BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
|
||||
}
|
||||
{
|
||||
boost::promise<movable2> p;
|
||||
boost::future<movable2> f = p.get_future();
|
||||
p.emplace(3);
|
||||
BOOST_TEST(f.get().value_ == 3);
|
||||
try
|
||||
{
|
||||
p.emplace(3);
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
catch (const boost::future_error& e)
|
||||
{
|
||||
BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
|
||||
}
|
||||
{
|
||||
boost::promise<A> p;
|
||||
boost::future<A> f = p.get_future();
|
||||
p.emplace(1,2);
|
||||
BOOST_TEST(f.get().value == 3);
|
||||
try
|
||||
{
|
||||
p.emplace(1,2);
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
catch (const boost::future_error& e)
|
||||
{
|
||||
BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
|
||||
}
|
||||
{
|
||||
typedef A T;
|
||||
boost::promise<T> p;
|
||||
boost::future<T> f = p.get_future();
|
||||
p.emplace(3);
|
||||
boost::promise<T> p2(boost::move(p));
|
||||
BOOST_TEST(f.get().value == 3);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
@@ -72,6 +72,30 @@ int main()
|
||||
}
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share();
|
||||
BOOST_TEST(f1.valid());
|
||||
boost::future<int> f2 = f1.then(&p2);
|
||||
boost::future<int> f3 = f1.then(&p2);
|
||||
BOOST_TEST(f2.valid());
|
||||
BOOST_TEST(f3.valid());
|
||||
try
|
||||
{
|
||||
BOOST_TEST(f2.get()==2);
|
||||
BOOST_TEST(f3.get()==2);
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share();
|
||||
BOOST_TEST(f1.valid());
|
||||
|
||||
455
test/sync/mutual_exclusion/deque_views/single_thread_pass.cpp
Normal file
455
test/sync/mutual_exclusion/deque_views/single_thread_pass.cpp
Normal file
@@ -0,0 +1,455 @@
|
||||
// Copyright (C) 2014 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)
|
||||
|
||||
// <boost/thread/sync_deque.hpp>
|
||||
|
||||
// class sync_deque<T>
|
||||
|
||||
// sync_deque();
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
//#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
|
||||
#include <boost/thread/concurrent_queues/sync_deque.hpp>
|
||||
#include <boost/thread/concurrent_queues/deque_adaptor.hpp>
|
||||
#include <boost/thread/concurrent_queues/deque_views.hpp>
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
class non_copyable
|
||||
{
|
||||
BOOST_THREAD_MOVABLE_ONLY(non_copyable)
|
||||
int val;
|
||||
public:
|
||||
non_copyable(int v) : val(v){}
|
||||
non_copyable(BOOST_RV_REF(non_copyable) x): val(x.val) {}
|
||||
non_copyable& operator=(BOOST_RV_REF(non_copyable) x) { val=x.val; return *this; }
|
||||
bool operator==(non_copyable const& x) const {return val==x.val;}
|
||||
template <typename OSTREAM>
|
||||
friend OSTREAM& operator <<(OSTREAM& os, non_copyable const&x )
|
||||
{
|
||||
os << x.val;
|
||||
return os;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#if defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
BOOST_STATIC_ASSERT( ! boost::is_copy_constructible<non_copyable>::value );
|
||||
BOOST_STATIC_ASSERT( boost::has_move_emulation_enabled<non_copyable>::value );
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
{
|
||||
// default queue invariants
|
||||
boost::deque_adaptor<boost::sync_deque<int> > sq;
|
||||
boost::deque_back<int> q(sq);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// default queue invariants
|
||||
boost::deque_adaptor<boost::sync_deque<int> > sq;
|
||||
boost::deque_front<int> q(sq);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
// empty queue try_pull fails
|
||||
boost::deque_adaptor<boost::sync_deque<int> > sq;
|
||||
boost::deque_front<int> q(sq);
|
||||
int i;
|
||||
BOOST_TEST( boost::queue_op_status::empty == q.try_pull(i));
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue push rvalue/copyable succeeds
|
||||
boost::deque_adaptor<boost::sync_deque<int> > sq;
|
||||
boost::deque_back<int> q(sq);
|
||||
q.push(1);
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue push lvalue/copyable succeeds
|
||||
boost::deque_adaptor<boost::sync_deque<int> > sq;
|
||||
boost::deque_back<int> q(sq);
|
||||
int i;
|
||||
q.push(i);
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
{
|
||||
// empty queue push rvalue/non_copyable succeeds
|
||||
boost::deque_adaptor<boost::sync_deque<non_copyable> > sq;
|
||||
boost::deque_back<non_copyable> q(sq);
|
||||
q.push(non_copyable(1));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
#endif
|
||||
{
|
||||
// empty queue push rvalue/non_copyable succeeds
|
||||
boost::deque_adaptor<boost::sync_deque<non_copyable> > q;
|
||||
//boost::sync_deque<non_copyable> q;
|
||||
//boost::deque_back<non_copyable> q(sq);
|
||||
non_copyable nc(1);
|
||||
q.push_back(boost::move(nc));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
|
||||
{
|
||||
// empty queue push rvalue succeeds
|
||||
boost::deque_adaptor<boost::sync_deque<int> > sq;
|
||||
boost::deque_back<int> q(sq);
|
||||
q.push(1);
|
||||
q.push(2);
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 2u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue push lvalue succeeds
|
||||
boost::deque_adaptor<boost::sync_deque<int> > sq;
|
||||
boost::deque_back<int> q(sq);
|
||||
int i;
|
||||
q.push(i);
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue try_push rvalue/copyable succeeds
|
||||
boost::deque_adaptor<boost::sync_deque<int> > sq;
|
||||
boost::deque_back<int> q(sq);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.try_push(1));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue try_push rvalue/copyable succeeds
|
||||
boost::deque_adaptor<boost::sync_deque<int> > sq;
|
||||
boost::deque_back<int> q(sq);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.try_push(1));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
|
||||
#if 0
|
||||
{
|
||||
// empty queue try_push rvalue/non-copyable succeeds
|
||||
boost::deque_adaptor<boost::sync_deque<non_copyable> > sq;
|
||||
boost::deque_back<non_copyable> q(sq);
|
||||
non_copyable nc(1);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.try_push(boost::move(nc)));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
// empty queue try_push lvalue succeeds
|
||||
boost::deque_adaptor<boost::sync_deque<int> > sq;
|
||||
boost::deque_back<int> q(sq);
|
||||
int i;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.try_push(i));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue try_push rvalue succeeds
|
||||
boost::deque_adaptor<boost::sync_deque<int> > sq;
|
||||
boost::deque_back<int> q(sq);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(1));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
{
|
||||
// empty queue nonblocking_push_back rvalue/non-copyable succeeds
|
||||
boost::deque_adaptor<boost::sync_deque<non_copyable> > sq;
|
||||
boost::deque_back<non_copyable> q(sq);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(non_copyable(1)));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
#endif
|
||||
{
|
||||
// empty queue nonblocking_push_back rvalue/non-copyable succeeds
|
||||
boost::deque_adaptor<boost::sync_deque<non_copyable> > sq;
|
||||
boost::deque_back<non_copyable> q(sq);
|
||||
non_copyable nc(1);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(boost::move(nc)));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue pull_front succeed
|
||||
boost::deque_adaptor<boost::sync_deque<int> > sq;
|
||||
boost::deque_front<int> q(sq);
|
||||
sq.push_back(1);
|
||||
int i;
|
||||
q.pull(i);
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue pull_front succeed
|
||||
boost::deque_adaptor<boost::sync_deque<non_copyable> > sq;
|
||||
boost::deque_front<non_copyable> q(sq);
|
||||
non_copyable nc1(1);
|
||||
sq.push_back(boost::move(nc1));
|
||||
non_copyable nc2(2);
|
||||
q.pull(nc2);
|
||||
BOOST_TEST_EQ(nc1, nc2);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue pull_front succeed
|
||||
boost::deque_adaptor<boost::sync_deque<int> > sq;
|
||||
boost::deque_front<int> q(sq);
|
||||
sq.push_back(1);
|
||||
int i = q.pull();
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue pull_front succeed
|
||||
boost::deque_adaptor<boost::sync_deque<non_copyable> > sq;
|
||||
boost::deque_front<non_copyable> q(sq);
|
||||
non_copyable nc1(1);
|
||||
sq.push_back(boost::move(nc1));
|
||||
non_copyable nc = q.pull();
|
||||
BOOST_TEST_EQ(nc, nc1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue try_pull_front succeed
|
||||
boost::deque_adaptor<boost::sync_deque<int> > sq;
|
||||
boost::deque_front<int> q(sq);
|
||||
sq.push_back(1);
|
||||
int i;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.try_pull(i));
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue try_pull_front succeed
|
||||
boost::deque_adaptor<boost::sync_deque<non_copyable> > sq;
|
||||
boost::deque_front<non_copyable> q(sq);
|
||||
non_copyable nc1(1);
|
||||
sq.push_back(boost::move(nc1));
|
||||
non_copyable nc(2);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.try_pull(nc));
|
||||
BOOST_TEST_EQ(nc, nc1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue nonblocking_pull_front succeed
|
||||
boost::deque_adaptor<boost::sync_deque<int> > sq;
|
||||
boost::deque_front<int> q(sq);
|
||||
sq.push_back(1);
|
||||
int i;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(i));
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue nonblocking_pull_front succeed
|
||||
boost::deque_adaptor<boost::sync_deque<non_copyable> > sq;
|
||||
boost::deque_front<non_copyable> q(sq);
|
||||
non_copyable nc1(1);
|
||||
sq.push_back(boost::move(nc1));
|
||||
non_copyable nc(2);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(nc));
|
||||
BOOST_TEST_EQ(nc, nc1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue wait_pull_front succeed
|
||||
boost::deque_adaptor<boost::sync_deque<non_copyable> > sq;
|
||||
boost::deque_front<non_copyable> q(sq);
|
||||
non_copyable nc1(1);
|
||||
sq.push_back(boost::move(nc1));
|
||||
non_copyable nc(2);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc));
|
||||
BOOST_TEST_EQ(nc, nc1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue wait_pull_front succeed
|
||||
boost::deque_adaptor<boost::sync_deque<int> > sq;
|
||||
boost::deque_front<int> q(sq);
|
||||
sq.push_back(1);
|
||||
int i;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i));
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue wait_pull_front succeed
|
||||
boost::deque_adaptor<boost::sync_deque<non_copyable> > sq;
|
||||
boost::deque_front<non_copyable> q(sq);
|
||||
non_copyable nc1(1);
|
||||
sq.push_back(boost::move(nc1));
|
||||
non_copyable nc(2);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc));
|
||||
BOOST_TEST_EQ(nc, nc1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
|
||||
{
|
||||
// closed invariants
|
||||
boost::deque_adaptor<boost::sync_deque<int> > sq;
|
||||
boost::deque_back<int> q(sq);
|
||||
q.close();
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(q.closed());
|
||||
}
|
||||
{
|
||||
// closed invariants
|
||||
boost::deque_adaptor<boost::sync_deque<int> > sq;
|
||||
boost::deque_front<int> q(sq);
|
||||
q.close();
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(q.closed());
|
||||
}
|
||||
{
|
||||
// closed queue push fails
|
||||
boost::deque_adaptor<boost::sync_deque<int> > sq;
|
||||
boost::deque_back<int> q(sq);
|
||||
q.close();
|
||||
try {
|
||||
q.push(1);
|
||||
BOOST_TEST(false);
|
||||
} catch (...) {
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(q.closed());
|
||||
}
|
||||
}
|
||||
{
|
||||
// 1-element closed queue pull succeed
|
||||
boost::deque_adaptor<boost::sync_deque<int> > sq;
|
||||
boost::deque_front<int> q(sq);
|
||||
sq.push_back(1);
|
||||
q.close();
|
||||
int i;
|
||||
q.pull(i);
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element closed queue wait_pull_front succeed
|
||||
boost::deque_adaptor<boost::sync_deque<int> > sq;
|
||||
boost::deque_front<int> q(sq);
|
||||
sq.push_back(1);
|
||||
q.close();
|
||||
int i;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i));
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(q.closed());
|
||||
}
|
||||
{
|
||||
// closed empty queue wait_pull_front fails
|
||||
boost::deque_adaptor<boost::sync_deque<int> > sq;
|
||||
boost::deque_front<int> q(sq);
|
||||
q.close();
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(q.closed());
|
||||
int i;
|
||||
BOOST_TEST(boost::queue_op_status::closed == q.wait_pull(i));
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(q.closed());
|
||||
}
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
//#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
|
||||
#include <boost/thread/sync_queue.hpp>
|
||||
#include <boost/thread/concurrent_queues/sync_queue.hpp>
|
||||
#include <boost/thread/concurrent_queues/queue_adaptor.hpp>
|
||||
#include <boost/thread/concurrent_queues/queue_views.hpp>
|
||||
|
||||
@@ -117,7 +117,7 @@ int main()
|
||||
//boost::sync_queue<non_copyable> q;
|
||||
//boost::queue_back<non_copyable> q(sq);
|
||||
non_copyable nc(1);
|
||||
q.push_back(boost::move(nc));
|
||||
q.push(boost::move(nc));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
@@ -206,7 +206,7 @@ int main()
|
||||
|
||||
#if 0
|
||||
{
|
||||
// empty queue nonblocking_push_back rvalue/non-copyable succeeds
|
||||
// empty queue nonblocking_push rvalue/non-copyable succeeds
|
||||
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
|
||||
boost::queue_back<non_copyable> q(sq);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(non_copyable(1)));
|
||||
@@ -217,7 +217,7 @@ int main()
|
||||
}
|
||||
#endif
|
||||
{
|
||||
// empty queue nonblocking_push_back rvalue/non-copyable succeeds
|
||||
// empty queue nonblocking_push rvalue/non-copyable succeeds
|
||||
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
|
||||
boost::queue_back<non_copyable> q(sq);
|
||||
non_copyable nc(1);
|
||||
@@ -228,10 +228,10 @@ int main()
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue pull_front succeed
|
||||
// 1-element queue pull succeed
|
||||
boost::queue_adaptor<boost::sync_queue<int> > sq;
|
||||
boost::queue_front<int> q(sq);
|
||||
sq.push_back(1);
|
||||
sq.push(1);
|
||||
int i;
|
||||
q.pull(i);
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
@@ -241,11 +241,11 @@ int main()
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue pull_front succeed
|
||||
// 1-element queue pull succeed
|
||||
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
|
||||
boost::queue_front<non_copyable> q(sq);
|
||||
non_copyable nc1(1);
|
||||
sq.push_back(boost::move(nc1));
|
||||
sq.push(boost::move(nc1));
|
||||
non_copyable nc2(2);
|
||||
q.pull(nc2);
|
||||
BOOST_TEST_EQ(nc1, nc2);
|
||||
@@ -255,10 +255,10 @@ int main()
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue pull_front succeed
|
||||
// 1-element queue pull succeed
|
||||
boost::queue_adaptor<boost::sync_queue<int> > sq;
|
||||
boost::queue_front<int> q(sq);
|
||||
sq.push_back(1);
|
||||
sq.push(1);
|
||||
int i = q.pull();
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
@@ -267,11 +267,11 @@ int main()
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue pull_front succeed
|
||||
// 1-element queue pull succeed
|
||||
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
|
||||
boost::queue_front<non_copyable> q(sq);
|
||||
non_copyable nc1(1);
|
||||
sq.push_back(boost::move(nc1));
|
||||
sq.push(boost::move(nc1));
|
||||
non_copyable nc = q.pull();
|
||||
BOOST_TEST_EQ(nc, nc1);
|
||||
BOOST_TEST(q.empty());
|
||||
@@ -280,10 +280,10 @@ int main()
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue try_pull_front succeed
|
||||
// 1-element queue try_pull succeed
|
||||
boost::queue_adaptor<boost::sync_queue<int> > sq;
|
||||
boost::queue_front<int> q(sq);
|
||||
sq.push_back(1);
|
||||
sq.push(1);
|
||||
int i;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.try_pull(i));
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
@@ -293,11 +293,11 @@ int main()
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue try_pull_front succeed
|
||||
// 1-element queue try_pull succeed
|
||||
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
|
||||
boost::queue_front<non_copyable> q(sq);
|
||||
non_copyable nc1(1);
|
||||
sq.push_back(boost::move(nc1));
|
||||
sq.push(boost::move(nc1));
|
||||
non_copyable nc(2);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.try_pull(nc));
|
||||
BOOST_TEST_EQ(nc, nc1);
|
||||
@@ -307,10 +307,10 @@ int main()
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue nonblocking_pull_front succeed
|
||||
// 1-element queue nonblocking_pull succeed
|
||||
boost::queue_adaptor<boost::sync_queue<int> > sq;
|
||||
boost::queue_front<int> q(sq);
|
||||
sq.push_back(1);
|
||||
sq.push(1);
|
||||
int i;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(i));
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
@@ -320,11 +320,11 @@ int main()
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue nonblocking_pull_front succeed
|
||||
// 1-element queue nonblocking_pull succeed
|
||||
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
|
||||
boost::queue_front<non_copyable> q(sq);
|
||||
non_copyable nc1(1);
|
||||
sq.push_back(boost::move(nc1));
|
||||
sq.push(boost::move(nc1));
|
||||
non_copyable nc(2);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(nc));
|
||||
BOOST_TEST_EQ(nc, nc1);
|
||||
@@ -334,11 +334,11 @@ int main()
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue wait_pull_front succeed
|
||||
// 1-element queue wait_pull succeed
|
||||
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
|
||||
boost::queue_front<non_copyable> q(sq);
|
||||
non_copyable nc1(1);
|
||||
sq.push_back(boost::move(nc1));
|
||||
sq.push(boost::move(nc1));
|
||||
non_copyable nc(2);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc));
|
||||
BOOST_TEST_EQ(nc, nc1);
|
||||
@@ -348,10 +348,10 @@ int main()
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue wait_pull_front succeed
|
||||
// 1-element queue wait_pull succeed
|
||||
boost::queue_adaptor<boost::sync_queue<int> > sq;
|
||||
boost::queue_front<int> q(sq);
|
||||
sq.push_back(1);
|
||||
sq.push(1);
|
||||
int i;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i));
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
@@ -361,11 +361,11 @@ int main()
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue wait_pull_front succeed
|
||||
// 1-element queue wait_pull succeed
|
||||
boost::queue_adaptor<boost::sync_queue<non_copyable> > sq;
|
||||
boost::queue_front<non_copyable> q(sq);
|
||||
non_copyable nc1(1);
|
||||
sq.push_back(boost::move(nc1));
|
||||
sq.push(boost::move(nc1));
|
||||
non_copyable nc(2);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc));
|
||||
BOOST_TEST_EQ(nc, nc1);
|
||||
@@ -414,7 +414,7 @@ int main()
|
||||
// 1-element closed queue pull succeed
|
||||
boost::queue_adaptor<boost::sync_queue<int> > sq;
|
||||
boost::queue_front<int> q(sq);
|
||||
sq.push_back(1);
|
||||
sq.push(1);
|
||||
q.close();
|
||||
int i;
|
||||
q.pull(i);
|
||||
@@ -425,10 +425,10 @@ int main()
|
||||
BOOST_TEST(q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element closed queue wait_pull_front succeed
|
||||
// 1-element closed queue wait_pull succeed
|
||||
boost::queue_adaptor<boost::sync_queue<int> > sq;
|
||||
boost::queue_front<int> q(sq);
|
||||
sq.push_back(1);
|
||||
sq.push(1);
|
||||
q.close();
|
||||
int i;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i));
|
||||
@@ -439,7 +439,7 @@ int main()
|
||||
BOOST_TEST(q.closed());
|
||||
}
|
||||
{
|
||||
// closed empty queue wait_pull_front fails
|
||||
// closed empty queue wait_pull fails
|
||||
boost::queue_adaptor<boost::sync_queue<int> > sq;
|
||||
boost::queue_front<int> q(sq);
|
||||
q.close();
|
||||
|
||||
256
test/sync/mutual_exclusion/sync_deque/multi_thread_pass.cpp
Normal file
256
test/sync/mutual_exclusion/sync_deque/multi_thread_pass.cpp
Normal file
@@ -0,0 +1,256 @@
|
||||
// Copyright (C) 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)
|
||||
|
||||
// <boost/thread/concurrent_queues/sync_deque.hpp>
|
||||
|
||||
// class sync_deque<T>
|
||||
|
||||
// push || pull;
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
|
||||
#include <boost/thread/concurrent_queues/sync_deque.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/thread/barrier.hpp>
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
template <typename ValueType>
|
||||
struct call_push_back
|
||||
{
|
||||
boost::sync_deque<ValueType> *q_;
|
||||
boost::barrier *go_;
|
||||
|
||||
call_push_back(boost::sync_deque<ValueType> *q, boost::barrier *go) :
|
||||
q_(q), go_(go)
|
||||
{
|
||||
}
|
||||
typedef void result_type;
|
||||
void operator()()
|
||||
{
|
||||
go_->count_down_and_wait();
|
||||
q_->push_back(42);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ValueType>
|
||||
struct call_pull_front
|
||||
{
|
||||
boost::sync_deque<ValueType> *q_;
|
||||
boost::barrier *go_;
|
||||
|
||||
call_pull_front(boost::sync_deque<ValueType> *q, boost::barrier *go) :
|
||||
q_(q), go_(go)
|
||||
{
|
||||
}
|
||||
typedef ValueType result_type;
|
||||
ValueType operator()()
|
||||
{
|
||||
go_->count_down_and_wait();
|
||||
return q_->pull_front();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ValueType>
|
||||
struct call_wait_pull_front
|
||||
{
|
||||
boost::sync_deque<ValueType> *q_;
|
||||
boost::barrier *go_;
|
||||
|
||||
call_wait_pull_front(boost::sync_deque<ValueType> *q, boost::barrier *go) :
|
||||
q_(q), go_(go)
|
||||
{
|
||||
}
|
||||
typedef boost::queue_op_status result_type;
|
||||
boost::queue_op_status operator()(ValueType& v)
|
||||
{
|
||||
go_->wait();
|
||||
return q_->wait_pull_front(v);
|
||||
}
|
||||
};
|
||||
|
||||
void test_concurrent_push_back_and_pull_front_on_empty_queue()
|
||||
{
|
||||
boost::sync_deque<int> q;
|
||||
|
||||
boost::barrier go(2);
|
||||
|
||||
boost::future<void> push_done;
|
||||
boost::future<int> pull_done;
|
||||
|
||||
try
|
||||
{
|
||||
push_done=boost::async(boost::launch::async,
|
||||
call_push_back<int>(&q,&go));
|
||||
pull_done=boost::async(boost::launch::async,
|
||||
call_pull_front<int>(&q,&go));
|
||||
|
||||
push_done.get();
|
||||
BOOST_TEST_EQ(pull_done.get(), 42);
|
||||
BOOST_TEST(q.empty());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
void test_concurrent_push_back_and_wait_pull_front_on_empty_queue()
|
||||
{
|
||||
boost::sync_deque<int> q;
|
||||
const unsigned int n = 3;
|
||||
boost::barrier go(n);
|
||||
|
||||
boost::future<boost::queue_op_status> pull_done[n];
|
||||
int results[n];
|
||||
|
||||
try
|
||||
{
|
||||
for (unsigned int i =0; i< n; ++i)
|
||||
pull_done[i]=boost::async(boost::launch::async,
|
||||
call_wait_pull_front<int>(&q,&go),
|
||||
boost::ref(results[i]));
|
||||
|
||||
for (unsigned int i =0; i< n; ++i)
|
||||
q.push_back(42);
|
||||
|
||||
for (unsigned int i = 0; i < n; ++i) {
|
||||
BOOST_TEST(pull_done[i].get() == boost::queue_op_status::success);
|
||||
BOOST_TEST_EQ(results[i], 42);
|
||||
}
|
||||
BOOST_TEST(q.empty());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
|
||||
void test_concurrent_wait_pull_front_and_close_on_empty_queue()
|
||||
{
|
||||
boost::sync_deque<int> q;
|
||||
const unsigned int n = 3;
|
||||
boost::barrier go(n);
|
||||
|
||||
boost::future<boost::queue_op_status> pull_done[n];
|
||||
int results[n];
|
||||
|
||||
try
|
||||
{
|
||||
for (unsigned int i =0; i< n; ++i)
|
||||
pull_done[i]=boost::async(boost::launch::async,
|
||||
call_wait_pull_front<int>(&q,&go),
|
||||
boost::ref(results[i]));
|
||||
|
||||
q.close();
|
||||
|
||||
for (unsigned int i = 0; i < n; ++i) {
|
||||
BOOST_TEST(pull_done[i].get() == boost::queue_op_status::closed);
|
||||
}
|
||||
BOOST_TEST(q.empty());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void test_concurrent_push_back_on_empty_queue()
|
||||
{
|
||||
boost::sync_deque<int> q;
|
||||
const unsigned int n = 3;
|
||||
boost::barrier go(n);
|
||||
boost::future<void> push_done[n];
|
||||
|
||||
try
|
||||
{
|
||||
for (unsigned int i =0; i< n; ++i)
|
||||
push_done[i]=boost::async(boost::launch::async,
|
||||
call_push_back<int>(&q,&go));
|
||||
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
try
|
||||
{
|
||||
for (unsigned int i = 0; i < n; ++i)
|
||||
push_done[i].get();
|
||||
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
try
|
||||
{
|
||||
BOOST_TEST(!q.empty());
|
||||
for (unsigned int i =0; i< n; ++i)
|
||||
BOOST_TEST_EQ(q.pull_front(), 42);
|
||||
BOOST_TEST(q.empty());
|
||||
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
|
||||
void test_concurrent_pull_front_on_queue()
|
||||
{
|
||||
boost::sync_deque<int> q;
|
||||
const unsigned int n = 3;
|
||||
boost::barrier go(n);
|
||||
|
||||
boost::future<int> pull_done[n];
|
||||
|
||||
try
|
||||
{
|
||||
for (unsigned int i =0; i< n; ++i)
|
||||
q.push_back(42);
|
||||
|
||||
for (unsigned int i =0; i< n; ++i)
|
||||
pull_done[i]=boost::async(boost::launch::async,
|
||||
#if ! defined BOOST_NO_CXX11_LAMBDAS
|
||||
[&q,&go]() -> int
|
||||
{
|
||||
go.wait();
|
||||
return q.pull_front();
|
||||
}
|
||||
#else
|
||||
call_pull_front<int>(&q,&go)
|
||||
#endif
|
||||
);
|
||||
|
||||
for (unsigned int i = 0; i < n; ++i)
|
||||
BOOST_TEST_EQ(pull_done[i].get(), 42);
|
||||
BOOST_TEST(q.empty());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_concurrent_push_back_and_pull_front_on_empty_queue();
|
||||
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
test_concurrent_push_back_and_wait_pull_front_on_empty_queue();
|
||||
test_concurrent_wait_pull_front_and_close_on_empty_queue();
|
||||
#endif
|
||||
test_concurrent_push_back_on_empty_queue();
|
||||
test_concurrent_pull_front_on_queue();
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
404
test/sync/mutual_exclusion/sync_deque/single_thread_pass.cpp
Normal file
404
test/sync/mutual_exclusion/sync_deque/single_thread_pass.cpp
Normal file
@@ -0,0 +1,404 @@
|
||||
// Copyright (C) 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)
|
||||
|
||||
// <boost/thread/concurrent_queues/sync_deque.hpp>
|
||||
|
||||
// class sync_deque<T>
|
||||
|
||||
// sync_deque();
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
|
||||
#include <boost/thread/concurrent_queues/sync_deque.hpp>
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
class non_copyable
|
||||
{
|
||||
BOOST_THREAD_MOVABLE_ONLY(non_copyable)
|
||||
int val;
|
||||
public:
|
||||
non_copyable(int v) : val(v){}
|
||||
non_copyable(BOOST_RV_REF(non_copyable) x): val(x.val) {}
|
||||
non_copyable& operator=(BOOST_RV_REF(non_copyable) x) { val=x.val; return *this; }
|
||||
bool operator==(non_copyable const& x) const {return val==x.val;}
|
||||
template <typename OSTREAM>
|
||||
friend OSTREAM& operator <<(OSTREAM& os, non_copyable const&x )
|
||||
{
|
||||
os << x.val;
|
||||
return os;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
{
|
||||
// default queue invariants
|
||||
boost::sync_deque<int> q;
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue try_pull fails
|
||||
boost::sync_deque<int> q;
|
||||
int i;
|
||||
BOOST_TEST( boost::queue_op_status::empty == q.try_pull_front(i));
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue push rvalue/copyable succeeds
|
||||
boost::sync_deque<int> q;
|
||||
q.push_back(1);
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue push lvalue/copyable succeeds
|
||||
boost::sync_deque<int> q;
|
||||
int i;
|
||||
q.push_back(i);
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
|
||||
#if 0
|
||||
{
|
||||
// empty queue push rvalue/non_copyable succeeds
|
||||
boost::sync_deque<non_copyable> q;
|
||||
q.push_back(non_copyable(1));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
#endif
|
||||
{
|
||||
// empty queue push rvalue/non_copyable succeeds
|
||||
boost::sync_deque<non_copyable> q;
|
||||
non_copyable nc(1);
|
||||
q.push_back(boost::move(nc));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
|
||||
{
|
||||
// empty queue push rvalue succeeds
|
||||
boost::sync_deque<int> q;
|
||||
q.push_back(1);
|
||||
q.push_back(2);
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 2u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue push lvalue succeeds
|
||||
boost::sync_deque<int> q;
|
||||
int i;
|
||||
q.push_back(i);
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue try_push rvalue/copyable succeeds
|
||||
boost::sync_deque<int> q;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.try_push_back(1));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue try_push rvalue/copyable succeeds
|
||||
boost::sync_deque<int> q;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.try_push_back(1));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
|
||||
#if 0
|
||||
{
|
||||
// empty queue try_push rvalue/non-copyable succeeds
|
||||
boost::sync_deque<non_copyable> q;
|
||||
BOOST_TEST(boost::queue_op_status::success ==q.try_push_back(non_copyable()));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
#endif
|
||||
{
|
||||
// empty queue try_push rvalue/non-copyable succeeds
|
||||
boost::sync_deque<non_copyable> q;
|
||||
non_copyable nc(1);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.try_push_back(boost::move(nc)));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
|
||||
{
|
||||
// empty queue try_push lvalue succeeds
|
||||
boost::sync_deque<int> q;
|
||||
int i=1;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.try_push_back(i));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue try_push rvalue succeeds
|
||||
boost::sync_deque<int> q;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push_back(1));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
{
|
||||
// empty queue nonblocking_push_back rvalue/non-copyable succeeds
|
||||
boost::sync_deque<non_copyable> q;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push_back(non_copyable(1)));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
#endif
|
||||
{
|
||||
// empty queue nonblocking_push_back rvalue/non-copyable succeeds
|
||||
boost::sync_deque<non_copyable> q;
|
||||
non_copyable nc(1);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push_back(boost::move(nc)));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue pull_front succeed
|
||||
boost::sync_deque<int> q;
|
||||
q.push_back(1);
|
||||
int i;
|
||||
q.pull_front(i);
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue pull_front succeed
|
||||
boost::sync_deque<non_copyable> q;
|
||||
non_copyable nc1(1);
|
||||
q.push_back(boost::move(nc1));
|
||||
non_copyable nc2(2);
|
||||
q.pull_front(nc2);
|
||||
BOOST_TEST_EQ(nc1, nc2);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue pull_front succeed
|
||||
boost::sync_deque<int> q;
|
||||
q.push_back(1);
|
||||
int i = q.pull_front();
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue pull_front succeed
|
||||
boost::sync_deque<non_copyable> q;
|
||||
non_copyable nc1(1);
|
||||
q.push_back(boost::move(nc1));
|
||||
non_copyable nc = q.pull_front();
|
||||
BOOST_TEST_EQ(nc, nc1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue try_pull_front succeed
|
||||
boost::sync_deque<int> q;
|
||||
q.push_back(1);
|
||||
int i;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.try_pull_front(i));
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue try_pull_front succeed
|
||||
boost::sync_deque<non_copyable> q;
|
||||
non_copyable nc1(1);
|
||||
q.push_back(boost::move(nc1));
|
||||
non_copyable nc(2);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.try_pull_front(nc));
|
||||
BOOST_TEST_EQ(nc, nc1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue nonblocking_pull_front succeed
|
||||
boost::sync_deque<int> q;
|
||||
q.push_back(1);
|
||||
int i;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull_front(i));
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue nonblocking_pull_front succeed
|
||||
boost::sync_deque<non_copyable> q;
|
||||
non_copyable nc1(1);
|
||||
q.push_back(boost::move(nc1));
|
||||
non_copyable nc(2);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull_front(nc));
|
||||
BOOST_TEST_EQ(nc, nc1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue wait_pull_front succeed
|
||||
boost::sync_deque<non_copyable> q;
|
||||
non_copyable nc1(1);
|
||||
q.push_back(boost::move(nc1));
|
||||
non_copyable nc(2);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(nc));
|
||||
BOOST_TEST_EQ(nc, nc1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue wait_pull_front succeed
|
||||
boost::sync_deque<int> q;
|
||||
q.push_back(1);
|
||||
int i;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(i));
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue wait_pull_front succeed
|
||||
boost::sync_deque<non_copyable> q;
|
||||
non_copyable nc1(1);
|
||||
q.push_back(boost::move(nc1));
|
||||
non_copyable nc(2);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(nc));
|
||||
BOOST_TEST_EQ(nc, nc1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
|
||||
{
|
||||
// closed invariants
|
||||
boost::sync_deque<int> q;
|
||||
q.close();
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(q.closed());
|
||||
}
|
||||
{
|
||||
// closed queue push fails
|
||||
boost::sync_deque<int> q;
|
||||
q.close();
|
||||
try {
|
||||
q.push_back(1);
|
||||
BOOST_TEST(false);
|
||||
} catch (...) {
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(q.closed());
|
||||
}
|
||||
}
|
||||
{
|
||||
// 1-element closed queue pull succeed
|
||||
boost::sync_deque<int> q;
|
||||
q.push_back(1);
|
||||
q.close();
|
||||
int i;
|
||||
q.pull_front(i);
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element closed queue wait_pull_front succeed
|
||||
boost::sync_deque<int> q;
|
||||
q.push_back(1);
|
||||
q.close();
|
||||
int i;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(i));
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(q.closed());
|
||||
}
|
||||
{
|
||||
// closed empty queue wait_pull_front fails
|
||||
boost::sync_deque<int> q;
|
||||
q.close();
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(q.closed());
|
||||
int i;
|
||||
BOOST_TEST(boost::queue_op_status::closed == q.wait_pull_front(i));
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(q.closed());
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ void test_pull(const int n)
|
||||
pq.push(i);
|
||||
}
|
||||
BOOST_TEST(!pq.empty());
|
||||
BOOST_TEST_EQ(pq.size(), n);
|
||||
BOOST_TEST_EQ(pq.size(), std::size_t(n));
|
||||
pq.close();
|
||||
BOOST_TEST(pq.closed());
|
||||
boost::barrier b(n);
|
||||
@@ -71,7 +71,7 @@ void test_push(const int n)
|
||||
}
|
||||
tg.join_all();
|
||||
BOOST_TEST(!pq.empty());
|
||||
BOOST_TEST_EQ(pq.size(), n);
|
||||
BOOST_TEST_EQ(pq.size(), std::size_t(n));
|
||||
}
|
||||
|
||||
void test_both(const int n)
|
||||
@@ -88,7 +88,7 @@ void test_both(const int n)
|
||||
}
|
||||
tg.join_all();
|
||||
BOOST_TEST(pq.empty());
|
||||
BOOST_TEST_EQ(pq.size(), 0);
|
||||
BOOST_TEST_EQ(pq.size(), std::size_t(0));
|
||||
}
|
||||
|
||||
void push_range(sync_pq* q, const int begin, const int end)
|
||||
|
||||
@@ -55,7 +55,7 @@ void test_pull_for()
|
||||
boost::queue_op_status st = pq.pull_for(milliseconds(500), val);
|
||||
steady_clock::duration diff = steady_clock::now() - start;
|
||||
BOOST_TEST(boost::queue_op_status::timeout == st);
|
||||
BOOST_TEST(diff < milliseconds(510) && diff > milliseconds(500));
|
||||
BOOST_TEST(diff < milliseconds(550) && diff > milliseconds(500));
|
||||
}
|
||||
|
||||
void test_pull_until()
|
||||
@@ -66,7 +66,7 @@ void test_pull_until()
|
||||
boost::queue_op_status st = pq.pull_until(start + milliseconds(500), val);
|
||||
steady_clock::duration diff = steady_clock::now() - start;
|
||||
BOOST_TEST(boost::queue_op_status::timeout == st);
|
||||
BOOST_TEST(diff < milliseconds(510) && diff > milliseconds(500));
|
||||
BOOST_TEST(diff < milliseconds(550) && diff > milliseconds(500));
|
||||
}
|
||||
|
||||
void test_nonblocking_pull()
|
||||
@@ -111,19 +111,19 @@ int main()
|
||||
sync_pq pq;
|
||||
BOOST_TEST(pq.empty());
|
||||
BOOST_TEST(!pq.closed());
|
||||
BOOST_TEST_EQ(pq.size(), 0);
|
||||
BOOST_TEST_EQ(pq.size(), std::size_t(0));
|
||||
|
||||
for(int i = 1; i <= 5; i++){
|
||||
pq.push(i);
|
||||
BOOST_TEST(!pq.empty());
|
||||
BOOST_TEST_EQ(pq.size(), i);
|
||||
BOOST_TEST_EQ(pq.size(), std::size_t(i));
|
||||
}
|
||||
|
||||
for(int i = 6; i <= 10; i++){
|
||||
boost::queue_op_status succ = pq.try_push(i);
|
||||
BOOST_TEST(succ == boost::queue_op_status::success );
|
||||
BOOST_TEST(!pq.empty());
|
||||
BOOST_TEST_EQ(pq.size(), i);
|
||||
BOOST_TEST_EQ(pq.size(), std::size_t(i));
|
||||
}
|
||||
|
||||
for(int i = 10; i > 5; i--){
|
||||
|
||||
@@ -30,18 +30,18 @@ void test_all()
|
||||
sync_tq pq;
|
||||
BOOST_TEST(pq.empty());
|
||||
BOOST_TEST(!pq.closed());
|
||||
BOOST_TEST_EQ(pq.size(), 0);
|
||||
BOOST_TEST_EQ(pq.size(), std::size_t(0));
|
||||
|
||||
for(int i = 1; i <= 5; i++){
|
||||
pq.push(i, milliseconds(i*100));
|
||||
BOOST_TEST(!pq.empty());
|
||||
BOOST_TEST_EQ(pq.size(), i);
|
||||
BOOST_TEST_EQ(pq.size(), std::size_t(i));
|
||||
}
|
||||
|
||||
for(int i = 6; i <= 10; i++){
|
||||
pq.push(i,steady_clock::now() + milliseconds(i*100));
|
||||
BOOST_TEST(!pq.empty());
|
||||
BOOST_TEST_EQ(pq.size(), i);
|
||||
BOOST_TEST_EQ(pq.size(), std::size_t(i));
|
||||
}
|
||||
|
||||
for(int i = 1; i <= 10; i++){
|
||||
@@ -63,20 +63,20 @@ void test_all_with_try()
|
||||
sync_tq pq;
|
||||
BOOST_TEST(pq.empty());
|
||||
BOOST_TEST(!pq.closed());
|
||||
BOOST_TEST_EQ(pq.size(), 0);
|
||||
BOOST_TEST_EQ(pq.size(), std::size_t(0));
|
||||
|
||||
for(int i = 1; i <= 5; i++){
|
||||
boost::queue_op_status st = pq.try_push(i, milliseconds(i*100));
|
||||
BOOST_TEST(st == boost::queue_op_status::success );
|
||||
BOOST_TEST(!pq.empty());
|
||||
BOOST_TEST_EQ(pq.size(), i);
|
||||
BOOST_TEST_EQ(pq.size(), std::size_t(i));
|
||||
}
|
||||
|
||||
for(int i = 6; i <= 10; i++){
|
||||
boost::queue_op_status st = pq.try_push(i,steady_clock::now() + milliseconds(i*100));
|
||||
BOOST_TEST(st == boost::queue_op_status::success );
|
||||
BOOST_TEST(!pq.empty());
|
||||
BOOST_TEST_EQ(pq.size(), i);
|
||||
BOOST_TEST_EQ(pq.size(), std::size_t(i));
|
||||
}
|
||||
|
||||
for(int i = 1; i <= 10; i++){
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#endif
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
//#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
|
||||
#include <boost/thread/sync_queue.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
@@ -23,13 +22,13 @@
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
template <typename ValueType>
|
||||
struct call_push
|
||||
{
|
||||
boost::sync_queue<int> *q_;
|
||||
boost::sync_queue<ValueType> *q_;
|
||||
boost::barrier *go_;
|
||||
|
||||
call_push(boost::sync_queue<int> *q, boost::barrier *go) :
|
||||
call_push(boost::sync_queue<ValueType> *q, boost::barrier *go) :
|
||||
q_(q), go_(go)
|
||||
{
|
||||
}
|
||||
@@ -38,53 +37,16 @@ struct call_push
|
||||
{
|
||||
go_->count_down_and_wait();
|
||||
q_->push(42);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ValueType>
|
||||
struct call_pull
|
||||
{
|
||||
boost::sync_queue<int> *q_;
|
||||
boost::barrier *go_;
|
||||
|
||||
call_pull(boost::sync_queue<int> *q, boost::barrier *go) :
|
||||
q_(q), go_(go)
|
||||
{
|
||||
}
|
||||
typedef int result_type;
|
||||
int operator()()
|
||||
{
|
||||
go_->count_down_and_wait();
|
||||
return q_->pull();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
template <typename ValueType>
|
||||
struct call_push_back
|
||||
{
|
||||
boost::sync_queue<ValueType> *q_;
|
||||
boost::barrier *go_;
|
||||
|
||||
call_push_back(boost::sync_queue<ValueType> *q, boost::barrier *go) :
|
||||
q_(q), go_(go)
|
||||
{
|
||||
}
|
||||
typedef void result_type;
|
||||
void operator()()
|
||||
{
|
||||
go_->count_down_and_wait();
|
||||
q_->push_back(42);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ValueType>
|
||||
struct call_pull_front
|
||||
{
|
||||
boost::sync_queue<ValueType> *q_;
|
||||
boost::barrier *go_;
|
||||
|
||||
call_pull_front(boost::sync_queue<ValueType> *q, boost::barrier *go) :
|
||||
call_pull(boost::sync_queue<ValueType> *q, boost::barrier *go) :
|
||||
q_(q), go_(go)
|
||||
{
|
||||
}
|
||||
@@ -92,17 +54,17 @@ struct call_pull_front
|
||||
ValueType operator()()
|
||||
{
|
||||
go_->count_down_and_wait();
|
||||
return q_->pull_front();
|
||||
return q_->pull();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ValueType>
|
||||
struct call_wait_pull_front
|
||||
struct call_wait_pull
|
||||
{
|
||||
boost::sync_queue<ValueType> *q_;
|
||||
boost::barrier *go_;
|
||||
|
||||
call_wait_pull_front(boost::sync_queue<ValueType> *q, boost::barrier *go) :
|
||||
call_wait_pull(boost::sync_queue<ValueType> *q, boost::barrier *go) :
|
||||
q_(q), go_(go)
|
||||
{
|
||||
}
|
||||
@@ -110,11 +72,10 @@ struct call_wait_pull_front
|
||||
boost::queue_op_status operator()(ValueType& v)
|
||||
{
|
||||
go_->wait();
|
||||
return q_->wait_pull_front(v);
|
||||
return q_->wait_pull(v);
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
void test_concurrent_push_and_pull_on_empty_queue()
|
||||
{
|
||||
boost::sync_queue<int> q;
|
||||
@@ -127,27 +88,9 @@ void test_concurrent_push_and_pull_on_empty_queue()
|
||||
try
|
||||
{
|
||||
push_done=boost::async(boost::launch::async,
|
||||
#if ! defined BOOST_NO_CXX11_LAMBDAS
|
||||
[&q,&go]()
|
||||
{
|
||||
go.wait();
|
||||
q.push(42);
|
||||
}
|
||||
#else
|
||||
call_push(&q,&go)
|
||||
#endif
|
||||
);
|
||||
call_push<int>(&q,&go));
|
||||
pull_done=boost::async(boost::launch::async,
|
||||
#if ! defined BOOST_NO_CXX11_LAMBDAS
|
||||
[&q,&go]() -> int
|
||||
{
|
||||
go.wait();
|
||||
return q.pull();
|
||||
}
|
||||
#else
|
||||
call_pull(&q,&go)
|
||||
#endif
|
||||
);
|
||||
call_pull<int>(&q,&go));
|
||||
|
||||
push_done.get();
|
||||
BOOST_TEST_EQ(pull_done.get(), 42);
|
||||
@@ -159,6 +102,68 @@ void test_concurrent_push_and_pull_on_empty_queue()
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
void test_concurrent_push_and_wait_pull_on_empty_queue()
|
||||
{
|
||||
boost::sync_queue<int> q;
|
||||
const unsigned int n = 3;
|
||||
boost::barrier go(n);
|
||||
|
||||
boost::future<boost::queue_op_status> pull_done[n];
|
||||
int results[n];
|
||||
|
||||
try
|
||||
{
|
||||
for (unsigned int i =0; i< n; ++i)
|
||||
pull_done[i]=boost::async(boost::launch::async,
|
||||
call_wait_pull<int>(&q,&go),
|
||||
boost::ref(results[i]));
|
||||
|
||||
for (unsigned int i =0; i< n; ++i)
|
||||
q.push(42);
|
||||
|
||||
for (unsigned int i = 0; i < n; ++i) {
|
||||
BOOST_TEST(pull_done[i].get() == boost::queue_op_status::success);
|
||||
BOOST_TEST_EQ(results[i], 42);
|
||||
}
|
||||
BOOST_TEST(q.empty());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
|
||||
void test_concurrent_wait_pull_and_close_on_empty_queue()
|
||||
{
|
||||
boost::sync_queue<int> q;
|
||||
const unsigned int n = 3;
|
||||
boost::barrier go(n);
|
||||
|
||||
boost::future<boost::queue_op_status> pull_done[n];
|
||||
int results[n];
|
||||
|
||||
try
|
||||
{
|
||||
for (unsigned int i =0; i< n; ++i)
|
||||
pull_done[i]=boost::async(boost::launch::async,
|
||||
call_wait_pull<int>(&q,&go),
|
||||
boost::ref(results[i]));
|
||||
|
||||
q.close();
|
||||
|
||||
for (unsigned int i = 0; i < n; ++i) {
|
||||
BOOST_TEST(pull_done[i].get() == boost::queue_op_status::closed);
|
||||
}
|
||||
BOOST_TEST(q.empty());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void test_concurrent_push_on_empty_queue()
|
||||
{
|
||||
boost::sync_queue<int> q;
|
||||
@@ -170,20 +175,25 @@ void test_concurrent_push_on_empty_queue()
|
||||
{
|
||||
for (unsigned int i =0; i< n; ++i)
|
||||
push_done[i]=boost::async(boost::launch::async,
|
||||
#if ! defined BOOST_NO_CXX11_LAMBDAS
|
||||
[&q,&go]()
|
||||
{
|
||||
go.wait();
|
||||
q.push(42);
|
||||
}
|
||||
#else
|
||||
call_push(&q,&go)
|
||||
#endif
|
||||
);
|
||||
call_push<int>(&q,&go));
|
||||
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
try
|
||||
{
|
||||
for (unsigned int i = 0; i < n; ++i)
|
||||
push_done[i].get();
|
||||
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
try
|
||||
{
|
||||
BOOST_TEST(!q.empty());
|
||||
for (unsigned int i =0; i< n; ++i)
|
||||
BOOST_TEST_EQ(q.pull(), 42);
|
||||
@@ -218,174 +228,7 @@ void test_concurrent_pull_on_queue()
|
||||
return q.pull();
|
||||
}
|
||||
#else
|
||||
call_pull(&q,&go)
|
||||
#endif
|
||||
);
|
||||
|
||||
for (unsigned int i = 0; i < n; ++i)
|
||||
BOOST_TEST_EQ(pull_done[i].get(), 42);
|
||||
BOOST_TEST(q.empty());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void test_concurrent_push_back_and_pull_front_on_empty_queue()
|
||||
{
|
||||
boost::sync_queue<int> q;
|
||||
|
||||
boost::barrier go(2);
|
||||
|
||||
boost::future<void> push_done;
|
||||
boost::future<int> pull_done;
|
||||
|
||||
try
|
||||
{
|
||||
push_done=boost::async(boost::launch::async,
|
||||
call_push_back<int>(&q,&go));
|
||||
pull_done=boost::async(boost::launch::async,
|
||||
call_pull_front<int>(&q,&go));
|
||||
|
||||
push_done.get();
|
||||
BOOST_TEST_EQ(pull_done.get(), 42);
|
||||
BOOST_TEST(q.empty());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
void test_concurrent_push_back_and_wait_pull_front_on_empty_queue()
|
||||
{
|
||||
boost::sync_queue<int> q;
|
||||
const unsigned int n = 3;
|
||||
boost::barrier go(n);
|
||||
|
||||
boost::future<boost::queue_op_status> pull_done[n];
|
||||
int results[n];
|
||||
|
||||
try
|
||||
{
|
||||
for (unsigned int i =0; i< n; ++i)
|
||||
pull_done[i]=boost::async(boost::launch::async,
|
||||
call_wait_pull_front<int>(&q,&go),
|
||||
boost::ref(results[i]));
|
||||
|
||||
for (unsigned int i =0; i< n; ++i)
|
||||
q.push_back(42);
|
||||
|
||||
for (unsigned int i = 0; i < n; ++i) {
|
||||
BOOST_TEST(pull_done[i].get() == boost::queue_op_status::success);
|
||||
BOOST_TEST_EQ(results[i], 42);
|
||||
}
|
||||
BOOST_TEST(q.empty());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
|
||||
void test_concurrent_wait_pull_front_and_close_on_empty_queue()
|
||||
{
|
||||
boost::sync_queue<int> q;
|
||||
const unsigned int n = 3;
|
||||
boost::barrier go(n);
|
||||
|
||||
boost::future<boost::queue_op_status> pull_done[n];
|
||||
int results[n];
|
||||
|
||||
try
|
||||
{
|
||||
for (unsigned int i =0; i< n; ++i)
|
||||
pull_done[i]=boost::async(boost::launch::async,
|
||||
call_wait_pull_front<int>(&q,&go),
|
||||
boost::ref(results[i]));
|
||||
|
||||
q.close();
|
||||
|
||||
for (unsigned int i = 0; i < n; ++i) {
|
||||
BOOST_TEST(pull_done[i].get() == boost::queue_op_status::closed);
|
||||
}
|
||||
BOOST_TEST(q.empty());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void test_concurrent_push_back_on_empty_queue()
|
||||
{
|
||||
boost::sync_queue<int> q;
|
||||
const unsigned int n = 3;
|
||||
boost::barrier go(n);
|
||||
boost::future<void> push_done[n];
|
||||
|
||||
try
|
||||
{
|
||||
for (unsigned int i =0; i< n; ++i)
|
||||
push_done[i]=boost::async(boost::launch::async,
|
||||
call_push_back<int>(&q,&go));
|
||||
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
try
|
||||
{
|
||||
for (unsigned int i = 0; i < n; ++i)
|
||||
push_done[i].get();
|
||||
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
try
|
||||
{
|
||||
BOOST_TEST(!q.empty());
|
||||
for (unsigned int i =0; i< n; ++i)
|
||||
BOOST_TEST_EQ(q.pull_front(), 42);
|
||||
BOOST_TEST(q.empty());
|
||||
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST(false);
|
||||
}
|
||||
}
|
||||
|
||||
void test_concurrent_pull_front_on_queue()
|
||||
{
|
||||
boost::sync_queue<int> q;
|
||||
const unsigned int n = 3;
|
||||
boost::barrier go(n);
|
||||
|
||||
boost::future<int> pull_done[n];
|
||||
|
||||
try
|
||||
{
|
||||
for (unsigned int i =0; i< n; ++i)
|
||||
q.push_back(42);
|
||||
|
||||
for (unsigned int i =0; i< n; ++i)
|
||||
pull_done[i]=boost::async(boost::launch::async,
|
||||
#if ! defined BOOST_NO_CXX11_LAMBDAS
|
||||
[&q,&go]() -> int
|
||||
{
|
||||
go.wait();
|
||||
return q.pull_front();
|
||||
}
|
||||
#else
|
||||
call_pull_front<int>(&q,&go)
|
||||
call_pull<int>(&q,&go)
|
||||
#endif
|
||||
);
|
||||
|
||||
@@ -401,18 +244,13 @@ void test_concurrent_pull_front_on_queue()
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
test_concurrent_push_and_pull_on_empty_queue();
|
||||
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
test_concurrent_push_and_wait_pull_on_empty_queue();
|
||||
test_concurrent_wait_pull_and_close_on_empty_queue();
|
||||
#endif
|
||||
test_concurrent_push_on_empty_queue();
|
||||
test_concurrent_pull_on_queue();
|
||||
#endif
|
||||
test_concurrent_push_back_and_pull_front_on_empty_queue();
|
||||
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
test_concurrent_push_back_and_wait_pull_front_on_empty_queue();
|
||||
test_concurrent_wait_pull_front_and_close_on_empty_queue();
|
||||
#endif
|
||||
test_concurrent_push_back_on_empty_queue();
|
||||
test_concurrent_pull_front_on_queue();
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
// sync_queue();
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
//#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
|
||||
#include <boost/thread/sync_queue.hpp>
|
||||
|
||||
@@ -47,78 +46,7 @@ int main()
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
{
|
||||
// empty queue try_pull fails
|
||||
boost::sync_queue<int> q;
|
||||
int i;
|
||||
BOOST_TEST(! q.try_pull(i));
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue try_pull fails
|
||||
boost::sync_queue<int> q;
|
||||
BOOST_TEST(! q.try_pull());
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue push rvalue/copyable succeeds
|
||||
boost::sync_queue<int> q;
|
||||
q.push(1);
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue push lvalue/copyable succeeds
|
||||
boost::sync_queue<int> q;
|
||||
int i;
|
||||
q.push(i);
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
// empty queue try_pull fails
|
||||
boost::sync_queue<int> q;
|
||||
int i;
|
||||
BOOST_TEST( boost::queue_op_status::empty == q.try_pull_front(i));
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue push rvalue/copyable succeeds
|
||||
boost::sync_queue<int> q;
|
||||
q.push_back(1);
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue push lvalue/copyable succeeds
|
||||
boost::sync_queue<int> q;
|
||||
int i;
|
||||
q.push_back(i);
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
|
||||
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
#if 0
|
||||
{
|
||||
// empty queue push rvalue/non_copyable succeeds
|
||||
@@ -164,7 +92,7 @@ int main()
|
||||
{
|
||||
// empty queue try_push rvalue/copyable succeeds
|
||||
boost::sync_queue<int> q;
|
||||
BOOST_TEST(q.try_push(1));
|
||||
BOOST_TEST(boost::queue_op_status::success == q.try_push(1));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
@@ -173,79 +101,18 @@ int main()
|
||||
{
|
||||
// empty queue try_push rvalue/copyable succeeds
|
||||
boost::sync_queue<int> q;
|
||||
BOOST_TEST(q.try_push(1));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
{
|
||||
// empty queue push rvalue/non_copyable succeeds
|
||||
boost::sync_queue<non_copyable> q;
|
||||
q.push_back(non_copyable(1));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
#endif
|
||||
{
|
||||
// empty queue push rvalue/non_copyable succeeds
|
||||
boost::sync_queue<non_copyable> q;
|
||||
non_copyable nc(1);
|
||||
q.push_back(boost::move(nc));
|
||||
BOOST_TEST(boost::queue_op_status::success == q.try_push(1));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
|
||||
{
|
||||
// empty queue push rvalue succeeds
|
||||
boost::sync_queue<int> q;
|
||||
q.push_back(1);
|
||||
q.push_back(2);
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 2u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue push lvalue succeeds
|
||||
boost::sync_queue<int> q;
|
||||
int i;
|
||||
q.push_back(i);
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue try_push rvalue/copyable succeeds
|
||||
boost::sync_queue<int> q;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.try_push_back(1));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue try_push rvalue/copyable succeeds
|
||||
boost::sync_queue<int> q;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.try_push_back(1));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
#if 0
|
||||
{
|
||||
// empty queue try_push rvalue/non-copyable succeeds
|
||||
boost::sync_queue<non_copyable> q;
|
||||
BOOST_TEST(q.try_push(non_copyable()));
|
||||
BOOST_TEST(boost::queue_op_status::success ==q.try_push(non_copyable()));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
@@ -256,7 +123,7 @@ int main()
|
||||
// empty queue try_push rvalue/non-copyable succeeds
|
||||
boost::sync_queue<non_copyable> q;
|
||||
non_copyable nc(1);
|
||||
BOOST_TEST(q.try_push(boost::move(nc)));
|
||||
BOOST_TEST(boost::queue_op_status::success == q.try_push(boost::move(nc)));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
@@ -267,7 +134,7 @@ int main()
|
||||
// empty queue try_push lvalue succeeds
|
||||
boost::sync_queue<int> q;
|
||||
int i=1;
|
||||
BOOST_TEST(q.try_push(i));
|
||||
BOOST_TEST(boost::queue_op_status::success == q.try_push(i));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
@@ -276,61 +143,18 @@ int main()
|
||||
{
|
||||
// empty queue try_push rvalue succeeds
|
||||
boost::sync_queue<int> q;
|
||||
BOOST_TEST(q.try_push(boost::no_block, 1));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
{
|
||||
// empty queue try_push rvalue/non-copyable succeeds
|
||||
boost::sync_queue<non_copyable> q;
|
||||
BOOST_TEST(boost::queue_op_status::success ==q.try_push_back(non_copyable()));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
#endif
|
||||
{
|
||||
// empty queue try_push rvalue/non-copyable succeeds
|
||||
boost::sync_queue<non_copyable> q;
|
||||
non_copyable nc(1);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.try_push_back(boost::move(nc)));
|
||||
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(1));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
|
||||
{
|
||||
// empty queue try_push lvalue succeeds
|
||||
boost::sync_queue<int> q;
|
||||
int i=1;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.try_push_back(i));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// empty queue try_push rvalue succeeds
|
||||
boost::sync_queue<int> q;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push_back(1));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
|
||||
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
#if 0
|
||||
{
|
||||
// empty queue try_push rvalue/non-copyable succeeds
|
||||
// empty queue nonblocking_push rvalue/non-copyable succeeds
|
||||
boost::sync_queue<non_copyable> q;
|
||||
BOOST_TEST(q.try_push(boost::no_block, non_copyable(1)));
|
||||
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(non_copyable(1)));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
@@ -338,10 +162,10 @@ int main()
|
||||
}
|
||||
#endif
|
||||
{
|
||||
// empty queue try_push rvalue/non-copyable succeeds
|
||||
// empty queue nonblocking_push rvalue/non-copyable succeeds
|
||||
boost::sync_queue<non_copyable> q;
|
||||
non_copyable nc(1);
|
||||
BOOST_TEST(q.try_push(boost::no_block, boost::move(nc)));
|
||||
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(boost::move(nc)));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
@@ -400,7 +224,7 @@ int main()
|
||||
boost::sync_queue<int> q;
|
||||
q.push(1);
|
||||
int i;
|
||||
BOOST_TEST(q.try_pull(i));
|
||||
BOOST_TEST(boost::queue_op_status::success == q.try_pull(i));
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
@@ -413,7 +237,7 @@ int main()
|
||||
non_copyable nc1(1);
|
||||
q.push(boost::move(nc1));
|
||||
non_copyable nc(2);
|
||||
BOOST_TEST(q.try_pull(nc));
|
||||
BOOST_TEST(boost::queue_op_status::success == q.try_pull(nc));
|
||||
BOOST_TEST_EQ(nc, nc1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
@@ -421,11 +245,11 @@ int main()
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue try_pull succeed
|
||||
// 1-element queue nonblocking_pull succeed
|
||||
boost::sync_queue<int> q;
|
||||
q.push(1);
|
||||
int i;
|
||||
BOOST_TEST(q.try_pull(boost::no_block, i));
|
||||
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(i));
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
@@ -433,12 +257,12 @@ int main()
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue try_pull succeed
|
||||
// 1-element queue nonblocking_pull succeed
|
||||
boost::sync_queue<non_copyable> q;
|
||||
non_copyable nc1(1);
|
||||
q.push(boost::move(nc1));
|
||||
non_copyable nc(2);
|
||||
BOOST_TEST(q.try_pull(boost::no_block, nc));
|
||||
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(nc));
|
||||
BOOST_TEST_EQ(nc, nc1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
@@ -446,11 +270,38 @@ int main()
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue try_pull succeed
|
||||
// 1-element queue wait_pull succeed
|
||||
boost::sync_queue<non_copyable> q;
|
||||
non_copyable nc1(1);
|
||||
q.push(boost::move(nc1));
|
||||
non_copyable nc(2);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc));
|
||||
BOOST_TEST_EQ(nc, nc1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue wait_pull succeed
|
||||
boost::sync_queue<int> q;
|
||||
q.push(1);
|
||||
boost::shared_ptr<int> i = q.try_pull();
|
||||
BOOST_TEST_EQ(*i, 1);
|
||||
int i;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i));
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue wait_pull succeed
|
||||
boost::sync_queue<non_copyable> q;
|
||||
non_copyable nc1(1);
|
||||
q.push(boost::move(nc1));
|
||||
non_copyable nc(2);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc));
|
||||
BOOST_TEST_EQ(nc, nc1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
@@ -480,28 +331,6 @@ int main()
|
||||
BOOST_TEST(q.closed());
|
||||
}
|
||||
}
|
||||
{
|
||||
// closed empty queue try_pull_front closed
|
||||
boost::sync_queue<int> q;
|
||||
q.close();
|
||||
int i;
|
||||
BOOST_TEST(boost::queue_op_status::closed == q.try_pull_front(i));
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(q.closed());
|
||||
}
|
||||
{
|
||||
// closed empty queue nonblocking_pull_front closed
|
||||
boost::sync_queue<int> q;
|
||||
q.close();
|
||||
int i;
|
||||
BOOST_TEST(boost::queue_op_status::closed == q.nonblocking_pull_front(i));
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element closed queue pull succeed
|
||||
boost::sync_queue<int> q;
|
||||
@@ -515,195 +344,13 @@ int main()
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(q.closed());
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
{
|
||||
// empty queue nonblocking_push_back rvalue/non-copyable succeeds
|
||||
boost::sync_queue<non_copyable> q;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push_back(non_copyable(1)));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
#endif
|
||||
{
|
||||
// empty queue nonblocking_push_back rvalue/non-copyable succeeds
|
||||
boost::sync_queue<non_copyable> q;
|
||||
non_copyable nc(1);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push_back(boost::move(nc)));
|
||||
BOOST_TEST(! q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 1u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue pull_front succeed
|
||||
// 1-element closed queue wait_pull succeed
|
||||
boost::sync_queue<int> q;
|
||||
q.push_back(1);
|
||||
int i;
|
||||
q.pull_front(i);
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue pull_front succeed
|
||||
boost::sync_queue<non_copyable> q;
|
||||
non_copyable nc1(1);
|
||||
q.push_back(boost::move(nc1));
|
||||
non_copyable nc2(2);
|
||||
q.pull_front(nc2);
|
||||
BOOST_TEST_EQ(nc1, nc2);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue pull_front succeed
|
||||
boost::sync_queue<int> q;
|
||||
q.push_back(1);
|
||||
int i = q.pull_front();
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue pull_front succeed
|
||||
boost::sync_queue<non_copyable> q;
|
||||
non_copyable nc1(1);
|
||||
q.push_back(boost::move(nc1));
|
||||
non_copyable nc = q.pull_front();
|
||||
BOOST_TEST_EQ(nc, nc1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue try_pull_front succeed
|
||||
boost::sync_queue<int> q;
|
||||
q.push_back(1);
|
||||
int i;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.try_pull_front(i));
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue try_pull_front succeed
|
||||
boost::sync_queue<non_copyable> q;
|
||||
non_copyable nc1(1);
|
||||
q.push_back(boost::move(nc1));
|
||||
non_copyable nc(2);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.try_pull_front(nc));
|
||||
BOOST_TEST_EQ(nc, nc1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue nonblocking_pull_front succeed
|
||||
boost::sync_queue<int> q;
|
||||
q.push_back(1);
|
||||
int i;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull_front(i));
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue nonblocking_pull_front succeed
|
||||
boost::sync_queue<non_copyable> q;
|
||||
non_copyable nc1(1);
|
||||
q.push_back(boost::move(nc1));
|
||||
non_copyable nc(2);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull_front(nc));
|
||||
BOOST_TEST_EQ(nc, nc1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue wait_pull_front succeed
|
||||
boost::sync_queue<non_copyable> q;
|
||||
non_copyable nc1(1);
|
||||
q.push_back(boost::move(nc1));
|
||||
non_copyable nc(2);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(nc));
|
||||
BOOST_TEST_EQ(nc, nc1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue wait_pull_front succeed
|
||||
boost::sync_queue<int> q;
|
||||
q.push_back(1);
|
||||
int i;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(i));
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element queue wait_pull_front succeed
|
||||
boost::sync_queue<non_copyable> q;
|
||||
non_copyable nc1(1);
|
||||
q.push_back(boost::move(nc1));
|
||||
non_copyable nc(2);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(nc));
|
||||
BOOST_TEST_EQ(nc, nc1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(! q.closed());
|
||||
}
|
||||
|
||||
{
|
||||
// closed invariants
|
||||
boost::sync_queue<int> q;
|
||||
q.close();
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(q.closed());
|
||||
}
|
||||
{
|
||||
// closed queue push fails
|
||||
boost::sync_queue<int> q;
|
||||
q.close();
|
||||
try {
|
||||
q.push_back(1);
|
||||
BOOST_TEST(false);
|
||||
} catch (...) {
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(q.closed());
|
||||
}
|
||||
}
|
||||
{
|
||||
// 1-element closed queue pull succeed
|
||||
boost::sync_queue<int> q;
|
||||
q.push_back(1);
|
||||
q.push(1);
|
||||
q.close();
|
||||
int i;
|
||||
q.pull_front(i);
|
||||
BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i));
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
@@ -711,26 +358,13 @@ int main()
|
||||
BOOST_TEST(q.closed());
|
||||
}
|
||||
{
|
||||
// 1-element closed queue wait_pull_front succeed
|
||||
boost::sync_queue<int> q;
|
||||
q.push_back(1);
|
||||
q.close();
|
||||
int i;
|
||||
BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(i));
|
||||
BOOST_TEST_EQ(i, 1);
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(! q.full());
|
||||
BOOST_TEST_EQ(q.size(), 0u);
|
||||
BOOST_TEST(q.closed());
|
||||
}
|
||||
{
|
||||
// closed empty queue wait_pull_front fails
|
||||
// closed empty queue wait_pull fails
|
||||
boost::sync_queue<int> q;
|
||||
q.close();
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(q.closed());
|
||||
int i;
|
||||
BOOST_TEST(boost::queue_op_status::closed == q.wait_pull_front(i));
|
||||
BOOST_TEST(boost::queue_op_status::closed == q.wait_pull(i));
|
||||
BOOST_TEST(q.empty());
|
||||
BOOST_TEST(q.closed());
|
||||
}
|
||||
|
||||
44
test/test_10963.cpp
Normal file
44
test/test_10963.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
// Copyright (C) 2014 Vicente Botet
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#include <boost/config.hpp>
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
|
||||
struct TestCallback
|
||||
{
|
||||
typedef boost::future<void> result_type;
|
||||
|
||||
result_type operator()(boost::future<void> future) const
|
||||
{
|
||||
future.get();
|
||||
return boost::make_ready_future();
|
||||
}
|
||||
|
||||
result_type operator()(boost::future<boost::future<void> > future) const
|
||||
{
|
||||
future.get();
|
||||
return boost::make_ready_future();
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE && ! defined BOOST_NO_CXX11_AUTO_DECLARATIONS
|
||||
boost::promise<void> test_promise;
|
||||
boost::future<void> test_future(test_promise.get_future());
|
||||
auto f1 = test_future.then(TestCallback());
|
||||
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
|
||||
auto f2 = f1.then(TestCallback());
|
||||
BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<boost::future<void> > >::value);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
76
test/test_10964.cpp
Normal file
76
test/test_10964.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
// Copyright (C) 2015 Vicente Botet
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#include <boost/config.hpp>
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
struct TestCallback
|
||||
{
|
||||
typedef boost::future<void> result_type;
|
||||
|
||||
result_type operator()(boost::future<void> future) const
|
||||
{
|
||||
future.get();
|
||||
return boost::make_ready_future();
|
||||
}
|
||||
|
||||
result_type operator()(boost::future<boost::future<void> > future) const
|
||||
{
|
||||
future.get();
|
||||
return boost::make_ready_future();
|
||||
}
|
||||
};
|
||||
|
||||
void p1()
|
||||
{
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE && ! defined BOOST_NO_CXX11_AUTO_DECLARATIONS
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
{
|
||||
auto f1 = boost::make_ready_future().then(TestCallback());
|
||||
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
|
||||
f1.wait();
|
||||
}
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
{
|
||||
auto f1 = boost::make_ready_future().then(TestCallback());
|
||||
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
|
||||
auto f2 = f1.unwrap();
|
||||
BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<void> >::value);
|
||||
f2.wait();
|
||||
}
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
{
|
||||
auto f1 = boost::make_ready_future().then(TestCallback());
|
||||
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
|
||||
auto f2 = f1.unwrap();
|
||||
BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<void> >::value);
|
||||
auto f3 = f2.then(TestCallback());
|
||||
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
|
||||
f3.wait();
|
||||
}
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
{
|
||||
boost::make_ready_future().then(
|
||||
TestCallback()).unwrap().then(TestCallback()).get();
|
||||
}
|
||||
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
|
||||
{
|
||||
boost::future<void> f = boost::async(p1);
|
||||
f.then(
|
||||
TestCallback()).unwrap().then(TestCallback()).get();
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#define BOOST_THREAD_VERSION 2
|
||||
#define BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
|
||||
#define BOOST_TEST_MODULE Boost.Threads: 2309
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <iostream>
|
||||
@@ -40,7 +40,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
void test()
|
||||
BOOST_AUTO_TEST_CASE(test)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -61,14 +61,5 @@
|
||||
}
|
||||
}
|
||||
|
||||
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
|
||||
{
|
||||
boost::unit_test_framework::test_suite* tests =
|
||||
BOOST_TEST_SUITE("Boost.Threads: 2309");
|
||||
|
||||
tests->add(BOOST_TEST_CASE(&test));
|
||||
|
||||
return tests;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#define BOOST_THREAD_VERSION 2
|
||||
|
||||
#define BOOST_TEST_MODULE Boost.Threads: thread attributes test suite
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/thread/thread_only.hpp>
|
||||
@@ -29,7 +29,7 @@ void simple_thread()
|
||||
test_value = 999;
|
||||
}
|
||||
|
||||
void test_native_handle()
|
||||
BOOST_AUTO_TEST_CASE(test_native_handle)
|
||||
{
|
||||
|
||||
boost::thread_attributes attrs;
|
||||
@@ -51,7 +51,7 @@ void test_native_handle()
|
||||
|
||||
}
|
||||
|
||||
void test_stack_size()
|
||||
BOOST_AUTO_TEST_CASE(test_stack_size)
|
||||
{
|
||||
boost::thread_attributes attrs;
|
||||
|
||||
@@ -70,18 +70,8 @@ void do_test_creation_with_attrs()
|
||||
BOOST_CHECK_EQUAL(test_value, 999);
|
||||
}
|
||||
|
||||
void test_creation_with_attrs()
|
||||
BOOST_AUTO_TEST_CASE(test_creation_with_attrs)
|
||||
{
|
||||
timed_test(&do_test_creation_with_attrs, 1);
|
||||
}
|
||||
|
||||
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
|
||||
{
|
||||
boost::unit_test_framework::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: thread attributes test suite");
|
||||
|
||||
test->add(BOOST_TEST_CASE(test_native_handle));
|
||||
test->add(BOOST_TEST_CASE(test_stack_size));
|
||||
test->add(BOOST_TEST_CASE(test_creation_with_attrs));
|
||||
|
||||
return test;
|
||||
}
|
||||
|
||||
@@ -24,18 +24,37 @@ void foo(IntPromise p)
|
||||
|
||||
void bar(boost::future<int> fooResult)
|
||||
{
|
||||
try {
|
||||
std::cout << "bar" << std::endl;
|
||||
int i = fooResult.get(); // Code hangs on this line (Due to future already being locked by the set_value call)
|
||||
std::cout << "i: " << i << std::endl;
|
||||
} catch(...) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << __FILE__ << ":" << __LINE__ << std::endl;
|
||||
try {
|
||||
IntPromise p(new boost::promise<int>());
|
||||
boost::thread t(boost::bind(foo, p));
|
||||
boost::future<int> f1 = p->get_future();
|
||||
//f1.then(launch::deferred, boost::bind(bar, _1));
|
||||
f1.then(boost::launch::deferred, &bar);
|
||||
t.join();
|
||||
} catch(...) {
|
||||
return 1;
|
||||
}
|
||||
std::cout << __FILE__ << ":" << __LINE__ << std::endl;
|
||||
try {
|
||||
IntPromise p(new boost::promise<int>());
|
||||
boost::thread t(boost::bind(foo, p));
|
||||
boost::future<int> f1 = p->get_future();
|
||||
f1.then(boost::launch::async, &bar);
|
||||
t.join();
|
||||
} catch(...) {
|
||||
return 2;
|
||||
}
|
||||
std::cout << __FILE__ << ":" << __LINE__ << std::endl;
|
||||
}
|
||||
|
||||
|
||||
29
test/test_9856.cpp
Normal file
29
test/test_9856.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#include "boost/atomic.hpp"
|
||||
#include "boost/thread.hpp"
|
||||
#include <iostream>
|
||||
|
||||
using namespace boost;
|
||||
|
||||
int main() {
|
||||
atomic<size_t> total(0), failures(0);
|
||||
|
||||
#pragma omp parallel shared(total, failures) num_threads(1000)
|
||||
{
|
||||
mutex mtx;
|
||||
condition_variable cond;
|
||||
unique_lock<mutex> lk(mtx);
|
||||
for (int i = 0; i < 500; i++) {
|
||||
++total;
|
||||
if (cv_status::timeout != cond.wait_for(lk, chrono::milliseconds(10)))
|
||||
++failures;
|
||||
}
|
||||
}
|
||||
if(failures)
|
||||
std::cout << "There were " << failures << " failures out of " << total << " timed waits." << std::endl;
|
||||
if((100*failures)/total>10)
|
||||
{
|
||||
std::cerr << "This exceeds 10%, so failing the test." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#define BOOST_THREAD_VERSION 2
|
||||
#define BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
|
||||
#define BOOST_TEST_MODULE Boost.Threads: condition test suite
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/thread/condition.hpp>
|
||||
@@ -156,7 +156,7 @@ void do_test_condition_waits()
|
||||
BOOST_CHECK_EQUAL(data.awoken, 5);
|
||||
}
|
||||
|
||||
void test_condition_waits()
|
||||
BOOST_AUTO_TEST_CASE(test_condition_waits)
|
||||
{
|
||||
// We should have already tested notify_one here, so
|
||||
// a timed test with the default execution_monitor::use_condition
|
||||
@@ -176,20 +176,8 @@ void do_test_condition_wait_is_a_interruption_point()
|
||||
}
|
||||
|
||||
|
||||
void test_condition_wait_is_a_interruption_point()
|
||||
BOOST_AUTO_TEST_CASE(test_condition_wait_is_a_interruption_point)
|
||||
{
|
||||
timed_test(&do_test_condition_wait_is_a_interruption_point, 1);
|
||||
}
|
||||
|
||||
boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
|
||||
{
|
||||
boost::unit_test::test_suite* test =
|
||||
BOOST_TEST_SUITE("Boost.Threads: condition test suite");
|
||||
|
||||
test->add(BOOST_TEST_CASE(&test_condition_waits));
|
||||
test->add(BOOST_TEST_CASE(&test_condition_wait_is_a_interruption_point));
|
||||
|
||||
return test;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#define BOOST_THREAD_VERSION 2
|
||||
|
||||
#define BOOST_TEST_MODULE Boost.Threads: condition_variable notify_all test suite
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/thread/thread_only.hpp>
|
||||
@@ -202,7 +202,7 @@ void do_test_notify_all_following_notify_one_wakes_all_threads()
|
||||
thread3.join();
|
||||
}
|
||||
|
||||
void test_condition_notify_all()
|
||||
BOOST_AUTO_TEST_CASE(test_condition_notify_all)
|
||||
{
|
||||
timed_test(&do_test_condition_notify_all_wakes_from_wait, timeout_seconds);
|
||||
timed_test(&do_test_condition_notify_all_wakes_from_wait_with_predicate, timeout_seconds);
|
||||
@@ -213,14 +213,4 @@ void test_condition_notify_all()
|
||||
}
|
||||
|
||||
|
||||
boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
|
||||
{
|
||||
boost::unit_test::test_suite* test =
|
||||
BOOST_TEST_SUITE("Boost.Threads: condition test suite");
|
||||
|
||||
test->add(BOOST_TEST_CASE(&test_condition_notify_all));
|
||||
|
||||
return test;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
#define BOOST_THREAD_VERSION 2
|
||||
|
||||
#define BOOST_TEST_MODULE Boost.Threads: condition_variable notify_one test suite
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/thread/thread_only.hpp>
|
||||
@@ -135,7 +137,7 @@ void do_test_multiple_notify_one_calls_wakes_multiple_threads()
|
||||
thread3.join();
|
||||
}
|
||||
|
||||
void test_condition_notify_one()
|
||||
BOOST_AUTO_TEST_CASE(test_condition_notify_one)
|
||||
{
|
||||
timed_test(&do_test_condition_notify_one_wakes_from_wait, timeout_seconds, execution_monitor::use_mutex);
|
||||
timed_test(&do_test_condition_notify_one_wakes_from_wait_with_predicate, timeout_seconds, execution_monitor::use_mutex);
|
||||
@@ -144,15 +146,3 @@ void test_condition_notify_one()
|
||||
timed_test(&do_test_condition_notify_one_wakes_from_relative_timed_wait_with_predicate, timeout_seconds, execution_monitor::use_mutex);
|
||||
timed_test(&do_test_multiple_notify_one_calls_wakes_multiple_threads, timeout_seconds, execution_monitor::use_mutex);
|
||||
}
|
||||
|
||||
|
||||
boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
|
||||
{
|
||||
boost::unit_test::test_suite* test =
|
||||
BOOST_TEST_SUITE("Boost.Threads: condition test suite");
|
||||
|
||||
test->add(BOOST_TEST_CASE(&test_condition_notify_one));
|
||||
|
||||
return test;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
#define BOOST_THREAD_VERSION 2
|
||||
|
||||
#define BOOST_TEST_MODULE Boost.Threads: condition_variable test suite
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/thread/condition.hpp>
|
||||
@@ -152,7 +154,7 @@ void do_test_cv_any_timed_wait_relative_times_out()
|
||||
}
|
||||
|
||||
|
||||
void test_timed_wait_times_out()
|
||||
BOOST_AUTO_TEST_CASE(test_timed_wait_times_out)
|
||||
{
|
||||
timed_test(&do_test_timed_wait_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
|
||||
timed_test(&do_test_timed_wait_with_predicate_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
|
||||
@@ -164,14 +166,4 @@ void test_timed_wait_times_out()
|
||||
timed_test(&do_test_cv_any_timed_wait_relative_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
|
||||
}
|
||||
|
||||
boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
|
||||
{
|
||||
boost::unit_test::test_suite* test =
|
||||
BOOST_TEST_SUITE("Boost.Threads: condition test suite");
|
||||
|
||||
test->add(BOOST_TEST_CASE(&test_timed_wait_times_out));
|
||||
|
||||
return test;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#define BOOST_THREAD_VERSION 2
|
||||
#define BOOST_TEST_MODULE Boost.Threads: futures test suite
|
||||
|
||||
#include <boost/thread/thread_only.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
@@ -93,7 +94,7 @@ void set_promise_exception_thread(boost::promise<int>* p)
|
||||
}
|
||||
|
||||
|
||||
void test_store_value_from_thread()
|
||||
BOOST_AUTO_TEST_CASE(test_store_value_from_thread)
|
||||
{
|
||||
LOG;
|
||||
try {
|
||||
@@ -122,8 +123,7 @@ void test_store_value_from_thread()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void test_store_exception()
|
||||
BOOST_AUTO_TEST_CASE(test_store_exception)
|
||||
{
|
||||
LOG;
|
||||
boost::promise<int> pi3;
|
||||
@@ -145,7 +145,7 @@ void test_store_exception()
|
||||
BOOST_CHECK(fi3.get_state()==boost::future_state::ready);
|
||||
}
|
||||
|
||||
void test_initial_state()
|
||||
BOOST_AUTO_TEST_CASE(test_initial_state)
|
||||
{
|
||||
LOG;
|
||||
boost::unique_future<int> fi;
|
||||
@@ -166,7 +166,7 @@ void test_initial_state()
|
||||
}
|
||||
}
|
||||
|
||||
void test_waiting_future()
|
||||
BOOST_AUTO_TEST_CASE(test_waiting_future)
|
||||
{
|
||||
LOG;
|
||||
boost::promise<int> pi;
|
||||
@@ -181,7 +181,7 @@ void test_waiting_future()
|
||||
BOOST_CHECK(i==0);
|
||||
}
|
||||
|
||||
void test_cannot_get_future_twice()
|
||||
BOOST_AUTO_TEST_CASE(test_cannot_get_future_twice)
|
||||
{
|
||||
LOG;
|
||||
boost::promise<int> pi;
|
||||
@@ -198,7 +198,7 @@ void test_cannot_get_future_twice()
|
||||
}
|
||||
}
|
||||
|
||||
void test_set_value_updates_future_state()
|
||||
BOOST_AUTO_TEST_CASE(test_set_value_updates_future_state)
|
||||
{
|
||||
LOG;
|
||||
boost::promise<int> pi;
|
||||
@@ -213,7 +213,7 @@ void test_set_value_updates_future_state()
|
||||
BOOST_CHECK(fi.get_state()==boost::future_state::ready);
|
||||
}
|
||||
|
||||
void test_set_value_can_be_retrieved()
|
||||
BOOST_AUTO_TEST_CASE(test_set_value_can_be_retrieved)
|
||||
{
|
||||
LOG;
|
||||
boost::promise<int> pi;
|
||||
@@ -231,7 +231,7 @@ void test_set_value_can_be_retrieved()
|
||||
BOOST_CHECK(fi.get_state()==boost::future_state::ready);
|
||||
}
|
||||
|
||||
void test_set_value_can_be_moved()
|
||||
BOOST_AUTO_TEST_CASE(test_set_value_can_be_moved)
|
||||
{
|
||||
LOG;
|
||||
// boost::promise<int> pi;
|
||||
@@ -249,7 +249,7 @@ void test_set_value_can_be_moved()
|
||||
// BOOST_CHECK(fi.get_state()==boost::future_state::ready);
|
||||
}
|
||||
|
||||
void test_future_from_packaged_task_is_waiting()
|
||||
BOOST_AUTO_TEST_CASE(test_future_from_packaged_task_is_waiting)
|
||||
{
|
||||
LOG;
|
||||
boost::packaged_task<int> pt(make_int);
|
||||
@@ -262,7 +262,7 @@ void test_future_from_packaged_task_is_waiting()
|
||||
BOOST_CHECK(i==0);
|
||||
}
|
||||
|
||||
void test_invoking_a_packaged_task_populates_future()
|
||||
BOOST_AUTO_TEST_CASE(test_invoking_a_packaged_task_populates_future)
|
||||
{
|
||||
LOG;
|
||||
boost::packaged_task<int> pt(make_int);
|
||||
@@ -279,7 +279,7 @@ void test_invoking_a_packaged_task_populates_future()
|
||||
BOOST_CHECK(i==42);
|
||||
}
|
||||
|
||||
void test_invoking_a_packaged_task_twice_throws()
|
||||
BOOST_AUTO_TEST_CASE(test_invoking_a_packaged_task_twice_throws)
|
||||
{
|
||||
LOG;
|
||||
boost::packaged_task<int> pt(make_int);
|
||||
@@ -297,7 +297,7 @@ void test_invoking_a_packaged_task_twice_throws()
|
||||
}
|
||||
|
||||
|
||||
void test_cannot_get_future_twice_from_task()
|
||||
BOOST_AUTO_TEST_CASE(test_cannot_get_future_twice_from_task)
|
||||
{
|
||||
LOG;
|
||||
boost::packaged_task<int> pt(make_int);
|
||||
@@ -313,7 +313,7 @@ void test_cannot_get_future_twice_from_task()
|
||||
}
|
||||
}
|
||||
|
||||
void test_task_stores_exception_if_function_throws()
|
||||
BOOST_AUTO_TEST_CASE(test_task_stores_exception_if_function_throws)
|
||||
{
|
||||
LOG;
|
||||
boost::packaged_task<int> pt(throw_runtime_error);
|
||||
@@ -341,7 +341,7 @@ void test_task_stores_exception_if_function_throws()
|
||||
|
||||
}
|
||||
|
||||
void test_void_promise()
|
||||
BOOST_AUTO_TEST_CASE(test_void_promise)
|
||||
{
|
||||
LOG;
|
||||
boost::promise<void> p;
|
||||
@@ -354,7 +354,7 @@ void test_void_promise()
|
||||
f.get();
|
||||
}
|
||||
|
||||
void test_reference_promise()
|
||||
BOOST_AUTO_TEST_CASE(test_reference_promise)
|
||||
{
|
||||
LOG;
|
||||
boost::promise<int&> p;
|
||||
@@ -371,7 +371,7 @@ void test_reference_promise()
|
||||
void do_nothing()
|
||||
{}
|
||||
|
||||
void test_task_returning_void()
|
||||
BOOST_AUTO_TEST_CASE(test_task_returning_void)
|
||||
{
|
||||
LOG;
|
||||
boost::packaged_task<void> pt(do_nothing);
|
||||
@@ -392,7 +392,7 @@ int& return_ref()
|
||||
return global_ref_target;
|
||||
}
|
||||
|
||||
void test_task_returning_reference()
|
||||
BOOST_AUTO_TEST_CASE(test_task_returning_reference)
|
||||
{
|
||||
LOG;
|
||||
boost::packaged_task<int&> pt(return_ref);
|
||||
@@ -408,7 +408,7 @@ void test_task_returning_reference()
|
||||
BOOST_CHECK(&i==&global_ref_target);
|
||||
}
|
||||
|
||||
void test_shared_future()
|
||||
BOOST_AUTO_TEST_CASE(test_shared_future)
|
||||
{
|
||||
LOG;
|
||||
boost::packaged_task<int> pt(make_int);
|
||||
@@ -428,7 +428,7 @@ void test_shared_future()
|
||||
BOOST_CHECK(i==42);
|
||||
}
|
||||
|
||||
void test_copies_of_shared_future_become_ready_together()
|
||||
BOOST_AUTO_TEST_CASE(test_copies_of_shared_future_become_ready_together)
|
||||
{
|
||||
LOG;
|
||||
boost::packaged_task<int> pt(make_int);
|
||||
@@ -467,7 +467,7 @@ void test_copies_of_shared_future_become_ready_together()
|
||||
BOOST_CHECK(i==42);
|
||||
}
|
||||
|
||||
void test_shared_future_can_be_move_assigned_from_unique_future()
|
||||
BOOST_AUTO_TEST_CASE(test_shared_future_can_be_move_assigned_from_unique_future)
|
||||
{
|
||||
LOG;
|
||||
boost::packaged_task<int> pt(make_int);
|
||||
@@ -483,7 +483,7 @@ void test_shared_future_can_be_move_assigned_from_unique_future()
|
||||
BOOST_CHECK(sf.get_state()==boost::future_state::waiting);
|
||||
}
|
||||
|
||||
void test_shared_future_void()
|
||||
BOOST_AUTO_TEST_CASE(test_shared_future_void)
|
||||
{
|
||||
LOG;
|
||||
boost::packaged_task<void> pt(do_nothing);
|
||||
@@ -501,7 +501,7 @@ void test_shared_future_void()
|
||||
sf.get();
|
||||
}
|
||||
|
||||
void test_shared_future_ref()
|
||||
BOOST_AUTO_TEST_CASE(test_shared_future_ref)
|
||||
{
|
||||
LOG;
|
||||
boost::promise<int&> p;
|
||||
@@ -515,7 +515,7 @@ void test_shared_future_ref()
|
||||
BOOST_CHECK(&f.get()==&i);
|
||||
}
|
||||
|
||||
void test_can_get_a_second_future_from_a_moved_promise()
|
||||
BOOST_AUTO_TEST_CASE(test_can_get_a_second_future_from_a_moved_promise)
|
||||
{
|
||||
LOG;
|
||||
boost::promise<int> pi;
|
||||
@@ -533,7 +533,7 @@ void test_can_get_a_second_future_from_a_moved_promise()
|
||||
BOOST_CHECK(fi2.get()==42);
|
||||
}
|
||||
|
||||
void test_can_get_a_second_future_from_a_moved_void_promise()
|
||||
BOOST_AUTO_TEST_CASE(test_can_get_a_second_future_from_a_moved_void_promise)
|
||||
{
|
||||
LOG;
|
||||
boost::promise<void> pi;
|
||||
@@ -549,7 +549,7 @@ void test_can_get_a_second_future_from_a_moved_void_promise()
|
||||
BOOST_CHECK(fi2.is_ready());
|
||||
}
|
||||
|
||||
void test_unique_future_for_move_only_udt()
|
||||
BOOST_AUTO_TEST_CASE(test_unique_future_for_move_only_udt)
|
||||
{
|
||||
LOG;
|
||||
boost::promise<X> pt;
|
||||
@@ -560,7 +560,7 @@ void test_unique_future_for_move_only_udt()
|
||||
BOOST_CHECK(res.i==42);
|
||||
}
|
||||
|
||||
void test_unique_future_for_string()
|
||||
BOOST_AUTO_TEST_CASE(test_unique_future_for_string)
|
||||
{
|
||||
LOG;
|
||||
boost::promise<std::string> pt;
|
||||
@@ -611,7 +611,7 @@ void do_nothing_callback(boost::promise<int>& /*pi*/)
|
||||
++callback_called;
|
||||
}
|
||||
|
||||
void test_wait_callback()
|
||||
BOOST_AUTO_TEST_CASE(test_wait_callback)
|
||||
{
|
||||
LOG;
|
||||
callback_called=0;
|
||||
@@ -626,7 +626,7 @@ void test_wait_callback()
|
||||
BOOST_CHECK(callback_called==1);
|
||||
}
|
||||
|
||||
void test_wait_callback_with_timed_wait()
|
||||
BOOST_AUTO_TEST_CASE(test_wait_callback_with_timed_wait)
|
||||
{
|
||||
LOG;
|
||||
callback_called=0;
|
||||
@@ -665,7 +665,7 @@ void wait_callback_for_task(boost::packaged_task<int>& pt)
|
||||
}
|
||||
|
||||
|
||||
void test_wait_callback_for_packaged_task()
|
||||
BOOST_AUTO_TEST_CASE(test_wait_callback_for_packaged_task)
|
||||
{
|
||||
LOG;
|
||||
callback_called=0;
|
||||
@@ -680,7 +680,7 @@ void test_wait_callback_for_packaged_task()
|
||||
BOOST_CHECK(callback_called==1);
|
||||
}
|
||||
|
||||
void test_packaged_task_can_be_moved()
|
||||
BOOST_AUTO_TEST_CASE(test_packaged_task_can_be_moved)
|
||||
{
|
||||
LOG;
|
||||
boost::packaged_task<int> pt(make_int);
|
||||
@@ -708,7 +708,7 @@ void test_packaged_task_can_be_moved()
|
||||
BOOST_CHECK(fi.is_ready());
|
||||
}
|
||||
|
||||
void test_destroying_a_promise_stores_broken_promise()
|
||||
BOOST_AUTO_TEST_CASE(test_destroying_a_promise_stores_broken_promise)
|
||||
{
|
||||
LOG;
|
||||
boost::unique_future<int> f;
|
||||
@@ -728,7 +728,7 @@ void test_destroying_a_promise_stores_broken_promise()
|
||||
}
|
||||
}
|
||||
|
||||
void test_destroying_a_packaged_task_stores_broken_promise()
|
||||
BOOST_AUTO_TEST_CASE(test_destroying_a_packaged_task_stores_broken_promise)
|
||||
{
|
||||
LOG;
|
||||
boost::unique_future<int> f;
|
||||
@@ -754,7 +754,7 @@ int make_int_slowly()
|
||||
return 42;
|
||||
}
|
||||
|
||||
void test_wait_for_either_of_two_futures_1()
|
||||
BOOST_AUTO_TEST_CASE(test_wait_for_either_of_two_futures_1)
|
||||
{
|
||||
LOG;
|
||||
boost::packaged_task<int> pt(make_int_slowly);
|
||||
@@ -772,7 +772,7 @@ void test_wait_for_either_of_two_futures_1()
|
||||
BOOST_CHECK(f1.get()==42);
|
||||
}
|
||||
|
||||
void test_wait_for_either_of_two_futures_2()
|
||||
BOOST_AUTO_TEST_CASE(test_wait_for_either_of_two_futures_2)
|
||||
{
|
||||
LOG;
|
||||
boost::packaged_task<int> pt(make_int_slowly);
|
||||
@@ -790,7 +790,7 @@ void test_wait_for_either_of_two_futures_2()
|
||||
BOOST_CHECK(f2.get()==42);
|
||||
}
|
||||
|
||||
void test_wait_for_either_of_three_futures_1()
|
||||
BOOST_AUTO_TEST_CASE(test_wait_for_either_of_three_futures_1)
|
||||
{
|
||||
LOG;
|
||||
boost::packaged_task<int> pt(make_int_slowly);
|
||||
@@ -811,7 +811,7 @@ void test_wait_for_either_of_three_futures_1()
|
||||
BOOST_CHECK(f1.get()==42);
|
||||
}
|
||||
|
||||
void test_wait_for_either_of_three_futures_2()
|
||||
BOOST_AUTO_TEST_CASE(test_wait_for_either_of_three_futures_2)
|
||||
{
|
||||
LOG;
|
||||
boost::packaged_task<int> pt(make_int_slowly);
|
||||
@@ -832,7 +832,7 @@ void test_wait_for_either_of_three_futures_2()
|
||||
BOOST_CHECK(f2.get()==42);
|
||||
}
|
||||
|
||||
void test_wait_for_either_of_three_futures_3()
|
||||
BOOST_AUTO_TEST_CASE(test_wait_for_either_of_three_futures_3)
|
||||
{
|
||||
LOG;
|
||||
boost::packaged_task<int> pt(make_int_slowly);
|
||||
@@ -853,7 +853,7 @@ void test_wait_for_either_of_three_futures_3()
|
||||
BOOST_CHECK(f3.get()==42);
|
||||
}
|
||||
|
||||
void test_wait_for_either_of_four_futures_1()
|
||||
BOOST_AUTO_TEST_CASE(test_wait_for_either_of_four_futures_1)
|
||||
{
|
||||
LOG;
|
||||
boost::packaged_task<int> pt(make_int_slowly);
|
||||
@@ -877,7 +877,7 @@ void test_wait_for_either_of_four_futures_1()
|
||||
BOOST_CHECK(f1.get()==42);
|
||||
}
|
||||
|
||||
void test_wait_for_either_of_four_futures_2()
|
||||
BOOST_AUTO_TEST_CASE(test_wait_for_either_of_four_futures_2)
|
||||
{
|
||||
LOG;
|
||||
boost::packaged_task<int> pt(make_int_slowly);
|
||||
@@ -901,7 +901,7 @@ void test_wait_for_either_of_four_futures_2()
|
||||
BOOST_CHECK(f2.get()==42);
|
||||
}
|
||||
|
||||
void test_wait_for_either_of_four_futures_3()
|
||||
BOOST_AUTO_TEST_CASE(test_wait_for_either_of_four_futures_3)
|
||||
{
|
||||
LOG;
|
||||
boost::packaged_task<int> pt(make_int_slowly);
|
||||
@@ -925,7 +925,7 @@ void test_wait_for_either_of_four_futures_3()
|
||||
BOOST_CHECK(f3.get()==42);
|
||||
}
|
||||
|
||||
void test_wait_for_either_of_four_futures_4()
|
||||
BOOST_AUTO_TEST_CASE(test_wait_for_either_of_four_futures_4)
|
||||
{
|
||||
LOG;
|
||||
boost::packaged_task<int> pt(make_int_slowly);
|
||||
@@ -949,7 +949,7 @@ void test_wait_for_either_of_four_futures_4()
|
||||
BOOST_CHECK(f4.get()==42);
|
||||
}
|
||||
|
||||
void test_wait_for_either_of_five_futures_1()
|
||||
BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_1)
|
||||
{
|
||||
LOG;
|
||||
boost::packaged_task<int> pt(make_int_slowly);
|
||||
@@ -976,7 +976,7 @@ void test_wait_for_either_of_five_futures_1()
|
||||
BOOST_CHECK(f1.get()==42);
|
||||
}
|
||||
|
||||
void test_wait_for_either_of_five_futures_2()
|
||||
BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_2)
|
||||
{
|
||||
LOG;
|
||||
boost::packaged_task<int> pt(make_int_slowly);
|
||||
@@ -1002,7 +1002,7 @@ void test_wait_for_either_of_five_futures_2()
|
||||
BOOST_CHECK(!f5.is_ready());
|
||||
BOOST_CHECK(f2.get()==42);
|
||||
}
|
||||
void test_wait_for_either_of_five_futures_3()
|
||||
BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_3)
|
||||
{
|
||||
LOG;
|
||||
boost::packaged_task<int> pt(make_int_slowly);
|
||||
@@ -1028,7 +1028,7 @@ void test_wait_for_either_of_five_futures_3()
|
||||
BOOST_CHECK(!f5.is_ready());
|
||||
BOOST_CHECK(f3.get()==42);
|
||||
}
|
||||
void test_wait_for_either_of_five_futures_4()
|
||||
BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_4)
|
||||
{
|
||||
LOG;
|
||||
boost::packaged_task<int> pt(make_int_slowly);
|
||||
@@ -1054,7 +1054,7 @@ void test_wait_for_either_of_five_futures_4()
|
||||
BOOST_CHECK(!f5.is_ready());
|
||||
BOOST_CHECK(f4.get()==42);
|
||||
}
|
||||
void test_wait_for_either_of_five_futures_5()
|
||||
BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_5)
|
||||
{
|
||||
LOG;
|
||||
boost::packaged_task<int> pt(make_int_slowly);
|
||||
@@ -1081,7 +1081,7 @@ void test_wait_for_either_of_five_futures_5()
|
||||
BOOST_CHECK(f5.get()==42);
|
||||
}
|
||||
|
||||
void test_wait_for_either_invokes_callbacks()
|
||||
BOOST_AUTO_TEST_CASE(test_wait_for_either_invokes_callbacks)
|
||||
{
|
||||
LOG;
|
||||
callback_called=0;
|
||||
@@ -1098,7 +1098,7 @@ void test_wait_for_either_invokes_callbacks()
|
||||
BOOST_CHECK(fi.get()==42);
|
||||
}
|
||||
|
||||
void test_wait_for_any_from_range()
|
||||
BOOST_AUTO_TEST_CASE(test_wait_for_any_from_range)
|
||||
{
|
||||
LOG;
|
||||
unsigned const count=10;
|
||||
@@ -1133,7 +1133,7 @@ void test_wait_for_any_from_range()
|
||||
}
|
||||
}
|
||||
|
||||
void test_wait_for_all_from_range()
|
||||
BOOST_AUTO_TEST_CASE(test_wait_for_all_from_range)
|
||||
{
|
||||
LOG;
|
||||
unsigned const count=10;
|
||||
@@ -1153,7 +1153,7 @@ void test_wait_for_all_from_range()
|
||||
}
|
||||
}
|
||||
|
||||
void test_wait_for_all_two_futures()
|
||||
BOOST_AUTO_TEST_CASE(test_wait_for_all_two_futures)
|
||||
{
|
||||
LOG;
|
||||
unsigned const count=2;
|
||||
@@ -1173,7 +1173,7 @@ void test_wait_for_all_two_futures()
|
||||
}
|
||||
}
|
||||
|
||||
void test_wait_for_all_three_futures()
|
||||
BOOST_AUTO_TEST_CASE(test_wait_for_all_three_futures)
|
||||
{
|
||||
LOG;
|
||||
unsigned const count=3;
|
||||
@@ -1193,7 +1193,7 @@ void test_wait_for_all_three_futures()
|
||||
}
|
||||
}
|
||||
|
||||
void test_wait_for_all_four_futures()
|
||||
BOOST_AUTO_TEST_CASE(test_wait_for_all_four_futures)
|
||||
{
|
||||
LOG;
|
||||
unsigned const count=4;
|
||||
@@ -1213,7 +1213,7 @@ void test_wait_for_all_four_futures()
|
||||
}
|
||||
}
|
||||
|
||||
void test_wait_for_all_five_futures()
|
||||
BOOST_AUTO_TEST_CASE(test_wait_for_all_five_futures)
|
||||
{
|
||||
LOG;
|
||||
unsigned const count=5;
|
||||
@@ -1232,68 +1232,3 @@ void test_wait_for_all_five_futures()
|
||||
BOOST_CHECK(futures[j].is_ready());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
|
||||
{
|
||||
boost::unit_test::test_suite* test =
|
||||
BOOST_TEST_SUITE("Boost.Threads: futures test suite");
|
||||
|
||||
test->add(BOOST_TEST_CASE(test_initial_state));
|
||||
test->add(BOOST_TEST_CASE(test_waiting_future));
|
||||
test->add(BOOST_TEST_CASE(test_cannot_get_future_twice));
|
||||
test->add(BOOST_TEST_CASE(test_set_value_updates_future_state));
|
||||
test->add(BOOST_TEST_CASE(test_set_value_can_be_retrieved));
|
||||
test->add(BOOST_TEST_CASE(test_set_value_can_be_moved));
|
||||
test->add(BOOST_TEST_CASE(test_store_value_from_thread));
|
||||
test->add(BOOST_TEST_CASE(test_store_exception));
|
||||
test->add(BOOST_TEST_CASE(test_future_from_packaged_task_is_waiting));
|
||||
test->add(BOOST_TEST_CASE(test_invoking_a_packaged_task_populates_future));
|
||||
test->add(BOOST_TEST_CASE(test_invoking_a_packaged_task_twice_throws));
|
||||
test->add(BOOST_TEST_CASE(test_cannot_get_future_twice_from_task));
|
||||
test->add(BOOST_TEST_CASE(test_task_stores_exception_if_function_throws));
|
||||
test->add(BOOST_TEST_CASE(test_void_promise));
|
||||
test->add(BOOST_TEST_CASE(test_reference_promise));
|
||||
test->add(BOOST_TEST_CASE(test_task_returning_void));
|
||||
test->add(BOOST_TEST_CASE(test_task_returning_reference));
|
||||
test->add(BOOST_TEST_CASE(test_shared_future));
|
||||
test->add(BOOST_TEST_CASE(test_copies_of_shared_future_become_ready_together));
|
||||
test->add(BOOST_TEST_CASE(test_shared_future_can_be_move_assigned_from_unique_future));
|
||||
test->add(BOOST_TEST_CASE(test_shared_future_void));
|
||||
test->add(BOOST_TEST_CASE(test_shared_future_ref));
|
||||
test->add(BOOST_TEST_CASE(test_can_get_a_second_future_from_a_moved_promise));
|
||||
test->add(BOOST_TEST_CASE(test_can_get_a_second_future_from_a_moved_void_promise));
|
||||
test->add(BOOST_TEST_CASE(test_unique_future_for_move_only_udt));
|
||||
test->add(BOOST_TEST_CASE(test_unique_future_for_string));
|
||||
test->add(BOOST_TEST_CASE(test_wait_callback));
|
||||
test->add(BOOST_TEST_CASE(test_wait_callback_with_timed_wait));
|
||||
test->add(BOOST_TEST_CASE(test_wait_callback_for_packaged_task));
|
||||
test->add(BOOST_TEST_CASE(test_packaged_task_can_be_moved));
|
||||
test->add(BOOST_TEST_CASE(test_destroying_a_promise_stores_broken_promise));
|
||||
test->add(BOOST_TEST_CASE(test_destroying_a_packaged_task_stores_broken_promise));
|
||||
test->add(BOOST_TEST_CASE(test_wait_for_either_of_two_futures_1));
|
||||
test->add(BOOST_TEST_CASE(test_wait_for_either_of_two_futures_2));
|
||||
test->add(BOOST_TEST_CASE(test_wait_for_either_of_three_futures_1));
|
||||
test->add(BOOST_TEST_CASE(test_wait_for_either_of_three_futures_2));
|
||||
test->add(BOOST_TEST_CASE(test_wait_for_either_of_three_futures_3));
|
||||
test->add(BOOST_TEST_CASE(test_wait_for_either_of_four_futures_1));
|
||||
test->add(BOOST_TEST_CASE(test_wait_for_either_of_four_futures_2));
|
||||
test->add(BOOST_TEST_CASE(test_wait_for_either_of_four_futures_3));
|
||||
test->add(BOOST_TEST_CASE(test_wait_for_either_of_four_futures_4));
|
||||
test->add(BOOST_TEST_CASE(test_wait_for_either_of_five_futures_1));
|
||||
test->add(BOOST_TEST_CASE(test_wait_for_either_of_five_futures_2));
|
||||
test->add(BOOST_TEST_CASE(test_wait_for_either_of_five_futures_3));
|
||||
test->add(BOOST_TEST_CASE(test_wait_for_either_of_five_futures_4));
|
||||
test->add(BOOST_TEST_CASE(test_wait_for_either_of_five_futures_5));
|
||||
test->add(BOOST_TEST_CASE(test_wait_for_either_invokes_callbacks));
|
||||
test->add(BOOST_TEST_CASE(test_wait_for_any_from_range));
|
||||
test->add(BOOST_TEST_CASE(test_wait_for_all_from_range));
|
||||
test->add(BOOST_TEST_CASE(test_wait_for_all_two_futures));
|
||||
test->add(BOOST_TEST_CASE(test_wait_for_all_three_futures));
|
||||
test->add(BOOST_TEST_CASE(test_wait_for_all_four_futures));
|
||||
test->add(BOOST_TEST_CASE(test_wait_for_all_five_futures));
|
||||
|
||||
return test;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -5,13 +5,15 @@
|
||||
|
||||
#define BOOST_THREAD_VERSION 2
|
||||
|
||||
#define BOOST_TEST_MODULE Boost.Threads: generic locks test suite
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/thread_only.hpp>
|
||||
#include <boost/thread/locks.hpp>
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
|
||||
void test_lock_two_uncontended()
|
||||
BOOST_AUTO_TEST_CASE(test_lock_two_uncontended)
|
||||
{
|
||||
boost::mutex m1,m2;
|
||||
|
||||
@@ -87,7 +89,7 @@ void lock_pair(boost::mutex* m1,boost::mutex* m2)
|
||||
l2(*m2,boost::adopt_lock);
|
||||
}
|
||||
|
||||
void test_lock_two_other_thread_locks_in_order()
|
||||
BOOST_AUTO_TEST_CASE(test_lock_two_other_thread_locks_in_order)
|
||||
{
|
||||
boost::mutex m1,m2;
|
||||
wait_data locked;
|
||||
@@ -106,7 +108,7 @@ void test_lock_two_other_thread_locks_in_order()
|
||||
t.join();
|
||||
}
|
||||
|
||||
void test_lock_two_other_thread_locks_in_opposite_order()
|
||||
BOOST_AUTO_TEST_CASE(test_lock_two_other_thread_locks_in_opposite_order)
|
||||
{
|
||||
boost::mutex m1,m2;
|
||||
wait_data locked;
|
||||
@@ -125,7 +127,7 @@ void test_lock_two_other_thread_locks_in_opposite_order()
|
||||
t.join();
|
||||
}
|
||||
|
||||
void test_lock_five_uncontended()
|
||||
BOOST_AUTO_TEST_CASE(test_lock_five_uncontended)
|
||||
{
|
||||
boost::mutex m1,m2,m3,m4,m5;
|
||||
|
||||
@@ -176,7 +178,7 @@ void lock_five(boost::mutex* m1,boost::mutex* m2,boost::mutex* m3,boost::mutex*
|
||||
m5->unlock();
|
||||
}
|
||||
|
||||
void test_lock_five_other_thread_locks_in_order()
|
||||
BOOST_AUTO_TEST_CASE(test_lock_five_other_thread_locks_in_order)
|
||||
{
|
||||
boost::mutex m1,m2,m3,m4,m5;
|
||||
wait_data locked;
|
||||
@@ -195,7 +197,7 @@ void test_lock_five_other_thread_locks_in_order()
|
||||
t.join();
|
||||
}
|
||||
|
||||
void test_lock_five_other_thread_locks_in_different_order()
|
||||
BOOST_AUTO_TEST_CASE(test_lock_five_other_thread_locks_in_different_order)
|
||||
{
|
||||
boost::mutex m1,m2,m3,m4,m5;
|
||||
wait_data locked;
|
||||
@@ -224,7 +226,7 @@ void lock_n(boost::mutex* mutexes,unsigned count)
|
||||
}
|
||||
|
||||
|
||||
void test_lock_ten_other_thread_locks_in_different_order()
|
||||
BOOST_AUTO_TEST_CASE(test_lock_ten_other_thread_locks_in_different_order)
|
||||
{
|
||||
unsigned const num_mutexes=10;
|
||||
|
||||
@@ -285,7 +287,7 @@ namespace boost
|
||||
|
||||
|
||||
|
||||
void test_lock_five_in_range()
|
||||
BOOST_AUTO_TEST_CASE(test_lock_five_in_range)
|
||||
{
|
||||
unsigned const num_mutexes=5;
|
||||
dummy_mutex mutexes[num_mutexes];
|
||||
@@ -350,7 +352,7 @@ public:
|
||||
};
|
||||
|
||||
|
||||
void test_lock_five_in_range_custom_iterator()
|
||||
BOOST_AUTO_TEST_CASE(test_lock_five_in_range_custom_iterator)
|
||||
{
|
||||
unsigned const num_mutexes=5;
|
||||
dummy_mutex mutexes[num_mutexes];
|
||||
@@ -368,7 +370,7 @@ class dummy_mutex2:
|
||||
{};
|
||||
|
||||
|
||||
void test_lock_ten_in_range_inherited_mutex()
|
||||
BOOST_AUTO_TEST_CASE(test_lock_ten_in_range_inherited_mutex)
|
||||
{
|
||||
unsigned const num_mutexes=10;
|
||||
dummy_mutex2 mutexes[num_mutexes];
|
||||
@@ -381,7 +383,7 @@ void test_lock_ten_in_range_inherited_mutex()
|
||||
}
|
||||
}
|
||||
|
||||
void test_try_lock_two_uncontended()
|
||||
BOOST_AUTO_TEST_CASE(test_try_lock_two_uncontended)
|
||||
{
|
||||
dummy_mutex m1,m2;
|
||||
|
||||
@@ -391,7 +393,7 @@ void test_try_lock_two_uncontended()
|
||||
BOOST_CHECK(m1.is_locked);
|
||||
BOOST_CHECK(m2.is_locked);
|
||||
}
|
||||
void test_try_lock_two_first_locked()
|
||||
BOOST_AUTO_TEST_CASE(test_try_lock_two_first_locked)
|
||||
{
|
||||
dummy_mutex m1,m2;
|
||||
m1.lock();
|
||||
@@ -407,7 +409,7 @@ void test_try_lock_two_first_locked()
|
||||
BOOST_CHECK(!l1.owns_lock());
|
||||
BOOST_CHECK(!l2.owns_lock());
|
||||
}
|
||||
void test_try_lock_two_second_locked()
|
||||
BOOST_AUTO_TEST_CASE(test_try_lock_two_second_locked)
|
||||
{
|
||||
dummy_mutex m1,m2;
|
||||
m2.lock();
|
||||
@@ -424,7 +426,7 @@ void test_try_lock_two_second_locked()
|
||||
BOOST_CHECK(!l2.owns_lock());
|
||||
}
|
||||
|
||||
void test_try_lock_three()
|
||||
BOOST_AUTO_TEST_CASE(test_try_lock_three)
|
||||
{
|
||||
int const num_mutexes=3;
|
||||
|
||||
@@ -469,7 +471,7 @@ void test_try_lock_three()
|
||||
}
|
||||
}
|
||||
|
||||
void test_try_lock_four()
|
||||
BOOST_AUTO_TEST_CASE(test_try_lock_four)
|
||||
{
|
||||
int const num_mutexes=4;
|
||||
|
||||
@@ -517,7 +519,7 @@ void test_try_lock_four()
|
||||
}
|
||||
}
|
||||
|
||||
void test_try_lock_five()
|
||||
BOOST_AUTO_TEST_CASE(test_try_lock_five)
|
||||
{
|
||||
int const num_mutexes=5;
|
||||
|
||||
@@ -568,31 +570,3 @@ void test_try_lock_five()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
|
||||
{
|
||||
boost::unit_test::test_suite* test =
|
||||
BOOST_TEST_SUITE("Boost.Threads: generic locks test suite");
|
||||
|
||||
test->add(BOOST_TEST_CASE(&test_lock_two_uncontended));
|
||||
test->add(BOOST_TEST_CASE(&test_lock_two_other_thread_locks_in_order));
|
||||
test->add(BOOST_TEST_CASE(&test_lock_two_other_thread_locks_in_opposite_order));
|
||||
test->add(BOOST_TEST_CASE(&test_lock_five_uncontended));
|
||||
test->add(BOOST_TEST_CASE(&test_lock_five_other_thread_locks_in_order));
|
||||
test->add(BOOST_TEST_CASE(&test_lock_five_other_thread_locks_in_different_order));
|
||||
test->add(BOOST_TEST_CASE(&test_lock_five_in_range));
|
||||
test->add(BOOST_TEST_CASE(&test_lock_five_in_range_custom_iterator));
|
||||
test->add(BOOST_TEST_CASE(&test_lock_ten_in_range_inherited_mutex));
|
||||
test->add(BOOST_TEST_CASE(&test_lock_ten_other_thread_locks_in_different_order));
|
||||
test->add(BOOST_TEST_CASE(&test_try_lock_two_uncontended));
|
||||
test->add(BOOST_TEST_CASE(&test_try_lock_two_first_locked));
|
||||
test->add(BOOST_TEST_CASE(&test_try_lock_two_second_locked));
|
||||
test->add(BOOST_TEST_CASE(&test_try_lock_three));
|
||||
test->add(BOOST_TEST_CASE(&test_try_lock_four));
|
||||
test->add(BOOST_TEST_CASE(&test_try_lock_five));
|
||||
|
||||
return test;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,22 +2,16 @@
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#define BOOST_TEST_MODULE Boost.Threads: hardware_concurrency test suite
|
||||
|
||||
#include <boost/thread/thread_only.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
|
||||
void test_hardware_concurrency_is_non_zero()
|
||||
BOOST_AUTO_TEST_CASE(test_hardware_concurrency_is_non_zero)
|
||||
{
|
||||
BOOST_CHECK(boost::thread::hardware_concurrency()!=0);
|
||||
}
|
||||
|
||||
boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
|
||||
{
|
||||
boost::unit_test::test_suite* test =
|
||||
BOOST_TEST_SUITE("Boost.Threads: hardware concurrency test suite");
|
||||
|
||||
test->add(BOOST_TEST_CASE(test_hardware_concurrency_is_non_zero));
|
||||
return test;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#define BOOST_THREAD_VERSION 2
|
||||
#define BOOST_TEST_MODULE Boost.Threads: lock_concept test suite
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/test/test_case_template.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/lock_types.hpp>
|
||||
@@ -438,22 +440,30 @@ void test_lock_is_scoped_lock_concept_for_mutex()
|
||||
test_unlocked_after_try_lock_if_other_thread_has_lock<Mutex,Lock>()();
|
||||
}
|
||||
|
||||
typedef boost::mpl::vector<boost::mutex,boost::try_mutex,boost::timed_mutex,
|
||||
boost::recursive_mutex,boost::recursive_try_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_lock;
|
||||
|
||||
BOOST_TEST_CASE_TEMPLATE_FUNCTION(test_scoped_lock_concept,Mutex)
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE(test_scoped_lock_concept,Mutex,mutex_types_with_scoped_lock)
|
||||
{
|
||||
typedef typename Mutex::scoped_lock Lock;
|
||||
|
||||
test_lock_is_scoped_lock_concept_for_mutex<Mutex,Lock>();
|
||||
}
|
||||
|
||||
BOOST_TEST_CASE_TEMPLATE_FUNCTION(test_unique_lock_is_scoped_lock,Mutex)
|
||||
typedef boost::mpl::vector<boost::mutex,boost::try_mutex,boost::timed_mutex,
|
||||
boost::recursive_mutex,boost::recursive_try_mutex,boost::recursive_timed_mutex,boost::shared_mutex> all_mutex_types;
|
||||
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE(test_unique_lock_is_scoped_lock,Mutex,all_mutex_types)
|
||||
{
|
||||
typedef boost::unique_lock<Mutex> Lock;
|
||||
|
||||
test_lock_is_scoped_lock_concept_for_mutex<Mutex,Lock>();
|
||||
}
|
||||
|
||||
BOOST_TEST_CASE_TEMPLATE_FUNCTION(test_scoped_try_lock_concept,Mutex)
|
||||
typedef boost::mpl::vector<boost::try_mutex,boost::timed_mutex,
|
||||
boost::recursive_try_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_try_lock;
|
||||
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE(test_scoped_try_lock_concept,Mutex,mutex_types_with_scoped_try_lock)
|
||||
{
|
||||
typedef typename Mutex::scoped_try_lock Lock;
|
||||
|
||||
@@ -534,7 +544,7 @@ struct dummy_shared_mutex
|
||||
};
|
||||
|
||||
|
||||
void test_shared_lock()
|
||||
BOOST_AUTO_TEST_CASE(test_shared_lock)
|
||||
{
|
||||
typedef boost::shared_mutex Mutex;
|
||||
typedef boost::shared_lock<Mutex> Lock;
|
||||
@@ -564,27 +574,27 @@ void test_shared_lock()
|
||||
BOOST_CHECK(dummy.shared_timed_locked_absolute);
|
||||
}
|
||||
|
||||
boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
|
||||
{
|
||||
boost::unit_test::test_suite* test =
|
||||
BOOST_TEST_SUITE("Boost.Threads: lock concept test suite");
|
||||
|
||||
typedef boost::mpl::vector<boost::mutex,boost::try_mutex,boost::timed_mutex,
|
||||
boost::recursive_mutex,boost::recursive_try_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_lock;
|
||||
|
||||
test->add(BOOST_TEST_CASE_TEMPLATE(test_scoped_lock_concept,mutex_types_with_scoped_lock));
|
||||
|
||||
typedef boost::mpl::vector<boost::try_mutex,boost::timed_mutex,
|
||||
boost::recursive_try_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_try_lock;
|
||||
|
||||
test->add(BOOST_TEST_CASE_TEMPLATE(test_scoped_try_lock_concept,mutex_types_with_scoped_try_lock));
|
||||
|
||||
typedef boost::mpl::vector<boost::mutex,boost::try_mutex,boost::timed_mutex,
|
||||
boost::recursive_mutex,boost::recursive_try_mutex,boost::recursive_timed_mutex,boost::shared_mutex> all_mutex_types;
|
||||
|
||||
test->add(BOOST_TEST_CASE_TEMPLATE(test_unique_lock_is_scoped_lock,all_mutex_types));
|
||||
test->add(BOOST_TEST_CASE(&test_shared_lock));
|
||||
|
||||
return test;
|
||||
}
|
||||
//boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
|
||||
//{
|
||||
// boost::unit_test::test_suite* test =
|
||||
// BOOST_TEST_SUITE("Boost.Threads: lock concept test suite");
|
||||
//
|
||||
// typedef boost::mpl::vector<boost::mutex,boost::try_mutex,boost::timed_mutex,
|
||||
// boost::recursive_mutex,boost::recursive_try_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_lock;
|
||||
//
|
||||
// test->add(BOOST_TEST_CASE_TEMPLATE(test_scoped_lock_concept,mutex_types_with_scoped_lock));
|
||||
//
|
||||
// typedef boost::mpl::vector<boost::try_mutex,boost::timed_mutex,
|
||||
// boost::recursive_try_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_try_lock;
|
||||
//
|
||||
// test->add(BOOST_TEST_CASE_TEMPLATE(test_scoped_try_lock_concept,mutex_types_with_scoped_try_lock));
|
||||
//
|
||||
// typedef boost::mpl::vector<boost::mutex,boost::try_mutex,boost::timed_mutex,
|
||||
// boost::recursive_mutex,boost::recursive_try_mutex,boost::recursive_timed_mutex,boost::shared_mutex> all_mutex_types;
|
||||
//
|
||||
// test->add(BOOST_TEST_CASE_TEMPLATE(test_unique_lock_is_scoped_lock,all_mutex_types));
|
||||
// test->add(BOOST_TEST_CASE(&test_shared_lock));
|
||||
//
|
||||
// return test;
|
||||
//}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user