mirror of
https://github.com/boostorg/thread.git
synced 2026-02-03 09:42:16 +00:00
Compare commits
792 Commits
boost-1.54
...
boost-1.57
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5fb51a74fe | ||
|
|
02bb6abef4 | ||
|
|
1a4bd71616 | ||
|
|
63dd439992 | ||
|
|
1029fa9c59 | ||
|
|
3e28ea806c | ||
|
|
07dc40a9ff | ||
|
|
6f91af2154 | ||
|
|
c3cff80557 | ||
|
|
729c8b63bb | ||
|
|
6fe7f44ea0 | ||
|
|
8fd4755e79 | ||
|
|
02b007a20e | ||
|
|
c0c78e87fc | ||
|
|
58cde5af05 | ||
|
|
c1f2c8a1f1 | ||
|
|
bacf5b52ec | ||
|
|
3babf7966e | ||
|
|
f3de7bf10f | ||
|
|
90154217cf | ||
|
|
ac0b2f9ba7 | ||
|
|
da739e680a | ||
|
|
b240b097c7 | ||
|
|
debe2fb0d1 | ||
|
|
b264ec8fc0 | ||
|
|
372f8fe10f | ||
|
|
e3c240df0a | ||
|
|
748ea5164e | ||
|
|
b44627f97d | ||
|
|
c8cd7d1d08 | ||
|
|
f0d0c0551b | ||
|
|
bb72eadbd8 | ||
|
|
f52f32afda | ||
|
|
b973e9b32e | ||
|
|
1ffef9ed2d | ||
|
|
f24ea524bd | ||
|
|
4111471ba5 | ||
|
|
5e970b987e | ||
|
|
c7b5729cf3 | ||
|
|
291ebded8e | ||
|
|
0c2c8ed3b8 | ||
|
|
5294dfa149 | ||
|
|
7f5dfb633d | ||
|
|
f381a7d591 | ||
|
|
aceabda609 | ||
|
|
dc4b619b57 | ||
|
|
abb3fc97e0 | ||
|
|
ec6ae7b9b4 | ||
|
|
8c5ba97d39 | ||
|
|
617b979214 | ||
|
|
96667cfcce | ||
|
|
a981650ce9 | ||
|
|
00b25853b2 | ||
|
|
ef04ce8bce | ||
|
|
5091ad705f | ||
|
|
b77f802c47 | ||
|
|
da945436c1 | ||
|
|
27befdf26f | ||
|
|
f73007910a | ||
|
|
8c3cfacf06 | ||
|
|
7d4392e157 | ||
|
|
aff3f424a9 | ||
|
|
546ca909c4 | ||
|
|
7dac51706c | ||
|
|
5ee0e27b5a | ||
|
|
b4fd7fdeb1 | ||
|
|
c75ea7db89 | ||
|
|
19294dc756 | ||
|
|
52a360775e | ||
|
|
c632b75db1 | ||
|
|
11e4c950ac | ||
|
|
8440e9a7d8 | ||
|
|
02bc292c20 | ||
|
|
6d68bac44b | ||
|
|
5d0d128cab | ||
|
|
ec542d3c8b | ||
|
|
6e3216643b | ||
|
|
016f5653cf | ||
|
|
ce46539183 | ||
|
|
e93035ce42 | ||
|
|
53a46593a8 | ||
|
|
c2426b8fad | ||
|
|
7d841f6337 | ||
|
|
556bbde8a7 | ||
|
|
a0c1462a6a | ||
|
|
234df13faf | ||
|
|
24983f0bce | ||
|
|
722997379b | ||
|
|
f36f5d6dbb | ||
|
|
9ee1044f92 | ||
|
|
ebeb36646c | ||
|
|
8ebf0e7f21 | ||
|
|
0dc2f69bc1 | ||
|
|
c3b549d947 | ||
|
|
6552cf64b5 | ||
|
|
d5f335b8a4 | ||
|
|
80591fb64d | ||
|
|
0543b522cb | ||
|
|
3dbc5d0664 | ||
|
|
2d0272345b | ||
|
|
f1a274b51c | ||
|
|
b7f1706ab8 | ||
|
|
f299fb8083 | ||
|
|
074dcbcbf5 | ||
|
|
af6f80a3c7 | ||
|
|
957253401f | ||
|
|
3195253230 | ||
|
|
4336a7bbe3 | ||
|
|
3b75d6dabc | ||
|
|
fc0d7e23b3 | ||
|
|
aeabda8d45 | ||
|
|
3bde7e103c | ||
|
|
ea0889485e | ||
|
|
d4d46c64dd | ||
|
|
f3fa80c866 | ||
|
|
7e21f24991 | ||
|
|
2037a64c51 | ||
|
|
8bfd1cea31 | ||
|
|
a26e7eb8c4 | ||
|
|
e47eba8751 | ||
|
|
8aef8000d9 | ||
|
|
0b2a61bca0 | ||
|
|
78f1044c68 | ||
|
|
26042ca26a | ||
|
|
74132067ba | ||
|
|
c4d42e6b6c | ||
|
|
59c504d5d8 | ||
|
|
b81a838a43 | ||
|
|
c6e70226ea | ||
|
|
5cdd807718 | ||
|
|
2a6948d74d | ||
|
|
a06dde3794 | ||
|
|
726a3faf19 | ||
|
|
590a3d99b0 | ||
|
|
c977c8d420 | ||
|
|
a1faacd7bb | ||
|
|
866b78cbd0 | ||
|
|
0861f81b05 | ||
|
|
6488028a22 | ||
|
|
14dfe49c50 | ||
|
|
08c4599fb6 | ||
|
|
ca14e6187d | ||
|
|
f263c6014e | ||
|
|
9e962e12e2 | ||
|
|
6e154d45a4 | ||
|
|
c54e519f72 | ||
|
|
5c61dced5e | ||
|
|
8a7f927be9 | ||
|
|
6074487b73 | ||
|
|
04c53415fd | ||
|
|
fe6daec2bc | ||
|
|
f75b2ca155 | ||
|
|
68be44ec06 | ||
|
|
817591b87c | ||
|
|
d7a3f124db | ||
|
|
c6817aeb1c | ||
|
|
9ceea9822f | ||
|
|
c266790b8d | ||
|
|
00ad9dddb9 | ||
|
|
21617e1acb | ||
|
|
99ac322223 | ||
|
|
414fce4580 | ||
|
|
fe195e776b | ||
|
|
8a6d3d68ce | ||
|
|
3a5c926930 | ||
|
|
685ee1506a | ||
|
|
2062cebb54 | ||
|
|
126030eb8c | ||
|
|
ac1b9653f3 | ||
|
|
54ee07e745 | ||
|
|
ca298c2c86 | ||
|
|
4def87448e | ||
|
|
5719ea9e9f | ||
|
|
6583d87c92 | ||
|
|
fcf7a1811e | ||
|
|
d8f628ae65 | ||
|
|
0bd10b7244 | ||
|
|
24635c588f | ||
|
|
4f8106c00e | ||
|
|
3c4f1ea365 | ||
|
|
b5a50ab443 | ||
|
|
cb8a4a27bb | ||
|
|
8c0640e5be | ||
|
|
f807a678e0 | ||
|
|
49a1779d7f | ||
|
|
d3d2ad2390 | ||
|
|
abf844f50e | ||
|
|
4d52ef0740 | ||
|
|
40620e3d4b | ||
|
|
c3ab21a7ba | ||
|
|
c3002edc54 | ||
|
|
100bb706d6 | ||
|
|
de6a4df3a8 | ||
|
|
9669830a86 | ||
|
|
2937171413 | ||
|
|
dd0bfdd7ce | ||
|
|
89e340b177 | ||
|
|
c744899e45 | ||
|
|
0a4af0c5ed | ||
|
|
e6eb24d4a9 | ||
|
|
0d10e282fa | ||
|
|
e8181da6d4 | ||
|
|
68dc454a66 | ||
|
|
0e0ee99c61 | ||
|
|
f747d79c5b | ||
|
|
73fbc520e8 | ||
|
|
7d4f485ade | ||
|
|
143adde27d | ||
|
|
a7400061c6 | ||
|
|
d2a65d2427 | ||
|
|
82379f83a8 | ||
|
|
cc29295986 | ||
|
|
9d1c957625 | ||
|
|
1dbf7028fe | ||
|
|
0bba5e630e | ||
|
|
84c30313a2 | ||
|
|
54646e9959 | ||
|
|
3f5823f50a | ||
|
|
e1636bdbd5 | ||
|
|
750c849b0f | ||
|
|
0a05db8399 | ||
|
|
1d7da085ea | ||
|
|
75236fe3ae | ||
|
|
80634ee51e | ||
|
|
b1ac899f23 | ||
|
|
aa37de7aad | ||
|
|
9d527bebe0 | ||
|
|
f7c18c55bb | ||
|
|
1a2197c7f9 | ||
|
|
4a54ac0331 | ||
|
|
c6593d87b0 | ||
|
|
51e49c69b5 | ||
|
|
ab2a180de5 | ||
|
|
3772a8294b | ||
|
|
155ccfffbe | ||
|
|
bfa0ccee88 | ||
|
|
980772d514 | ||
|
|
94b27db991 | ||
|
|
0a58445b63 | ||
|
|
f02e25e4e7 | ||
|
|
acb117b5a9 | ||
|
|
8682f7cb48 | ||
|
|
4503c0e1da | ||
|
|
dc3397c452 | ||
|
|
af7fde5eae | ||
|
|
36bc3c0523 | ||
|
|
0218cb90b3 | ||
|
|
f4d4c16294 | ||
|
|
85d22a8d93 | ||
|
|
7eb67443dd | ||
|
|
4308e0ec24 | ||
|
|
ac9497dec9 | ||
|
|
8fec35f444 | ||
|
|
7b3fa08503 | ||
|
|
a2e1e80343 | ||
|
|
690feeb9ba | ||
|
|
5d76ab52e7 | ||
|
|
cb845f19e4 | ||
|
|
2886e985b4 | ||
|
|
f4d0ecbab5 | ||
|
|
d187732946 | ||
|
|
1fc78c7ceb | ||
|
|
5c18d92a5f | ||
|
|
06325961ef | ||
|
|
10b283e03a | ||
|
|
6ab71dc057 | ||
|
|
47be5228b1 | ||
|
|
6c5a6e4330 | ||
|
|
326842cc7f | ||
|
|
9f592860cd | ||
|
|
4148842426 | ||
|
|
7edae6614b | ||
|
|
2554065a91 | ||
|
|
74bb7d6b29 | ||
|
|
fbfda71555 | ||
|
|
f3a66f76e0 | ||
|
|
19346e1817 | ||
|
|
5753026ceb | ||
|
|
f6edd7cace | ||
|
|
126ed2428b | ||
|
|
fd631e2794 | ||
|
|
44f9a2f4ad | ||
|
|
8665c5d510 | ||
|
|
e1d6baddd6 | ||
|
|
9287a29c9d | ||
|
|
5c0cecaaf8 | ||
|
|
713f5a449c | ||
|
|
b336427571 | ||
|
|
2a16b649ad | ||
|
|
3723cedcab | ||
|
|
3ad582222c | ||
|
|
c9a33b8668 | ||
|
|
88880770d3 | ||
|
|
9138a2ae92 | ||
|
|
d558de7811 | ||
|
|
19290fddf9 | ||
|
|
2ac967d1dc | ||
|
|
6e81db4172 | ||
|
|
3a68a63478 | ||
|
|
7875edd234 | ||
|
|
2be0b4f8fd | ||
|
|
67528fc9af | ||
|
|
4da1e9dca1 | ||
|
|
d8c9be3449 | ||
|
|
f02390a804 | ||
|
|
955b207c05 | ||
|
|
c17f5d3fc7 | ||
|
|
8685c32d18 | ||
|
|
f51e8c812a | ||
|
|
51aff0fb00 | ||
|
|
bfe7af29bc | ||
|
|
4681104b33 | ||
|
|
d602f44af6 | ||
|
|
dc55945760 | ||
|
|
f7f0347780 | ||
|
|
d6c4be0cd0 | ||
|
|
e146febd70 | ||
|
|
67ca45ed83 | ||
|
|
cad6f2b9a6 | ||
|
|
7756df2ce0 | ||
|
|
ae831efe08 | ||
|
|
fc65611e82 | ||
|
|
8c6dcb9709 | ||
|
|
67afa35c49 | ||
|
|
63d9ae2b29 | ||
|
|
08aa0d2fb6 | ||
|
|
3c8334f8c4 | ||
|
|
0e2c8ed9e3 | ||
|
|
5bfa7cff41 | ||
|
|
e3a1498355 | ||
|
|
6fab117c17 | ||
|
|
4a63d4992c | ||
|
|
04e3d918fb | ||
|
|
0073516f0a | ||
|
|
89de3dcf4f | ||
|
|
47f40f991f | ||
|
|
8b351fe473 | ||
|
|
2da4e8c29e | ||
|
|
8dce737911 | ||
|
|
24f1e620e8 | ||
|
|
ed6459ecd2 | ||
|
|
3a7f0b1e78 | ||
|
|
8f06153f46 | ||
|
|
858816b2d2 | ||
|
|
4bc70444a4 | ||
|
|
fcc027369f | ||
|
|
5c78582794 | ||
|
|
7f479a1dec | ||
|
|
4f2a7b2256 | ||
|
|
5c88e6ce61 | ||
|
|
650e374492 | ||
|
|
6319080ef2 | ||
|
|
3ac48bdd65 | ||
|
|
c3c8ada97d | ||
|
|
325d8cf5ca | ||
|
|
134c323958 | ||
|
|
fd5dd0c2ed | ||
|
|
4a83aa58ed | ||
|
|
7d96aa625c | ||
|
|
5520763a73 | ||
|
|
ad010e0647 | ||
|
|
d57a4c6565 | ||
|
|
73f5c060ca | ||
|
|
c67e39f126 | ||
|
|
5a3c301582 | ||
|
|
dc5a8a9c4e | ||
|
|
1e49343ff4 | ||
|
|
93d1855e64 | ||
|
|
a39dd7e8b3 | ||
|
|
7e5cb92bab | ||
|
|
62cf0f86f6 | ||
|
|
c12e07754a | ||
|
|
cbc4266774 | ||
|
|
3a038d33e5 | ||
|
|
51ba4be998 | ||
|
|
2d50af8481 | ||
|
|
3fb971386a | ||
|
|
e438c98070 | ||
|
|
1e2a76de47 | ||
|
|
34311a60fa | ||
|
|
794d54a65c | ||
|
|
d759dd2dba | ||
|
|
fe46155997 | ||
|
|
cacb5b19a6 | ||
|
|
30803a38b2 | ||
|
|
9fc6fec1eb | ||
|
|
29babb974e | ||
|
|
66578bf57b | ||
|
|
1da5f9563c | ||
|
|
52039f75a3 | ||
|
|
bb6fcc3b5c | ||
|
|
1fc1d8aedb | ||
|
|
042a86c984 | ||
|
|
364f3ea030 | ||
|
|
c87d27a06d | ||
|
|
68d7c69a4b | ||
|
|
6873d85650 | ||
|
|
b59e57e4cc | ||
|
|
d0f9d6216a | ||
|
|
28564064ff | ||
|
|
ff9636b8e0 | ||
|
|
d83d23bee0 | ||
|
|
63f35e9f52 | ||
|
|
5ad38d52e8 | ||
|
|
9d6cd40d8d | ||
|
|
4362cd655e | ||
|
|
0c44630029 | ||
|
|
a01af79331 | ||
|
|
2df6ce78a4 | ||
|
|
3951871d70 | ||
|
|
5a1a9df623 | ||
|
|
a6f67e25e3 | ||
|
|
b69ec54695 | ||
|
|
465aee1b66 | ||
|
|
14d3c59682 | ||
|
|
3f2d8f8865 | ||
|
|
dc8449bd0e | ||
|
|
d3a6277714 | ||
|
|
81d8944b96 | ||
|
|
54faaaf087 | ||
|
|
5a43d5ffe9 | ||
|
|
c628e51e6c | ||
|
|
a66b269198 | ||
|
|
9e07202e21 | ||
|
|
9e2a34ca9d | ||
|
|
4cf80c6685 | ||
|
|
455c31c0e9 | ||
|
|
a8d5fd48c1 | ||
|
|
294a5404c2 | ||
|
|
6d01267030 | ||
|
|
1c48d237a8 | ||
|
|
11ae5c8c44 | ||
|
|
9d10bd035a | ||
|
|
7b48c02d2f | ||
|
|
d8a9331464 | ||
|
|
b60968b045 | ||
|
|
da41bdb632 | ||
|
|
5fcfd0e4e8 | ||
|
|
2d2d1112d6 | ||
|
|
7cf6934515 | ||
|
|
757327ba10 | ||
|
|
a82843d3ab | ||
|
|
5779f6676d | ||
|
|
b359424858 | ||
|
|
a5f7d92960 | ||
|
|
83167d8c15 | ||
|
|
7d2270f8c8 | ||
|
|
f87dbb83b1 | ||
|
|
1a613d03a9 | ||
|
|
d42f4ff169 | ||
|
|
ffbcf96d90 | ||
|
|
f5e246ebb0 | ||
|
|
467a88c4f8 | ||
|
|
f021bad1d5 | ||
|
|
ecd97ec4ea | ||
|
|
c71882816c | ||
|
|
ef5d43fac9 | ||
|
|
fb5404947e | ||
|
|
f24086fe89 | ||
|
|
3e64214e68 | ||
|
|
ed4f0f7b6d | ||
|
|
50c18d6274 | ||
|
|
d5cf734a21 | ||
|
|
43f0c059d3 | ||
|
|
e775ef5c27 | ||
|
|
06b7a41add | ||
|
|
06d2a11127 | ||
|
|
6dd195bbc6 | ||
|
|
8a259612cd | ||
|
|
9fb88b8f47 | ||
|
|
528fcbde56 | ||
|
|
a0397315b2 | ||
|
|
44ec248340 | ||
|
|
7eba48576c | ||
|
|
451027deec | ||
|
|
16b42b6c63 | ||
|
|
a543b918f0 | ||
|
|
619ddf54b9 | ||
|
|
116c947af9 | ||
|
|
a0931c117d | ||
|
|
79e1e88f2e | ||
|
|
af3b5f3227 | ||
|
|
7bebf0a062 | ||
|
|
6dad044ab7 | ||
|
|
19bd0d5eba | ||
|
|
f922fa56e4 | ||
|
|
290faf192d | ||
|
|
054bbad65a | ||
|
|
df7fbe085a | ||
|
|
b03cebff7b | ||
|
|
c9c46e87b5 | ||
|
|
d4e6332eca | ||
|
|
80594adcbb | ||
|
|
4ea14fb9da | ||
|
|
5a22af7639 | ||
|
|
7b157ab5f4 | ||
|
|
a73425eb00 | ||
|
|
b254afc229 | ||
|
|
a1edda3437 | ||
|
|
c784369f76 | ||
|
|
0b7462c4f2 | ||
|
|
23ff6e0120 | ||
|
|
06491889ea | ||
|
|
abf441ee63 | ||
|
|
9615a51123 | ||
|
|
a0bfa7faeb | ||
|
|
44b741e445 | ||
|
|
41d336e7fb | ||
|
|
fc177914e1 | ||
|
|
d0056e0cc8 | ||
|
|
6075cf2df6 | ||
|
|
1eacb8c71d | ||
|
|
7476f71af6 | ||
|
|
d86b5d2c0d | ||
|
|
09f86d603e | ||
|
|
ca3d7dab0b | ||
|
|
7e35a60650 | ||
|
|
2b5bd7275e | ||
|
|
ca37d07184 | ||
|
|
6f2efbcb32 | ||
|
|
1ce6a90f95 | ||
|
|
0a101e15d1 | ||
|
|
d2f7766f8a | ||
|
|
ba7a0935f2 | ||
|
|
7277a94411 | ||
|
|
197bbc1fd3 | ||
|
|
b9e2d7b13d | ||
|
|
579501d98e | ||
|
|
dc352450ca | ||
|
|
21b2bbc8ca | ||
|
|
bd9105a104 | ||
|
|
935d851cdf | ||
|
|
68142e8ff8 | ||
|
|
1dad495280 | ||
|
|
fb2310b48a | ||
|
|
247e9a4f09 | ||
|
|
c1ec1ada0e | ||
|
|
d030dbd61c | ||
|
|
bebd56ee21 | ||
|
|
75586eec0e | ||
|
|
659343d287 | ||
|
|
8e63c72867 | ||
|
|
65416bb8b6 | ||
|
|
71a647b66b | ||
|
|
fc57e9dde0 | ||
|
|
4acfe0975c | ||
|
|
158e8ead50 | ||
|
|
0fc69c4d9e | ||
|
|
e314bf03ce | ||
|
|
6f2decdacf | ||
|
|
4bd3e09a0d | ||
|
|
a16f508b8a | ||
|
|
1642db3441 | ||
|
|
b389079417 | ||
|
|
8f7be637b2 | ||
|
|
94c15aa0cc | ||
|
|
951c8952ff | ||
|
|
59f91a2405 | ||
|
|
f4a3d52654 | ||
|
|
517e177d7a | ||
|
|
e72184e9ee | ||
|
|
73348d69d2 | ||
|
|
15eff9e412 | ||
|
|
dd70cd5b40 | ||
|
|
b290f995d0 | ||
|
|
c1dd0e1e43 | ||
|
|
44a02c1f5f | ||
|
|
a0071b301b | ||
|
|
c77281f724 | ||
|
|
8a0578c93c | ||
|
|
c7dcb1daae | ||
|
|
af330fb61b | ||
|
|
ab64afa2a7 | ||
|
|
85792f9946 | ||
|
|
e0d4e63e48 | ||
|
|
b2bd9f4ca9 | ||
|
|
189356680b | ||
|
|
0e0cd2c950 | ||
|
|
a849a41367 | ||
|
|
4b1c13e5cb | ||
|
|
f3777b9306 | ||
|
|
3e5e12e1ac | ||
|
|
a50176c259 | ||
|
|
94e524a1e6 | ||
|
|
cb3259b23f | ||
|
|
ec811d3c4a | ||
|
|
bf67321336 | ||
|
|
4b71ef9354 | ||
|
|
23bf16a638 | ||
|
|
c3ada352f4 | ||
|
|
610bdc4aca | ||
|
|
6675f4645f | ||
|
|
2895bfe269 | ||
|
|
27e2d632cd | ||
|
|
abdaa7b5b3 | ||
|
|
e0ed1d6d61 | ||
|
|
f8b1287153 | ||
|
|
5ed50d68f2 | ||
|
|
2f0a6c01c2 | ||
|
|
c8edd6c795 | ||
|
|
2b8930a5bf | ||
|
|
7c89563108 | ||
|
|
fcb94bcecf | ||
|
|
593e9e0f2f | ||
|
|
4209dfaa7f | ||
|
|
0fac7be5b9 | ||
|
|
0936913bf6 | ||
|
|
03ebc320f1 | ||
|
|
ea11670593 | ||
|
|
607080857b | ||
|
|
6728fdb3b1 | ||
|
|
580c1b7be4 | ||
|
|
03a43d09a4 | ||
|
|
7f043d7b07 | ||
|
|
77a8c6667f | ||
|
|
418a3f6978 | ||
|
|
6b300d2e4c | ||
|
|
50ae9d93a6 | ||
|
|
168ee37d30 | ||
|
|
81528d64d5 | ||
|
|
e6b8a133a8 | ||
|
|
047ca43b72 | ||
|
|
3c6509184a | ||
|
|
ec1ce4cf98 | ||
|
|
526478338d | ||
|
|
f49e6e8dc3 | ||
|
|
186d58eef7 | ||
|
|
d2bbc1b7c1 | ||
|
|
2a503b5c81 | ||
|
|
a25b918a67 | ||
|
|
821376f552 | ||
|
|
4387de4be8 | ||
|
|
0663b30528 | ||
|
|
37b0eb2c48 | ||
|
|
de0272abcf | ||
|
|
cfc3634108 | ||
|
|
1c62b1599d | ||
|
|
1d2ec17d52 | ||
|
|
0d9e8a0c3c | ||
|
|
9b28bb59c9 | ||
|
|
0fce559711 | ||
|
|
de191d213e | ||
|
|
ae89c307bf | ||
|
|
0dba7ba99b | ||
|
|
1b67c83359 | ||
|
|
d28465b656 | ||
|
|
bb3493bdf0 | ||
|
|
0cd8326f21 | ||
|
|
5c5c818bc5 | ||
|
|
124b99b2a4 | ||
|
|
1cabac151a | ||
|
|
df48b734a2 | ||
|
|
039d744960 | ||
|
|
004e8a4fcf | ||
|
|
d8f8acbe38 | ||
|
|
8a01f9ee09 | ||
|
|
315af061cd | ||
|
|
18491c933d | ||
|
|
d01c0232da | ||
|
|
91e32e3f02 | ||
|
|
88294f4161 | ||
|
|
9cdc23159a | ||
|
|
c95f1d95af | ||
|
|
45c87d392f | ||
|
|
1c0a4999b8 | ||
|
|
30bfc7bcea | ||
|
|
48f8c1c1c8 | ||
|
|
c47ea136b6 | ||
|
|
a3d30b2a89 | ||
|
|
11e15ff0f2 | ||
|
|
fb4b4fb14a | ||
|
|
0ede82e059 | ||
|
|
708b660c0b | ||
|
|
9f27bba490 | ||
|
|
095da2890e | ||
|
|
389d76cbc1 | ||
|
|
493cbc030c | ||
|
|
2f7b936cd6 | ||
|
|
6f3ee1eebf | ||
|
|
32f7b212bd | ||
|
|
4fcdabca90 | ||
|
|
b03de37155 | ||
|
|
73af713503 | ||
|
|
a903532cef | ||
|
|
d6178b3139 | ||
|
|
ec1241a6d8 | ||
|
|
ae819901ab | ||
|
|
3c0294cf3a | ||
|
|
21bc767445 | ||
|
|
47b6368ef7 | ||
|
|
a3098b5dfd | ||
|
|
bd69c9382f | ||
|
|
b47f43df59 | ||
|
|
e9217d02f0 | ||
|
|
6741c8420a | ||
|
|
fe45847841 | ||
|
|
5d13b87dd3 | ||
|
|
e1f5fbdc33 | ||
|
|
b342cf683b | ||
|
|
e94946cc8c | ||
|
|
8604ca1b85 | ||
|
|
9847f57ce7 | ||
|
|
74e2c4cbcb | ||
|
|
7b54159af3 | ||
|
|
16ad9c868e | ||
|
|
26f4ad3db2 | ||
|
|
715928e143 | ||
|
|
40d694e893 | ||
|
|
4d84fb97c9 | ||
|
|
ab7bb7a82d | ||
|
|
171be40a1f | ||
|
|
18d4a8a0f8 | ||
|
|
dedaa7e617 | ||
|
|
6173ae42a9 | ||
|
|
792604127e | ||
|
|
81d0aaf7bc | ||
|
|
26c495e5b3 | ||
|
|
a1f8717170 | ||
|
|
460a38b994 | ||
|
|
dbefae706c | ||
|
|
a33e82af60 | ||
|
|
8f283b3c2b | ||
|
|
b1ae3a98e8 | ||
|
|
fcaaa68f87 | ||
|
|
b7622b7407 | ||
|
|
a56358c8f8 | ||
|
|
dafe4bea1a | ||
|
|
408a6cb70e | ||
|
|
97c0ddbee4 | ||
|
|
330502ea1e | ||
|
|
662118b5c6 | ||
|
|
8bee2291fd | ||
|
|
39c4db3e66 | ||
|
|
749b1034f9 | ||
|
|
735102d4a0 | ||
|
|
5e30d7486e | ||
|
|
71f864bc5c | ||
|
|
b31c1a11d5 | ||
|
|
bf03f733a6 | ||
|
|
ca04d699bc | ||
|
|
530aaaae38 | ||
|
|
36970f3240 | ||
|
|
7c97dc8131 | ||
|
|
a7336c2c5e | ||
|
|
8866935d0b | ||
|
|
4f06c2392b | ||
|
|
677113cfbe | ||
|
|
a01faf1bb8 | ||
|
|
050b43757f | ||
|
|
448c4b21b5 | ||
|
|
84d8dea5ba | ||
|
|
5fa5b680f0 | ||
|
|
5b26427079 | ||
|
|
d426d2ca88 | ||
|
|
2e5bc32b33 | ||
|
|
b0b975e8ef | ||
|
|
1f4df63577 | ||
|
|
cf7c218a65 | ||
|
|
1a1751b45d | ||
|
|
0354c2fcc3 | ||
|
|
1679cd2fff | ||
|
|
32db9f2e71 | ||
|
|
6b98bee683 | ||
|
|
7de77cf13c | ||
|
|
8334f4e68a | ||
|
|
1ac7e7129d | ||
|
|
daec1268f9 | ||
|
|
c47bd34760 | ||
|
|
0d9ebfc820 | ||
|
|
3332d8df66 | ||
|
|
852c173c96 | ||
|
|
bcf30f2dfc | ||
|
|
2ea1aec7fd | ||
|
|
dc5a26c5d3 | ||
|
|
3c8f164371 | ||
|
|
93c14be188 | ||
|
|
b305cc29fc | ||
|
|
c2001fb9d2 | ||
|
|
d3a8321be0 | ||
|
|
8bfd588b4c | ||
|
|
5268fd3749 | ||
|
|
19bbd85d9d | ||
|
|
deca987299 | ||
|
|
1a4eed3b69 | ||
|
|
1214f99227 | ||
|
|
51530e03a5 | ||
|
|
66263dd7b3 | ||
|
|
6b0ce64d5e | ||
|
|
3b080058ed | ||
|
|
00996a2a02 | ||
|
|
c0299f4a1e | ||
|
|
e09105de98 |
40
.gitignore
vendored
Normal file
40
.gitignore
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
#mac
|
||||
.DS_Store
|
||||
|
||||
#projects
|
||||
.project
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
bin/*
|
||||
test/bin/*
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
#doc
|
||||
|
||||
doc/html
|
||||
8
README.md
Normal file
8
README.md
Normal file
@@ -0,0 +1,8 @@
|
||||
thread
|
||||
======
|
||||
|
||||
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).
|
||||
@@ -36,6 +36,7 @@ import os ;
|
||||
import feature ;
|
||||
import indirect ;
|
||||
import path ;
|
||||
import configure ;
|
||||
|
||||
project boost/thread
|
||||
: source-location ../src
|
||||
@@ -77,19 +78,19 @@ project boost/thread
|
||||
<toolset>pathscale:<cxxflags>-pedantic
|
||||
|
||||
<toolset>clang:<cxxflags>-Wextra
|
||||
<toolset>clang:<cxxflags>-pedantic
|
||||
#<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>gcc-mingw-4.4.0:<cxxflags>-fdiagnostics-show-option
|
||||
<toolset>gcc-mingw-4.5.0:<cxxflags>-fdiagnostics-show-option
|
||||
<toolset>gcc-mingw-4.6.0:<cxxflags>-fdiagnostics-show-option
|
||||
<toolset>gcc-mingw-4.6.3:<cxxflags>-fdiagnostics-show-option
|
||||
<toolset>gcc-mingw-4.7.0:<cxxflags>-fdiagnostics-show-option
|
||||
<toolset>gcc-mingw-4.8.0:<cxxflags>-fdiagnostics-show-option
|
||||
#<toolset>gcc-mingw-4.4.0:<cxxflags>-fdiagnostics-show-option
|
||||
#<toolset>gcc-mingw-4.5.0:<cxxflags>-fdiagnostics-show-option
|
||||
#<toolset>gcc-mingw-4.6.0:<cxxflags>-fdiagnostics-show-option
|
||||
#<toolset>gcc-mingw-4.6.3:<cxxflags>-fdiagnostics-show-option
|
||||
#<toolset>gcc-mingw-4.7.0:<cxxflags>-fdiagnostics-show-option
|
||||
#<toolset>gcc-mingw-4.8.0:<cxxflags>-fdiagnostics-show-option
|
||||
#<toolset>gcc:<cxxflags>-Wno-missing-field-initializers
|
||||
|
||||
<toolset>darwin-4.6.2:<cxxflags>-Wno-delete-non-virtual-dtor
|
||||
@@ -140,6 +141,8 @@ local rule default_threadapi ( )
|
||||
feature.feature threadapi : pthread win32 : propagated ;
|
||||
feature.set-default threadapi : [ default_threadapi ] ;
|
||||
|
||||
exe has_atomic_flag_lockfree : ../build/has_atomic_flag_lockfree_test.cpp ;
|
||||
|
||||
rule tag ( name : type ? : property-set )
|
||||
{
|
||||
local result = $(name) ;
|
||||
@@ -236,10 +239,10 @@ rule usage-requirements ( properties * )
|
||||
}
|
||||
}
|
||||
|
||||
if ! <toolset>vacpp in $(properties) || <toolset-vacpp:version>11.1 in $(properties) || <toolset-vacpp:version>12.1.0.1 in $(properties) || <toolset-vacpp:version>12.1 in $(properties)
|
||||
{
|
||||
#if ! <toolset>vacpp in $(properties) || <toolset-vacpp:version>11.1 in $(properties) || <toolset-vacpp:version>12.1.0.1 in $(properties) || <toolset-vacpp:version>12.1 in $(properties)
|
||||
#{
|
||||
result += <library>/boost/chrono//boost_chrono ;
|
||||
}
|
||||
#}
|
||||
|
||||
return $(result) ;
|
||||
}
|
||||
@@ -264,16 +267,15 @@ rule requirements ( properties * )
|
||||
}
|
||||
}
|
||||
result += <define>BOOST_THREAD_DONT_USE_CHRONO ;
|
||||
if ! [ configure.builds has_atomic_flag_lockfree
|
||||
: $(properties) : "lockfree boost::atomic_flag" ] {
|
||||
result += <library>/boost/atomic//boost_atomic ;
|
||||
}
|
||||
} else {
|
||||
result += <define>BOOST_THREAD_USES_CHRONO ;
|
||||
result += <library>/boost/chrono//boost_chrono ;
|
||||
}
|
||||
|
||||
if <toolset>pgi in $(properties) || <toolset>vacpp in $(properties)
|
||||
{
|
||||
result += <library>/boost/atomic//boost_atomic ;
|
||||
}
|
||||
|
||||
return $(result) ;
|
||||
}
|
||||
|
||||
|
||||
13
build/has_atomic_flag_lockfree_test.cpp
Normal file
13
build/has_atomic_flag_lockfree_test.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
// Copyright (c) 2013, Petr Machata, Red Hat Inc.
|
||||
//
|
||||
// Use modification and distribution are subject to the boost Software
|
||||
// License, Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt).
|
||||
|
||||
#include "../../../boost/atomic.hpp"
|
||||
#include "../../../boost/static_assert.hpp"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
BOOST_STATIC_ASSERT(BOOST_ATOMIC_FLAG_LOCK_FREE);
|
||||
return 0;
|
||||
}
|
||||
1006
doc/async_executors.qbk
Normal file
1006
doc/async_executors.qbk
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,12 @@
|
||||
[/
|
||||
(C) Copyright 2007-8 Anthony Williams.
|
||||
(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).
|
||||
]
|
||||
|
||||
[section:barriers Barriers]
|
||||
[section:barriers Barriers -- EXTENSION]
|
||||
|
||||
A barrier is a simple concept. Also known as a ['rendezvous], it is a synchronization point between multiple threads. The barrier is
|
||||
configured for a particular number of threads (`n`), and as threads reach the barrier they must wait until all `n` threads have
|
||||
@@ -22,14 +23,18 @@ arrived. Once the `n`-th thread has reached the barrier, all the waiting threads
|
||||
barrier& operator=(barrier const&) = delete;
|
||||
|
||||
barrier(unsigned int count);
|
||||
template <typename F>
|
||||
barrier(unsigned int count, F&&);
|
||||
|
||||
~barrier();
|
||||
|
||||
bool wait();
|
||||
void count_down_and_wait();
|
||||
};
|
||||
|
||||
Instances of __barrier__ are not copyable or movable.
|
||||
|
||||
[heading Constructor]
|
||||
[section Constructor `barrier(unsigned int)`]
|
||||
|
||||
barrier(unsigned int count);
|
||||
|
||||
@@ -41,7 +46,24 @@ Instances of __barrier__ are not copyable or movable.
|
||||
|
||||
]
|
||||
|
||||
[heading Destructor]
|
||||
[endsect]
|
||||
[section Constructor `barrier(unsigned int, F&&)`]
|
||||
|
||||
barrier(unsigned int count, F&& completion);
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Requires:] [The result type of the completion function call `completion()` is `void` or `unsigned int`.]]
|
||||
|
||||
[[Effects:] [Construct a barrier for `count` threads and a completion function `completion`.]]
|
||||
|
||||
[[Throws:] [__thread_resource_error__ if an error occurs.]]
|
||||
|
||||
]
|
||||
|
||||
|
||||
[endsect]
|
||||
[section Destructor `~barrier()`]
|
||||
|
||||
~barrier();
|
||||
|
||||
@@ -55,24 +77,55 @@ Instances of __barrier__ are not copyable or movable.
|
||||
|
||||
]
|
||||
|
||||
[heading Member function `wait`]
|
||||
[endsect]
|
||||
[section Member Function `wait()`]
|
||||
|
||||
bool wait();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Block until `count` threads have called `wait` on `*this`. When the `count`-th thread calls `wait`, all waiting threads
|
||||
are unblocked, and the barrier is reset. ]]
|
||||
[[Effects:] [Block until `count` threads have called `wait` or `count_down_and_wait` on `*this`. When the `count`-th thread calls `wait`, the barrier is reset and all waiting threads are unblocked.
|
||||
The reset depends on whether the barrier was constructed with a completion function or not. If there is no completion function or if the completion function result is void, the reset consists in restoring the original count. Otherwise the rest consist in assigning the result of the completion function (which must not be 0).]]
|
||||
|
||||
[[Returns:] [`true` for exactly one thread from each batch of waiting threads, `false` otherwise.]]
|
||||
|
||||
[[Throws:] [__thread_resource_error__ if an error occurs. __thread_interrupted__ if the wait was interrupted by a call to
|
||||
__interrupt__ on the __thread__ object associated with the current thread of execution.]]
|
||||
[[Throws:] [
|
||||
|
||||
- __thread_resource_error__ if an error occurs.
|
||||
|
||||
- __thread_interrupted__ if the wait was interrupted by a call to
|
||||
__interrupt__ on the __thread__ object associated with the current thread of execution.
|
||||
|
||||
]]
|
||||
|
||||
[[Notes:] [`wait()` is an ['interruption point].]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[section Member Function `count_down_and_wait()`]
|
||||
|
||||
void count_down_and_wait();
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Block until `count` threads have called `wait` or `count_down_and_wait` on `*this`. When the `count`-th thread calls `wait`, the barrier is reset and all waiting threads are unblocked.
|
||||
The reset depends on whether the barrier was constructed with a completion function or not. If there is no completion function or if the completion function result is void, the reset consists in restoring the original count. Otherwise the rest consist in assigning the result of the completion function (which must not be 0).]]
|
||||
|
||||
[[Throws:] [
|
||||
|
||||
- __thread_resource_error__ if an error occurs.
|
||||
|
||||
- __thread_interrupted__ if the wait was interrupted by a call to
|
||||
__interrupt__ on the __thread__ object associated with the current thread of execution.
|
||||
|
||||
]]
|
||||
|
||||
[[Notes:] [`count_down_and_wait()` is an ['interruption point].]]
|
||||
|
||||
]
|
||||
|
||||
|
||||
[endsect]
|
||||
[endsect]
|
||||
[endsect]
|
||||
|
||||
192
doc/changes.qbk
192
doc/changes.qbk
@@ -1,6 +1,6 @@
|
||||
[/
|
||||
(C) Copyright 2007-11 Anthony Williams.
|
||||
(C) Copyright 2011-13 Vicente J. Botet Escriba.
|
||||
(C) Copyright 2011-14 Vicente J. Botet Escriba.
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt).
|
||||
@@ -8,23 +8,171 @@
|
||||
|
||||
[section:changes History]
|
||||
|
||||
[/
|
||||
[heading Version 4.2.0 - boost 1.55]
|
||||
[heading Version 4.4.0 - boost 1.57]
|
||||
|
||||
[*New Features:]
|
||||
[*Know Bugs:]
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8273 #8273] Synchro:Add externally locked streams.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8274 #8274] Synchro:Add concurrent queue.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8515 #8515] Async: Add shared_future::then.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8518 #8518] Synchro: Add a latch class.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8615 #8615] Async: Replace make_future/make_shared_future by make_ready_future.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8627 #8627] Async: Add future<>::unwrap.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8677 #8677] Async: Add future<>::get_or.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8678 #8678] Async: Add future<>::fallback_to.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/2442 #2442] Application statically linked with Boost.Thread crashes when Google Desktop is installed (Windows XP)
|
||||
* [@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/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/9310 #9310] test_4648_lib fails on clang-darwin-asan11
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9311 #9311] ex_lambda_future fails on msvc-11.0
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10537 #10537] Application crash on throw exception
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10651 #10651] boost::thread leaks memory when using the MinGW compiler
|
||||
|
||||
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,
|
||||
|
||||
[*New Experimental Features:]
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/6227 #6227] Synchro: Use of variadic templates on Generic Locking Algorithms on compilers providing them
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10298 #10298] Synchro: Added queue views.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10300 #10300] Async: Added generic_executor_ref.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10552 #10552] Add make_valid_future
|
||||
|
||||
[*Fixed Bugs:]
|
||||
|
||||
]
|
||||
* [@http://svn.boost.org/trac/boost/ticket/6782 #6782] call_once uses incorrect barrier intrinsic on Visual Studio
|
||||
* [@http://svn.boost.org/trac/boost/ticket/6787 #6787] boost::thread::sleep() hangs if system time is rolled back
|
||||
* [@http://svn.boost.org/trac/boost/ticket/7665 #7665] this_thread::sleep_for no longer uses steady_clock in thread
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9307 #9307] future::fallback_to assert with ERRORRRRR boost: mutex lock failed in pthread_mutex_lock: Invalid argument
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9308 #9308] future::async fails with terminate called throwing an exception when called with a lambda - clang-darwin-asan11
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9310 #9310] test_4648_lib fails on clang-darwin-asan11
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9425 #9425] Boost promise & future does not use supplied allocator for value storage
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9558 #9558] future continuations unit test hangs in get()/pthread_cond_wait() on Mac 10.7/32-bit/x86/darwin-4.2.1
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9787 #9787] [windows] Small duration value passed down to basic_timed_mutex::try_lock_until and condition_variable::wait_until can cause infinite or near infinite wait for win32
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9880 #9880] [windows] boost::condition_variable.timed_wait() exception if system time < 1970
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10159 #10159] GCC 4.4 error sorry, unimplemented
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10196 #10196] thread_specific_ptr does not support void*
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10296 #10296] Boost.Thread 1.56 rc1 does not compile on Mingw
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10297 #10297] Boost.Thread 1.56 rc1 hangs when built with clang on armhf
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10340 #10340] No boost::promise<T>::set_value(const T&) overload present in C++03 mode
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10425 #10425] Missing documentation for when_all/when_any.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10426 #10426] Take in account the deferred futures in when_all.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10427 #10427] Take in account the deferred and ready futures in when_any.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10428 #10428] Adapt to new unique_ptr interface in Boost.Move
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10465 #10465] Missing implementation of when_all/when_any when the result is a tuple.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10476 #10476] classes using BOOST_THREAD_MOVABLE_ONLY<T> dont satisfy is_copy_constructible<T>::value == false
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10478 #10478] Data race in boost/thread/future.hpp
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10529 #10529] The pthread/condition_variable_any constructor reports incorrect error code for pthread_cond_init
|
||||
* [@http://svn.boost.org/trac/boost/ticket/10563 #10563] shared_future<R>::then should be const
|
||||
|
||||
|
||||
[heading Version 4.3.0 - boost 1.56]
|
||||
|
||||
[*Know Bugs:]
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/2442 #2442] Application statically linked with Boost.Thread crashes when Google Desktop is installed (Windows XP)
|
||||
* [@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/6782 #6782] call_once uses incorrect barrier intrinsic on Visual Studio
|
||||
* [@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/9307 #9307] future::fallback_to assert with ERRORRRRR boost: mutex lock failed in pthread_mutex_lock: Invalid argument
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9308 #9308] future::async fails with terminate called throwing an exception when called with a lambda - clang-darwin-asan11
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9310 #9310] test_4648_lib fails on clang-darwin-asan11
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9311 #9311] ex_lambda_future fails on msvc-11.0
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9425 #9425] Boost promise & future does not use supplied allocator for value storage
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9558 #9558] future continuations unit test hangs in get()/pthread_cond_wait() on Mac 10.7/32-bit/x86/darwin-4.2.1
|
||||
|
||||
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,
|
||||
* The experimental features of boost::future have some severe holes that make the program crash unexpectedly.
|
||||
|
||||
[*New Experimental Features:]
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/7446 #7446] Async: Add when_any.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/7447 #7447] Async: Add when_all.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/7448 #7448] Async: Add async taking a scheduler parameter.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8274 #8274] Synchro: Add concurrent queue
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8518 #8518] Synchro: Add a latch class.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8513 #8513] Async: Add a basic thread_pool executor.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8516 #8516] Async: Add future/shared_future::then taking a scheduler as parameter.
|
||||
|
||||
[*Fixed Bugs:]
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8070 #8070] prefer GetTickCount64 over GetTickCount
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9333 #9333] ex_scoped_thread compile fails on msvc-12.0
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9366 #9366] async(Executor, ...) fails to compile with msvc-10,11,12
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9402 #9402] test_excutor regression on msvc-10,11,12
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9404 #9404] ex_make_future regression error
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9471 #9471] Synchronization documentation nits
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9535 #9535] Missing exception safety might result in crash
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9618 #9618] try_join_for problem: program is not terminate.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9673 #9673] thread compilation with MingW/gcc on Windows gives errors
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9708 #9708] boost::condition_variable::timed_wait unexpectedly wakes up while should wait infinite
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9711 #9711] future continuation called twice
|
||||
|
||||
[heading Version 4.2.0 - boost 1.55]
|
||||
|
||||
[*Know Bugs:]
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/2442 #2442] Application statically linked with Boost.Thread crashes when Google Desktop is installed (Windows XP)
|
||||
* [@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/6782 #6782] call_once uses incorrect barrier intrinsic on Visual Studio
|
||||
* [@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/9307 #9307] future::fallback_to assert with ERRORRRRR boost: mutex lock failed in pthread_mutex_lock: Invalid argument
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9308 #9308] future::async fails with terminate called throwing an exception when called with a lambda - clang-darwin-asan11
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9311 #9311] ex_lambda_future fails on msvc-11.0
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9310 #9310] test_4648_lib fails on clang-darwin-asan11
|
||||
|
||||
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 trunk regression test] to see the current state.
|
||||
|
||||
[*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,
|
||||
* The experimental features of boost::future have some severe holes that make the program crash unexpectedly.
|
||||
|
||||
[*New Features:]
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8519 #8519] Synchro: Update class barrier with a completion function.
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8515 #8515] Async: Add shared_future::then.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8519 #8519] Synchro: Update class barrier with a completion function
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8615 #8615] Async: Replace make_future/make_shared_future by make_ready_future.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8627 #8627] Async: Add future<>::unwrap and unwrapping constructor.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8677 #8677] Async: Add future<>::get_or.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8678 #8678] Async: Add future<>::fallback_to.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8891 #8891] upgrade_to_unique_lock: missing mutex() function.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8955 #8955] Request for more efficient way to get exception_ptr from future.
|
||||
|
||||
[*Fixed Bugs:]
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/7461 #7461] detail::win32::ReleaseSemaphore may be called with count_to_release equal to 0
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8070 #8070] prefer GetTickCount64 over GetTickCount
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8768 #8768] win32 condition_variable::wait_until infinite wait in rare cases.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8817 #8817] Boost Thread Windows CE _createthreadex handling breaks mingw w64.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8943 #8943] Failed to compile code using boost::call_once with Intel C++ Composer XE 2013 on Windows.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8931 #8931] Typos in external_locking reference.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9029 #9029] Misprint in documentation.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9037 #9037] gcc -Wshadow gives warnings in condition_variable{,_fwd}.hpp.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9041 #9041] Boost.Thread DSO's may need to link with Boost.Atomic.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9048 #9048] boost::scoped_thread useless ctor with variadic template arguments.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/9079 #9079] Condition variable will wait forever for some timepoint values (Win).
|
||||
|
||||
[heading Version 4.1.0 - boost 1.54]
|
||||
|
||||
@@ -416,26 +564,14 @@ The following features will be included in next releases.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/7589 #7589] Synchro: Add polymorphic lockables.
|
||||
|
||||
# Add some features based on C++ proposals, in particular
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8273 #8273] Add externally locked streams
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8274 #8274] Add concurrent queue
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8518 #8518] Sync: Add a latch class
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8519 #8519] Sync: Add a completion_latch class
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8513 #8513] Async: Add a basic thread_pool executor.
|
||||
* [@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 some of the extension proposed in [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3428.pdf A Standardized Representation of Asynchronous Operations] or extension to them, in particular
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/7446 #7446] Async: Add when_any.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/7447 #7447] Async: Add when_all.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/7448 #7448] Async: Add async taking a scheduler parameter.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8515 #8515] Async: Add shared_future::then.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8516 #8516] Async: Add future/shared_future::then taking a scheduler as parameter.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8627 #8627] Async: Add future<>::unwrap.
|
||||
# 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/8677 #8677] Async: Add future<>::get_or.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8678 #8678] Async: Add future<>::fallback_to.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/8517 #8517] Async: Add a variadic shared_future::then.
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[/
|
||||
(C) Copyright 2011-12 Vicente J. Botet Escriba.
|
||||
(C) Copyright 2011-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).
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
[section:cpp11 C++11 standard Thread library]
|
||||
|
||||
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3376.html C++11 standard]]
|
||||
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3376.html C++11 - Standard for Programming Language C++]]]
|
||||
|
||||
|
||||
[table C++11 standard Conformance
|
||||
@@ -73,24 +73,23 @@
|
||||
[[30.6.9] [Class template packaged_task] [Yes] [-] [-]]
|
||||
]
|
||||
|
||||
[/
|
||||
|
||||
[table Extension
|
||||
[[Section] [Description] [Comments]]
|
||||
[[30.3.1.5.x] [interrupt] [-]]
|
||||
[[30.3.2.x] [Interruption] [-]]
|
||||
[[30.3.2.y] [at_thread_exit] [-]]
|
||||
[[30.4.3.x] [Generic locking algorithms begin/end] [-]]
|
||||
[[30.x] [Barriers] [-]]
|
||||
[[30.y] [Thread Local Storage] [-]]
|
||||
[[30.z] [Class thread_group] [-]]
|
||||
]
|
||||
|
||||
[/
|
||||
[[30.x] [Thread Local Storage] [-]]
|
||||
[[30.y] [Class thread_group] [-]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
|
||||
[section:cxx14 C++14 standard Thread library - accepted changes]
|
||||
|
||||
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3485.html C++14 on-going standard]]
|
||||
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3797.html Working Draft, Standard for Programming Language C++]]
|
||||
|
||||
|
||||
[table [@http://isocpp.org/files/papers/N3659.html N3659 Shared locking in C++ revision 2] Conformance
|
||||
@@ -102,12 +101,36 @@
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:cxx1y C++1y TS Concurrency - On going proposals]
|
||||
|
||||
[section:cxx1y C++14 TS Extensions for Concurrency V1 ]
|
||||
|
||||
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4107.html N4107-Extensions for Concurrency]]
|
||||
|
||||
|
||||
[table Improvements to std::future<T> and related APIs]
|
||||
[[Section] [Description] [Status] [Comments]]
|
||||
[[2.1] [ - ] [ - ] [ - ]]
|
||||
[[2.2] [Class template future] [Partial] [ - ]]
|
||||
[[2.2] [then] [ Partial ] [ without implicit unwrapping #10550 and blocking #10551 ]]
|
||||
[[2.2] [is_ready] [ Yes ] [ - ]]
|
||||
[[2.3] [Class template shared_future] [Partial] [ - ]]
|
||||
[[2.3] [then] [ Partial ] [ Without implicit unwrapping #10550 and blocking #10551 ]]
|
||||
[[2.3] [is_ready] [ Yes ] [ - ]]
|
||||
[[2.4] [Function template when_all] [Partial] [ interface not complete #10426 and blocking #10551 ]]
|
||||
[[2.5] [Function template when_any] [Partial] [ interface not complete #10427 and blocking #10551 ]]
|
||||
[[2.6] [Function template when_any_back] [No] [ #XXXX ]]
|
||||
[[2.7] [Function template make_ready_future] [Yes] [ - ]]
|
||||
]
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:cxx1y C++1z TS Concurrency - On going proposals]
|
||||
|
||||
[section:latch C++ Latches and Barriers]
|
||||
|
||||
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3600.html N3659 C++ Latches and Barriers]]
|
||||
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3666.html N3659 C++ Latches and Barriers]]
|
||||
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3600.html N3600 C++ Latches and Barriers]]
|
||||
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3817.html N3817 C++ Latches and Barriers]]
|
||||
|
||||
[table C++ Latches and Barriers Conformance
|
||||
[[Section] [Description] [Status] [Comments]]
|
||||
@@ -124,105 +147,84 @@
|
||||
[[Section] [Description] [Status] [Comments]]
|
||||
[[X.1] [Conceptual interface] [Partial] [ The interface provided has some differences respect to this proposal. All the functions having a queue_op_status are not provided. No lock-free concrete classes ]]
|
||||
[[X.1.1] [Basic Operations] [Partial] [ - ]]
|
||||
[[X.1.1.1] [push] [yes] [ - ]]
|
||||
[[X.1.1.2] [value_pop] [no] [ renamed pull with two flavors + a ptr_pull that returns a sharted_ptr<>. ]]
|
||||
[[X.1.1.1] [push] [yes] [ renamed push_back. ]]
|
||||
[[X.1.1.2] [value_pop] [no] [ renamed pull_front with two flavors. ]]
|
||||
[[X.1.2] [Non-waiting operations] [ - ] [ - ]]
|
||||
[[X.1.2.1] [try_push] [Partial] [ return bool instead ]]
|
||||
[[X.1.2.2] [try_pop] [Partial] [ renamed try_pull, returns null ]]
|
||||
[[X.1.2.1] [try_push] [yes] [ renamed try_push_back ]]
|
||||
[[X.1.2.2] [try_pop] [yes] [ renamed try_pull_back ]]
|
||||
[[X.1.3] [Non-blocking operations] [ - ] [ - ]]
|
||||
[[X.1.3.1] [nonblocking_push] [Partial] [ renamed try_push(no_block, ]]
|
||||
[[X.1.3.2] [nonblocking_pop] [Partial] [ renamed try_pop(no_block, ]]
|
||||
[[X.1.3.1] [nonblocking_push] [Yes] [ renamed nonblocking_push_back ]]
|
||||
[[X.1.3.2] [nonblocking_pop] [Yes] [ renamed nonblocking_pull_front ]]
|
||||
[[X.1.4] [Push-front operations] [No] [ - ]]
|
||||
[[X.1.5] [Closed queues] [Partial] [ - ]]
|
||||
[[X.1.5.1] [close] [Yes] [ - ]]
|
||||
[[X.1.5.2] [is_closed] [Yes] [ - ]]
|
||||
[[X.1.5.3] [wait_push] [Partial] [ - ]]
|
||||
[[X.1.5.4] [wait_pop] [Partial] [ - ]]
|
||||
[[X.1.5.2] [is_closed] [Yes] [ renamed closed ]]
|
||||
[[X.1.5.3] [wait_push] [Yes] [ renamed wait_push_back ]]
|
||||
[[X.1.5.4] [wait_pop] [Yes] [ renamed wait_pull_front ]]
|
||||
[[X.1.5.5] [wait_push_front] [no] [ - ]]
|
||||
[[X.1.5.6] [wait_pop] [Partial] [ - ]]
|
||||
[[X.1.5.6] [wait_pop_back] [no] [ - ]]
|
||||
[[X.1.5.6] [open] [no] [ - ]]
|
||||
[[X.1.6] [Empty and Full Queues] [Yes] [ - ]]
|
||||
[[X.1.6.1] [is_empty] [Yes] [ - ]]
|
||||
[[X.1.6.2] [is_full] [Yes] [ Added capacity ]]
|
||||
[[X.1.7] [Queue Names] [No] [ Not considere a must for the time been. ]]
|
||||
[[X.1.7] [Queue Names] [No] [ Not considered a must for the time been. ]]
|
||||
[[X.1.8] [Element Type Requirements] [Yes?] [ - ]]
|
||||
[[X.1.9] [Exception Handling] [Yes?] [ - ]]
|
||||
[[X.1.10] [Queue Ordering] [Yes?] [ - ]]
|
||||
[[X.1.11] [Lock-Free Implementations] [No] [ waiting to stabilize the lock-based interface. Will use Boost.LockFree once it is Move aware. ]]
|
||||
[[X.1.11] [Lock-Free Implementations] [No] [ waiting to stabilize the lock-based interface. Will use Boost.LockFree once it is Boost.Move aware. ]]
|
||||
[[X.2] [Concrete queues] [Partial] [ - ]]
|
||||
[[X.2.1] [Locking Buffer Queue] [Partial] [ classes sync_queue and a sync_bounded_queue. ]]
|
||||
[[X.2.1] [Lock-Free Buffer Queue] [No] [ - ]]
|
||||
[[X.2.1] [Lock-Free Buffer Queue] [No] [ waiting to stabilize the lock-based interface. Will use Boost.LockFree once it is Boost.Move aware. ]]
|
||||
[[X.3] [Additional Conceptual Tools] [No] [ - ]]
|
||||
[[X.3.1] [Fronts and Backs] [No] [ - ]]
|
||||
[[X.3.2] [Streaming Iterators] [No] [ - ]]
|
||||
[[X.3.2] [Streaming Iterators] [No] [ - ]]
|
||||
[[X.3.3] [Storage Iterators] [No] [ - ]]
|
||||
[[X.3.4] [Binary Interfaces] [No] [ - ]]
|
||||
[[X.3.4] [Managed Indirection] [No] [ - ]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
|
||||
[section:executors Asynchronous Executors]
|
||||
|
||||
While Boost.Thread implementation of executors would not use dynamic polymorphism, it is worth comparing with the current trend on the standard.
|
||||
|
||||
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3378.pdf N3378 A preliminary proposal for work executors]]
|
||||
|
||||
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3785.pdf N3785 Executors and Schedulers]]
|
||||
|
||||
[table Asynchronous Executors
|
||||
[[Section] [Description] [Status] [Comments]]
|
||||
[[30.X.1] [Class executor] [No] [ - ]]
|
||||
[[30.X.1.1] [add] [No] [ renamed with a function template submit ]]
|
||||
[[30.X.1.1] [num_of_pendin_closures] [??] [ ]]
|
||||
[[30.X.2] [Class sceduled_executor] [No] [ - ]]
|
||||
[[30.X.2.1] [add_at] [No] [ renamed with a function template submit_at ]]
|
||||
[[30.X.2.2] [add_after] [No] [ renamed with a function template submit_after ]]
|
||||
[[30.X.3] [Executor utilities functions] [No] [ - ]]
|
||||
[[30.X.3.1] [default_executor] [No] [ - ]]
|
||||
[[30.X.3.2] [set_default_executor] [No] [ - ]]
|
||||
[[30.X.3.3] [singleton_inline_executor] [No] [ - ]]
|
||||
[[30.X.4] [Concrete executor classes] [No] [ - ]]
|
||||
[[30.X.4.1] [loop_executor] [No] [ - ]]
|
||||
[[30.X.4.1] [serial_executor] [No] [ - ]]
|
||||
[[30.X.4.1] [thread_pool] [No] [ #8513 ]]
|
||||
[[V.1.1] [Class executor] [Yes] [ - ]]
|
||||
[[V.1.1] [add] [Yes] [ renamed with a function template submit ]]
|
||||
[[V.1.1] [num_of_pendin_closures] [No] [ ]]
|
||||
[[V.1.2] [Class sceduled_executor] [No] [ - ]]
|
||||
[[V.1.2] [add_at] [No] [ renamed with a function template submit_at ]]
|
||||
[[V.1.2] [add_after] [No] [ renamed with a function template submit_after ]]
|
||||
[[V.2] [Concrete executor classes] [No] [ - ]]
|
||||
[[V.2.1] [thread_pool] [Yes] [ static version Basic_thread_pool, dynamic one execduler_adaptor<basic_thread_pool> ]]
|
||||
[[V.2.2] [serial_executor] [yes] [ - ]]
|
||||
[[V.2.3] [loop_executor] [Yes] [ static version loop_scheduler, dynamic one execduler_adaptor<loop_scheduler> ]]
|
||||
[[V.2.4] [inline_executor] [Yes] [ static version inline_executor, dynamic one execduler_adaptor<inline_executor> ]]
|
||||
[[V.2.5] [thread_executor] [Yes] [ static version thread_executor, dynamic one execduler_adaptor<thread_executor> ]]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3784.pdf N3784-Improvements to `std::future<T> and Related APIs]]
|
||||
|
||||
|
||||
[section:async A Standardized Representation of Asynchronous Operations]
|
||||
|
||||
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3558.pdf N3558 A Standardized Representation of Asynchronous Operations]]
|
||||
[note These functions are based on the [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3634.pdf [*N3634 - Improvements to std::future<T> and related APIs]] C++1y proposal by N. Gustafsson, A. Laksberg, H. Sutter, S. Mithani.]
|
||||
|
||||
[table Improvements to std::future<T> and related APIs]
|
||||
[table `async, future/shared_future::then`and Executors
|
||||
[[Section] [Description] [Status] [Comments]]
|
||||
[[30.6.6] [Class template future] [Partial] [ - ]]
|
||||
[[30.6.6.1] [then] [Partial] [ executor interface missing #8516 ]]
|
||||
[[30.6.6.2] [unwrap] [Yes] [ - ]]
|
||||
[[30.6.6.3] [ready] [Partial] [ is_ready ]]
|
||||
[[30.6.7] [Class template shared_future] [Partial] [ - ]]
|
||||
[[30.6.7.1] [then] [Yes] [ executor interface missing #8516 ]]
|
||||
[[30.6.7.2] [unwrap] [No] [ #XXXX ]]
|
||||
[[30.6.7.3] [ready] [Partial] [ is_ready ]]
|
||||
[[30.6.X] [Function template when_any] [No] [ #7446 ]]
|
||||
[[30.6.X] [Function template when_all] [No] [ #7447 ]]
|
||||
[[30.6.X] [Function template make_ready_future] [Yes] [ - ]]
|
||||
[[30.6.8] [Function template async ] [No] [ executor interface missing #7448 ]]
|
||||
[[30.6.6] [`future<T>::then`] [Yes] [ ]]
|
||||
[[30.6.7] [`shared_future<T>::then`] [Yes] [ ]]
|
||||
[[30.6.8] [`async`] [Yes] [ - ]]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:stream_mutex C++ Stream Mutexes - C++ Stream Guards]
|
||||
|
||||
While Boost.Thread implementation of stream mutexes differ in the approach, it is worth comparing with the current trend on the standard.
|
||||
|
||||
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3535.html N3535 - C++ Stream Mutexes]. This has been replaced already by N3678 - C++ Stream Guards.]
|
||||
[note These functions are based on [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3535.html [*N3535 - C++ Stream Mutexes]] by Lawrence Crowl.]
|
||||
|
||||
[table C++ C++ Stream MutexesConformance
|
||||
[note This proposal has been replaced already by [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3678.html N3678 - C++ Stream Guards], which has been replaced by [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3678.html N3665 - Uninterleaved String Output Streaming] and [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3678.html N3750 - C++ Ostream Buffers]]
|
||||
|
||||
[table C++ Stream Mutexes Conformance
|
||||
[[Section] [Description] [Status] [Comments]]
|
||||
[[X.1] [Class template stream_mutex] [Partial] [ externally_locked_stream<> ]]
|
||||
[[X.2.1] [constructor] [Partial] [ externally_locked_stream needs a mutex in addition as argumement. ]]
|
||||
[[X.1] [Class template stream_mutex] [Partial] [ Renamed externally_locked_stream<> ]]
|
||||
[[X.2.1] [constructor] [Partial] [ externally_locked_stream needs a mutex in addition as argument. ]]
|
||||
[[X.2.2] [lock] [yes] [ - ]]
|
||||
[[X.2.3] [unlock] [yes] [ - ]]
|
||||
[[X.2.4] [try_lock] [yes] [ - ]]
|
||||
@@ -232,12 +234,10 @@ While Boost.Thread implementation of stream mutexes differ in the approach, it i
|
||||
[[X.2.1] [stream_guard] [Yes] [ - ]]
|
||||
[[X.2.2] [~stream_guard] [Yes] [ - ]]
|
||||
[[X.2.3] [bypass] [Yes] [ - ]]
|
||||
[[X.3] [Stream Operators] [Yes] [.]]
|
||||
[[X.4] [Predefined Objects] [No] [.]]
|
||||
[[X.3] [Stream Operators] [Yes] [-]]
|
||||
[[X.4] [Predefined Objects] [No] [-]]
|
||||
]
|
||||
|
||||
[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3678.html N3678 - C++ Stream Guards]]
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
@@ -78,20 +78,28 @@ When `BOOST_THREAD_VERSION>3` && defined BOOST_THREAD_PLATFORM_PTHREAD define `
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:move Boost.Atomic]
|
||||
|
||||
[section:thread_eq `boost::thread::oprator==` deprecated]
|
||||
Boost.Thread uses by default an Boost.Atomic in POSIX platforms to implement call_once..
|
||||
|
||||
The following nested typedefs are deprecated:
|
||||
Define `BOOST_THREAD_USES_ATOMIC ` if you want to use Boost.Atomic.
|
||||
Define `BOOST_THREAD_DONT_USE_ATOMIC ` if you don't want to use Boost.Atomic or if it is not supported in your platform.
|
||||
|
||||
* `boost::thread::oprator==`
|
||||
* `boost::thread::oprator!=`
|
||||
[endsect]
|
||||
|
||||
[section:thread_eq `boost::thread::operator==` deprecated]
|
||||
|
||||
The following operators are deprecated:
|
||||
|
||||
* `boost::thread::operator==`
|
||||
* `boost::thread::operator!=`
|
||||
|
||||
When `BOOST_THREAD_PROVIDES_THREAD_EQ` is defined Boost.Thread provides these deprecated feature.
|
||||
|
||||
Use instead
|
||||
|
||||
* `boost::thread::id::oprator==`
|
||||
* `boost::thread::id::oprator!=`
|
||||
* `boost::thread::id::operator==`
|
||||
* `boost::thread::id::operator!=`
|
||||
|
||||
[warning This is a breaking change respect to version 1.x.]
|
||||
|
||||
@@ -296,8 +304,12 @@ When `BOOST_THREAD_VERSION>=4` define `BOOST_THREAD_DONT_PROVIDE_SIGNATURE_PACKA
|
||||
|
||||
C++11 thread constructor accep a variable number of rvalue argumentshas. When `BOOST_THREAD_PROVIDES_VARIADIC_THREAD ` is defined Boost.Thread provides this C++ feature if the following are not defined
|
||||
|
||||
* BOOST_NO_SFINAE_EXPR
|
||||
* BOOST_NO_CXX11_VARIADIC_TEMPLATES
|
||||
* BOOST_NO_CXX11_DECLTYPE
|
||||
* BOOST_NO_CXX11_DECLTYPE_N3276
|
||||
* BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
* BOOST_NO_CXX11_TRAILING_RESULT_TYPES
|
||||
* BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
* BOOST_NO_CXX11_HDR_TUPLE
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[/
|
||||
/ Copyright (c) 2008,2012 Vicente J. Botet Escriba
|
||||
/ Copyright (c) 2008,2012,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)
|
||||
@@ -8,7 +8,7 @@
|
||||
[section External Locking -- `strict_lock` and `externally_locked` classes]
|
||||
|
||||
|
||||
[note This tutorial is an adaptation of the paper of Andrei Alexandrescu "Multithreading and the C++ Type System"
|
||||
[note This tutorial is an adaptation of the paper by Andrei Alexandrescu "Multithreading and the C++ Type System"
|
||||
to the Boost library.]
|
||||
|
||||
[/
|
||||
@@ -163,7 +163,7 @@ Obviously, the caller-ensured locking approach has a safety problem. BankAccount
|
||||
To conclude, if in designing a multi-threaded class you settle on internal locking, you expose yourself to inefficiency or deadlocks. On the other hand, if you rely on caller-provided locking, you make your class error-prone and difficult to use. Finally, external locking completely avoids the issue by leaving it all to the client code.
|
||||
[endsect]
|
||||
]
|
||||
[section Locks as Permits]
|
||||
[section Locks as permits]
|
||||
|
||||
So what to do? Ideally, the BankAccount class should do the following:
|
||||
|
||||
@@ -182,9 +182,9 @@ For now, let's make a couple of enhancements to the `lock_guard` class template
|
||||
We'll call the enhanced version `strict_lock`. Essentially, a `strict_lock`'s role is only to live on the stack as an automatic variable.
|
||||
`strict_lock` must adhere to a non-copy and non-alias policy.
|
||||
`strict_lock` disables copying by making the copy constructor and the assignment operator private.
|
||||
[/
|
||||
While we're at it, let's disable operator new and operator delete.
|
||||
|
||||
[/
|
||||
`strict_lock` are not intended to be allocated on the heap.
|
||||
`strict_lock` avoids aliasing by using a slightly less orthodox and less well-known technique: disable address taking.
|
||||
]
|
||||
@@ -217,7 +217,7 @@ Silence can be sometimes louder than words-what's forbidden to do with a `strict
|
||||
* You can create a `strict_lock<T>` only starting from a valid T object. Notice that there is no other way you can create a `strict_lock<T>`.
|
||||
|
||||
BankAccount myAccount("John Doe", "123-45-6789");
|
||||
strict_locerk<BankAccount> myLock(myAccount); // ok
|
||||
strict_lock<BankAccount> myLock(myAccount); // ok
|
||||
|
||||
* You cannot copy `strict_lock`s to one another. In particular, you cannot pass `strict_lock`s by value to functions or have them returned by functions:
|
||||
|
||||
@@ -293,7 +293,7 @@ A little code is worth 1,000 words, a (hacked into) saying goes, so here's the n
|
||||
}
|
||||
};
|
||||
|
||||
Now, if you want the benefit of internal locking, you simply call Deposit(int) and Withdraw(int). If you want to use external locking, you lock the object by constructing a `strict_lock<BankAccount>` and then you call `Deposit(int, strict_lock<BankAccount>&)` and `Withdraw(int, strict_lock<BankAccount>&)`. For example, here's the `ATMWithdrawal` function implemented correctly:
|
||||
Now, if you want the benefit of internal locking, you simply call `Deposit(int)` and `Withdraw(int)`. If you want to use external locking, you lock the object by constructing a `strict_lock<BankAccount>` and then you call `Deposit(int, strict_lock<BankAccount>&)` and `Withdraw(int, strict_lock<BankAccount>&)`. For example, here's the `ATMWithdrawal` function implemented correctly:
|
||||
|
||||
void ATMWithdrawal(BankAccount& acct, int sum) {
|
||||
strict_lock<BankAccount> guard(acct);
|
||||
@@ -453,7 +453,7 @@ We achieved two important goals. First, the declaration of `checkingAcct_` and `
|
||||
|
||||
[section Allowing other strict locks]
|
||||
|
||||
Now imagine that the AccountManager function needs to take a `unique_lock` in order to reduce the critical regions. And at some time it needs to access to the `checkingAcct_`. As `unique_lock` is not a strict lock the following code doesn't compiles:
|
||||
Now imagine that the AccountManager function needs to take a `unique_lock` in order to reduce the critical regions. And at some time it needs to access to the `checkingAcct_`. As `unique_lock` is not a strict lock the following code doesn't compile:
|
||||
|
||||
void AccountManager::AMoreComplicatedChecking2Savings(int amount) {
|
||||
unique_lock<AccountManager> guard(*this, defer_lock);
|
||||
@@ -465,10 +465,10 @@ Now imagine that the AccountManager function needs to take a `unique_lock` in or
|
||||
do_something_else();
|
||||
}
|
||||
|
||||
We need a way to transfer the ownership from the `unique_lock` to a `strict_lock` the time we are working with `savingsAcct_` and then restore the ownership on `unique_lock`.
|
||||
We need a way to transfer the ownership from the `unique_lock` to a `strict_lock` during the time we are working with `savingsAcct_` and then restore the ownership on `unique_lock`.
|
||||
|
||||
void AccountManager::AMoreComplicatedChecking2Savings(int amount) {
|
||||
unique_lock<AccountManager> guard(*this, defer_lock);
|
||||
unique_lock<AccountManager> guard1(*this, defer_lock);
|
||||
if (some_condition()) {
|
||||
guard1.lock();
|
||||
}
|
||||
@@ -480,9 +480,9 @@ We need a way to transfer the ownership from the `unique_lock` to a `strict_lock
|
||||
guard1.unlock();
|
||||
}
|
||||
|
||||
In order to make this code compilable we need to store either a Lockable or a `unique_lock<Lockable>` reference depending on the constructor. Store which kind of reference we have stored,and in the destructor call either to the Lockable `unlock` or restore the ownership.
|
||||
In order to make this code compilable we need to store either a Lockable or a `unique_lock<Lockable>` reference depending on the constructor. We also need to store which kind of reference we have stored, and in the destructor call either to the Lockable `unlock` or restore the ownership.
|
||||
|
||||
This seams too complicated to me. Another possibility is to define a nested strict lock class. The drawback is that instead of having only one strict lock we have two and we need either to duplicate every function taking a `strict_lock` or make these function templates functions. The problem with template functions is that we don't profit anymore of the C++ type system. We must add some static metafunction that check that the Locker parameter is a strict lock. The problem is that we can not really check this or can we?. The `is_strict_lock` metafunction must be specialized by the strict lock developer. We need to belive it "sur parole". The advantage is that now we can manage with more than two strict locks without changing our code. Ths is really nice.
|
||||
This seems too complicated to me. Another possibility is to define a nested strict lock class. The drawback is that instead of having only one strict lock we have two and we need either to duplicate every function taking a `strict_lock` or make these function templates. The problem with template functions is that we don't profit anymore of the C++ type system. We must add some static metafunction that checks that the Locker parameter is a strict lock. The problem is that we can not really check this or can we?. The `is_strict_lock` metafunction must be specialized by the strict lock developer. We need to believe it "sur parole". The advantage is that now we can manage with more than two strict locks without changing our code. This is really nice.
|
||||
|
||||
Now we need to state that both classes are `strict_lock`s.
|
||||
|
||||
@@ -496,9 +496,9 @@ Now we need to state that both classes are `strict_lock`s.
|
||||
struct is_strict_lock<nested_strict_lock<Locker> > : mpl::true_ {}
|
||||
|
||||
|
||||
Well let me show how this `nested_strict_lock` class looks like and the impacts on the `externally_locked` class and the `AccountManager::AMoreComplicatedFunction` function.
|
||||
Well let me show what this `nested_strict_lock` class looks like and the impacts on the `externally_locked` class and the `AccountManager::AMoreComplicatedFunction` function.
|
||||
|
||||
First `nested_strict_lock` class will store on a temporary lock the `Locker`, and transfer the lock ownership on the constructor. On destruction he will restore the ownership. Note also that the Locker needs to have already a reference to the mutex otherwise an exception is thrown and the use of the `lock_traits`.
|
||||
First `nested_strict_lock` class will store on a temporary lock the `Locker`, and transfer the lock ownership on the constructor. On destruction it will restore the ownership. Note the use of `lock_traits` and that the `Locker` needs to have a reference to the mutex otherwise and exception is thrown.
|
||||
|
||||
template <typename Locker >
|
||||
class nested_strict_lock
|
||||
|
||||
1036
doc/future_ref.qbk
1036
doc/future_ref.qbk
File diff suppressed because it is too large
Load Diff
@@ -293,7 +293,7 @@ that is to allow multiple concurrent get operations.
|
||||
|
||||
[heading Multiple get]
|
||||
|
||||
The second `get()` call in the following example future
|
||||
The second `get()` call in the following example is undefined.
|
||||
|
||||
void bad_second_use( type arg ) {
|
||||
|
||||
@@ -308,7 +308,7 @@ The second `get()` call in the following example future
|
||||
use3( ftr.get() ); // second use is undefined
|
||||
}
|
||||
|
||||
Using a `shared_mutex` solves the issue
|
||||
Using a `shared_future` solves the issue
|
||||
|
||||
void good_second_use( type arg ) {
|
||||
|
||||
@@ -341,7 +341,7 @@ Here `share()` could be used to simplify the code
|
||||
use3( ftr.get() ); // second use is defined
|
||||
}
|
||||
|
||||
[heading Writting on get()]
|
||||
[heading Writing on get()]
|
||||
|
||||
The user can either read or write the future avariable.
|
||||
|
||||
@@ -369,17 +369,17 @@ and a `shared_future` that can be shared between several threads, but there were
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:make_future Making immediate futures easier]
|
||||
[section:make_ready_future Making immediate futures easier]
|
||||
|
||||
Some functions may know the value at the point of construction. In these cases the value is immediately available,
|
||||
but needs to be returned as a future or shared_future. By using make_future (make_shared_future) a future (shared_future)
|
||||
but needs to be returned as a future or shared_future. By using make_ready_future a future
|
||||
can be created which holds a pre-computed result in its shared state.
|
||||
|
||||
Without these features it is non-trivial to create a future directly from a value.
|
||||
First a promise must be created, then the promise is set, and lastly the future is retrieved from the promise.
|
||||
This can now be done with one operation.
|
||||
|
||||
[heading make_future / make_shared_future]
|
||||
[heading make_ready_future]
|
||||
|
||||
This function creates a future for a given value. If no value is given then a future<void> is returned.
|
||||
This function is primarily useful in cases where sometimes, the return value is immediately available, but sometimes
|
||||
@@ -389,16 +389,14 @@ the function must return an eventual value represented as a future.
|
||||
|
||||
boost::future<int> compute(int x)
|
||||
{
|
||||
if (x == 0) return boost::make_future(0);
|
||||
if (x < 0) return boost::make_future(-1);
|
||||
if (x == 0) return boost::make_ready_future(0);
|
||||
if (x < 0) return boost::make_ready_future<int>(std::logic_error("Error"));
|
||||
boost::future<int> f1 = boost::async([]() { return x+1; });
|
||||
return f1;
|
||||
}
|
||||
|
||||
There are two variations of this function. The first takes a value of any type, and returns a future of that type.
|
||||
The input value is passed to the shared state of the returned future. The second version takes no input and returns a future<void>.
|
||||
make_shared_future has the same functionality as make_future, except has a return type of shared_future.
|
||||
|
||||
The input value is passed to the shared state of the returned future. The second version takes no input and returns a future<void>.
|
||||
|
||||
[endsect]
|
||||
|
||||
@@ -406,16 +404,16 @@ make_shared_future has the same functionality as make_future, except has a retur
|
||||
|
||||
In asynchronous programming, it is very common for one asynchronous operation, on completion, to invoke a second
|
||||
operation and pass data to it. The current C++ standard does not allow one to register a continuation to a future.
|
||||
With .then, instead of waiting for the result, a continuation is "attached" to the asynchronous operation, which is
|
||||
invoked when the result is ready. Continuations registered using the .then function will help to avoid blocking waits
|
||||
With `.then`, instead of waiting for the result, a continuation is "attached" to the asynchronous operation, which is
|
||||
invoked when the result is ready. Continuations registered using the `.then` function will help to avoid blocking waits
|
||||
or wasting threads on polling, greatly improving the responsiveness and scalability of an application.
|
||||
|
||||
future.then provides the ability to sequentially compose two futures by declaring one to be the continuation of another.
|
||||
With .then the antecedent future is ready (has a value or exception stored in the shared state) before the continuation
|
||||
`future.then()` provides the ability to sequentially compose two futures by declaring one to be the continuation of another.
|
||||
With `.then()` the antecedent future is ready (has a value or exception stored in the shared state) before the continuation
|
||||
starts as instructed by the lambda function.
|
||||
|
||||
In the example below the future<int> f2 is registered to be a continuation of future<int> f1 using the .then member
|
||||
function. This operation takes a lambda function which describes how f2 should proceed after f1 is ready.
|
||||
In the example below the `future<string>` `f2` is registered to be a continuation of `future<int>` `f1` using the `.then()` member
|
||||
function. This operation takes a lambda function which describes how `f2` should proceed after `f1` is ready.
|
||||
|
||||
|
||||
#include <boost/thread/future.hpp>
|
||||
@@ -428,7 +426,7 @@ function. This operation takes a lambda function which describes how f2 should p
|
||||
|
||||
One key feature of this function is the ability to chain multiple asynchronous operations. In asynchronous programming,
|
||||
it's common to define a sequence of operations, in which each continuation executes only when the previous one completes.
|
||||
In some cases, the antecedent future produces a value that the continuation accepts as input. By using future.then,
|
||||
In some cases, the antecedent future produces a value that the continuation accepts as input. By using `future.then()`,
|
||||
creating a chain of continuations becomes straightforward and intuitive:
|
||||
|
||||
myFuture.then(...).then(...).then(...).
|
||||
@@ -441,21 +439,20 @@ Some points to note are:
|
||||
|
||||
Input Parameters:
|
||||
|
||||
* Lambda function2: One option which was considered was to follow JavaScript's approach and take two functions, one for
|
||||
success and one for error handling. However this option is not viable in C++ as there is no single base type for
|
||||
exceptions as there is in JavaScript. The lambda function takes a future as its input which carries the exception
|
||||
* Lambda function: One option which can be considered is to take two functions, one for
|
||||
success and one for error handling. However this option has not been retained for the moment.
|
||||
The lambda function takes a future as its input which carries the exception
|
||||
through. This makes propagating exceptions straightforward. This approach also simplifies the chaining of continuations.
|
||||
* Scheduler: Providing an overload to .then, to take a scheduler reference places great flexibility over the execution
|
||||
* Scheduler: Providing an overload to `.then`, to take a scheduler reference places great flexibility over the execution
|
||||
of the future in the programmer's hand. As described above, often taking a launch policy is not sufficient for powerful
|
||||
asynchronous operations. The lifetime of the scheduler must outlive the continuation.
|
||||
* Launch policy: if the additional flexibility that the scheduler provides is not required.
|
||||
|
||||
|
||||
Return values: The decision to return a future was based primarily on the ability to chain multiple continuations using
|
||||
.then. This benefit of composability gives the programmer incredible control and flexibility over their code. Returning
|
||||
a future object rather than a shared_future is also a much cheaper operation thereby improving performance. A
|
||||
shared_future object is not necessary to take advantage of the chaining feature. It is also easy to go from a future
|
||||
to a shared_future when needed using future::share().
|
||||
`.then()`. This benefit of composability gives the programmer incredible control and flexibility over their code. Returning
|
||||
a `future` object rather than a `shared_future` is also a much cheaper operation thereby improving performance. A
|
||||
`shared_future` object is not necessary to take advantage of the chaining feature. It is also easy to go from a `future`
|
||||
to a `shared_future` when needed using future::share().
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[/
|
||||
/ Copyright (c) 2008 Vicente J. Botet Escriba
|
||||
/ Copyright (c) 2008,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)
|
||||
@@ -14,7 +14,7 @@ Consider, for example, modeling a bank account class that supports simultaneous
|
||||
|
||||
From here a component is a model of the `Callable` concept.
|
||||
|
||||
On C++11 (Boost) concurrent execution of a component is obtained by means of the `std::thread`(`boost::thread`):
|
||||
I C++11 (Boost) concurrent execution of a component is obtained by means of the `std::thread`(`boost::thread`):
|
||||
|
||||
boost::thread thread1(S);
|
||||
|
||||
@@ -53,12 +53,12 @@ The following example includes a bank account of a person (Joe) and two componen
|
||||
return 0;
|
||||
}
|
||||
|
||||
From time to time, the `bankAgent` will deposit $500 in `JoesAccount`. Joe will similarly withdraw $100 from his account. These sentences describe that the bankAgent and Joe are executed concurrently.
|
||||
From time to time, the `bankAgent` will deposit $500 in `JoesAccount`. `Joe` will similarly withdraw $100 from his account. These sentences describe that the `bankAgent` and `Joe` are executed concurrently.
|
||||
|
||||
[endsect]
|
||||
[section Internal locking]
|
||||
|
||||
The above example works well as long as the bankAgent and Joe doesn't access JoesAccount at the same time. There is, however, no guarantee that this will not happen. We may use a mutex to guarantee exclusive access to each bank.
|
||||
The above example works well as long as the components `bankAgent` and `Joe` doesn't access `JoesAccount` at the same time. There is, however, no guarantee that this will not happen. We may use a mutex to guarantee exclusive access to each bank.
|
||||
|
||||
class BankAccount {
|
||||
boost::mutex mtx_;
|
||||
@@ -82,11 +82,11 @@ The above example works well as long as the bankAgent and Joe doesn't access Joe
|
||||
}
|
||||
};
|
||||
|
||||
Execution of the Deposit and Withdraw operations will no longer be able to make simultaneous access to balance.
|
||||
Execution of the `Deposit` and `Withdraw` operations will no longer be able to make simultaneous access to balance.
|
||||
|
||||
Mutex is a simple and basic mechanism for obtaining synchronization. In the above example it is relatively easy to be convinced that the synchronization works correctly (in the absence of exception). In a system with several concurrent objects and several shared objects, it may be difficult to describe synchronization by means of mutexes. Programs that make heavy use of mutexes may be difficult to read and write. Instead, we shall introduce a number of generic classes for handling more complicated forms of synchronization and communication.
|
||||
A mutex is a simple and basic mechanism for obtaining synchronization. In the above example it is relatively easy to be convinced that the synchronization works correctly (in the absence of exception). In a system with several concurrent objects and several shared objects, it may be difficult to describe synchronization by means of mutexes. Programs that make heavy use of mutexes may be difficult to read and write. Instead, we shall introduce a number of generic classes for handling more complicated forms of synchronization and communication.
|
||||
|
||||
With the RAII idiom we can simplify a lot this using the scoped locks. In the code below, guard's constructor locks the passed-in object this, and guard's destructor unlocks this.
|
||||
With the RAII idiom we can simplify a lot this using the scoped locks. In the code below, guard's constructor locks the passed-in object `mtx_`, and guard's destructor unlocks `mtx_`.
|
||||
|
||||
class BankAccount {
|
||||
boost::mutex mtx_; // explicit mutex declaration
|
||||
@@ -135,10 +135,10 @@ In an attempt to solve this problem, let's lock the account from the outside dur
|
||||
acct.Withdraw(2);
|
||||
}
|
||||
|
||||
Notice that the code above doesn't compiles, the `mtx_` field is private.
|
||||
Notice that the code above doesn't compile, the `mtx_` field is private.
|
||||
We have two possibilities:
|
||||
|
||||
* make `mtx_` public which seams odd
|
||||
* make `mtx_` public which seems odd
|
||||
* make the `BankAccount` lockable by adding the lock/unlock functions
|
||||
|
||||
We can add these functions explicitly
|
||||
|
||||
@@ -7,13 +7,19 @@
|
||||
|
||||
[section:latches Latches -- EXPERIMENTAL]
|
||||
|
||||
[////////////////////]
|
||||
[section Introdcution]
|
||||
|
||||
Latches are a thread co-ordination mechanism that allow one or more threads to block until one or more threads have reached a point. An individual latch is a reusable object; once the operation has been completed, the threads can re-use the same barrier. It is thus useful for managing repeated tasks handled by multiple threads.
|
||||
Latches are a thread co-ordination mechanism that allow one or more threads to block until one or more threads have reached a point.
|
||||
|
||||
[/
|
||||
An individual latch is a reusable object; once the operation has been completed, the threads can re-use the same barrier. It is thus useful for managing repeated tasks handled by multiple threads.
|
||||
|
||||
A completion latch is like a latch that allows to associate a completion function which will be called once the internal counter reaches the value 0 and all the consumer threads have taken care of the notification.
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[////////////////]
|
||||
[section Examples]
|
||||
|
||||
Sample use cases for the latch include:
|
||||
@@ -38,7 +44,6 @@ An example of the first use case would be as follows:
|
||||
|
||||
An example of the second use case is shown below. We need to load data and then process it using a number of threads. Loading the data is I/O bound, whereas starting threads and creating data structures is CPU bound. By running these in parallel, throughput can be increased.
|
||||
|
||||
|
||||
void DoWork() {
|
||||
latch start_latch(1);
|
||||
vector<thread*> workers;
|
||||
@@ -57,6 +62,7 @@ An example of the second use case is shown below. We need to load data and then
|
||||
start_latch.count_down();
|
||||
}
|
||||
|
||||
[/
|
||||
The completion latches can be used to co-ordinate also a set of threads carrying out a repeated task. The number of threads can be adjusted dynamically to respond to changing requirements.
|
||||
|
||||
In the example below, a number of threads are performing a multi-stage task. Some tasks may require fewer steps than others, meaning that some threads may finish before others. We reduce the number of threads waiting on the latch when this happens.
|
||||
@@ -96,8 +102,10 @@ In the example below, a number of threads are performing a multi-stage task. Som
|
||||
GetNextStage(tasks);
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[///////////////////////////]
|
||||
[section:latch Class `latch`]
|
||||
|
||||
#include <boost/thread/latch.hpp>
|
||||
@@ -119,16 +127,20 @@ In the example below, a number of threads are performing a multi-stage task. Som
|
||||
cv_status wait_until(const chrono::time_point<Clock, Duration>& abs_time);
|
||||
void count_down();
|
||||
void count_down_and_wait();
|
||||
void reset(std::size_t count);
|
||||
|
||||
};
|
||||
|
||||
|
||||
[/
|
||||
void reset(std::size_t count);
|
||||
]
|
||||
|
||||
A latch maintains an internal counter that is initialized when the latch is created. One or more threads may block waiting until the counter is decremented to 0.
|
||||
|
||||
Instances of __latch__ are not copyable or movable.
|
||||
|
||||
[section Constructor]
|
||||
[///////////////////]
|
||||
[section Constructor `latch(std::size_t)`]
|
||||
|
||||
latch(std::size_t count);
|
||||
|
||||
@@ -136,14 +148,15 @@ Instances of __latch__ are not copyable or movable.
|
||||
|
||||
[[Effects:] [Construct a latch with is initial value for the internal counter.]]
|
||||
|
||||
[[Note:] [The counter could be zero and reset later.]]
|
||||
[[Note:] [The counter could be zero.]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[section Destructor]
|
||||
[//////////////////]
|
||||
[section Destructor `~latch()`]
|
||||
|
||||
~latch();
|
||||
|
||||
@@ -158,7 +171,8 @@ Instances of __latch__ are not copyable or movable.
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[section:wait Member function `wait()`]
|
||||
[/////////////////////////////////////]
|
||||
[section:wait Member Function `wait()`]
|
||||
|
||||
void wait();
|
||||
|
||||
@@ -178,8 +192,8 @@ are unblocked. ]]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:try_wait Member function `try_wait()`]
|
||||
[/////////////////////////////////////////////]
|
||||
[section:try_wait Member Function `try_wait()`]
|
||||
|
||||
bool try_wait();
|
||||
|
||||
@@ -194,8 +208,8 @@ are unblocked. ]]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:wait_for Member function `wait_for() `]
|
||||
[//////////////////////////////////////////////]
|
||||
[section:wait_for Member Function `wait_for() `]
|
||||
|
||||
template <class Rep, class Period>
|
||||
cv_status wait_for(const chrono::duration<Rep, Period>& rel_time);
|
||||
@@ -216,7 +230,8 @@ are unblocked. ]]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[section:wait_until Member function `wait_until()`]
|
||||
[/////////////////////////////////////////////////]
|
||||
[section:wait_until Member Function `wait_until()`]
|
||||
|
||||
template <class lock_type, class Clock, class Duration>
|
||||
cv_status wait_until(const chrono::time_point<Clock, Duration>& abs_time);
|
||||
@@ -237,7 +252,8 @@ are unblocked. ]]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[section:count_down Member function `count_down()`]
|
||||
[/////////////////////////////////////////////////]
|
||||
[section:count_down Member Function `count_down()`]
|
||||
|
||||
void count_down();
|
||||
|
||||
@@ -256,7 +272,8 @@ are unblocked. ]]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[section:count_down_and_wait Member function `count_down_and_wait()`]
|
||||
[///////////////////////////////////////////////////////////////////]
|
||||
[section:count_down_and_wait Member Function `count_down_and_wait()`]
|
||||
|
||||
void count_down_and_wait();
|
||||
|
||||
@@ -275,8 +292,9 @@ are unblocked. ]]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:reset Member function `reset()`]
|
||||
[///////////////////////////////////////]
|
||||
[
|
||||
[section:reset Member Function `reset()`]
|
||||
|
||||
reset( size_t );
|
||||
|
||||
@@ -293,9 +311,11 @@ are unblocked. ]]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
]
|
||||
[endsect] [/ latch]
|
||||
|
||||
[/
|
||||
[//////////////////////////////////////////////////]
|
||||
[section:completion_latch Class `completion_latch `]
|
||||
|
||||
#include <boost/thread/completion_latch.hpp>
|
||||
@@ -333,6 +353,7 @@ Instances of completion_latch are not copyable or movable.
|
||||
|
||||
Only the additional functions are documented.
|
||||
|
||||
[/////////////////////]
|
||||
[section:c Constructor]
|
||||
|
||||
completion_latch(std::size_t count);
|
||||
@@ -348,6 +369,7 @@ Only the additional functions are documented.
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[///////////////////////////////////////////////]
|
||||
[section:cf Constructor with completion function]
|
||||
|
||||
template <typename F>
|
||||
@@ -368,7 +390,8 @@ Only the additional functions are documented.
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[section:then Member function `then`]
|
||||
[///////////////////////////////////]
|
||||
[section:then Member Function `then`]
|
||||
|
||||
template <typename F>
|
||||
completion_function then(F&& funct);
|
||||
@@ -391,6 +414,6 @@ Only the additional functions are documented.
|
||||
[endsect]
|
||||
|
||||
[endsect] [/ completion_latch]
|
||||
|
||||
]
|
||||
|
||||
[endsect] [/ Latches]
|
||||
|
||||
@@ -298,8 +298,6 @@ reached. If the specified time has already passed, behaves as __try_lock_ref__.]
|
||||
[warning
|
||||
DEPRECATED since 4.00. The following expressions were required on version 2, but are now deprecated.
|
||||
|
||||
Available only up to Boost 1.58.
|
||||
|
||||
Use instead __try_lock_for, __try_lock_until.
|
||||
]
|
||||
|
||||
@@ -460,8 +458,6 @@ ownership of `m`.]]
|
||||
[warning
|
||||
DEPRECATED since 3.00. The following expressions were required on version 2, but are now deprecated.
|
||||
|
||||
Available only up to Boost 1.56.
|
||||
|
||||
Use instead __try_lock_shared_for, __try_lock_shared_until.
|
||||
]
|
||||
|
||||
@@ -1119,6 +1115,44 @@ object passed to the constructor.]]
|
||||
]
|
||||
|
||||
|
||||
[endsect]
|
||||
[endsect]
|
||||
|
||||
|
||||
[section:with_lock_guard With Lock Guard]
|
||||
|
||||
// #include <boost/thread/with_lock_guard.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template <class Lockable, class Function, class... Args>
|
||||
auto with_lock_guard(Lockable& m, Function&& func, Args&&... args) -> decltype(func(boost::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
[section:with_lock_guard Non Member Function `with_lock_guard`]
|
||||
|
||||
template <class Lockable, class Function, class... Args>
|
||||
auto with_lock_guard(
|
||||
Lockable& m,
|
||||
Function&& func,
|
||||
Args&&... args
|
||||
) -> decltype(func(boost::forward<Args>(args)...));
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Precondition:] [`m` must be in unlocked state]]
|
||||
[[Effects:] [call `func` in scope locked by `m`]]
|
||||
[[Returns:] [Result of `func(args...)` call]]
|
||||
[[Throws:] [Any exception thrown by the call to `m.lock` and `func(args...)`]]
|
||||
[[Postcondition:] [`m` is in unlocked state]]
|
||||
|
||||
[[Limitations:] [Without c++11 variadic templates support number of arguments is limited to `4`]]
|
||||
[[] [Without rvalue references support calling class method with `boost::bind` must be const]]
|
||||
[[] [For correct work with lambda macro `BOOST_RESULT_OF_USE_DECLTYPE` may be needed to define]]
|
||||
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[endsect]
|
||||
|
||||
@@ -1273,7 +1307,7 @@ The following classes are models of `StrictLock`:
|
||||
explicit operator bool() const noexcept;
|
||||
bool owns_lock() const noexcept;
|
||||
|
||||
Lockable* mutex() const noexcept;
|
||||
mutex_type* mutex() const noexcept;
|
||||
|
||||
#if defined BOOST_THREAD_USE_DATE_TIME || defined BOOST_THREAD_DONT_USE_CHRONO
|
||||
unique_lock(Lockable& m_,system_time const& target_time);
|
||||
@@ -1535,7 +1569,7 @@ object associated with `*this`.]]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:mutex `Lockable* mutex() const`]
|
||||
[section:mutex `Lockable* mutex() const noexcept`]
|
||||
|
||||
[variablelist
|
||||
|
||||
@@ -1907,7 +1941,7 @@ state (including the destructor) must be called by the same thread that acquired
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:upgrade_to_unique_lock Class template `upgrade_to_unique_lock`]
|
||||
[section:upgrade_to_unique_lock Class template `upgrade_to_unique_lock` -- EXTENSION]
|
||||
|
||||
// #include <boost/thread/locks.hpp>
|
||||
// #include <boost/thread/lock_types.hpp>
|
||||
@@ -1930,6 +1964,8 @@ state (including the destructor) must be called by the same thread that acquired
|
||||
|
||||
explicit operator bool() const;
|
||||
bool owns_lock() const;
|
||||
mutex_type* mutex() const;
|
||||
|
||||
};
|
||||
|
||||
__upgrade_to_unique_lock__ allows for a temporary upgrade of an __upgrade_lock__ to exclusive ownership. When constructed with a
|
||||
@@ -1939,7 +1975,7 @@ __lockable_concept_type__ is downgraded back to ['upgrade ownership].
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:scoped_try_lock Mutex-specific class `scoped_try_lock`]
|
||||
[section:scoped_try_lock Mutex-specific class `scoped_try_lock` -- DEPRECATED]
|
||||
|
||||
class MutexType::scoped_try_lock
|
||||
{
|
||||
|
||||
@@ -34,9 +34,10 @@ Scoped Threads are wrappers around a thread that allows the user to state what t
|
||||
|
||||
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.
|
||||
|
||||
boost::strict_scoped_thread<> t1((boost::thread(F)));
|
||||
boost::strict_scoped_thread<> t2((boost::thread(F)));
|
||||
t2.interrupt();
|
||||
boost::strict_scoped_thread<> t1((boost::thread(f)));
|
||||
//t1.detach(); // compile fails
|
||||
boost::scoped_thread<> t2((boost::thread(f)));
|
||||
t2.detach();
|
||||
|
||||
[endsect]
|
||||
|
||||
@@ -190,7 +191,7 @@ This wrapper can be used to join the thread before destroying it seems a natural
|
||||
|
||||
explicit scoped_thread(thread&& th) noexcept;
|
||||
template <typename F&&, typename ...Args>
|
||||
explicit strict_scoped_thread(F&&, Args&&...);
|
||||
explicit scoped_thread(F&&, Args&&...);
|
||||
|
||||
~scoped_thread();
|
||||
|
||||
@@ -216,6 +217,7 @@ This wrapper can be used to join the thread before destroying it seems a natural
|
||||
void detach();
|
||||
|
||||
static unsigned hardware_concurrency() noexcept;
|
||||
static unsigned physical_concurrency() noexcept;
|
||||
|
||||
typedef thread::native_handle_type native_handle_type;
|
||||
native_handle_type native_handle();
|
||||
@@ -323,7 +325,7 @@ any) to `*this`.
|
||||
[section:call_constructor Move Constructor from a Callable]
|
||||
|
||||
template <typename F&&, typename ...Args>
|
||||
explicit strict_scoped_thread(F&&, Args&&...);
|
||||
explicit scoped_thread(F&&, Args&&...);
|
||||
|
||||
[variablelist
|
||||
|
||||
@@ -458,6 +460,20 @@ any) to `*this`.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[section:physical_concurrency Static member function `physical_concurrency()`]
|
||||
|
||||
unsigned physical_concurrency() noexecpt;
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Equivalent to return `thread::physical_concurrency()`.]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[section:nativehandle Member function `native_handle()`]
|
||||
|
||||
typedef thread::native_handle_type native_handle_type;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -16,6 +16,7 @@
|
||||
|
||||
[endsect] [/tutorial]
|
||||
|
||||
[/////////////////////]
|
||||
[section:ref Reference]
|
||||
|
||||
#include <boost/thread/externally_locked_stream.hpp>
|
||||
@@ -48,7 +49,7 @@
|
||||
operator>>(externally_locked_stream<Stream, RecursiveMutex>& mtx, T& arg);
|
||||
}
|
||||
|
||||
|
||||
[/////////////////////////////////////////]
|
||||
[section:stream_guard Class `stream_guard`]
|
||||
|
||||
#include <boost/thread/externally_locked_stream.hpp>
|
||||
@@ -78,6 +79,7 @@
|
||||
|
||||
`stream_guard` is a model of __StrictLock.
|
||||
|
||||
[//////////////////////////////////////////////////]
|
||||
[section:constructor `stream_guard(mutex_type & m)`]
|
||||
|
||||
[variablelist
|
||||
@@ -89,7 +91,7 @@
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[////////////////////////////////////////////////////////////////////////////]
|
||||
[section:constructor_adopt `stream_guard(mutex_type & m,boost::adopt_lock_t)`]
|
||||
|
||||
[variablelist
|
||||
@@ -105,8 +107,7 @@ obtained by a call to [lock_ref_link `m.lock()`].]]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[//////////////////////////////////////////////////////////]
|
||||
[section:move_constructor `stream_guard(stream_guard && m)`]
|
||||
|
||||
|
||||
@@ -119,8 +120,7 @@ obtained by a call to [lock_ref_link `m.lock()`].]]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[////////////////////////////////////]
|
||||
[section:destructor `~stream_guard()`]
|
||||
|
||||
[variablelist
|
||||
@@ -134,8 +134,8 @@ object passed to the constructor.]]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[endsect]
|
||||
[//////////////////////////////////////////////////////////////////]
|
||||
[section:externally_locked_stream Class `externally_locked_stream `]
|
||||
|
||||
#include <boost/thread/externally_locked_stream.hpp>
|
||||
@@ -152,7 +152,6 @@ object passed to the constructor.]]
|
||||
|
||||
// Modifiers
|
||||
stream_guard<Stream, RecursiveMutex> hold();
|
||||
Stream& bypass() const;
|
||||
|
||||
};
|
||||
}
|
||||
@@ -162,6 +161,7 @@ provides full access to that object through the `get` member functions, provided
|
||||
pass a reference to a strict lock object.
|
||||
|
||||
|
||||
[////////////////////////////////////////////////////////////////////////]
|
||||
[section:constructor `externally_locked_stream(Stream&, RecursiveMutex&)`]
|
||||
|
||||
[variablelist
|
||||
@@ -172,6 +172,7 @@ pass a reference to a strict lock object.
|
||||
|
||||
[endsect]
|
||||
|
||||
[/////////////////////]
|
||||
[section:hold `hold()`]
|
||||
|
||||
[variablelist
|
||||
@@ -182,6 +183,8 @@ pass a reference to a strict lock object.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
@@ -20,24 +20,44 @@ In addition to the C++11 standard locks, Boost.Thread provides other locks and s
|
||||
|
||||
[section:with Executing Around a Function]
|
||||
|
||||
In particular, the library provides some lock factories.
|
||||
In particular, the library provides a way to lock around the execution of a function.
|
||||
|
||||
template <class Lockable, class Function>
|
||||
auto with_lock_guard(Lockable& m, Function f) -> decltype(fn())
|
||||
{
|
||||
auto&& _ = boost::make_lock_guard(f);
|
||||
f();
|
||||
template <class Lockable, class Function, class... Args>
|
||||
auto with_lock_guard(
|
||||
Lockable& m,
|
||||
Function&& func,
|
||||
Args&&... args
|
||||
) -> decltype(func(boost::forward<Args>(args)...)) {
|
||||
boost::lock_guard<Lockable> lock(m);
|
||||
return func(boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
that can be used with regular functions:
|
||||
|
||||
that can be used as
|
||||
int func(int, int&);
|
||||
//...
|
||||
boost::mutex m;
|
||||
int a;
|
||||
int result = boost::with_lock_guard(m, func, 1, boost::ref(a));
|
||||
|
||||
int i = with_lock_guard(mtx, {}() -> bool
|
||||
{
|
||||
// access the protected state
|
||||
return true;
|
||||
});
|
||||
with boost::bind:
|
||||
|
||||
int result = boost::with_lock_guard(
|
||||
m, boost::bind(func, 2, boost::ref(a))
|
||||
);
|
||||
|
||||
or with lambda expression:
|
||||
|
||||
int a;
|
||||
int result = boost::with_lock_guard(
|
||||
m,
|
||||
[&a](int x) {
|
||||
// this scope is protected by mutex m
|
||||
a = 3;
|
||||
return x + 4;
|
||||
},
|
||||
5
|
||||
);
|
||||
|
||||
[endsect] [/ With]
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/]
|
||||
|
||||
|
||||
[section:synchronized_valuesxxx Synchronized values - EXPERIMENTAL]
|
||||
[section:synchronized_valuesxxx Synchronized Values - EXPERIMENTAL]
|
||||
|
||||
[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 :(]
|
||||
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
|
||||
[library Thread
|
||||
[quickbook 1.5]
|
||||
[version 4.1.0]
|
||||
[version 4.4.0]
|
||||
[authors [Williams, Anthony] [Botet Escriba, Vicente J.]]
|
||||
[copyright 2007-11 Anthony Williams]
|
||||
[copyright 2011-13 Vicente J. Botet Escriba]
|
||||
[copyright 2011-14 Vicente J. Botet Escriba]
|
||||
[purpose C++ Library for launching threads and synchronizing data between them]
|
||||
[category text]
|
||||
[license
|
||||
@@ -239,9 +239,9 @@
|
||||
[include condition_variables.qbk]
|
||||
[include once.qbk]
|
||||
[include barrier.qbk]
|
||||
[/include latch.qbk]
|
||||
[include latch.qbk]
|
||||
[include async_executors.qbk]
|
||||
[include futures.qbk]
|
||||
[/include async_executors.qbk]
|
||||
[endsect]
|
||||
|
||||
|
||||
@@ -249,7 +249,7 @@
|
||||
|
||||
[section:sds Synchronized Data Structures]
|
||||
[include synchronized_value.qbk]
|
||||
[/include sync_queues_ref.qbk]
|
||||
[include sync_queues_ref.qbk]
|
||||
[/include sync_streams.qbk]
|
||||
[endsect]
|
||||
|
||||
|
||||
@@ -26,7 +26,13 @@
|
||||
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
|
||||
template <class Rep, class Period>
|
||||
void sleep_for(const chrono::duration<Rep, Period>& rel_time);
|
||||
|
||||
namespace no_interruption_point // EXTENSION
|
||||
{
|
||||
template <class Clock, class Duration>
|
||||
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
|
||||
template <class Rep, class Period>
|
||||
void sleep_for(const chrono::duration<Rep, Period>& rel_time);
|
||||
}
|
||||
template<typename Callable>
|
||||
void at_thread_exit(Callable func); // EXTENSION
|
||||
|
||||
@@ -470,6 +476,7 @@ This behavior is incompatible with the current Boost.Thread design, so the use o
|
||||
void detach();
|
||||
|
||||
static unsigned hardware_concurrency() noexcept;
|
||||
static unsigned physical_concurrency() noexcept;
|
||||
|
||||
typedef platform-specific-type native_handle_type;
|
||||
native_handle_type native_handle();
|
||||
@@ -532,24 +539,14 @@ This behavior is incompatible with the current Boost.Thread design, so the use o
|
||||
|
||||
thread& operator=(thread&& other) noexcept;
|
||||
|
||||
|
||||
[warning
|
||||
DEPRECATED since 3.0.0: BOOST_THREAD_DONT_PROVIDE_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE behavior.
|
||||
|
||||
Available only up to Boost 1.56.
|
||||
|
||||
Join the thread before moving.
|
||||
]
|
||||
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [Transfers ownership of the thread managed by `other` (if
|
||||
any) to `*this`.
|
||||
|
||||
- if defined BOOST_THREAD_DONT_PROVIDE_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE: If there was a thread previously associated with `*this` then that thread is detached, DEPRECATED
|
||||
- if defined BOOST_THREAD_DONT_PROVIDE_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE: If the thread is joinable call __detach__, DEPRECATED
|
||||
|
||||
- if defined BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE: If the thread is joinable calls to std::terminate.
|
||||
- if defined BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE: If the thread is joinable calls to `std::terminate()`.
|
||||
]]
|
||||
|
||||
[[Postconditions:] [`other->get_id()==thread::id()` and `get_id()` returns the value of `other.get_id()` prior to the assignment.]]
|
||||
@@ -568,7 +565,7 @@ any) to `*this`.
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Requires:] [`Callable` must by Copyable and `func()` must be a valid expression.]]
|
||||
[[Requires:] [`Callable` must be Copyable and `func()` must be a valid expression.]]
|
||||
|
||||
[[Effects:] [`func` is copied into storage managed internally by the thread library, and that copy is invoked on a newly-created
|
||||
thread of execution. If this invocation results in an exception being propagated into the internals of the thread library that is
|
||||
@@ -595,7 +592,7 @@ not of type __thread_interrupted__, then `std::terminate()` will be called. Any
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Preconditions:] [`Callable` must by copyable.]]
|
||||
[[Preconditions:] [`Callable` must be copyable.]]
|
||||
|
||||
[[Effects:] [`func` is copied into storage managed internally by the thread library, and that copy is invoked on a newly-created
|
||||
thread of execution with the specified attributes. If this invocation results in an exception being propagated into the internals of the thread library that is
|
||||
@@ -623,7 +620,7 @@ If the attributes declare the native thread as detached, the boost::thread will
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Preconditions:] [`Callable` must by Movable.]]
|
||||
[[Preconditions:] [`Callable` must be Movable.]]
|
||||
|
||||
[[Effects:] [`func` is moved into storage managed internally by the thread library, and that copy is invoked on a newly-created
|
||||
thread of execution. If this invocation results in an exception being propagated into the internals of the thread library that is
|
||||
@@ -650,7 +647,7 @@ not of type __thread_interrupted__, then `std::terminate()` will be called. Any
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Preconditions:] [`Callable` must by copyable.]]
|
||||
[[Preconditions:] [`Callable` must be copyable.]]
|
||||
|
||||
[[Effects:] [`func` is copied into storage managed internally by the thread library, and that copy is invoked on a newly-created
|
||||
thread of execution with the specified attributes. If this invocation results in an exception being propagated into the internals of the thread library that is
|
||||
@@ -679,7 +676,7 @@ If the attributes declare the native thread as detached, the boost::thread will
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Preconditions:] [`F` and each `A`n must by copyable or movable.]]
|
||||
[[Preconditions:] [`F` and each `A`n must be copyable or movable.]]
|
||||
|
||||
[[Effects:] [As if [link
|
||||
thread.thread_management.thread.callable_constructor
|
||||
@@ -706,24 +703,17 @@ are copied into internal storage for access by the new thread.]]]
|
||||
|
||||
~thread();
|
||||
|
||||
[warning
|
||||
DEPRECATED since 3.0.0: BOOST_THREAD_DONT_PROVIDE_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE behavior.
|
||||
|
||||
Available only up to Boost 1.56.
|
||||
|
||||
Join the thread before destroying or use a scoped thread.
|
||||
]
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Effects:] [
|
||||
- if defined BOOST_THREAD_DONT_PROVIDE_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE: If `*this` has an associated thread of execution, calls __detach__, DEPRECATED
|
||||
- if defined BOOST_THREAD_DONT_PROVIDE_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE: If the thread is joinable calls __detach__, DEPRECATED
|
||||
|
||||
- BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE: If the thread is joinable calls to std::terminate. Destroys `*this`.]]
|
||||
- if defined BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE: If the thread is joinable calls to `std::terminate`. Destroys `*this`.]]
|
||||
|
||||
[[Throws:] [Nothing.]]
|
||||
|
||||
[[Note:] [Either implicitly detaching or joining a `joinable()` thread in its destructor could result in difficult to debug correctness (for `detach`) or performance (for `join`) bugs encountered only when an exception is raised. Thus the programmer must ensure that the destructor is never executed while the thread is still joinable.]]
|
||||
[[Note:] [The reason to moving to std::terminate is that either implicitly detaching or joining a `joinable()` thread in its destructor could result in difficult to debug correctness (for `detach`) or performance (for `join`) bugs encountered only when an exception is raised. Thus the programmer must ensure that the destructor is never executed while the thread is still joinable. Join the thread before destroying or use an scoped thread.]]
|
||||
|
||||
]
|
||||
|
||||
@@ -768,7 +758,7 @@ corresponding successful `join()` return. ]]
|
||||
|
||||
[*resource_deadlock_would_occur]: if deadlock is detected or `this->get_id() == boost::this_thread::get_id()`.
|
||||
|
||||
[*invalid_argument]: if the thread is not joinable and `BOOST_THREAD_TRHOW_IF_PRECONDITION_NOT_SATISFIED` is defined.
|
||||
[*invalid_argument]: if the thread is not joinable and `BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED` is defined.
|
||||
|
||||
|
||||
[/
|
||||
@@ -794,8 +784,6 @@ corresponding successful `join()` return. ]]
|
||||
[warning
|
||||
DEPRECATED since 3.00.
|
||||
|
||||
Available only up to Boost 1.56.
|
||||
|
||||
Use instead __try_join_for, __try_join_until.
|
||||
]
|
||||
|
||||
@@ -819,7 +807,7 @@ unchanged.]]
|
||||
|
||||
[*resource_deadlock_would_occur]: if deadlock is detected or this->get_id() == boost::this_thread::get_id().
|
||||
|
||||
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_TRHOW_IF_PRECONDITION_NOT_SATISFIED is defined.
|
||||
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is defined.
|
||||
|
||||
|
||||
[/
|
||||
@@ -859,7 +847,7 @@ unchanged.]]
|
||||
|
||||
[*resource_deadlock_would_occur]: if deadlock is detected or this->get_id() == boost::this_thread::get_id().
|
||||
|
||||
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_TRHOW_IF_PRECONDITION_NOT_SATISFIED is defined.
|
||||
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is defined.
|
||||
|
||||
|
||||
[/
|
||||
@@ -899,7 +887,7 @@ unchanged.]]
|
||||
|
||||
[*resource_deadlock_would_occur]: if deadlock is detected or this->get_id() == boost::this_thread::get_id().
|
||||
|
||||
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_TRHOW_IF_PRECONDITION_NOT_SATISFIED is defined.
|
||||
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is defined.
|
||||
|
||||
|
||||
[/
|
||||
@@ -935,7 +923,7 @@ unchanged.]]
|
||||
|
||||
[*no_such_process]: if the thread is not valid.
|
||||
|
||||
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_TRHOW_IF_PRECONDITION_NOT_SATISFIED is defined.
|
||||
[*invalid_argument]: if the thread is not joinable and BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is defined.
|
||||
|
||||
]]
|
||||
|
||||
@@ -991,6 +979,21 @@ or 0 if this information is not available.]]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:physical_concurrency Static member function `physical_concurrency()`]
|
||||
|
||||
unsigned physical_concurrency() noexecpt;
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Returns:] [The number of physical cores available on the current system. In contrast to `hardware_concurrency()` it does not return
|
||||
the number of virtual cores, but it counts only physical cores.]]
|
||||
|
||||
[[Throws:] [Nothing]]
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:nativehandle Member function `native_handle()`]
|
||||
|
||||
typedef platform-specific-type native_handle_type;
|
||||
@@ -1014,8 +1017,6 @@ implementation. If no such instance exists, `native_handle()` and `native_handle
|
||||
[warning
|
||||
DEPRECATED since 4.0.0.
|
||||
|
||||
Available only up to Boost 1.58.
|
||||
|
||||
Use `a.__get_id()==b.__get_id()` instead`.
|
||||
]
|
||||
|
||||
@@ -1036,8 +1037,6 @@ Use `a.__get_id()==b.__get_id()` instead`.
|
||||
[warning
|
||||
DEPRECATED since 4.0.0.
|
||||
|
||||
Available only up to Boost 1.58.
|
||||
|
||||
Use `a.__get_id()!=b.__get_id()` instead`.
|
||||
]
|
||||
|
||||
@@ -1056,8 +1055,6 @@ Use `a.__get_id()!=b.__get_id()` instead`.
|
||||
[warning
|
||||
DEPRECATED since 3.0.0.
|
||||
|
||||
Available only up to Boost 1.56.
|
||||
|
||||
Use `this_thread::__sleep_for()` or `this_thread::__sleep_until()`.
|
||||
]
|
||||
|
||||
@@ -1081,8 +1078,6 @@ Use `this_thread::__sleep_for()` or `this_thread::__sleep_until()`.
|
||||
[warning
|
||||
DEPRECATED since 3.0.0.
|
||||
|
||||
Available only up to Boost 1.56.
|
||||
|
||||
Use `this_thread::__yield()`.
|
||||
]
|
||||
|
||||
@@ -1474,8 +1469,6 @@ thread attributes implementation. If no such instance exists, `native_handle()`
|
||||
[warning
|
||||
DEPRECATED since 3.0.0.
|
||||
|
||||
Available only up to Boost 1.56.
|
||||
|
||||
Use `__sleep_for()` and `__sleep_until()` instead.
|
||||
]
|
||||
|
||||
@@ -1502,6 +1495,11 @@ specified by `rel_time` has elapsed or the time point specified by
|
||||
{
|
||||
template <class Clock, class Duration>
|
||||
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
|
||||
namespace no_interruption_point
|
||||
{
|
||||
template <class Clock, class Duration>
|
||||
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
|
||||
}
|
||||
}
|
||||
|
||||
[variablelist
|
||||
@@ -1513,6 +1511,7 @@ specified by `rel_time` has elapsed or the time point specified by
|
||||
do not throw exceptions. __thread_interrupted__ if the current thread of execution is interrupted. ]]
|
||||
|
||||
[[Notes:] [`sleep_until()` is one of the predefined __interruption_points__.]]
|
||||
[[Notes:] [`no_interruption_point::sleep_until()` is NOT one of the __interruption_points__.]]
|
||||
|
||||
]
|
||||
|
||||
@@ -1526,6 +1525,11 @@ do not throw exceptions. __thread_interrupted__ if the current thread of executi
|
||||
{
|
||||
template <class Rep, class Period>
|
||||
void sleep_for(const chrono::duration<Rep, Period>& rel_time);
|
||||
namespace no_interruption_point
|
||||
{
|
||||
template <class Rep, class Period>
|
||||
void sleep_for(const chrono::duration<Rep, Period>& rel_time);
|
||||
}
|
||||
}
|
||||
|
||||
[variablelist
|
||||
@@ -1536,6 +1540,7 @@ by `rel_time` has elapsed.]]
|
||||
[[Throws:] [Nothing if operations of chrono::duration<Rep, Period> do not throw exceptions. __thread_interrupted__ if the current thread of execution is interrupted.]]
|
||||
|
||||
[[Notes:] [`sleep_for()` is one of the predefined __interruption_points__.]]
|
||||
[[Notes:] [`no_interruption_point:: sleep_for()` is NOT one of the __interruption_points__.]]
|
||||
|
||||
]
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ class bounded_buffer : private boost::noncopyable
|
||||
public:
|
||||
typedef boost::unique_lock<boost::mutex> lock;
|
||||
|
||||
bounded_buffer(int n) : begin(0), end(0), buffered(0), circular_buf(n) { }
|
||||
bounded_buffer(int n) : boost::noncopyable(), begin(0), end(0), buffered(0), circular_buf(n) { }
|
||||
|
||||
void send (int m) {
|
||||
lock lk(monitor);
|
||||
|
||||
150
example/executor.cpp
Normal file
150
example/executor.cpp
Normal file
@@ -0,0 +1,150 @@
|
||||
// Copyright (C) 2012-2013 Vicente Botet
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
//#define BOOST_THREAD_USES_LOG
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
|
||||
#include <boost/thread/caller_context.hpp>
|
||||
#include <boost/thread/executors/basic_thread_pool.hpp>
|
||||
#include <boost/thread/executors/loop_executor.hpp>
|
||||
#include <boost/thread/executors/serial_executor.hpp>
|
||||
#include <boost/thread/executors/inline_executor.hpp>
|
||||
#include <boost/thread/executors/thread_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(200));
|
||||
}
|
||||
|
||||
void p2()
|
||||
{
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
//boost::this_thread::sleep_for(boost::chrono::seconds(10));
|
||||
}
|
||||
|
||||
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::executor& tp)
|
||||
{
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
tp.submit(&p2);
|
||||
}
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
tp.submit(&p1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void at_th_entry(boost::basic_thread_pool& )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int test_executor_adaptor()
|
||||
{
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
{
|
||||
try
|
||||
{
|
||||
{
|
||||
boost::executor_adaptor < boost::basic_thread_pool > ea(4);
|
||||
submit_some( ea);
|
||||
{
|
||||
boost::future<int> t1 = boost::async(ea, &f1);
|
||||
boost::future<int> t2 = boost::async(ea, &f1);
|
||||
// std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
|
||||
// std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl;
|
||||
}
|
||||
submit_some(ea);
|
||||
{
|
||||
boost::basic_thread_pool ea3(1);
|
||||
boost::future<int> t1 = boost::async(ea3, &f1);
|
||||
boost::future<int> t2 = boost::async(ea3, &f1);
|
||||
//boost::future<int> t2 = boost::async(ea3, f2, 1); // todo this doesn't compiles yet on C++11
|
||||
//boost::future<int> t2 = boost::async(ea3, boost::bind(f2, 1)); // todo this doesn't compiles yet on C++98
|
||||
// std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
|
||||
// std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl;
|
||||
}
|
||||
submit_some(ea);
|
||||
}
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
{
|
||||
boost::executor_adaptor < boost::loop_executor > ea2;
|
||||
submit_some( ea2);
|
||||
ea2.underlying_executor().run_queued_closures();
|
||||
}
|
||||
#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
{
|
||||
boost::executor_adaptor < boost::basic_thread_pool > ea1(4);
|
||||
boost::executor_adaptor < boost::serial_executor > ea2(ea1);
|
||||
submit_some(ea2);
|
||||
}
|
||||
#endif
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
{
|
||||
boost::executor_adaptor < boost::inline_executor > ea1;
|
||||
submit_some(ea1);
|
||||
}
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
{
|
||||
boost::executor_adaptor < boost::thread_executor > ea1;
|
||||
submit_some(ea1);
|
||||
}
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
{
|
||||
boost::basic_thread_pool ea(4, at_th_entry);
|
||||
boost::future<int> t1 = boost::async(ea, &f1);
|
||||
// std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << 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();
|
||||
}
|
||||
103
example/future_fallback_to.cpp
Normal file
103
example/future_fallback_to.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
// Copyright (C) 2012-2013 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_USES_LOG
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
|
||||
#include <boost/thread/detail/log.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <exception>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
||||
|
||||
int p1_ex()
|
||||
{
|
||||
BOOST_THREAD_LOG << "P1" << BOOST_THREAD_END_LOG;
|
||||
throw std::logic_error("kk");
|
||||
}
|
||||
|
||||
int p1()
|
||||
{
|
||||
BOOST_THREAD_LOG << "P1" << BOOST_THREAD_END_LOG;
|
||||
return 1;;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
const int number_of_tests = 100;
|
||||
BOOST_THREAD_LOG << "<MAIN" << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
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();
|
||||
BOOST_ASSERT(f2.get()==1);
|
||||
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
std::cout << "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;
|
||||
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;
|
||||
boost::future<int> f2 = f1.fallback_to(-1);
|
||||
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
||||
f2.wait();
|
||||
BOOST_ASSERT(f2.get()==-1);
|
||||
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
std::cout << "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;
|
||||
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
BOOST_THREAD_LOG << "MAIN>" << BOOST_THREAD_END_LOG;
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -3,8 +3,14 @@
|
||||
// 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_USES_LOG
|
||||
//#define BOOST_THREAD_USES_LOG
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
|
||||
#include <boost/thread/detail/log.hpp>
|
||||
@@ -19,15 +25,16 @@ int p1()
|
||||
return 123;
|
||||
}
|
||||
|
||||
int p2(boost::future<int>& f)
|
||||
int p2(boost::future<int> f)
|
||||
{
|
||||
BOOST_THREAD_LOG << "<P2" << BOOST_THREAD_END_LOG;
|
||||
BOOST_THREAD_LOG << "P2<" << BOOST_THREAD_END_LOG;
|
||||
try
|
||||
{
|
||||
return 2 * f.get();
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
std::cout << "ERRORRRRR "<<ex.what() << "" << std::endl;
|
||||
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
|
||||
BOOST_ASSERT(false);
|
||||
}
|
||||
@@ -37,26 +44,81 @@ int p2(boost::future<int>& f)
|
||||
BOOST_ASSERT(false);
|
||||
}
|
||||
BOOST_THREAD_LOG << "P2>" << BOOST_THREAD_END_LOG;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main()
|
||||
int p2s(boost::shared_future<int> f)
|
||||
{
|
||||
BOOST_THREAD_LOG << "<MAIN" << BOOST_THREAD_END_LOG;
|
||||
BOOST_THREAD_LOG << "<P2S" << BOOST_THREAD_END_LOG;
|
||||
try
|
||||
{
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
boost::future<int> f2 = f1.then(&p2);
|
||||
(void)f2.get();
|
||||
return 2 * f.get();
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
std::cout << "ERRORRRRR "<<ex.what() << "" << std::endl;
|
||||
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
|
||||
return 1;
|
||||
BOOST_ASSERT(false);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
|
||||
return 2;
|
||||
BOOST_ASSERT(false);
|
||||
}
|
||||
BOOST_THREAD_LOG << "P2S>" << BOOST_THREAD_END_LOG;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
const int number_of_tests = 100;
|
||||
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(&p1);
|
||||
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
||||
boost::future<int> f2 = f1.then(&p2);
|
||||
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
||||
(void)f2.get();
|
||||
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
std::cout << "ERRORRRRR "<<ex.what() << "" << std::endl;
|
||||
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
|
||||
return 1;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
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::shared_future<int> f1 = boost::async(&p1).share();
|
||||
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
||||
boost::future<int> f2 = f1.then(&p2s);
|
||||
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
||||
(void)f2.get();
|
||||
BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
std::cout << "ERRORRRRR "<<ex.what() << "" << std::endl;
|
||||
BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
|
||||
return 1;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
BOOST_THREAD_LOG << "MAIN>" << BOOST_THREAD_END_LOG;
|
||||
return 0;
|
||||
|
||||
70
example/future_unwrap.cpp
Normal file
70
example/future_unwrap.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
// Copyright (C) 2012-2013 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_USES_LOG
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
|
||||
#include <boost/thread/detail/log.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
|
||||
|
||||
int p1()
|
||||
{
|
||||
BOOST_THREAD_LOG << "P1" << BOOST_THREAD_END_LOG;
|
||||
return 123;
|
||||
}
|
||||
|
||||
boost::future<int> p2()
|
||||
{
|
||||
BOOST_THREAD_LOG << "<P2" << BOOST_THREAD_END_LOG;
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
BOOST_THREAD_LOG << "P2>" << BOOST_THREAD_END_LOG;
|
||||
return boost::move(f1);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
const int number_of_tests = 100;
|
||||
BOOST_THREAD_LOG << "<MAIN" << BOOST_THREAD_END_LOG;
|
||||
for (int i=0; i< number_of_tests; i++)
|
||||
try
|
||||
{
|
||||
boost::future<boost::future<int> > outer_future = boost::async(boost::launch::async, &p2);
|
||||
boost::future<int> inner_future = outer_future.unwrap();
|
||||
int ii = inner_future.get();
|
||||
BOOST_THREAD_LOG << "ii= "<< ii << "" << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
std::cout << "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;
|
||||
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
|
||||
return 2;
|
||||
}
|
||||
BOOST_THREAD_LOG << "MAIN>" << BOOST_THREAD_END_LOG;
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
323
example/future_when_all.cpp
Normal file
323
example/future_when_all.cpp
Normal file
@@ -0,0 +1,323 @@
|
||||
// Copyright (C) 2012-2013 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_USES_LOG
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/thread/csbl/vector.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/thread/detail/log.hpp>
|
||||
#include <string>
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
|
||||
|
||||
int p1()
|
||||
{
|
||||
BOOST_THREAD_LOG
|
||||
<< "P1" << BOOST_THREAD_END_LOG;
|
||||
boost::this_thread::sleep_for(boost::chrono::seconds(1));
|
||||
return 123;
|
||||
}
|
||||
int p1b()
|
||||
{
|
||||
BOOST_THREAD_LOG
|
||||
<< "P1b" << BOOST_THREAD_END_LOG;
|
||||
boost::this_thread::sleep_for(boost::chrono::seconds(1));
|
||||
return 321;
|
||||
}
|
||||
|
||||
int p2(boost::future<int> f)
|
||||
{
|
||||
BOOST_THREAD_LOG
|
||||
<< " P2 " << BOOST_THREAD_END_LOG;
|
||||
try
|
||||
{
|
||||
return 2 * f.get();
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
BOOST_THREAD_LOG
|
||||
<< "ERRORRRRR " << ex.what() << "" << BOOST_THREAD_END_LOG;
|
||||
BOOST_ASSERT(false);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_THREAD_LOG
|
||||
<< " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
|
||||
BOOST_ASSERT(false);
|
||||
}
|
||||
BOOST_THREAD_LOG
|
||||
<< "P2>" << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
int p2s(boost::shared_future<int> f)
|
||||
{
|
||||
BOOST_THREAD_LOG
|
||||
<< "<P2" << BOOST_THREAD_END_LOG;
|
||||
try
|
||||
{
|
||||
return 2 * f.get();
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
BOOST_THREAD_LOG
|
||||
<< "ERRORRRRR " << ex.what() << "" << BOOST_THREAD_END_LOG;
|
||||
BOOST_ASSERT(false);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_THREAD_LOG
|
||||
<< " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
|
||||
BOOST_ASSERT(false);
|
||||
}
|
||||
BOOST_THREAD_LOG
|
||||
<< "P2>" << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
BOOST_THREAD_LOG
|
||||
<< "<MAIN" << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
try
|
||||
{
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<boost::csbl::tuple<> > all0 = boost::when_all();
|
||||
BOOST_THREAD_LOG
|
||||
<< BOOST_THREAD_END_LOG;
|
||||
}
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1));
|
||||
boost::csbl::tuple<boost::future<int> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1));
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::csbl::tuple<boost::future<int> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
#endif
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<int> f1 = boost::make_ready_future(1);
|
||||
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1));
|
||||
boost::csbl::tuple<boost::future<int> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
boost::future<int> f2 = boost::async(boost::launch::async, &p1b);
|
||||
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2));
|
||||
//(void) all.wait();
|
||||
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
boost::future<std::string> f2 = boost::make_ready_future(std::string("nnnnnnn"));;
|
||||
boost::future<boost::csbl::tuple<boost::future<int>, boost::future<std::string> > > all = boost::when_all(boost::move(f1), boost::move(f2));
|
||||
//(void) all.wait();
|
||||
boost::csbl::tuple<boost::future<int>, boost::future<std::string> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::csbl::vector<boost::future<int> > v;
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
v.push_back(boost::async(boost::launch::async, &p1));
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
v.push_back(boost::async(boost::launch::async, &p1b));
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(v.begin(), v.end());
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::csbl::vector<boost::future<int> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< res[0].get() <<" " << BOOST_THREAD_END_LOG;
|
||||
BOOST_THREAD_LOG
|
||||
<< res[1].get() <<" " << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
BOOST_THREAD_LOG
|
||||
<< "ERRORRRRR " << ex.what() << "" << BOOST_THREAD_END_LOG;
|
||||
return 1;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_THREAD_LOG
|
||||
<< " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
{
|
||||
try
|
||||
{
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<boost::csbl::tuple<> > all0 = boost::when_any();
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_any(boost::move(f1));
|
||||
boost::csbl::tuple<boost::future<int> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);
|
||||
boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_any(boost::move(f1));
|
||||
boost::csbl::tuple<boost::future<int> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
#endif
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
boost::future<int> f2 = boost::async(boost::launch::async, &p1b);
|
||||
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
|
||||
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<int> f1 = boost::make_ready_future(1);
|
||||
boost::future<int> f2 = boost::async(boost::launch::async, &p1b);
|
||||
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
|
||||
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<std::string> f1 = boost::make_ready_future(std::string("aaaa"));
|
||||
boost::future<int> f2 = boost::async(boost::launch::async, &p1b);
|
||||
boost::future<boost::csbl::tuple<boost::future<std::string>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
|
||||
boost::csbl::tuple<boost::future<std::string>,boost::future<int> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<int> f2 = boost::make_ready_future(1);
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1b);
|
||||
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
|
||||
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);
|
||||
boost::future<int> f2 = boost::async(boost::launch::async, &p1b);
|
||||
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
|
||||
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
|
||||
boost::future<int> f2 = boost::async(boost::launch::deferred, &p1b);
|
||||
boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2));
|
||||
boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
#endif
|
||||
{
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::csbl::vector<boost::future<int> > v;
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
v.push_back(boost::async(boost::launch::async, &p1));
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
v.push_back(boost::async(boost::launch::async, &p1b));
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end());
|
||||
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
|
||||
boost::csbl::vector<boost::future<int> > res = all.get();
|
||||
BOOST_THREAD_LOG
|
||||
<< res[0].get() <<" " << BOOST_THREAD_END_LOG;
|
||||
BOOST_THREAD_LOG
|
||||
<< res[1].get() <<" " << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
BOOST_THREAD_LOG
|
||||
<< "ERRORRRRR " << ex.what() << "" << BOOST_THREAD_END_LOG;
|
||||
return 1;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_THREAD_LOG
|
||||
<< " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
BOOST_THREAD_LOG
|
||||
<< "MAIN>" << BOOST_THREAD_END_LOG;
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#include <boost/thread/csbl/vector.hpp>
|
||||
using namespace boost;
|
||||
|
||||
void f( boost::csbl::vector<future<int> > &//vec
|
||||
, BOOST_THREAD_RV_REF(future<int>) //f
|
||||
) {
|
||||
}
|
||||
int main()
|
||||
{
|
||||
boost::csbl::vector<future<int> > vec;
|
||||
f(vec, make_ready_future(0));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
153
example/generic_executor_ref.cpp
Normal file
153
example/generic_executor_ref.cpp
Normal file
@@ -0,0 +1,153 @@
|
||||
// Copyright (C) 2014 Vicente Botet
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
//#define BOOST_THREAD_USES_LOG
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
|
||||
#include <boost/thread/caller_context.hpp>
|
||||
#include <boost/thread/executors/basic_thread_pool.hpp>
|
||||
#include <boost/thread/executors/loop_executor.hpp>
|
||||
#include <boost/thread/executors/serial_executor.hpp>
|
||||
#include <boost/thread/executors/inline_executor.hpp>
|
||||
#include <boost/thread/executors/thread_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(200));
|
||||
}
|
||||
|
||||
void p2()
|
||||
{
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
//boost::this_thread::sleep_for(boost::chrono::seconds(10));
|
||||
}
|
||||
|
||||
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::generic_executor_ref tp)
|
||||
{
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
tp.submit(&p2);
|
||||
}
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
tp.submit(&p1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void at_th_entry(boost::basic_thread_pool& )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int test_generic_executor_ref()
|
||||
{
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
{
|
||||
try
|
||||
{
|
||||
{
|
||||
boost::basic_thread_pool ea(4);
|
||||
submit_some( ea);
|
||||
{
|
||||
boost::future<int> t1 = boost::async(ea, &f1);
|
||||
boost::future<int> t2 = boost::async(ea, &f1);
|
||||
// std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
|
||||
// std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl;
|
||||
}
|
||||
submit_some(ea);
|
||||
{
|
||||
boost::basic_thread_pool ea3(1);
|
||||
boost::future<int> t1 = boost::async(ea3, &f1);
|
||||
boost::future<int> t2 = boost::async(ea3, &f1);
|
||||
//boost::future<int> t2 = boost::async(ea3, f2, 1); // todo this doesn't compiles yet on C++11
|
||||
//boost::future<int> t2 = boost::async(ea3, boost::bind(f2, 1)); // todo this doesn't compiles yet on C++98
|
||||
// std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl;
|
||||
// std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl;
|
||||
}
|
||||
submit_some(ea);
|
||||
}
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
{
|
||||
boost::loop_executor ea2;
|
||||
submit_some( ea2);
|
||||
ea2.run_queued_closures();
|
||||
}
|
||||
#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);
|
||||
}
|
||||
#endif
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
{
|
||||
boost::inline_executor ea1;
|
||||
submit_some(ea1);
|
||||
}
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
{
|
||||
//boost::thread_executor ea1;
|
||||
//submit_some(ea1);
|
||||
}
|
||||
// std::cout << BOOST_CONTEXTOF << std::endl;
|
||||
{
|
||||
boost::basic_thread_pool ea(4, at_th_entry);
|
||||
boost::future<int> t1 = boost::async(ea, &f1);
|
||||
// std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << 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_generic_executor_ref();
|
||||
|
||||
|
||||
}
|
||||
@@ -8,22 +8,27 @@
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_USES_LOG
|
||||
//#define BOOST_THREAD_USES_LOG
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
|
||||
#include <boost/thread/detail/log.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION \
|
||||
&& ! defined BOOST_NO_CXX11_LAMBDAS
|
||||
&& ! defined BOOST_NO_CXX11_LAMBDAS && ! (defined BOOST_MSVC && _MSC_VER < 1700)
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
const int number_of_tests = 100;
|
||||
BOOST_THREAD_LOG << "<MAIN" << BOOST_THREAD_END_LOG;
|
||||
|
||||
for (int i=0; i< number_of_tests; i++)
|
||||
try
|
||||
{
|
||||
{
|
||||
@@ -33,18 +38,20 @@ int main()
|
||||
}
|
||||
{
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, []() {return 123;});
|
||||
boost::future<int> f2 = f1.then([](boost::future<int>& f) {return 2*f.get(); });
|
||||
boost::future<int> f2 = f1.then([](boost::future<int> f) {return 2*f.get(); });
|
||||
int result = f2.get();
|
||||
BOOST_THREAD_LOG << "f2 " << result << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
std::cout << "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;
|
||||
BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
|
||||
return 2;
|
||||
}
|
||||
|
||||
@@ -3,59 +3,127 @@
|
||||
// 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
|
||||
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <iostream>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
exception_ptr make_exception_ptr(T v)
|
||||
{
|
||||
return copy_exception(v);
|
||||
}
|
||||
}
|
||||
|
||||
int p1() { return 5; }
|
||||
int& p1r() { static int i=0; return i; }
|
||||
|
||||
void p() { }
|
||||
|
||||
#if defined BOOST_THREAD_USES_MOVE
|
||||
boost::future<void> void_compute()
|
||||
{
|
||||
return BOOST_THREAD_MAKE_RV_REF(boost::make_future());
|
||||
return BOOST_THREAD_MAKE_RV_REF(boost::make_ready_future());
|
||||
}
|
||||
#endif
|
||||
|
||||
boost::future<int> compute(int x)
|
||||
{
|
||||
if (x == 0) return boost::make_future(0);
|
||||
if (x < 0) return boost::make_future(-1);
|
||||
if (x == 0) return boost::make_ready_future(0);
|
||||
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
if (x < 0) return boost::make_exceptional_future<int>(std::logic_error("Error"));
|
||||
#else
|
||||
if (x < 0) return boost::make_exceptional(std::logic_error("Error"));
|
||||
#endif
|
||||
//boost::future<int> f1 = boost::async([]() { return x+1; });
|
||||
boost::future<int> f1 = boost::async(boost::launch::async, p1);
|
||||
boost::future<int> f1 = boost::async(p1);
|
||||
return boost::move(f1);
|
||||
}
|
||||
|
||||
boost::future<int&> compute_ref(int x)
|
||||
{
|
||||
static int i = 0;
|
||||
//if (x == 0) return boost::make_ready_future<int&>(i); //This must not compile as the type is deduced as boost::future<int>
|
||||
if (x == 0) return boost::make_ready_no_decay_future<int&>(i);
|
||||
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
if (x < 0) return boost::make_exceptional_future<int&>(std::logic_error("Error"));
|
||||
#else
|
||||
if (x < 0) return boost::make_exceptional(std::logic_error("Error"));
|
||||
#endif
|
||||
boost::future<int&> f1 = boost::async(p1r);
|
||||
return boost::move(f1);
|
||||
}
|
||||
|
||||
boost::shared_future<int> shared_compute(int x)
|
||||
{
|
||||
if (x == 0) return boost::make_shared_future(0);
|
||||
if (x < 0) return boost::make_shared_future(-1);
|
||||
if (x == 0) return boost::make_ready_future(0).share();
|
||||
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
if (x < 0) return boost::make_exceptional_future<int>(std::logic_error("Error")).share();
|
||||
#else
|
||||
if (x < 0) return boost::make_exceptional(std::logic_error("Error"));
|
||||
#endif
|
||||
//boost::future<int> f1 = boost::async([]() { return x+1; });
|
||||
boost::shared_future<int> f1 = boost::async(p1).share();
|
||||
return boost::move(f1);
|
||||
boost::shared_future<int> f1 = boost::async(&p1).share();
|
||||
return f1;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
const int number_of_tests = 100;
|
||||
for (int i=0; i< number_of_tests; i++)
|
||||
try
|
||||
{
|
||||
// {
|
||||
// std::cout << __FILE__ << " "<<__LINE__ << std::endl;
|
||||
// boost::future<int> f = boost::async(boost::launch::async, p1);
|
||||
// std::cout << i << " "<<f.get() << std::endl;
|
||||
// }
|
||||
#if defined BOOST_THREAD_USES_MOVE
|
||||
{
|
||||
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
|
||||
boost::future<void> f = void_compute();
|
||||
f.get();
|
||||
}
|
||||
#endif
|
||||
{
|
||||
boost::future<int> f = compute(2);
|
||||
std::cout << f.get() << std::endl;
|
||||
}
|
||||
{
|
||||
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
|
||||
boost::future<int> f = compute(0);
|
||||
std::cout << f.get() << std::endl;
|
||||
}
|
||||
{
|
||||
boost::shared_future<int> f = shared_compute(2);
|
||||
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
|
||||
boost::future<int&> f = compute_ref(0);
|
||||
std::cout << f.get() << std::endl;
|
||||
}
|
||||
// {
|
||||
// std::cout << __FILE__ << " "<< __LINE__ << std::endl;
|
||||
// boost::future<int> f = compute(2);
|
||||
// std::cout << f.get() << std::endl;
|
||||
// }
|
||||
{
|
||||
std::cout << __FILE__ << " "<< __LINE__ << std::endl;
|
||||
boost::shared_future<int> f = shared_compute(0);
|
||||
std::cout << f.get() << std::endl;
|
||||
}
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
std::cout << "ERRORRRRR "<<ex.what() << "" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cout << "ERRORRRRR "<<"ERRORRRRR exception thrown" << std::endl;
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -44,8 +44,8 @@ int main()
|
||||
externally_locked_stream<std::ostream> mcout(std::cout, terminal_mutex);
|
||||
externally_locked_stream<std::istream> mcin(std::cin, terminal_mutex);
|
||||
|
||||
scoped_thread<> t1(thread(use_cerr, boost::ref(mcerr)));
|
||||
scoped_thread<> t2(thread(use_cout, boost::ref(mcout)));
|
||||
scoped_thread<> t1(boost::thread(use_cerr, boost::ref(mcerr)));
|
||||
scoped_thread<> t2(boost::thread(use_cout, boost::ref(mcout)));
|
||||
this_thread::sleep_for(chrono::seconds(2));
|
||||
std::string nm;
|
||||
{
|
||||
|
||||
61
example/not_interleaved2.cpp
Normal file
61
example/not_interleaved2.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
// (C) Copyright 2012 Howard Hinnant
|
||||
// (C) Copyright 2012 Vicente Botet
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// adapted from the example given by Howard Hinnant in
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
|
||||
#include <iostream>
|
||||
#include <boost/thread/scoped_thread.hpp>
|
||||
#include <boost/thread/ostream_buffer.hpp>
|
||||
|
||||
void use_cerr()
|
||||
{
|
||||
using namespace boost;
|
||||
chrono::steady_clock::time_point tf = chrono::steady_clock::now() + chrono::seconds(5);
|
||||
int i = 0;
|
||||
while (chrono::steady_clock::now() < tf)
|
||||
{
|
||||
ostream_buffer<std::ostream> mcerr(std::cerr);
|
||||
mcerr.stream() << "logging data to cerr " << i++ << "\n";
|
||||
this_thread::sleep_for(chrono::milliseconds(250));
|
||||
}
|
||||
}
|
||||
|
||||
void use_cout()
|
||||
{
|
||||
using namespace boost;
|
||||
chrono::steady_clock::time_point tf = chrono::steady_clock::now() + chrono::seconds(5);
|
||||
int i = 0;
|
||||
while (chrono::steady_clock::now() < tf)
|
||||
{
|
||||
ostream_buffer<std::ostream> mcout(std::cout);
|
||||
mcout.stream() << "logging data to cout " << i++ << "\n";
|
||||
this_thread::sleep_for(chrono::milliseconds(500));
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace boost;
|
||||
|
||||
scoped_thread<> t1(&use_cerr);
|
||||
scoped_thread<> t2(&use_cout);
|
||||
this_thread::sleep_for(chrono::seconds(2));
|
||||
std::string nm = "he, he\n";
|
||||
{
|
||||
ostream_buffer<std::ostream> mcout(std::cout);
|
||||
mcout.stream() << "Enter name: \n";
|
||||
}
|
||||
t1.join();
|
||||
t2.join();
|
||||
{
|
||||
ostream_buffer<std::ostream> mcout(std::cout);
|
||||
mcout.stream() << nm;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
102
example/parallel_accumulate.cpp
Normal file
102
example/parallel_accumulate.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
// Copyright (C) 2014 Vicente Botet
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
|
||||
#include <boost/thread/executors/basic_thread_pool.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
|
||||
#include <numeric>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
|
||||
template<typename Iterator,typename T>
|
||||
struct accumulate_block
|
||||
{
|
||||
//typedef T result_type;
|
||||
T operator()(Iterator first,Iterator last)
|
||||
{
|
||||
return std::accumulate(first,last,T());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Iterator,typename T>
|
||||
T parallel_accumulate(Iterator first,Iterator last,T init)
|
||||
{
|
||||
unsigned long const length=std::distance(first,last);
|
||||
|
||||
if(!length)
|
||||
return init;
|
||||
|
||||
unsigned long const block_size=25;
|
||||
unsigned long const num_blocks=(length+block_size-1)/block_size;
|
||||
|
||||
boost::csbl::vector<boost::future<T> > futures(num_blocks-1);
|
||||
boost::basic_thread_pool pool;
|
||||
|
||||
Iterator block_start=first;
|
||||
for(unsigned long i=0;i<(num_blocks-1);++i)
|
||||
{
|
||||
Iterator block_end=block_start;
|
||||
std::advance(block_end,block_size);
|
||||
futures[i]=boost::async(pool, accumulate_block<Iterator,T>(), block_start, block_end);
|
||||
block_start=block_end;
|
||||
}
|
||||
T last_result=accumulate_block<Iterator,T>()(block_start,last);
|
||||
T result=init;
|
||||
for(unsigned long i=0;i<(num_blocks-1);++i)
|
||||
{
|
||||
result+=futures[i].get();
|
||||
}
|
||||
result += last_result;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
try
|
||||
{
|
||||
const int s = 1001;
|
||||
std::vector<int> vec;
|
||||
vec.reserve(s);
|
||||
for (int i=0; i<s;++i)
|
||||
vec.push_back(1);
|
||||
int r = parallel_accumulate(vec.begin(), vec.end(),0);
|
||||
std::cout << r << 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;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
///#warning "This compiler doesn't supports variadics"
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
110
example/parallel_quick_sort.cpp
Normal file
110
example/parallel_quick_sort.cpp
Normal file
@@ -0,0 +1,110 @@
|
||||
// Copyright (C) 2012-2013 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>
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_PROVIDES_EXECUTORS
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
|
||||
#include <boost/thread/executors/basic_thread_pool.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
||||
|
||||
#include <numeric>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
|
||||
template<typename T>
|
||||
struct sorter
|
||||
{
|
||||
boost::basic_thread_pool pool;
|
||||
typedef std::list<T> return_type;
|
||||
|
||||
std::list<T> do_sort(std::list<T> chunk_data)
|
||||
{
|
||||
if(chunk_data.empty())
|
||||
{
|
||||
return chunk_data;
|
||||
}
|
||||
|
||||
std::list<T> result;
|
||||
result.splice(result.begin(),chunk_data, chunk_data.begin());
|
||||
T const& partition_val=*result.begin();
|
||||
|
||||
typename std::list<T>::iterator divide_point=
|
||||
std::partition(chunk_data.begin(), chunk_data.end(), [&](T const& val){return val<partition_val;});
|
||||
|
||||
std::list<T> new_lower_chunk;
|
||||
new_lower_chunk.splice(new_lower_chunk.end(), chunk_data, chunk_data.begin(), divide_point);
|
||||
|
||||
boost::future<std::list<T> > new_lower = boost::async(pool, &sorter::do_sort, this, std::move(new_lower_chunk));
|
||||
//boost::future<std::list<T> > new_lower = boost::async<return_type>(pool, &sorter::do_sort, this, std::move(new_lower_chunk));
|
||||
|
||||
std::list<T> new_higher(do_sort(chunk_data));
|
||||
|
||||
result.splice(result.end(),new_higher);
|
||||
while(!new_lower.is_ready())
|
||||
{
|
||||
pool.schedule_one_or_yield();
|
||||
}
|
||||
|
||||
result.splice(result.begin(),new_lower.get());
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
std::list<T> parallel_quick_sort(std::list<T>& input)
|
||||
{
|
||||
if(input.empty())
|
||||
{
|
||||
return input;
|
||||
}
|
||||
sorter<T> s;
|
||||
|
||||
return s.do_sort(input);
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
try
|
||||
{
|
||||
const int s = 101;
|
||||
std::list<int> lst;
|
||||
for (int i=0; i<s;++i)
|
||||
lst.push_back(100-i);
|
||||
std::list<int> r = parallel_quick_sort(lst);
|
||||
for (std::list<int>::const_iterator it=r.begin(); it != r.end(); ++it)
|
||||
std::cout << *it << 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;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
//#warning "This compiler doesn't supports variadics and move semantics"
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -143,7 +143,7 @@ namespace
|
||||
{
|
||||
typedef SharedData<Types> S;
|
||||
|
||||
auto best_producer_time = std::numeric_limits<Stopwatch::rep>::max();
|
||||
auto best_producer_time = std::numeric_limits<Stopwatch::rep>::max BOOST_PREVENT_MACRO_SUBSTITUTION ();
|
||||
|
||||
std::vector<std::thread> consumers
|
||||
{ consumer_count };
|
||||
@@ -165,7 +165,7 @@ namespace
|
||||
for (unsigned i = 0; i < consumer_count; ++i)
|
||||
consumers[i].join();
|
||||
|
||||
best_producer_time = std::min(best_producer_time, shared_data.producer_time);
|
||||
best_producer_time = std::min BOOST_PREVENT_MACRO_SUBSTITUTION (best_producer_time, shared_data.producer_time);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ void unique()
|
||||
|
||||
int main()
|
||||
{
|
||||
boost::chrono::high_resolution_clock::duration best_time(std::numeric_limits<boost::chrono::high_resolution_clock::duration::rep>::max());
|
||||
boost::chrono::high_resolution_clock::duration best_time(std::numeric_limits<boost::chrono::high_resolution_clock::duration::rep>::max BOOST_PREVENT_MACRO_SUBSTITUTION ());
|
||||
for (int i =100; i>0; --i) {
|
||||
boost::chrono::high_resolution_clock clock;
|
||||
boost::chrono::high_resolution_clock::time_point s1 = clock.now();
|
||||
@@ -61,7 +61,7 @@ int main()
|
||||
// t13.join();
|
||||
boost::chrono::high_resolution_clock::time_point f1 = clock.now();
|
||||
//std::cout << " Time spent:" << (f1 - s1) << std::endl;
|
||||
best_time = std::min(best_time, f1 - s1);
|
||||
best_time = std::min BOOST_PREVENT_MACRO_SUBSTITUTION (best_time, f1 - s1);
|
||||
|
||||
}
|
||||
std::cout << "Best Time spent:" << best_time << std::endl;
|
||||
|
||||
@@ -6,22 +6,33 @@
|
||||
|
||||
// adapted from the example given by Howard Hinnant in
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
#include <iostream>
|
||||
#include <boost/thread/scoped_thread.hpp>
|
||||
#ifdef XXXX
|
||||
#include <boost/thread/externally_locked_stream.hpp>
|
||||
typedef boost::externally_locked_stream<std::ostream> the_ostream;
|
||||
#else
|
||||
typedef std::ostream the_ostream;
|
||||
typedef std::istream the_istream;
|
||||
#endif
|
||||
#include <boost/thread/sync_queue.hpp>
|
||||
|
||||
void producer(boost::externally_locked_stream<std::ostream> &mos, boost::sync_queue<int> & sbq)
|
||||
void producer(the_ostream &mos, boost::sync_queue<int> & sbq)
|
||||
{
|
||||
using namespace boost;
|
||||
try {
|
||||
for(int i=0; ;++i)
|
||||
{
|
||||
//sbq.push(i);
|
||||
sbq << i;
|
||||
mos << "push(" << i << ") "<< sbq.size()<<"\n";
|
||||
sbq.push_back(i);
|
||||
//sbq << i;
|
||||
mos << "push_back(" << i << ") "<< sbq.size()<<"\n";
|
||||
this_thread::sleep_for(chrono::milliseconds(200));
|
||||
}
|
||||
}
|
||||
@@ -35,16 +46,19 @@ void producer(boost::externally_locked_stream<std::ostream> &mos, boost::sync_qu
|
||||
}
|
||||
}
|
||||
|
||||
void consumer(boost::externally_locked_stream<std::ostream> &mos, boost::sync_queue<int> & sbq)
|
||||
void consumer(
|
||||
the_ostream &mos,
|
||||
boost::sync_queue<int> & sbq)
|
||||
{
|
||||
using namespace boost;
|
||||
try {
|
||||
for(int i=0; ;++i)
|
||||
{
|
||||
int r;
|
||||
//sbq.pull(r);
|
||||
sbq >> r;
|
||||
sbq.pull_front(r);
|
||||
//sbq >> r;
|
||||
mos << i << " pull(" << r << ") "<< sbq.size()<<"\n";
|
||||
|
||||
this_thread::sleep_for(chrono::milliseconds(250));
|
||||
}
|
||||
}
|
||||
@@ -57,17 +71,36 @@ void consumer(boost::externally_locked_stream<std::ostream> &mos, boost::sync_qu
|
||||
mos << "exception !!!\n";
|
||||
}
|
||||
}
|
||||
void consumer2(boost::externally_locked_stream<std::ostream> &mos, boost::sync_queue<int> & sbq)
|
||||
void consumer2(the_ostream &mos, boost::sync_queue<int> & sbq)
|
||||
{
|
||||
using namespace boost;
|
||||
try {
|
||||
bool closed=false;
|
||||
for(int i=0; ;++i)
|
||||
{
|
||||
int r;
|
||||
sbq.pull(r, closed);
|
||||
if (closed) break;
|
||||
mos << i << " pull(" << r << ")\n";
|
||||
queue_op_status st = sbq.try_pull_front(r);
|
||||
if (queue_op_status::closed == st) break;
|
||||
if (queue_op_status::success == st) {
|
||||
mos << i << " pull(" << r << ")\n";
|
||||
}
|
||||
this_thread::sleep_for(chrono::milliseconds(250));
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
mos << "exception !!!\n";
|
||||
}
|
||||
}
|
||||
void consumer3(the_ostream &mos, boost::sync_queue<int> & sbq)
|
||||
{
|
||||
using namespace boost;
|
||||
try {
|
||||
for(int i=0; ;++i)
|
||||
{
|
||||
int r;
|
||||
queue_op_status res = sbq.wait_pull_front(r);
|
||||
if (res==queue_op_status::closed) break;
|
||||
mos << i << " wait_pull_front(" << r << ")\n";
|
||||
this_thread::sleep_for(chrono::milliseconds(250));
|
||||
}
|
||||
}
|
||||
@@ -76,43 +109,30 @@ void consumer2(boost::externally_locked_stream<std::ostream> &mos, boost::sync_q
|
||||
mos << "exception !!!\n";
|
||||
}
|
||||
}
|
||||
//void consumer3(boost::externally_locked_stream<std::ostream> &mos, boost::sync_queue<int> & sbq)
|
||||
//{
|
||||
// using namespace boost;
|
||||
// bool closed=false;
|
||||
// try {
|
||||
// for(int i=0; ;++i)
|
||||
// {
|
||||
// int r;
|
||||
// queue_op_status res = sbq.wait_and_pull(r);
|
||||
// if (res==queue_op_status::closed) break;
|
||||
// mos << i << " wait_and_pull(" << r << ")\n";
|
||||
// this_thread::sleep_for(chrono::milliseconds(250));
|
||||
// }
|
||||
// }
|
||||
// catch(...)
|
||||
// {
|
||||
// mos << "exception !!!\n";
|
||||
// }
|
||||
//}
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace boost;
|
||||
|
||||
#ifdef XXXX
|
||||
recursive_mutex terminal_mutex;
|
||||
|
||||
externally_locked_stream<std::ostream> mcerr(std::cerr, terminal_mutex);
|
||||
externally_locked_stream<std::ostream> mcout(std::cout, terminal_mutex);
|
||||
externally_locked_stream<std::istream> mcin(std::cin, terminal_mutex);
|
||||
#else
|
||||
the_ostream &mcerr = std::cout;
|
||||
the_ostream &mcout = std::cerr;
|
||||
//the_istream &mcin = std::cin;
|
||||
#endif
|
||||
|
||||
sync_queue<int> sbq;
|
||||
|
||||
{
|
||||
mcout << "begin of main" << std::endl;
|
||||
scoped_thread<> t11(thread(producer, boost::ref(mcerr), boost::ref(sbq)));
|
||||
scoped_thread<> t12(thread(producer, boost::ref(mcerr), boost::ref(sbq)));
|
||||
scoped_thread<> t2(thread(consumer, boost::ref(mcout), boost::ref(sbq)));
|
||||
scoped_thread<> t11(boost::thread(producer, boost::ref(mcerr), boost::ref(sbq)));
|
||||
scoped_thread<> t12(boost::thread(producer, boost::ref(mcerr), boost::ref(sbq)));
|
||||
scoped_thread<> t2(boost::thread(consumer, boost::ref(mcout), boost::ref(sbq)));
|
||||
|
||||
this_thread::sleep_for(chrono::seconds(1));
|
||||
|
||||
|
||||
150
example/producer_consumer2.cpp
Normal file
150
example/producer_consumer2.cpp
Normal file
@@ -0,0 +1,150 @@
|
||||
// (C) Copyright 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)
|
||||
|
||||
// adapted from the example given by Howard Hinnant in
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
//#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
#include <iostream>
|
||||
#include <boost/thread/scoped_thread.hpp>
|
||||
#ifdef XXXX
|
||||
#include <boost/thread/externally_locked_stream.hpp>
|
||||
typedef boost::externally_locked_stream<std::ostream> the_ostream;
|
||||
#else
|
||||
typedef std::ostream the_ostream;
|
||||
typedef std::istream the_istream;
|
||||
#endif
|
||||
#include <boost/thread/sync_queue.hpp>
|
||||
#include <boost/thread/concurrent_queues/queue_adaptor.hpp>
|
||||
#include <boost/thread/concurrent_queues/queue_views.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
|
||||
void producer(the_ostream &mos, boost::queue_back<int> sbq)
|
||||
{
|
||||
using namespace boost;
|
||||
try {
|
||||
for(int i=0; ;++i)
|
||||
{
|
||||
sbq.push(i);
|
||||
//sbq << i;
|
||||
mos << "push(" << i << ") " << sbq.size() <<"\n";
|
||||
this_thread::sleep_for(chrono::milliseconds(200));
|
||||
}
|
||||
}
|
||||
catch(sync_queue_is_closed&)
|
||||
{
|
||||
mos << "closed !!!\n";
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
mos << "exception !!!\n";
|
||||
}
|
||||
}
|
||||
|
||||
void consumer(
|
||||
the_ostream &mos,
|
||||
boost::queue_front<int> sbq)
|
||||
{
|
||||
using namespace boost;
|
||||
try {
|
||||
for(int i=0; ;++i)
|
||||
{
|
||||
int r;
|
||||
sbq.pull(r);
|
||||
//sbq >> r;
|
||||
mos << i << " pull(" << r << ") " << sbq.size() <<"\n";
|
||||
|
||||
this_thread::sleep_for(chrono::milliseconds(250));
|
||||
}
|
||||
}
|
||||
catch(sync_queue_is_closed&)
|
||||
{
|
||||
mos << "closed !!!\n";
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
mos << "exception !!!\n";
|
||||
}
|
||||
}
|
||||
void consumer2(the_ostream &mos, boost::queue_front<int> sbq)
|
||||
{
|
||||
using namespace boost;
|
||||
try {
|
||||
for(int i=0; ;++i)
|
||||
{
|
||||
int r;
|
||||
queue_op_status st = sbq.try_pull(r);
|
||||
if (queue_op_status::closed == st) break;
|
||||
if (queue_op_status::success == st) {
|
||||
mos << i << " try_pull(" << r << ")\n";
|
||||
}
|
||||
this_thread::sleep_for(chrono::milliseconds(250));
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
mos << "exception !!!\n";
|
||||
}
|
||||
}
|
||||
void consumer3(the_ostream &mos, boost::queue_front<int> sbq)
|
||||
{
|
||||
using namespace boost;
|
||||
try {
|
||||
for(int i=0; ;++i)
|
||||
{
|
||||
int r;
|
||||
queue_op_status res = sbq.wait_pull(r);
|
||||
if (res==queue_op_status::closed) break;
|
||||
mos << i << " wait_pull(" << r << ")\n";
|
||||
this_thread::sleep_for(chrono::milliseconds(250));
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
mos << "exception !!!\n";
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace boost;
|
||||
|
||||
#ifdef XXXX
|
||||
recursive_mutex terminal_mutex;
|
||||
|
||||
externally_locked_stream<std::ostream> mcerr(std::cerr, terminal_mutex);
|
||||
externally_locked_stream<std::ostream> mcout(std::cout, terminal_mutex);
|
||||
externally_locked_stream<std::istream> mcin(std::cin, terminal_mutex);
|
||||
#else
|
||||
the_ostream &mcerr = std::cout;
|
||||
the_ostream &mcout = std::cerr;
|
||||
//the_istream &mcin = std::cin;
|
||||
#endif
|
||||
|
||||
queue_adaptor<sync_queue<int> > sbq;
|
||||
|
||||
{
|
||||
mcout << "begin of main" << std::endl;
|
||||
scoped_thread<> t11(boost::thread(producer, boost::ref(mcerr), concurrent::queue_back<int>(sbq)));
|
||||
scoped_thread<> t12(boost::thread(producer, boost::ref(mcerr), concurrent::queue_back<int>(sbq)));
|
||||
scoped_thread<> t2(boost::thread(consumer, boost::ref(mcout), concurrent::queue_front<int>(sbq)));
|
||||
|
||||
this_thread::sleep_for(chrono::seconds(1));
|
||||
|
||||
mcout << "closed()" << std::endl;
|
||||
sbq.close();
|
||||
mcout << "closed()" << std::endl;
|
||||
|
||||
} // all threads joined here.
|
||||
mcout << "end of main" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -6,77 +6,92 @@
|
||||
|
||||
// adapted from the example given by Howard Hinnant in
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
//#define XXXX
|
||||
|
||||
#include <iostream>
|
||||
#include <boost/thread/scoped_thread.hpp>
|
||||
#ifdef XXXX
|
||||
#include <boost/thread/externally_locked_stream.hpp>
|
||||
typedef boost::externally_locked_stream<std::ostream> the_ostream;
|
||||
#else
|
||||
typedef std::ostream the_ostream;
|
||||
typedef std::istream the_istream;
|
||||
#endif
|
||||
|
||||
#include <boost/thread/sync_bounded_queue.hpp>
|
||||
|
||||
void producer(boost::externally_locked_stream<std::ostream> &mos, boost::sync_bounded_queue<int> & sbq)
|
||||
void producer(the_ostream &/*mos*/, boost::sync_bounded_queue<int> & sbq)
|
||||
{
|
||||
using namespace boost;
|
||||
try {
|
||||
for(int i=0; ;++i)
|
||||
{
|
||||
//sbq.push(i);
|
||||
sbq << i;
|
||||
mos << "push(" << i << ") "<< sbq.size()<<"\n";
|
||||
sbq.push_back(i);
|
||||
//sbq << i;
|
||||
//mos << "push_back(" << i << ") "<< sbq.size()<<"\n";
|
||||
this_thread::sleep_for(chrono::milliseconds(200));
|
||||
}
|
||||
}
|
||||
catch(sync_queue_is_closed&)
|
||||
{
|
||||
mos << "closed !!!\n";
|
||||
//mos << "closed !!!\n";
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
mos << "exception !!!\n";
|
||||
//mos << "exception !!!\n";
|
||||
}
|
||||
}
|
||||
|
||||
void consumer(boost::externally_locked_stream<std::ostream> &mos, boost::sync_bounded_queue<int> & sbq)
|
||||
void consumer(the_ostream &/*mos*/, boost::sync_bounded_queue<int> & sbq)
|
||||
{
|
||||
using namespace boost;
|
||||
try {
|
||||
for(int i=0; ;++i)
|
||||
{
|
||||
int r;
|
||||
//sbq.pull(r);
|
||||
sbq >> r;
|
||||
mos << i << " pull(" << r << ") "<< sbq.size()<<"\n";
|
||||
sbq.pull_front(r);
|
||||
//sbq >> r;
|
||||
//mos << i << " pull_front(" << r << ") "<< sbq.size()<<"\n";
|
||||
this_thread::sleep_for(chrono::milliseconds(250));
|
||||
}
|
||||
}
|
||||
catch(sync_queue_is_closed&)
|
||||
{
|
||||
mos << "closed !!!\n";
|
||||
//mos << "closed !!!\n";
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
mos << "exception !!!\n";
|
||||
//mos << "exception !!!\n";
|
||||
}
|
||||
}
|
||||
void consumer2(boost::externally_locked_stream<std::ostream> &mos, boost::sync_bounded_queue<int> & sbq)
|
||||
void consumer2(the_ostream &/*mos*/, boost::sync_bounded_queue<int> & sbq)
|
||||
{
|
||||
using namespace boost;
|
||||
try {
|
||||
bool closed=false;
|
||||
for(int i=0; ;++i)
|
||||
{
|
||||
int r;
|
||||
sbq.pull(r, closed);
|
||||
if (closed) break;
|
||||
mos << i << " pull(" << r << ")\n";
|
||||
queue_op_status st = sbq.try_pull_front(r);
|
||||
if (queue_op_status::closed == st) break;
|
||||
if (queue_op_status::success == st) {
|
||||
//mos << i << " pull(" << r << ")\n";
|
||||
}
|
||||
this_thread::sleep_for(chrono::milliseconds(250));
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
mos << "exception !!!\n";
|
||||
//mos << "exception !!!\n";
|
||||
}
|
||||
}
|
||||
//void consumer3(boost::externally_locked_stream<std::ostream> &mos, boost::sync_bounded_queue<int> & sbq)
|
||||
//void consumer3(the_ostream &mos, boost::sync_bounded_queue<int> & sbq)
|
||||
//{
|
||||
// using namespace boost;
|
||||
// bool closed=false;
|
||||
@@ -86,33 +101,38 @@ void consumer2(boost::externally_locked_stream<std::ostream> &mos, boost::sync_b
|
||||
// int r;
|
||||
// queue_op_status res = sbq.wait_and_pull(r);
|
||||
// if (res==queue_op_status::closed) break;
|
||||
// mos << i << " wait_and_pull(" << r << ")\n";
|
||||
// //mos << i << " wait_and_pull(" << r << ")\n";
|
||||
// this_thread::sleep_for(chrono::milliseconds(250));
|
||||
// }
|
||||
// }
|
||||
// catch(...)
|
||||
// {
|
||||
// mos << "exception !!!\n";
|
||||
// //mos << "exception !!!\n";
|
||||
// }
|
||||
//}
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace boost;
|
||||
|
||||
#ifdef XXXX
|
||||
recursive_mutex terminal_mutex;
|
||||
|
||||
externally_locked_stream<std::ostream> mcerr(std::cerr, terminal_mutex);
|
||||
externally_locked_stream<std::ostream> mcout(std::cout, terminal_mutex);
|
||||
externally_locked_stream<std::istream> mcin(std::cin, terminal_mutex);
|
||||
#else
|
||||
the_ostream &mcerr = std::cout;
|
||||
the_ostream &mcout = std::cerr;
|
||||
//the_istream &mcin = std::cin;
|
||||
#endif
|
||||
|
||||
sync_bounded_queue<int> sbq(10);
|
||||
|
||||
{
|
||||
mcout << "begin of main" << std::endl;
|
||||
scoped_thread<> t11(thread(producer, boost::ref(mcerr), boost::ref(sbq)));
|
||||
scoped_thread<> t12(thread(producer, boost::ref(mcerr), boost::ref(sbq)));
|
||||
scoped_thread<> t2(thread(consumer, boost::ref(mcout), boost::ref(sbq)));
|
||||
scoped_thread<> t11(boost::thread(producer, boost::ref(mcerr), boost::ref(sbq)));
|
||||
scoped_thread<> t12(boost::thread(producer, boost::ref(mcerr), boost::ref(sbq)));
|
||||
scoped_thread<> t2(boost::thread(consumer, boost::ref(mcout), boost::ref(sbq)));
|
||||
|
||||
this_thread::sleep_for(chrono::seconds(1));
|
||||
|
||||
|
||||
@@ -13,6 +13,9 @@ void do_something(int& i)
|
||||
{
|
||||
++i;
|
||||
}
|
||||
void f(int, int)
|
||||
{
|
||||
}
|
||||
|
||||
struct func
|
||||
{
|
||||
@@ -81,7 +84,10 @@ int main()
|
||||
|
||||
do_something_in_current_thread();
|
||||
}
|
||||
|
||||
{
|
||||
boost::scoped_thread<> g( &f, 1, 2 );
|
||||
do_something_in_current_thread();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#undef BOOST_THREAD_VERSION
|
||||
#define BOOST_THREAD_VERSION 2
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/condition.hpp>
|
||||
#include <boost/thread/thread_only.hpp>
|
||||
|
||||
73
example/thread_pool.cpp
Normal file
73
example/thread_pool.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
// Copyright (C) 2012-2013 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>
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
//#define BOOST_THREAD_USES_LOG
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
|
||||
#include <boost/thread/detail/log.hpp>
|
||||
#include <boost/thread/executors/basic_thread_pool.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <string>
|
||||
|
||||
void p1()
|
||||
{
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::this_thread::get_id() << " P1" << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
|
||||
void p2()
|
||||
{
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::this_thread::get_id() << " P2" << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
|
||||
void submit_some(boost::basic_thread_pool& tp) {
|
||||
tp.submit(&p1);
|
||||
tp.submit(&p2);
|
||||
tp.submit(&p1);
|
||||
tp.submit(&p2);
|
||||
tp.submit(&p1);
|
||||
tp.submit(&p2);
|
||||
tp.submit(&p1);
|
||||
tp.submit(&p2);
|
||||
tp.submit(&p1);
|
||||
tp.submit(&p2);
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::this_thread::get_id() << " <MAIN" << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::basic_thread_pool tp;
|
||||
submit_some(tp);
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
BOOST_THREAD_LOG
|
||||
<< "ERRORRRRR " << ex.what() << "" << BOOST_THREAD_END_LOG;
|
||||
return 1;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_THREAD_LOG
|
||||
<< " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::this_thread::get_id() << "MAIN>" << BOOST_THREAD_END_LOG;
|
||||
return 0;
|
||||
}
|
||||
75
example/user_scheduler.cpp
Normal file
75
example/user_scheduler.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
// Copyright (C) 2013 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>
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
//#define BOOST_THREAD_USES_LOG
|
||||
#define BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
#if ! defined BOOST_NO_CXX11_DECLTYPE
|
||||
#define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
#include <boost/thread/detail/log.hpp>
|
||||
#include <boost/thread/executors/loop_executor.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/thread/thread_only.hpp>
|
||||
#include <string>
|
||||
|
||||
void p1()
|
||||
{
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::this_thread::get_id() << " P1" << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
|
||||
void p2()
|
||||
{
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::this_thread::get_id() << " P2" << BOOST_THREAD_END_LOG;
|
||||
}
|
||||
|
||||
void submit_some(boost::loop_executor& tp) {
|
||||
tp.submit(&p1);
|
||||
tp.submit(&p2);
|
||||
tp.submit(&p1);
|
||||
tp.submit(&p2);
|
||||
tp.submit(&p1);
|
||||
tp.submit(&p2);
|
||||
tp.submit(&p1);
|
||||
tp.submit(&p2);
|
||||
tp.submit(&p1);
|
||||
tp.submit(&p2);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::this_thread::get_id() << " <MAIN" << BOOST_THREAD_END_LOG;
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::loop_executor tp;
|
||||
submit_some(tp);
|
||||
tp.run_queued_closures();
|
||||
submit_some(tp);
|
||||
tp.run_queued_closures();
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
BOOST_THREAD_LOG
|
||||
<< "ERRORRRRR " << ex.what() << "" << BOOST_THREAD_END_LOG;
|
||||
return 1;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_THREAD_LOG
|
||||
<< " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_THREAD_LOG
|
||||
<< boost::this_thread::get_id() << "MAIN>" << BOOST_THREAD_END_LOG;
|
||||
return 0;
|
||||
}
|
||||
53
example/with_lock_guard.cpp
Normal file
53
example/with_lock_guard.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
// (C) Copyright 2013 Ruslan Baratov
|
||||
// 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)
|
||||
|
||||
// See www.boost.org/libs/thread for documentation.
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
|
||||
#include <iostream> // std::cout
|
||||
#include <boost/thread/scoped_thread.hpp>
|
||||
#include <boost/thread/with_lock_guard.hpp>
|
||||
|
||||
boost::mutex m; // protection for 'x' and 'std::cout'
|
||||
int x;
|
||||
|
||||
#if defined(BOOST_NO_CXX11_LAMBDAS) || (defined BOOST_MSVC && _MSC_VER < 1700)
|
||||
void print_x() {
|
||||
++x;
|
||||
std::cout << "x = " << x << std::endl;
|
||||
}
|
||||
|
||||
void job() {
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
boost::with_lock_guard(m, print_x);
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
|
||||
}
|
||||
}
|
||||
#else
|
||||
void job() {
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
boost::with_lock_guard(
|
||||
m,
|
||||
[]() {
|
||||
++x;
|
||||
std::cout << "x = " << x << std::endl;
|
||||
}
|
||||
);
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int main() {
|
||||
#if defined(BOOST_NO_CXX11_LAMBDAS) || (defined BOOST_MSVC && _MSC_VER < 1700)
|
||||
std::cout << "(no lambdas)" << std::endl;
|
||||
#endif
|
||||
boost::scoped_thread<> thread_1((boost::thread(job)));
|
||||
boost::scoped_thread<> thread_2((boost::thread(job)));
|
||||
boost::scoped_thread<> thread_3((boost::thread(job)));
|
||||
return 0;
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (C) 2002-2003
|
||||
// David Moore, William E. Kempf
|
||||
// Copyright (C) 2007-8 Anthony Williams
|
||||
// (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)
|
||||
@@ -17,51 +18,236 @@
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <boost/thread/detail/nullary_function.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/is_void.hpp>
|
||||
#include <boost/core/enable_if.hpp>
|
||||
#include <boost/utility/result_of.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace thread_detail
|
||||
{
|
||||
typedef detail::nullary_function<void()> void_completion_function;
|
||||
typedef detail::nullary_function<size_t()> size_completion_function;
|
||||
|
||||
class barrier
|
||||
struct default_barrier_reseter
|
||||
{
|
||||
public:
|
||||
BOOST_THREAD_NO_COPYABLE( barrier )
|
||||
unsigned int size_;
|
||||
default_barrier_reseter(unsigned int size) :
|
||||
size_(size)
|
||||
{
|
||||
}
|
||||
BOOST_THREAD_MOVABLE(default_barrier_reseter)
|
||||
//BOOST_THREAD_COPYABLE_AND_MOVABLE(default_barrier_reseter)
|
||||
|
||||
barrier(unsigned int count)
|
||||
: m_threshold(count), m_count(count), m_generation(0)
|
||||
{
|
||||
if (count == 0)
|
||||
boost::throw_exception(thread_exception(system::errc::invalid_argument, "barrier constructor: count cannot be zero."));
|
||||
}
|
||||
default_barrier_reseter(default_barrier_reseter const& other) BOOST_NOEXCEPT :
|
||||
size_(other.size_)
|
||||
{
|
||||
}
|
||||
default_barrier_reseter(BOOST_THREAD_RV_REF(default_barrier_reseter) other) BOOST_NOEXCEPT :
|
||||
size_(BOOST_THREAD_RV(other).size_)
|
||||
{
|
||||
}
|
||||
|
||||
bool wait()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lock(m_mutex);
|
||||
unsigned int gen = m_generation;
|
||||
|
||||
if (--m_count == 0)
|
||||
{
|
||||
m_generation++;
|
||||
m_count = m_threshold;
|
||||
m_cond.notify_all();
|
||||
return true;
|
||||
}
|
||||
|
||||
while (gen == m_generation)
|
||||
m_cond.wait(lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
mutex m_mutex;
|
||||
condition_variable m_cond;
|
||||
unsigned int m_threshold;
|
||||
unsigned int m_count;
|
||||
unsigned int m_generation;
|
||||
unsigned int operator()()
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
struct void_functor_barrier_reseter
|
||||
{
|
||||
unsigned int size_;
|
||||
void_completion_function fct_;
|
||||
template <typename F>
|
||||
void_functor_barrier_reseter(unsigned int size, BOOST_THREAD_RV_REF(F) funct)
|
||||
: size_(size), fct_(boost::move(funct))
|
||||
{}
|
||||
template <typename F>
|
||||
void_functor_barrier_reseter(unsigned int size, F& funct)
|
||||
: size_(size), fct_(funct)
|
||||
{}
|
||||
|
||||
BOOST_THREAD_MOVABLE(void_functor_barrier_reseter)
|
||||
//BOOST_THREAD_COPYABLE_AND_MOVABLE(void_functor_barrier_reseter)
|
||||
|
||||
void_functor_barrier_reseter(void_functor_barrier_reseter const& other) BOOST_NOEXCEPT :
|
||||
size_(other.size_), fct_(other.fct_)
|
||||
{
|
||||
}
|
||||
void_functor_barrier_reseter(BOOST_THREAD_RV_REF(void_functor_barrier_reseter) other) BOOST_NOEXCEPT :
|
||||
size_(BOOST_THREAD_RV(other).size_), fct_(BOOST_THREAD_RV(other).fct_)
|
||||
//size_(BOOST_THREAD_RV(other).size_), fct_(boost::move(BOOST_THREAD_RV(other).fct_))
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int operator()()
|
||||
{
|
||||
fct_();
|
||||
return size_;
|
||||
}
|
||||
};
|
||||
struct void_fct_ptr_barrier_reseter
|
||||
{
|
||||
unsigned int size_;
|
||||
void(*fct_)();
|
||||
void_fct_ptr_barrier_reseter(unsigned int size, void(*funct)()) :
|
||||
size_(size), fct_(funct)
|
||||
{
|
||||
}
|
||||
BOOST_THREAD_MOVABLE(void_fct_ptr_barrier_reseter)
|
||||
//BOOST_THREAD_COPYABLE_AND_MOVABLE(void_fct_ptr_barrier_reseter)
|
||||
|
||||
void_fct_ptr_barrier_reseter(void_fct_ptr_barrier_reseter const& other) BOOST_NOEXCEPT :
|
||||
size_(other.size_), fct_(other.fct_)
|
||||
{
|
||||
}
|
||||
void_fct_ptr_barrier_reseter(BOOST_THREAD_RV_REF(void_fct_ptr_barrier_reseter) other) BOOST_NOEXCEPT :
|
||||
size_(BOOST_THREAD_RV(other).size_), fct_(BOOST_THREAD_RV(other).fct_)
|
||||
{
|
||||
}
|
||||
unsigned int operator()()
|
||||
{
|
||||
fct_();
|
||||
return size_;
|
||||
}
|
||||
};
|
||||
}
|
||||
//BOOST_THREAD_DCL_MOVABLE(thread_detail::default_barrier_reseter)
|
||||
//BOOST_THREAD_DCL_MOVABLE(thread_detail::void_functor_barrier_reseter)
|
||||
//BOOST_THREAD_DCL_MOVABLE(thread_detail::void_fct_ptr_barrier_reseter)
|
||||
|
||||
class barrier
|
||||
{
|
||||
static inline unsigned int check_counter(unsigned int count)
|
||||
{
|
||||
if (count == 0) boost::throw_exception(
|
||||
thread_exception(system::errc::invalid_argument, "barrier constructor: count cannot be zero."));
|
||||
return count;
|
||||
}
|
||||
struct dummy
|
||||
{
|
||||
};
|
||||
|
||||
public:
|
||||
BOOST_THREAD_NO_COPYABLE( barrier)
|
||||
|
||||
explicit barrier(unsigned int count) :
|
||||
m_count(check_counter(count)), m_generation(0), fct_(BOOST_THREAD_MAKE_RV_REF(thread_detail::default_barrier_reseter(count)))
|
||||
{
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
barrier(
|
||||
unsigned int count,
|
||||
BOOST_THREAD_RV_REF(F) funct,
|
||||
typename enable_if<
|
||||
typename is_void<typename result_of<F>::type>::type, dummy*
|
||||
>::type=0
|
||||
)
|
||||
: m_count(check_counter(count)),
|
||||
m_generation(0),
|
||||
fct_(BOOST_THREAD_MAKE_RV_REF(thread_detail::void_functor_barrier_reseter(count,
|
||||
boost::move(funct)))
|
||||
)
|
||||
{
|
||||
}
|
||||
template <typename F>
|
||||
barrier(
|
||||
unsigned int count,
|
||||
F &funct,
|
||||
typename enable_if<
|
||||
typename is_void<typename result_of<F>::type>::type, dummy*
|
||||
>::type=0
|
||||
)
|
||||
: m_count(check_counter(count)),
|
||||
m_generation(0),
|
||||
fct_(BOOST_THREAD_MAKE_RV_REF(thread_detail::void_functor_barrier_reseter(count,
|
||||
funct))
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
barrier(
|
||||
unsigned int count,
|
||||
BOOST_THREAD_RV_REF(F) funct,
|
||||
typename enable_if<
|
||||
typename is_same<typename result_of<F>::type, unsigned int>::type, dummy*
|
||||
>::type=0
|
||||
)
|
||||
: m_count(check_counter(count)),
|
||||
m_generation(0),
|
||||
fct_(boost::move(funct))
|
||||
{
|
||||
}
|
||||
template <typename F>
|
||||
barrier(
|
||||
unsigned int count,
|
||||
F& funct,
|
||||
typename enable_if<
|
||||
typename is_same<typename result_of<F>::type, unsigned int>::type, dummy*
|
||||
>::type=0
|
||||
)
|
||||
: m_count(check_counter(count)),
|
||||
m_generation(0),
|
||||
fct_(funct)
|
||||
{
|
||||
}
|
||||
|
||||
barrier(unsigned int count, void(*funct)()) :
|
||||
m_count(check_counter(count)), m_generation(0),
|
||||
fct_(funct
|
||||
? BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(BOOST_THREAD_MAKE_RV_REF(thread_detail::void_fct_ptr_barrier_reseter(count, funct))))
|
||||
: BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(BOOST_THREAD_MAKE_RV_REF(thread_detail::default_barrier_reseter(count))))
|
||||
)
|
||||
{
|
||||
}
|
||||
barrier(unsigned int count, unsigned int(*funct)()) :
|
||||
m_count(check_counter(count)), m_generation(0),
|
||||
fct_(funct
|
||||
? BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(funct))
|
||||
: BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(BOOST_THREAD_MAKE_RV_REF(thread_detail::default_barrier_reseter(count))))
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
bool wait()
|
||||
{
|
||||
boost::unique_lock < boost::mutex > lock(m_mutex);
|
||||
unsigned int gen = m_generation;
|
||||
|
||||
if (--m_count == 0)
|
||||
{
|
||||
m_generation++;
|
||||
m_count = static_cast<unsigned int>(fct_());
|
||||
BOOST_ASSERT(m_count != 0);
|
||||
m_cond.notify_all();
|
||||
return true;
|
||||
}
|
||||
|
||||
while (gen == m_generation)
|
||||
m_cond.wait(lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
void count_down_and_wait()
|
||||
{
|
||||
wait();
|
||||
}
|
||||
|
||||
private:
|
||||
mutex m_mutex;
|
||||
condition_variable m_cond;
|
||||
unsigned int m_count;
|
||||
unsigned int m_generation;
|
||||
thread_detail::size_completion_function fct_;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
|
||||
56
include/boost/thread/caller_context.hpp
Normal file
56
include/boost/thread/caller_context.hpp
Normal file
@@ -0,0 +1,56 @@
|
||||
// (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_CALL_CONTEXT_HPP
|
||||
#define BOOST_THREAD_CALL_CONTEXT_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#if defined BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
#include <boost/thread/thread.hpp>
|
||||
#endif
|
||||
#include <boost/current_function.hpp>
|
||||
#include <iomanip>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
struct caller_context_t
|
||||
{
|
||||
const char * filename;
|
||||
unsigned lineno;
|
||||
const char * func;
|
||||
caller_context_t(const char * filename, unsigned lineno, const char * func) :
|
||||
filename(filename), lineno(lineno), func(func)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#define BOOST_CONTEXTOF boost::caller_context_t(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION)
|
||||
|
||||
template <typename OStream>
|
||||
OStream& operator<<(OStream& os, caller_context_t const& ctx)
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_LOG_THREAD_ID
|
||||
{
|
||||
io::ios_flags_saver ifs( os );
|
||||
os << std::left << std::setw(14) << boost::this_thread::get_id() << " ";
|
||||
}
|
||||
#endif
|
||||
{
|
||||
io::ios_flags_saver ifs(os);
|
||||
os << ctx.filename << "["
|
||||
<< std::setw(4) << std::right << std::dec<< ctx.lineno << "] ";
|
||||
os << ctx.func << " " ;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif // header
|
||||
@@ -16,12 +16,8 @@
|
||||
#include <boost/chrono/duration.hpp>
|
||||
#include <boost/chrono/time_point.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#ifdef BOOST_NO_CXX11_HDR_FUNCTIONAL
|
||||
#include <boost/function.hpp>
|
||||
#else
|
||||
#include <functional>
|
||||
#endif
|
||||
//#include <boost/thread/latch.hpp>
|
||||
//#include <boost/thread/detail/nullary_function.hpp>
|
||||
#include <boost/thread/csbl/functional.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
@@ -37,11 +33,8 @@ namespace boost
|
||||
{
|
||||
public:
|
||||
/// the implementation defined completion function type
|
||||
#ifdef BOOST_NO_CXX11_HDR_FUNCTIONAL
|
||||
typedef function<void()> completion_function;
|
||||
#else
|
||||
typedef std::function<void()> completion_function;
|
||||
#endif
|
||||
//typedef detail::nullary_function<void()> completion_function;
|
||||
typedef csbl::function<void()> completion_function;
|
||||
/// noop completion function factory
|
||||
static completion_function noop()
|
||||
{
|
||||
|
||||
209
include/boost/thread/concurrent_queues/queue_adaptor.hpp
Normal file
209
include/boost/thread/concurrent_queues/queue_adaptor.hpp
Normal file
@@ -0,0 +1,209 @@
|
||||
#ifndef BOOST_THREAD_QUEUE_ADAPTOR_HPP
|
||||
#define BOOST_THREAD_QUEUE_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/queue_base.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace concurrent
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename Queue>
|
||||
class queue_adaptor_copyable_only :
|
||||
public boost::queue_base<typename Queue::value_type>
|
||||
{
|
||||
Queue queue;
|
||||
public:
|
||||
typedef typename Queue::value_type value_type;
|
||||
typedef std::size_t size_type;
|
||||
|
||||
// Constructors/Assignment/Destructors
|
||||
queue_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 queue_adaptor_movable_only :
|
||||
public boost::queue_base<typename Queue::value_type>
|
||||
{
|
||||
Queue queue;
|
||||
public:
|
||||
typedef typename Queue::value_type value_type;
|
||||
typedef std::size_t size_type;
|
||||
|
||||
// Constructors/Assignment/Destructors
|
||||
|
||||
queue_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 queue_adaptor_copyable_and_movable :
|
||||
public boost::queue_base<typename Queue::value_type>
|
||||
{
|
||||
Queue queue;
|
||||
public:
|
||||
typedef typename Queue::value_type value_type;
|
||||
typedef std::size_t size_type;
|
||||
|
||||
// Constructors/Assignment/Destructors
|
||||
|
||||
queue_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__
|
||||
#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 queue_adaptor;
|
||||
|
||||
template <class Q, class T>
|
||||
struct queue_adaptor<Q, T, true, true> {
|
||||
typedef queue_adaptor_copyable_and_movable<Q> type;
|
||||
};
|
||||
template <class Q, class T>
|
||||
struct queue_adaptor<Q, T, true, false> {
|
||||
typedef queue_adaptor_copyable_only<Q> type;
|
||||
};
|
||||
template <class Q, class T>
|
||||
struct queue_adaptor<Q, T, false, true> {
|
||||
typedef queue_adaptor_movable_only<Q> type;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <typename Queue>
|
||||
class queue_adaptor :
|
||||
public detail::queue_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 ~queue_adaptor() {};
|
||||
};
|
||||
}
|
||||
using concurrent::queue_adaptor;
|
||||
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
202
include/boost/thread/concurrent_queues/queue_base.hpp
Executable file
202
include/boost/thread/concurrent_queues/queue_base.hpp
Executable file
@@ -0,0 +1,202 @@
|
||||
#ifndef BOOST_THREAD_QUEUE_BASE_HPP
|
||||
#define BOOST_THREAD_QUEUE_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 queue_base_copyable_only
|
||||
{
|
||||
public:
|
||||
typedef ValueType value_type;
|
||||
typedef std::size_t size_type;
|
||||
|
||||
// Constructors/Assignment/Destructors
|
||||
virtual ~queue_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 queue_base_movable_only
|
||||
{
|
||||
public:
|
||||
typedef ValueType value_type;
|
||||
typedef std::size_t size_type;
|
||||
// Constructors/Assignment/Destructors
|
||||
virtual ~queue_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 queue_base_copyable_and_movable
|
||||
{
|
||||
public:
|
||||
typedef ValueType value_type;
|
||||
typedef std::size_t size_type;
|
||||
// Constructors/Assignment/Destructors
|
||||
virtual ~queue_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__
|
||||
#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 queue_base;
|
||||
|
||||
template <class T>
|
||||
struct queue_base<T, true, true> {
|
||||
typedef queue_base_copyable_and_movable<T> type;
|
||||
};
|
||||
template <class T>
|
||||
struct queue_base<T, true, false> {
|
||||
typedef queue_base_copyable_only<T> type;
|
||||
};
|
||||
template <class T>
|
||||
struct queue_base<T, false, true> {
|
||||
typedef queue_base_movable_only<T> type;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <typename ValueType>
|
||||
class queue_base :
|
||||
public detail::queue_base<ValueType>::type
|
||||
{
|
||||
public:
|
||||
typedef ValueType value_type;
|
||||
typedef std::size_t size_type;
|
||||
// Constructors/Assignment/Destructors
|
||||
virtual ~queue_base() {};
|
||||
};
|
||||
|
||||
}
|
||||
using concurrent::queue_base;
|
||||
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
46
include/boost/thread/concurrent_queues/queue_op_status.hpp
Normal file
46
include/boost/thread/concurrent_queues/queue_op_status.hpp
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef BOOST_THREAD_QUEUE_OP_STATUS_HPP
|
||||
#define BOOST_THREAD_QUEUE_OP_STATUS_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/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace concurrent
|
||||
{
|
||||
|
||||
BOOST_SCOPED_ENUM_DECLARE_BEGIN(queue_op_status)
|
||||
{ success = 0, empty, full, closed, busy }
|
||||
BOOST_SCOPED_ENUM_DECLARE_END(queue_op_status)
|
||||
|
||||
struct sync_queue_is_closed : std::exception
|
||||
{
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
|
||||
struct no_block_tag{};
|
||||
BOOST_CONSTEXPR_OR_CONST no_block_tag no_block = {};
|
||||
#endif
|
||||
|
||||
using concurrent::queue_op_status;
|
||||
using concurrent::sync_queue_is_closed;
|
||||
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
165
include/boost/thread/concurrent_queues/queue_views.hpp
Normal file
165
include/boost/thread/concurrent_queues/queue_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/queue_base.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace concurrent
|
||||
{
|
||||
|
||||
template <typename Queue>
|
||||
class queue_back_view
|
||||
{
|
||||
Queue* queue;
|
||||
public:
|
||||
typedef typename Queue::value_type value_type;
|
||||
typedef typename Queue::size_type size_type;
|
||||
|
||||
// Constructors/Assignment/Destructors
|
||||
queue_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 queue_front_view
|
||||
{
|
||||
Queue* queue;
|
||||
public:
|
||||
typedef typename Queue::value_type value_type;
|
||||
typedef typename Queue::size_type size_type;
|
||||
|
||||
// Constructors/Assignment/Destructors
|
||||
queue_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 queue_back = queue_back_view<queue_base<T> > ;
|
||||
template <class T>
|
||||
using queue_front = queue_front_view<queue_base<T> > ;
|
||||
|
||||
#else
|
||||
|
||||
template <class T>
|
||||
struct queue_back : queue_back_view<queue_base<T> >
|
||||
{
|
||||
typedef queue_back_view<queue_base<T> > base_type;
|
||||
queue_back(queue_base<T>& q) BOOST_NOEXCEPT : base_type(q) {}
|
||||
};
|
||||
template <class T>
|
||||
struct queue_front : queue_front_view<queue_base<T> >
|
||||
{
|
||||
typedef queue_front_view<queue_base<T> > base_type;
|
||||
queue_front(queue_base<T>& q) BOOST_NOEXCEPT : base_type(q) {}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// template <class Queue>
|
||||
// queue_back_view<Queue> back(Queue & q) { return queue_back_view<Queue>(q); }
|
||||
// template <class Queue>
|
||||
// queue_front_view<Queue> front(Queue & q) { return queue_front_view<Queue>(q); }
|
||||
//#if 0
|
||||
// template <class T>
|
||||
// queue_back<T> back(queue_base<T> & q) { return queue_back<T>(q); }
|
||||
// template <class T>
|
||||
// queue_front<T> front(queue_base<T> & q) { return queue_front<T>(q); }
|
||||
//#else
|
||||
// template <class T>
|
||||
// typename queue_back<T>::type back(queue_base<T> & q) { return typename queue_back<T>::type(q); }
|
||||
// template <class T>
|
||||
// typename queue_front<T>::type front(queue_base<T> & q) { return typename queue_front<T>::type(q); }
|
||||
//#endif
|
||||
}
|
||||
|
||||
using concurrent::queue_back_view;
|
||||
using concurrent::queue_front_view;
|
||||
using concurrent::queue_back;
|
||||
using concurrent::queue_front;
|
||||
//using concurrent::back;
|
||||
//using concurrent::front;
|
||||
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
45
include/boost/thread/csbl/deque.hpp
Normal file
45
include/boost/thread/csbl/deque.hpp
Normal file
@@ -0,0 +1,45 @@
|
||||
// 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_DEQUE_HPP
|
||||
#define BOOST_CSBL_DEQUE_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_DEQUE || defined BOOST_NO_CXX11_HDR_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
|
||||
#include <boost/container/deque.hpp>
|
||||
#else
|
||||
#include <deque>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace csbl
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_BOOST_DEQUE
|
||||
using ::boost::container::deque;
|
||||
|
||||
#else
|
||||
using ::std::deque;
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
#endif // header
|
||||
49
include/boost/thread/csbl/functional.hpp
Normal file
49
include/boost/thread/csbl/functional.hpp
Normal file
@@ -0,0 +1,49 @@
|
||||
// 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_FUNCTIONAL_HPP
|
||||
#define BOOST_CSBL_FUNCTIONAL_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <functional>
|
||||
|
||||
#if defined BOOST_THREAD_USES_BOOST_FUNCTIONAL || defined BOOST_NO_CXX11_HDR_FUNCTIONAL || defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
#ifndef BOOST_THREAD_USES_BOOST_FUNCTIONAL
|
||||
#define BOOST_THREAD_USES_BOOST_FUNCTIONAL
|
||||
#endif
|
||||
#include <boost/function.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace csbl
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_BOOST_FUNCTIONAL
|
||||
using ::boost::function;
|
||||
#else
|
||||
// D.8.1, base (deprecated):
|
||||
// 20.9.3, reference_wrapper:
|
||||
// 20.9.4, arithmetic operations:
|
||||
// 20.9.5, comparisons:
|
||||
// 20.9.6, logical operations:
|
||||
// 20.9.7, bitwise operations:
|
||||
// 20.9.8, negators:
|
||||
// 20.9.9, bind:
|
||||
// D.9, binders (deprecated):
|
||||
// D.8.2.1, adaptors (deprecated):
|
||||
// D.8.2.2, adaptors (deprecated):
|
||||
// 20.9.10, member function adaptors:
|
||||
// 20.9.11 polymorphic function wrappers:
|
||||
using ::std::function;
|
||||
// 20.9.12, hash function primary template:
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
#endif // header
|
||||
35
include/boost/thread/csbl/list.hpp
Normal file
35
include/boost/thread/csbl/list.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
// 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_LIST_HPP
|
||||
#define BOOST_CSBL_LIST_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if defined BOOST_THREAD_USES_BOOST_LIST || defined BOOST_NO_CXX11_HDR_LIST || defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
#ifndef BOOST_THREAD_USES_BOOST_LIST
|
||||
#define BOOST_THREAD_USES_BOOST_LIST
|
||||
#endif
|
||||
#include <boost/container/list.hpp>
|
||||
#else
|
||||
#include <list>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace csbl
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_BOOST_LIST
|
||||
using ::boost::container::list;
|
||||
#else
|
||||
using ::std::list;
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
#endif // header
|
||||
61
include/boost/thread/csbl/memory.hpp
Normal file
61
include/boost/thread/csbl/memory.hpp
Normal file
@@ -0,0 +1,61 @@
|
||||
// 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_MEMORY_HPP
|
||||
#define BOOST_CSBL_MEMORY_HPP
|
||||
|
||||
// 20.7.2 Header <memory> synopsis
|
||||
|
||||
// 20.7.3, pointer traits
|
||||
#include <boost/thread/csbl/memory/pointer_traits.hpp>
|
||||
|
||||
// 20.7.4, pointer safety
|
||||
// 20.7.5, pointer alignment function
|
||||
|
||||
// 20.7.6, allocator argument tag
|
||||
#include <boost/thread/csbl/memory/allocator_arg.hpp>
|
||||
|
||||
// 20.7.8, allocator traits
|
||||
#include <boost/thread/csbl/memory/allocator_traits.hpp>
|
||||
|
||||
// 20.7.7, uses_allocator
|
||||
#include <boost/thread/csbl/memory/scoped_allocator.hpp>
|
||||
|
||||
// 20.7.9, the default allocator:
|
||||
namespace boost
|
||||
{
|
||||
namespace csbl
|
||||
{
|
||||
using ::std::allocator;
|
||||
}
|
||||
}
|
||||
// 20.7.10, raw storage iterator:
|
||||
// 20.7.11, temporary buffers:
|
||||
// 20.7.12, specialized algorithms:
|
||||
|
||||
// 20.8.1 class template unique_ptr:
|
||||
// default_delete
|
||||
#include <boost/thread/csbl/memory/default_delete.hpp>
|
||||
#include <boost/thread/csbl/memory/unique_ptr.hpp>
|
||||
|
||||
// 20.8.2.1, class bad_weak_ptr:
|
||||
// 20.8.2.2, class template shared_ptr:
|
||||
// 20.8.2.2.6, shared_ptr creation
|
||||
// 20.8.2.2.7, shared_ptr comparisons:
|
||||
// 20.8.2.2.8, shared_ptr specialized algorithms:
|
||||
// 20.8.2.2.9, shared_ptr casts:
|
||||
// 20.8.2.2.10, shared_ptr get_deleter:
|
||||
// 20.8.2.2.11, shared_ptr I/O:
|
||||
// 20.8.2.3, class template weak_ptr:
|
||||
// 20.8.2.3.6, weak_ptr specialized algorithms:
|
||||
// 20.8.2.3.7, class template owner_less:
|
||||
// 20.8.2.4, class template enable_shared_from_this:
|
||||
// 20.8.2.5, shared_ptr atomic access:
|
||||
// 20.8.2.6 hash support
|
||||
|
||||
#endif // header
|
||||
41
include/boost/thread/csbl/memory/allocator_arg.hpp
Normal file
41
include/boost/thread/csbl/memory/allocator_arg.hpp
Normal file
@@ -0,0 +1,41 @@
|
||||
// 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_MEMORY_ALLOCATOR_ARG_HPP
|
||||
#define BOOST_CSBL_MEMORY_ALLOCATOR_ARG_HPP
|
||||
|
||||
#include <boost/thread/csbl/memory/config.hpp>
|
||||
|
||||
// 20.7.6, allocator argument tag
|
||||
#if defined BOOST_NO_CXX11_ALLOCATOR
|
||||
#include <boost/container/scoped_allocator.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace csbl
|
||||
{
|
||||
using ::boost::container::allocator_arg_t;
|
||||
using ::boost::container::allocator_arg;
|
||||
}
|
||||
}
|
||||
#else
|
||||
namespace boost
|
||||
{
|
||||
namespace csbl
|
||||
{
|
||||
using ::std::allocator_arg_t;
|
||||
using ::std::allocator_arg;
|
||||
}
|
||||
}
|
||||
#endif // BOOST_NO_CXX11_ALLOCATOR
|
||||
namespace boost
|
||||
{
|
||||
using ::boost::csbl::allocator_arg_t;
|
||||
using ::boost::csbl::allocator_arg;
|
||||
}
|
||||
#endif // header
|
||||
35
include/boost/thread/csbl/memory/allocator_traits.hpp
Normal file
35
include/boost/thread/csbl/memory/allocator_traits.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
// 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_MEMORY_ALLOCATOR_TRAITS_HPP
|
||||
#define BOOST_CSBL_MEMORY_ALLOCATOR_TRAITS_HPP
|
||||
|
||||
#include <boost/thread/csbl/memory/config.hpp>
|
||||
|
||||
// 20.7.8, allocator traits
|
||||
#if defined BOOST_NO_CXX11_ALLOCATOR
|
||||
#include <boost/container/allocator_traits.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace csbl
|
||||
{
|
||||
using ::boost::container::allocator_traits;
|
||||
}
|
||||
}
|
||||
#else
|
||||
namespace boost
|
||||
{
|
||||
namespace csbl
|
||||
{
|
||||
using ::std::allocator_traits;
|
||||
}
|
||||
}
|
||||
#endif // BOOST_NO_CXX11_POINTER_TRAITS
|
||||
|
||||
#endif // header
|
||||
16
include/boost/thread/csbl/memory/config.hpp
Normal file
16
include/boost/thread/csbl/memory/config.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
// 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_MEMORY_CONFIG_HPP
|
||||
#define BOOST_CSBL_MEMORY_CONFIG_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#endif // header
|
||||
41
include/boost/thread/csbl/memory/default_delete.hpp
Normal file
41
include/boost/thread/csbl/memory/default_delete.hpp
Normal file
@@ -0,0 +1,41 @@
|
||||
// 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_MEMORY_DEFAULT_DELETE_HPP
|
||||
#define BOOST_CSBL_MEMORY_DEFAULT_DELETE_HPP
|
||||
|
||||
#include <boost/thread/csbl/memory/config.hpp>
|
||||
|
||||
// 20.8.1 class template unique_ptr:
|
||||
// default_delete
|
||||
|
||||
#if defined BOOST_NO_CXX11_SMART_PTR
|
||||
#include <boost/move/unique_ptr.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace csbl
|
||||
{
|
||||
using ::boost::movelib::default_delete;
|
||||
}
|
||||
}
|
||||
#else
|
||||
namespace boost
|
||||
{
|
||||
namespace csbl
|
||||
{
|
||||
using ::std::default_delete;
|
||||
}
|
||||
}
|
||||
#endif // defined BOOST_NO_CXX11_SMART_PTR
|
||||
|
||||
namespace boost
|
||||
{
|
||||
using ::boost::csbl::default_delete;
|
||||
}
|
||||
#endif // header
|
||||
35
include/boost/thread/csbl/memory/pointer_traits.hpp
Normal file
35
include/boost/thread/csbl/memory/pointer_traits.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
// 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_MEMORY_POINTER_TRAITS_HPP
|
||||
#define BOOST_CSBL_MEMORY_POINTER_TRAITS_HPP
|
||||
|
||||
#include <boost/thread/csbl/memory/config.hpp>
|
||||
|
||||
// 20.7.3, pointer traits
|
||||
#if defined BOOST_NO_CXX11_ALLOCATOR
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace csbl
|
||||
{
|
||||
using ::boost::intrusive::pointer_traits;
|
||||
}
|
||||
}
|
||||
#else
|
||||
namespace boost
|
||||
{
|
||||
namespace csbl
|
||||
{
|
||||
using ::std::pointer_traits;
|
||||
}
|
||||
}
|
||||
#endif // BOOST_NO_CXX11_ALLOCATOR
|
||||
|
||||
#endif // header
|
||||
35
include/boost/thread/csbl/memory/scoped_allocator.hpp
Normal file
35
include/boost/thread/csbl/memory/scoped_allocator.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
// 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_MEMORY_SCOPED_ALLOCATOR_HPP
|
||||
#define BOOST_CSBL_MEMORY_SCOPED_ALLOCATOR_HPP
|
||||
|
||||
#include <boost/thread/csbl/memory/config.hpp>
|
||||
|
||||
// 20.7.7, uses_allocator
|
||||
#if defined BOOST_NO_CXX11_ALLOCATOR
|
||||
#include <boost/container/scoped_allocator.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace csbl
|
||||
{
|
||||
using ::boost::container::uses_allocator;
|
||||
}
|
||||
}
|
||||
#else
|
||||
namespace boost
|
||||
{
|
||||
namespace csbl
|
||||
{
|
||||
using ::std::uses_allocator;
|
||||
}
|
||||
}
|
||||
#endif // BOOST_NO_CXX11_POINTER_TRAITS
|
||||
|
||||
#endif // header
|
||||
42
include/boost/thread/csbl/memory/shared_ptr.hpp
Normal file
42
include/boost/thread/csbl/memory/shared_ptr.hpp
Normal file
@@ -0,0 +1,42 @@
|
||||
// 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)
|
||||
//
|
||||
// 2014/10 Vicente J. Botet Escriba
|
||||
// Creation.
|
||||
|
||||
#ifndef BOOST_CSBL_MEMORY_SHARED_PTR_HPP
|
||||
#define BOOST_CSBL_MEMORY_SHARED_PTR_HPP
|
||||
|
||||
#include <boost/thread/csbl/memory/config.hpp>
|
||||
|
||||
#if defined BOOST_NO_CXX11_SMART_PTR
|
||||
|
||||
#include <boost/smart_ptr/shared_ptr.hpp>
|
||||
#include <boost/smart_ptr/make_shared.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace csbl
|
||||
{
|
||||
using ::boost::shared_ptr;
|
||||
using ::boost::make_shared;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace csbl
|
||||
{
|
||||
using std::shared_ptr;
|
||||
using std::make_shared;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // header
|
||||
28
include/boost/thread/csbl/memory/unique_ptr.hpp
Normal file
28
include/boost/thread/csbl/memory/unique_ptr.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
// Copyright (C) 2013-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)
|
||||
//
|
||||
// 2013/10 Vicente J. Botet Escriba
|
||||
// Creation using interprocess::unique_ptr.
|
||||
// 2014/09 Vicente J. Botet Escriba
|
||||
// Adaptation to movelib::unique_ptr
|
||||
|
||||
#ifndef BOOST_CSBL_MEMORY_UNIQUE_PTR_HPP
|
||||
#define BOOST_CSBL_MEMORY_UNIQUE_PTR_HPP
|
||||
|
||||
#include <boost/thread/csbl/memory/config.hpp>
|
||||
|
||||
#include <boost/move/unique_ptr.hpp>
|
||||
#include <boost/move/make_unique.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace csbl
|
||||
{
|
||||
using ::boost::movelib::unique_ptr;
|
||||
using ::boost::movelib::make_unique;
|
||||
|
||||
}
|
||||
}
|
||||
#endif // header
|
||||
49
include/boost/thread/csbl/tuple.hpp
Normal file
49
include/boost/thread/csbl/tuple.hpp
Normal file
@@ -0,0 +1,49 @@
|
||||
// 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_TUPLE_HPP
|
||||
#define BOOST_CSBL_TUPLE_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if defined BOOST_THREAD_USES_BOOST_TUPLE || defined BOOST_NO_CXX11_HDR_TUPLE || defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#ifndef BOOST_THREAD_USES_BOOST_TUPLE
|
||||
#define BOOST_THREAD_USES_BOOST_TUPLE
|
||||
#endif
|
||||
|
||||
#else
|
||||
#include <tuple>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace csbl
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_BOOST_TUPLE
|
||||
using ::boost::tuple;
|
||||
using ::boost::get;
|
||||
using ::boost::make_tuple;
|
||||
//using ::boost::tuple_size;
|
||||
#else
|
||||
// 20.4.2, class template tuple:
|
||||
using ::std::tuple;
|
||||
using ::std::get;
|
||||
using ::std::make_tuple;
|
||||
using ::std::tuple_size;
|
||||
// 20.4.2.4, tuple creation functions:
|
||||
// 20.4.2.5, tuple helper classes:
|
||||
// 20.4.2.6, element access:
|
||||
// 20.4.2.7, relational operators:
|
||||
// 20.4.2.8, allocator-related traits
|
||||
// 20.4.2.9, specialized algorithms:
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
#endif // header
|
||||
35
include/boost/thread/csbl/vector.hpp
Normal file
35
include/boost/thread/csbl/vector.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
// 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_VECTOR_HPP
|
||||
#define BOOST_CSBL_VECTOR_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if defined BOOST_THREAD_USES_BOOST_VECTOR || defined BOOST_NO_CXX11_HDR_VECTOR || defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
#ifndef BOOST_THREAD_USES_BOOST_VECTOR
|
||||
#define BOOST_THREAD_USES_BOOST_VECTOR
|
||||
#endif
|
||||
#include <boost/container/vector.hpp>
|
||||
#else
|
||||
#include <vector>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace csbl
|
||||
{
|
||||
#if defined BOOST_THREAD_USES_BOOST_VECTOR
|
||||
using ::boost::container::vector;
|
||||
#else
|
||||
using ::std::vector;
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
#endif // header
|
||||
@@ -9,7 +9,7 @@
|
||||
#ifndef BOOST_THREAD_CV_STATUS_HPP
|
||||
#define BOOST_THREAD_CV_STATUS_HPP
|
||||
|
||||
#include <boost/detail/scoped_enum_emulation.hpp>
|
||||
#include <boost/core/scoped_enum.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
@@ -1,571 +0,0 @@
|
||||
// Copyright (C) 2012 Vicente J. Botet Escriba
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// 2013/04 Vicente J. Botet Escriba
|
||||
// Provide implementation up to 9 parameters when BOOST_NO_CXX11_VARIADIC_TEMPLATES is defined.
|
||||
// Make use of Boost.Move
|
||||
// Make use of Boost.Tuple (movable)
|
||||
// 2012/11 Vicente J. Botet Escriba
|
||||
// Adapt to boost libc++ implementation
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// The async_func code is based on the one from libcxx.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef BOOST_THREAD_DETAIL_ASYNC_FUNCT_HPP
|
||||
#define BOOST_THREAD_DETAIL_ASYNC_FUNCT_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <boost/utility/result_of.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/detail/invoke.hpp>
|
||||
#include <boost/thread/detail/make_tuple_indices.hpp>
|
||||
|
||||
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
|
||||
! defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
#include <tuple>
|
||||
#else
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
|
||||
! defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
|
||||
template <class Fp, class ... Args>
|
||||
class async_func
|
||||
{
|
||||
std::tuple<Fp, Args...> f_;
|
||||
|
||||
public:
|
||||
BOOST_THREAD_MOVABLE_ONLY( async_func)
|
||||
//typedef typename invoke_of<_Fp, _Args...>::type Rp;
|
||||
typedef typename result_of<Fp(Args...)>::type result_type;
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
explicit async_func(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args)... args)
|
||||
: f_(boost::move(f), boost::move(args)...)
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
async_func(BOOST_THREAD_RV_REF(async_func) f) : f_(boost::move(f.f_))
|
||||
{}
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
typedef typename make_tuple_indices<1+sizeof...(Args), 1>::type Index;
|
||||
return execute(Index());
|
||||
}
|
||||
private:
|
||||
template <size_t ...Indices>
|
||||
result_type
|
||||
execute(tuple_indices<Indices...>)
|
||||
{
|
||||
return invoke(boost::move(std::get<0>(f_)), boost::move(std::get<Indices>(f_))...);
|
||||
}
|
||||
};
|
||||
//BOOST_THREAD_DCL_MOVABLE_BEG(X) async_func<Fp> BOOST_THREAD_DCL_MOVABLE_END
|
||||
#else
|
||||
template <class Fp,
|
||||
class T0 = tuples::null_type, class T1 = tuples::null_type, class T2 = tuples::null_type,
|
||||
class T3 = tuples::null_type, class T4 = tuples::null_type, class T5 = tuples::null_type,
|
||||
class T6 = tuples::null_type, class T7 = tuples::null_type, class T8 = tuples::null_type
|
||||
, class T9 = tuples::null_type
|
||||
>
|
||||
class async_func;
|
||||
|
||||
template <class Fp,
|
||||
class T0 , class T1 , class T2 ,
|
||||
class T3 , class T4 , class T5 ,
|
||||
class T6 , class T7 , class T8 >
|
||||
class async_func<Fp, T0, T1, T2, T3, T4, T5, T6, T7, T8>
|
||||
{
|
||||
Fp fp_;
|
||||
T0 v0_;
|
||||
T1 v1_;
|
||||
T2 v2_;
|
||||
T3 v3_;
|
||||
T4 v4_;
|
||||
T5 v5_;
|
||||
T6 v6_;
|
||||
T7 v7_;
|
||||
T8 v8_;
|
||||
//::boost::tuple<Fp, T0, T1, T2, T3, T4, T5, T6, T7, T8> f_;
|
||||
|
||||
public:
|
||||
BOOST_THREAD_MOVABLE_ONLY(async_func)
|
||||
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5, T6, T7, T8)>::type result_type;
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
explicit async_func(BOOST_THREAD_RV_REF(Fp) f
|
||||
, BOOST_THREAD_RV_REF(T0) a0
|
||||
, BOOST_THREAD_RV_REF(T1) a1
|
||||
, BOOST_THREAD_RV_REF(T2) a2
|
||||
, BOOST_THREAD_RV_REF(T3) a3
|
||||
, BOOST_THREAD_RV_REF(T4) a4
|
||||
, BOOST_THREAD_RV_REF(T5) a5
|
||||
, BOOST_THREAD_RV_REF(T6) a6
|
||||
, BOOST_THREAD_RV_REF(T7) a7
|
||||
, BOOST_THREAD_RV_REF(T8) a8
|
||||
)
|
||||
: fp_(boost::move(f))
|
||||
, v0_(boost::move(a0))
|
||||
, v1_(boost::move(a1))
|
||||
, v2_(boost::move(a2))
|
||||
, v3_(boost::move(a3))
|
||||
, v4_(boost::move(a4))
|
||||
, v5_(boost::move(a5))
|
||||
, v6_(boost::move(a6))
|
||||
, v7_(boost::move(a7))
|
||||
, v8_(boost::move(a8))
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
async_func(BOOST_THREAD_RV_REF(async_func) f)
|
||||
: fp_(boost::move(f.fp))
|
||||
, v0_(boost::move(f.a0))
|
||||
, v1_(boost::move(f.a1))
|
||||
, v2_(boost::move(f.a2))
|
||||
, v3_(boost::move(f.a3))
|
||||
, v4_(boost::move(f.a4))
|
||||
, v5_(boost::move(f.a5))
|
||||
, v6_(boost::move(f.a6))
|
||||
, v7_(boost::move(f.a7))
|
||||
, v8_(boost::move(f.a8))
|
||||
{}
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
return invoke(boost::move(fp_)
|
||||
, boost::move(v0_)
|
||||
, boost::move(v1_)
|
||||
, boost::move(v2_)
|
||||
, boost::move(v3_)
|
||||
, boost::move(v4_)
|
||||
, boost::move(v5_)
|
||||
, boost::move(v6_)
|
||||
, boost::move(v7_)
|
||||
, boost::move(v8_)
|
||||
);
|
||||
}
|
||||
};
|
||||
template <class Fp, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7 >
|
||||
class async_func<Fp, T0, T1, T2, T3, T4, T5, T6, T7>
|
||||
{
|
||||
Fp fp_;
|
||||
T0 v0_;
|
||||
T1 v1_;
|
||||
T2 v2_;
|
||||
T3 v3_;
|
||||
T4 v4_;
|
||||
T5 v5_;
|
||||
T6 v6_;
|
||||
T7 v7_;
|
||||
public:
|
||||
BOOST_THREAD_MOVABLE_ONLY(async_func)
|
||||
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5, T6, T7)>::type result_type;
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
explicit async_func(BOOST_THREAD_RV_REF(Fp) f
|
||||
, BOOST_THREAD_RV_REF(T0) a0
|
||||
, BOOST_THREAD_RV_REF(T1) a1
|
||||
, BOOST_THREAD_RV_REF(T2) a2
|
||||
, BOOST_THREAD_RV_REF(T3) a3
|
||||
, BOOST_THREAD_RV_REF(T4) a4
|
||||
, BOOST_THREAD_RV_REF(T5) a5
|
||||
, BOOST_THREAD_RV_REF(T6) a6
|
||||
, BOOST_THREAD_RV_REF(T7) a7
|
||||
)
|
||||
: fp_(boost::move(f))
|
||||
, v0_(boost::move(a0))
|
||||
, v1_(boost::move(a1))
|
||||
, v2_(boost::move(a2))
|
||||
, v3_(boost::move(a3))
|
||||
, v4_(boost::move(a4))
|
||||
, v5_(boost::move(a5))
|
||||
, v6_(boost::move(a6))
|
||||
, v7_(boost::move(a7))
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
async_func(BOOST_THREAD_RV_REF(async_func) f)
|
||||
: fp_(boost::move(f.fp))
|
||||
, v0_(boost::move(f.a0))
|
||||
, v1_(boost::move(f.a1))
|
||||
, v2_(boost::move(f.a2))
|
||||
, v3_(boost::move(f.a3))
|
||||
, v4_(boost::move(f.a4))
|
||||
, v5_(boost::move(f.a5))
|
||||
, v6_(boost::move(f.a6))
|
||||
, v7_(boost::move(f.a7))
|
||||
{}
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
return invoke(boost::move(fp_)
|
||||
, boost::move(v0_)
|
||||
, boost::move(v1_)
|
||||
, boost::move(v2_)
|
||||
, boost::move(v3_)
|
||||
, boost::move(v4_)
|
||||
, boost::move(v5_)
|
||||
, boost::move(v6_)
|
||||
, boost::move(v7_)
|
||||
);
|
||||
}
|
||||
};
|
||||
template <class Fp, class T0, class T1, class T2, class T3, class T4, class T5, class T6>
|
||||
class async_func<Fp, T0, T1, T2, T3, T4, T5, T6>
|
||||
{
|
||||
Fp fp_;
|
||||
T0 v0_;
|
||||
T1 v1_;
|
||||
T2 v2_;
|
||||
T3 v3_;
|
||||
T4 v4_;
|
||||
T5 v5_;
|
||||
T6 v6_;
|
||||
public:
|
||||
BOOST_THREAD_MOVABLE_ONLY(async_func)
|
||||
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5, T6)>::type result_type;
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
explicit async_func(BOOST_THREAD_RV_REF(Fp) f
|
||||
, BOOST_THREAD_RV_REF(T0) a0
|
||||
, BOOST_THREAD_RV_REF(T1) a1
|
||||
, BOOST_THREAD_RV_REF(T2) a2
|
||||
, BOOST_THREAD_RV_REF(T3) a3
|
||||
, BOOST_THREAD_RV_REF(T4) a4
|
||||
, BOOST_THREAD_RV_REF(T5) a5
|
||||
, BOOST_THREAD_RV_REF(T6) a6
|
||||
)
|
||||
: fp_(boost::move(f))
|
||||
, v0_(boost::move(a0))
|
||||
, v1_(boost::move(a1))
|
||||
, v2_(boost::move(a2))
|
||||
, v3_(boost::move(a3))
|
||||
, v4_(boost::move(a4))
|
||||
, v5_(boost::move(a5))
|
||||
, v6_(boost::move(a6))
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
async_func(BOOST_THREAD_RV_REF(async_func) f)
|
||||
: fp_(boost::move(f.fp))
|
||||
, v0_(boost::move(f.a0))
|
||||
, v1_(boost::move(f.a1))
|
||||
, v2_(boost::move(f.a2))
|
||||
, v3_(boost::move(f.a3))
|
||||
, v4_(boost::move(f.a4))
|
||||
, v5_(boost::move(f.a5))
|
||||
, v6_(boost::move(f.a6))
|
||||
{}
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
return invoke(boost::move(fp_)
|
||||
, boost::move(v0_)
|
||||
, boost::move(v1_)
|
||||
, boost::move(v2_)
|
||||
, boost::move(v3_)
|
||||
, boost::move(v4_)
|
||||
, boost::move(v5_)
|
||||
, boost::move(v6_)
|
||||
);
|
||||
}
|
||||
};
|
||||
template <class Fp, class T0, class T1, class T2, class T3, class T4, class T5>
|
||||
class async_func<Fp, T0, T1, T2, T3, T4, T5>
|
||||
{
|
||||
Fp fp_;
|
||||
T0 v0_;
|
||||
T1 v1_;
|
||||
T2 v2_;
|
||||
T3 v3_;
|
||||
T4 v4_;
|
||||
T5 v5_;
|
||||
public:
|
||||
BOOST_THREAD_MOVABLE_ONLY(async_func)
|
||||
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5)>::type result_type;
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
explicit async_func(BOOST_THREAD_RV_REF(Fp) f
|
||||
, BOOST_THREAD_RV_REF(T0) a0
|
||||
, BOOST_THREAD_RV_REF(T1) a1
|
||||
, BOOST_THREAD_RV_REF(T2) a2
|
||||
, BOOST_THREAD_RV_REF(T3) a3
|
||||
, BOOST_THREAD_RV_REF(T4) a4
|
||||
, BOOST_THREAD_RV_REF(T5) a5
|
||||
)
|
||||
: fp_(boost::move(f))
|
||||
, v0_(boost::move(a0))
|
||||
, v1_(boost::move(a1))
|
||||
, v2_(boost::move(a2))
|
||||
, v3_(boost::move(a3))
|
||||
, v4_(boost::move(a4))
|
||||
, v5_(boost::move(a5))
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
async_func(BOOST_THREAD_RV_REF(async_func) f)
|
||||
: fp_(boost::move(f.fp))
|
||||
, v0_(boost::move(f.a0))
|
||||
, v1_(boost::move(f.a1))
|
||||
, v2_(boost::move(f.a2))
|
||||
, v3_(boost::move(f.a3))
|
||||
, v4_(boost::move(f.a4))
|
||||
, v5_(boost::move(f.a5))
|
||||
{}
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
return invoke(boost::move(fp_)
|
||||
, boost::move(v0_)
|
||||
, boost::move(v1_)
|
||||
, boost::move(v2_)
|
||||
, boost::move(v3_)
|
||||
, boost::move(v4_)
|
||||
, boost::move(v5_)
|
||||
);
|
||||
}
|
||||
};
|
||||
template <class Fp, class T0, class T1, class T2, class T3, class T4>
|
||||
class async_func<Fp, T0, T1, T2, T3, T4>
|
||||
{
|
||||
Fp fp_;
|
||||
T0 v0_;
|
||||
T1 v1_;
|
||||
T2 v2_;
|
||||
T3 v3_;
|
||||
T4 v4_;
|
||||
public:
|
||||
BOOST_THREAD_MOVABLE_ONLY(async_func)
|
||||
typedef typename result_of<Fp(T0, T1, T2, T3, T4)>::type result_type;
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
explicit async_func(BOOST_THREAD_RV_REF(Fp) f
|
||||
, BOOST_THREAD_RV_REF(T0) a0
|
||||
, BOOST_THREAD_RV_REF(T1) a1
|
||||
, BOOST_THREAD_RV_REF(T2) a2
|
||||
, BOOST_THREAD_RV_REF(T3) a3
|
||||
, BOOST_THREAD_RV_REF(T4) a4
|
||||
)
|
||||
: fp_(boost::move(f))
|
||||
, v0_(boost::move(a0))
|
||||
, v1_(boost::move(a1))
|
||||
, v2_(boost::move(a2))
|
||||
, v3_(boost::move(a3))
|
||||
, v4_(boost::move(a4))
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
async_func(BOOST_THREAD_RV_REF(async_func) f)
|
||||
: fp_(boost::move(f.fp))
|
||||
, v0_(boost::move(f.a0))
|
||||
, v1_(boost::move(f.a1))
|
||||
, v2_(boost::move(f.a2))
|
||||
, v3_(boost::move(f.a3))
|
||||
, v4_(boost::move(f.a4))
|
||||
{}
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
return invoke(boost::move(fp_)
|
||||
, boost::move(v0_)
|
||||
, boost::move(v1_)
|
||||
, boost::move(v2_)
|
||||
, boost::move(v3_)
|
||||
, boost::move(v4_)
|
||||
);
|
||||
}
|
||||
};
|
||||
template <class Fp, class T0, class T1, class T2, class T3>
|
||||
class async_func<Fp, T0, T1, T2, T3>
|
||||
{
|
||||
Fp fp_;
|
||||
T0 v0_;
|
||||
T1 v1_;
|
||||
T2 v2_;
|
||||
T3 v3_;
|
||||
public:
|
||||
BOOST_THREAD_MOVABLE_ONLY(async_func)
|
||||
typedef typename result_of<Fp(T0, T1, T2, T3)>::type result_type;
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
explicit async_func(BOOST_THREAD_RV_REF(Fp) f
|
||||
, BOOST_THREAD_RV_REF(T0) a0
|
||||
, BOOST_THREAD_RV_REF(T1) a1
|
||||
, BOOST_THREAD_RV_REF(T2) a2
|
||||
, BOOST_THREAD_RV_REF(T3) a3
|
||||
)
|
||||
: fp_(boost::move(f))
|
||||
, v0_(boost::move(a0))
|
||||
, v1_(boost::move(a1))
|
||||
, v2_(boost::move(a2))
|
||||
, v3_(boost::move(a3))
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
async_func(BOOST_THREAD_RV_REF(async_func) f)
|
||||
: fp_(boost::move(f.fp))
|
||||
, v0_(boost::move(f.a0))
|
||||
, v1_(boost::move(f.a1))
|
||||
, v2_(boost::move(f.a2))
|
||||
, v3_(boost::move(f.a3))
|
||||
{}
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
return invoke(boost::move(fp_)
|
||||
, boost::move(v0_)
|
||||
, boost::move(v1_)
|
||||
, boost::move(v2_)
|
||||
, boost::move(v3_)
|
||||
);
|
||||
}
|
||||
};
|
||||
template <class Fp, class T0, class T1, class T2>
|
||||
class async_func<Fp, T0, T1, T2>
|
||||
{
|
||||
Fp fp_;
|
||||
T0 v0_;
|
||||
T1 v1_;
|
||||
T2 v2_;
|
||||
public:
|
||||
BOOST_THREAD_MOVABLE_ONLY(async_func)
|
||||
typedef typename result_of<Fp(T0, T1, T2)>::type result_type;
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
explicit async_func(BOOST_THREAD_RV_REF(Fp) f
|
||||
, BOOST_THREAD_RV_REF(T0) a0
|
||||
, BOOST_THREAD_RV_REF(T1) a1
|
||||
, BOOST_THREAD_RV_REF(T2) a2
|
||||
)
|
||||
: fp_(boost::move(f))
|
||||
, v0_(boost::move(a0))
|
||||
, v1_(boost::move(a1))
|
||||
, v2_(boost::move(a2))
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
async_func(BOOST_THREAD_RV_REF(async_func) f)
|
||||
: fp_(boost::move(f.fp))
|
||||
, v0_(boost::move(f.a0))
|
||||
, v1_(boost::move(f.a1))
|
||||
, v2_(boost::move(f.a2))
|
||||
{}
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
return invoke(boost::move(fp_)
|
||||
, boost::move(v0_)
|
||||
, boost::move(v1_)
|
||||
, boost::move(v2_)
|
||||
);
|
||||
}
|
||||
};
|
||||
template <class Fp, class T0, class T1>
|
||||
class async_func<Fp, T0, T1>
|
||||
{
|
||||
Fp fp_;
|
||||
T0 v0_;
|
||||
T1 v1_;
|
||||
public:
|
||||
BOOST_THREAD_MOVABLE_ONLY(async_func)
|
||||
typedef typename result_of<Fp(T0, T1)>::type result_type;
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
explicit async_func(BOOST_THREAD_RV_REF(Fp) f
|
||||
, BOOST_THREAD_RV_REF(T0) a0
|
||||
, BOOST_THREAD_RV_REF(T1) a1
|
||||
)
|
||||
: fp_(boost::move(f))
|
||||
, v0_(boost::move(a0))
|
||||
, v1_(boost::move(a1))
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
async_func(BOOST_THREAD_RV_REF(async_func) f)
|
||||
: fp_(boost::move(f.fp))
|
||||
, v0_(boost::move(f.a0))
|
||||
, v1_(boost::move(f.a1))
|
||||
{}
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
return invoke(boost::move(fp_)
|
||||
, boost::move(v0_)
|
||||
, boost::move(v1_)
|
||||
);
|
||||
}
|
||||
};
|
||||
template <class Fp, class T0>
|
||||
class async_func<Fp, T0>
|
||||
{
|
||||
Fp fp_;
|
||||
T0 v0_;
|
||||
public:
|
||||
BOOST_THREAD_MOVABLE_ONLY(async_func)
|
||||
typedef typename result_of<Fp(T0)>::type result_type;
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
explicit async_func(BOOST_THREAD_RV_REF(Fp) f
|
||||
, BOOST_THREAD_RV_REF(T0) a0
|
||||
)
|
||||
: fp_(boost::move(f))
|
||||
, v0_(boost::move(a0))
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
async_func(BOOST_THREAD_RV_REF(async_func) f)
|
||||
: fp_(boost::move(f.fp))
|
||||
, v0_(boost::move(f.a0))
|
||||
{}
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
return invoke(boost::move(fp_)
|
||||
, boost::move(v0_)
|
||||
);
|
||||
}
|
||||
};
|
||||
template <class Fp>
|
||||
class async_func<Fp>
|
||||
{
|
||||
Fp fp_;
|
||||
public:
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE(async_func)
|
||||
typedef typename result_of<Fp()>::type result_type;
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
explicit async_func(BOOST_THREAD_FWD_REF(Fp) f)
|
||||
: fp_(boost::move(f))
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
async_func(BOOST_THREAD_FWD_REF(async_func) f)
|
||||
: fp_(boost::move(f.fp_))
|
||||
{}
|
||||
result_type operator()()
|
||||
{
|
||||
return fp_();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // header
|
||||
@@ -15,8 +15,7 @@
|
||||
//#define BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS
|
||||
// ATTRIBUTE_MAY_ALIAS
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) > 302 \
|
||||
&& !defined(__INTEL_COMPILER)
|
||||
#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
|
||||
|
||||
// GCC since 3.3 has may_alias attribute that helps to alleviate optimizer issues with
|
||||
// regard to violation of the strict aliasing rules.
|
||||
@@ -240,7 +239,7 @@
|
||||
! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
|
||||
! defined(BOOST_NO_CXX11_DECLTYPE) && \
|
||||
! defined(BOOST_NO_CXX11_DECLTYPE_N3276) && \
|
||||
! defined(BOOST_NO_CXX11_AUTO) && \
|
||||
! defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) && \
|
||||
! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
|
||||
! defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
|
||||
@@ -248,6 +247,22 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ! defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY \
|
||||
&& ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_WHEN_ALL_WHEN_ANY
|
||||
|
||||
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
|
||||
! defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
|
||||
#define BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// ! defined(BOOST_NO_SFINAE_EXPR) &&
|
||||
// ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) &&
|
||||
// ! defined(BOOST_NO_CXX11_AUTO) &&
|
||||
// ! defined(BOOST_NO_CXX11_DECLTYPE) &&
|
||||
// ! defined(BOOST_NO_CXX11_DECLTYPE_N3276) &&
|
||||
|
||||
|
||||
// MAKE_READY_AT_THREAD_EXIT
|
||||
#if ! defined BOOST_THREAD_PROVIDES_MAKE_READY_AT_THREAD_EXIT \
|
||||
@@ -264,6 +279,11 @@
|
||||
#define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
||||
#endif
|
||||
|
||||
#if ! defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP \
|
||||
&& ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_UNWRAP
|
||||
#define BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
|
||||
#endif
|
||||
|
||||
// FUTURE_INVALID_AFTER_GET
|
||||
#if ! defined BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET \
|
||||
&& ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_INVALID_AFTER_GET
|
||||
@@ -333,6 +353,12 @@
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES || defined BOOST_THREAD_USES_MOVE
|
||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
#define BOOST_THREAD_FUTURE_USES_OPTIONAL
|
||||
#endif
|
||||
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, < 0x600)
|
||||
# pragma warn -8008 // Condition always true/false
|
||||
# pragma warn -8080 // Identifier declared but never used
|
||||
@@ -358,7 +384,9 @@
|
||||
// compatibility with the rest of Boost's auto-linking code:
|
||||
#if defined(BOOST_THREAD_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)
|
||||
# undef BOOST_THREAD_USE_LIB
|
||||
# define BOOST_THREAD_USE_DLL
|
||||
# if !defined(BOOST_THREAD_USE_DLL)
|
||||
# define BOOST_THREAD_USE_DLL
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_THREAD_BUILD_DLL) //Build dll
|
||||
|
||||
@@ -75,15 +75,28 @@ namespace boost
|
||||
};
|
||||
struct counter_is_not_zero
|
||||
{
|
||||
counter_is_not_zero(const counter& count) : count_(count) {}
|
||||
counter_is_not_zero(counter const& count) : count_(count) {}
|
||||
bool operator()() const { return count_ != 0; }
|
||||
const counter& count_;
|
||||
counter const& count_;
|
||||
};
|
||||
struct counter_is_zero
|
||||
{
|
||||
counter_is_zero(const counter& count) : count_(count) {}
|
||||
counter_is_zero(counter const& count) : count_(count) {}
|
||||
bool operator()() const { return count_ == 0; }
|
||||
const counter& count_;
|
||||
counter const& count_;
|
||||
};
|
||||
struct is_zero
|
||||
{
|
||||
is_zero(std::size_t& count) : count_(count) {}
|
||||
bool operator()() const { return count_ == 0; }
|
||||
std::size_t& count_;
|
||||
};
|
||||
struct not_equal
|
||||
{
|
||||
not_equal(std::size_t& x, std::size_t& y) : x_(x), y_(y) {}
|
||||
bool operator()() const { return x_ != y_; }
|
||||
std::size_t& x_;
|
||||
std::size_t& y_;
|
||||
};
|
||||
}
|
||||
} // namespace boost
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
* BOOST_THREAD_DELETE_COPY_ASSIGN deletes the copy assignment when the compiler supports it or
|
||||
* makes it private.
|
||||
*/
|
||||
#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS
|
||||
|
||||
#if ! defined BOOST_NO_CXX11_DELETED_FUNCTIONS && ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
#define BOOST_THREAD_DELETE_COPY_CTOR(CLASS) \
|
||||
CLASS(CLASS const&) = delete; \
|
||||
|
||||
|
||||
93
include/boost/thread/detail/function_wrapper.hpp
Normal file
93
include/boost/thread/detail/function_wrapper.hpp
Normal file
@@ -0,0 +1,93 @@
|
||||
// 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/09 Vicente J. Botet Escriba
|
||||
// Adapt to boost from CCIA C++11 implementation
|
||||
// Make use of Boost.Move
|
||||
|
||||
#ifndef BOOST_THREAD_DETAIL_FUNCTION_WRAPPER_HPP
|
||||
#define BOOST_THREAD_DETAIL_FUNCTION_WRAPPER_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/thread/detail/memory.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
|
||||
#include <boost/thread/csbl/memory/unique_ptr.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
class function_wrapper
|
||||
{
|
||||
struct impl_base
|
||||
{
|
||||
virtual void call()=0;
|
||||
virtual ~impl_base()
|
||||
{
|
||||
}
|
||||
};
|
||||
typedef boost::csbl::unique_ptr<impl_base> impl_base_type;
|
||||
impl_base_type impl;
|
||||
template <typename F>
|
||||
struct impl_type: impl_base
|
||||
{
|
||||
F f;
|
||||
impl_type(F const &f_)
|
||||
: f(f_)
|
||||
{}
|
||||
impl_type(BOOST_THREAD_RV_REF(F) f_)
|
||||
: f(boost::move(f_))
|
||||
{}
|
||||
|
||||
void call()
|
||||
{
|
||||
if (impl) f();
|
||||
}
|
||||
};
|
||||
public:
|
||||
BOOST_THREAD_MOVABLE_ONLY(function_wrapper)
|
||||
|
||||
//#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
template<typename F>
|
||||
function_wrapper(F const& f):
|
||||
impl(new impl_type<F>(f))
|
||||
{}
|
||||
//#endif
|
||||
template<typename F>
|
||||
function_wrapper(BOOST_THREAD_RV_REF(F) f):
|
||||
impl(new impl_type<F>(boost::forward<F>(f)))
|
||||
{}
|
||||
function_wrapper(BOOST_THREAD_RV_REF(function_wrapper) other) BOOST_NOEXCEPT :
|
||||
impl(other.impl)
|
||||
{
|
||||
other.impl = 0;
|
||||
}
|
||||
function_wrapper()
|
||||
: impl(0)
|
||||
{
|
||||
}
|
||||
~function_wrapper()
|
||||
{
|
||||
}
|
||||
|
||||
function_wrapper& operator=(BOOST_THREAD_RV_REF(function_wrapper) other) BOOST_NOEXCEPT
|
||||
{
|
||||
impl=other.impl;
|
||||
other.impl=0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void operator()()
|
||||
{ impl->call();}
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // header
|
||||
@@ -28,7 +28,11 @@
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/core/enable_if.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/type_traits/is_base_of.hpp>
|
||||
#include <boost/type_traits/is_pointer.hpp>
|
||||
#include <boost/type_traits/is_member_function_pointer.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#ifndef BOOST_NO_CXX11_HDR_FUNCTIONAL
|
||||
#include <functional>
|
||||
@@ -40,11 +44,10 @@ namespace boost
|
||||
{
|
||||
|
||||
|
||||
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
|
||||
! defined(BOOST_NO_SFINAE_EXPR) && \
|
||||
#if ! defined(BOOST_NO_SFINAE_EXPR) && \
|
||||
! defined(BOOST_NO_CXX11_DECLTYPE) && \
|
||||
! defined(BOOST_NO_CXX11_DECLTYPE_N3276) && \
|
||||
! defined(BOOST_NO_CXX11_AUTO)
|
||||
! defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES)
|
||||
|
||||
#define BOOST_THREAD_PROVIDES_INVOKE
|
||||
|
||||
@@ -58,6 +61,13 @@ namespace boost
|
||||
{
|
||||
return (boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...);
|
||||
}
|
||||
template <class R, class Fp, class A0, class ...Args>
|
||||
inline auto
|
||||
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args)
|
||||
-> decltype((boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...))
|
||||
{
|
||||
return (boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class Fp, class A0, class ...Args>
|
||||
inline auto
|
||||
@@ -66,6 +76,13 @@ namespace boost
|
||||
{
|
||||
return ((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...);
|
||||
}
|
||||
template <class R, class Fp, class A0, class ...Args>
|
||||
inline auto
|
||||
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args)
|
||||
-> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...))
|
||||
{
|
||||
return ((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// bullets 3 and 4
|
||||
|
||||
@@ -85,14 +102,38 @@ namespace boost
|
||||
return (*boost::forward<A0>(a0)).*f;
|
||||
}
|
||||
|
||||
template <class R, class Fp, class A0>
|
||||
inline auto
|
||||
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
|
||||
-> decltype(boost::forward<A0>(a0).*f)
|
||||
{
|
||||
return boost::forward<A0>(a0).*f;
|
||||
}
|
||||
|
||||
template <class R, class Fp, class A0>
|
||||
inline auto
|
||||
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
|
||||
-> decltype((*boost::forward<A0>(a0)).*f)
|
||||
{
|
||||
return (*boost::forward<A0>(a0)).*f;
|
||||
}
|
||||
|
||||
|
||||
// bullet 5
|
||||
|
||||
template <class R, class Fp, class ...Args>
|
||||
inline auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args)
|
||||
-> decltype(boost::forward<Fp>(f)(boost::forward<Args>(args)...))
|
||||
{
|
||||
return boost::forward<Fp>(f)(boost::forward<Args>(args)...);
|
||||
}
|
||||
template <class Fp, class ...Args>
|
||||
inline auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args)
|
||||
-> decltype(boost::forward<Fp>(f)(boost::forward<Args>(args)...))
|
||||
{
|
||||
return boost::forward<Fp>(f)(boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
|
||||
|
||||
// bullets 1 and 2
|
||||
@@ -105,21 +146,45 @@ namespace boost
|
||||
{
|
||||
return (boost::forward<A0>(a0).*f)();
|
||||
}
|
||||
template <class R, class Fp, class A0>
|
||||
inline
|
||||
auto
|
||||
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
|
||||
-> decltype((boost::forward<A0>(a0).*f)())
|
||||
{
|
||||
return (boost::forward<A0>(a0).*f)();
|
||||
}
|
||||
template <class Fp, class A0, class A1>
|
||||
inline
|
||||
auto
|
||||
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
|
||||
-> decltype((boost::forward<A0>(a0).*f)(boost::forward<Args>(a1)))
|
||||
-> decltype((boost::forward<A0>(a0).*f)(boost::forward<A1>(a1)))
|
||||
{
|
||||
return (boost::forward<A0>(a0).*f)(boost::forward<Args>(a1));
|
||||
return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1));
|
||||
}
|
||||
template <class R, class Fp, class A0, class A1>
|
||||
inline
|
||||
auto
|
||||
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
|
||||
-> decltype((boost::forward<A0>(a0).*f)(boost::forward<A1>(a1)))
|
||||
{
|
||||
return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1));
|
||||
}
|
||||
template <class Fp, class A0, class A1, class A2>
|
||||
inline
|
||||
auto
|
||||
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
|
||||
-> decltype((boost::forward<A0>(a0).*f)(boost::forward<Args>(a1), boost::forward<Args>(a2)))
|
||||
-> decltype((boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)))
|
||||
{
|
||||
return (boost::forward<A0>(a0).*f)(boost::forward<Args>(a1), boost::forward<Args>(a2));
|
||||
return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
|
||||
}
|
||||
template <class R, class Fp, class A0, class A1, class A2>
|
||||
inline
|
||||
auto
|
||||
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
|
||||
-> decltype((boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)))
|
||||
{
|
||||
return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
|
||||
}
|
||||
|
||||
template <class Fp, class A0>
|
||||
@@ -130,21 +195,45 @@ namespace boost
|
||||
{
|
||||
return ((*boost::forward<A0>(a0)).*f)();
|
||||
}
|
||||
template <class R, class Fp, class A0>
|
||||
inline
|
||||
auto
|
||||
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
|
||||
-> decltype(((*boost::forward<A0>(a0)).*f)())
|
||||
{
|
||||
return ((*boost::forward<A0>(a0)).*f)();
|
||||
}
|
||||
template <class Fp, class A0, class A1>
|
||||
inline
|
||||
auto
|
||||
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
|
||||
-> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(a1)))
|
||||
-> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1)))
|
||||
{
|
||||
return ((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(a1));
|
||||
return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1));
|
||||
}
|
||||
template <class Fp, class A0, class A1>
|
||||
template <class R, class Fp, class A0, class A1>
|
||||
inline
|
||||
auto
|
||||
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
|
||||
-> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1)))
|
||||
{
|
||||
return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1));
|
||||
}
|
||||
template <class Fp, class A0, class A1, class A2>
|
||||
inline
|
||||
auto
|
||||
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
|
||||
-> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(a1), boost::forward<Args>(a2)))
|
||||
-> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)))
|
||||
{
|
||||
return ((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(a1), boost::forward<Args>(a2));
|
||||
return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
|
||||
}
|
||||
template <class R, class Fp, class A0, class A1, class A2>
|
||||
inline
|
||||
auto
|
||||
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
|
||||
-> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)))
|
||||
{
|
||||
return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
|
||||
}
|
||||
|
||||
// bullets 3 and 4
|
||||
@@ -157,6 +246,14 @@ namespace boost
|
||||
{
|
||||
return boost::forward<A0>(a0).*f;
|
||||
}
|
||||
template <class R, class Fp, class A0>
|
||||
inline
|
||||
auto
|
||||
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
|
||||
-> decltype(boost::forward<A0>(a0).*f)
|
||||
{
|
||||
return boost::forward<A0>(a0).*f;
|
||||
}
|
||||
|
||||
template <class Fp, class A0>
|
||||
inline
|
||||
@@ -166,6 +263,14 @@ namespace boost
|
||||
{
|
||||
return (*boost::forward<A0>(a0)).*f;
|
||||
}
|
||||
template <class R, class Fp, class A0>
|
||||
inline
|
||||
auto
|
||||
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
|
||||
-> decltype((*boost::forward<A0>(a0)).*f)
|
||||
{
|
||||
return (*boost::forward<A0>(a0)).*f;
|
||||
}
|
||||
|
||||
// bullet 5
|
||||
|
||||
@@ -178,7 +283,7 @@ namespace boost
|
||||
}
|
||||
template <class Fp, class A1>
|
||||
inline
|
||||
auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) a1)
|
||||
auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
|
||||
-> decltype(boost::forward<Fp>(f)(boost::forward<A1>(a1)))
|
||||
{
|
||||
return boost::forward<Fp>(f)(boost::forward<A1>(a1));
|
||||
@@ -197,6 +302,36 @@ namespace boost
|
||||
return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
|
||||
}
|
||||
|
||||
|
||||
template <class R, class Fp>
|
||||
inline
|
||||
auto invoke(BOOST_THREAD_RV_REF(Fp) f)
|
||||
-> decltype(boost::forward<Fp>(f)())
|
||||
{
|
||||
return boost::forward<Fp>(f)();
|
||||
}
|
||||
template <class R, class Fp, class A1>
|
||||
inline
|
||||
auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
|
||||
-> decltype(boost::forward<Fp>(f)(boost::forward<A1>(a1)))
|
||||
{
|
||||
return boost::forward<Fp>(f)(boost::forward<A1>(a1));
|
||||
}
|
||||
template <class R, class Fp, class A1, class A2>
|
||||
inline
|
||||
auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
|
||||
-> decltype(boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2)))
|
||||
{
|
||||
return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
|
||||
}
|
||||
template <class R, class Fp, class A1, class A2, class A3>
|
||||
inline
|
||||
auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
|
||||
-> decltype(boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3)))
|
||||
{
|
||||
return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
|
||||
}
|
||||
|
||||
#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
|
||||
|
||||
#elif ! defined(BOOST_NO_SFINAE_EXPR) && \
|
||||
@@ -395,22 +530,28 @@ namespace boost
|
||||
// bullet 5
|
||||
// f(t1, t2, ..., tN) in all other cases.
|
||||
|
||||
template <class Ret, class Fp, class ...Args>
|
||||
inline Ret do_invoke(mpl::false_, BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args)
|
||||
{
|
||||
return boost::forward<Fp>(f)(boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class Ret, class Fp, class ...Args>
|
||||
inline Ret do_invoke(mpl::true_, BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args)
|
||||
{
|
||||
return f(boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class Ret, class Fp, class ...Args>
|
||||
inline
|
||||
typename enable_if_c
|
||||
typename disable_if_c
|
||||
<
|
||||
! is_member_function_pointer<Fp>::value,
|
||||
is_member_function_pointer<Fp>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args)
|
||||
{
|
||||
return boost::forward<Fp>(f)(boost::forward<Args>(args)...);
|
||||
}
|
||||
template <class Ret, class ...Args>
|
||||
inline Ret
|
||||
invoke(Ret(*f)(Args... ), BOOST_THREAD_RV_REF(Args) ...args)
|
||||
{
|
||||
return f(boost::forward<Args>(args)...);
|
||||
return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), boost::forward<Args>(args)...);
|
||||
}
|
||||
#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
|
||||
// bullet 1
|
||||
@@ -424,9 +565,34 @@ namespace boost
|
||||
is_base_of<A, typename remove_reference<A0>::type>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(Ret (A::*f)(), BOOST_THREAD_RV_REF(A0) a0)
|
||||
invoke(Ret (A::*f)(), A0& a0)
|
||||
{
|
||||
return (boost::forward<A0>(a0).*f)();
|
||||
return (a0.*f)();
|
||||
}
|
||||
template <class Ret, class A, class A0>
|
||||
inline
|
||||
typename enable_if_c
|
||||
<
|
||||
is_base_of<A, typename remove_reference<A0>::type>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(Ret (A::*f)(), A0* a0)
|
||||
{
|
||||
return ((*a0).*f)();
|
||||
}
|
||||
|
||||
template <class Ret, class A, class A0, class A1>
|
||||
inline
|
||||
typename enable_if_c
|
||||
<
|
||||
is_base_of<A, typename remove_reference<A0>::type>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(Ret (A::*f)(A1),
|
||||
A0& a0, BOOST_THREAD_RV_REF(A1) a1
|
||||
)
|
||||
{
|
||||
return (a0.*f)(boost::forward<A1>(a1));
|
||||
}
|
||||
template <class Ret, class A, class A0, class A1>
|
||||
inline
|
||||
@@ -435,21 +601,33 @@ namespace boost
|
||||
is_base_of<A, typename remove_reference<A0>::type>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(Ret (A::*f)(A1), BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
|
||||
{
|
||||
return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1));
|
||||
}
|
||||
template <class Ret, class A, class A0, class A1>
|
||||
inline
|
||||
typename enable_if_c
|
||||
<
|
||||
is_base_of<A, typename remove_reference<A0>::type>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(Ret (A::*f)(A1), A0 a0, A1 a1)
|
||||
invoke(Ret (A::*f)(A1), A0& a0, A1 a1)
|
||||
{
|
||||
return (a0.*f)(a1);
|
||||
}
|
||||
template <class Ret, class A, class A0, class A1>
|
||||
inline
|
||||
typename enable_if_c
|
||||
<
|
||||
is_base_of<A, typename remove_reference<A0>::type>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(Ret (A::*f)(A1), A0* a0, BOOST_THREAD_RV_REF(A1) a1
|
||||
)
|
||||
{
|
||||
return (*(a0).*f)(boost::forward<A1>(a1));
|
||||
}
|
||||
template <class Ret, class A, class A0, class A1>
|
||||
inline
|
||||
typename enable_if_c
|
||||
<
|
||||
is_base_of<A, typename remove_reference<A0>::type>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(Ret (A::*f)(A1), A0* a0, A1 a1)
|
||||
{
|
||||
return (*a0.*f)(a1);
|
||||
}
|
||||
template <class Ret, class A, class A0, class A1, class A2>
|
||||
inline
|
||||
typename enable_if_c
|
||||
@@ -458,10 +636,10 @@ namespace boost
|
||||
Ret
|
||||
>::type
|
||||
invoke(Ret (A::*f)(A1, A2),
|
||||
BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2
|
||||
A0& a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2
|
||||
)
|
||||
{
|
||||
return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
|
||||
return (a0.*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
|
||||
}
|
||||
template <class Ret, class A, class A0, class A1, class A2>
|
||||
inline
|
||||
@@ -470,9 +648,9 @@ namespace boost
|
||||
is_base_of<A, typename remove_reference<A0>::type>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(Ret (A::*f)(A1, A2), A0 a0, A1 a1, A2 a2)
|
||||
invoke(Ret (A::*f)(A1, A2), A0* a0, A1 a1, A2 a2)
|
||||
{
|
||||
return (a0.*f)(a1, a2);
|
||||
return ((*a0).*f)(a1, a2);
|
||||
}
|
||||
template <class Ret, class A, class A0, class A1, class A2, class A3>
|
||||
inline
|
||||
@@ -482,9 +660,9 @@ namespace boost
|
||||
Ret
|
||||
>::type
|
||||
invoke(Ret (A::*f)(A1, A2, A3),
|
||||
BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
|
||||
A0& a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
|
||||
{
|
||||
return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
|
||||
return (a0.*f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
|
||||
}
|
||||
template <class Ret, class A, class A0, class A1, class A2, class A3>
|
||||
inline
|
||||
@@ -493,9 +671,9 @@ namespace boost
|
||||
is_base_of<A, typename remove_reference<A0>::type>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(Ret (A::*f)(A1, A2, A3), A0 a0, A1 a1, A2 a2, A3 a3)
|
||||
invoke(Ret (A::*f)(A1, A2, A3), A0* a0, A1 a1, A2 a2, A3 a3)
|
||||
{
|
||||
return (a0.*f)(a1, a2, a3);
|
||||
return ((*a0).*f)(a1, a2, a3);
|
||||
}
|
||||
|
||||
///
|
||||
@@ -506,9 +684,20 @@ namespace boost
|
||||
is_base_of<A, typename remove_reference<A0>::type>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(Ret (A::*f)() const, BOOST_THREAD_RV_REF(A0) a0)
|
||||
invoke(Ret (A::*f)() const, A0 const& a0)
|
||||
{
|
||||
return (boost::forward<A0>(a0).*f)();
|
||||
return (a0.*f)();
|
||||
}
|
||||
template <class Ret, class A, class A0>
|
||||
inline
|
||||
typename enable_if_c
|
||||
<
|
||||
is_base_of<A, typename remove_reference<A0>::type>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(Ret (A::*f)() const, A0 const* a0)
|
||||
{
|
||||
return ((*a0).*f)();
|
||||
}
|
||||
template <class Ret, class A, class A0, class A1>
|
||||
inline
|
||||
@@ -517,9 +706,9 @@ namespace boost
|
||||
is_base_of<A, typename remove_reference<A0>::type>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(Ret (A::*f)(A1) const, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
|
||||
invoke(Ret (A::*f)(A1) const, A0 const& a0, BOOST_THREAD_RV_REF(A1) a1)
|
||||
{
|
||||
return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1));
|
||||
return (a0.*f)(boost::forward<A1>(a1));
|
||||
}
|
||||
template <class Ret, class A, class A0, class A1>
|
||||
inline
|
||||
@@ -528,7 +717,19 @@ namespace boost
|
||||
is_base_of<A, typename remove_reference<A0>::type>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(Ret (A::*f)(A1) const, A0 a0, A1 a1)
|
||||
invoke(Ret (A::*f)(A1) const, A0 const* a0, BOOST_THREAD_RV_REF(A1) a1)
|
||||
{
|
||||
return ((*a0).*f)(boost::forward<A1>(a1));
|
||||
}
|
||||
|
||||
template <class Ret, class A, class A0, class A1>
|
||||
inline
|
||||
typename enable_if_c
|
||||
<
|
||||
is_base_of<A, typename remove_reference<A0>::type>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(Ret (A::*f)(A1) const, A0 const& a0, A1 a1)
|
||||
{
|
||||
return (a0.*f)(a1);
|
||||
}
|
||||
@@ -540,7 +741,7 @@ namespace boost
|
||||
Ret
|
||||
>::type
|
||||
invoke(Ret (A::*f)(A1, A2) const,
|
||||
BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2
|
||||
A0 const& a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2
|
||||
)
|
||||
{
|
||||
return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)
|
||||
@@ -553,7 +754,7 @@ namespace boost
|
||||
is_base_of<A, typename remove_reference<A0>::type>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(Ret (A::*f)(A1, A2) const, A0 a0, A1 a1, A2 a2)
|
||||
invoke(Ret (A::*f)(A1, A2) const, A0 const& a0, A1 a1, A2 a2)
|
||||
{
|
||||
return (a0.*f)(a1, a2);
|
||||
}
|
||||
@@ -1159,189 +1360,241 @@ namespace boost
|
||||
// f(t1, t2, ..., tN) in all other cases.
|
||||
|
||||
template <class Ret, class Fp>
|
||||
inline
|
||||
typename enable_if_c
|
||||
<
|
||||
! is_member_function_pointer<Fp>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(BOOST_THREAD_RV_REF(Fp) f)
|
||||
inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f)
|
||||
{
|
||||
return boost::forward<Fp>(f)();
|
||||
}
|
||||
template <class Ret, class Fp, class A1>
|
||||
template <class Ret, class Fp>
|
||||
inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f)
|
||||
{
|
||||
return f();
|
||||
}
|
||||
template <class Ret, class Fp>
|
||||
inline
|
||||
typename enable_if_c
|
||||
typename disable_if_c
|
||||
<
|
||||
! is_member_function_pointer<Fp>::value,
|
||||
is_member_function_pointer<Fp>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
|
||||
invoke(BOOST_THREAD_FWD_REF(Fp) f)
|
||||
{
|
||||
return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f));
|
||||
}
|
||||
|
||||
template <class Ret, class Fp, class A1>
|
||||
inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
|
||||
{
|
||||
return boost::forward<Fp>(f)(boost::forward<A1>(a1));
|
||||
}
|
||||
template <class Ret, class Fp, class A1>
|
||||
inline
|
||||
typename enable_if_c
|
||||
<
|
||||
! is_member_function_pointer<Fp>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(BOOST_THREAD_RV_REF(Fp) f, A1 a1)
|
||||
{
|
||||
return boost::forward<Fp>(f)(a1);
|
||||
}
|
||||
template <class Ret, class Fp, class A1, class A2>
|
||||
inline
|
||||
typename enable_if_c
|
||||
<
|
||||
! is_member_function_pointer<Fp>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
|
||||
{
|
||||
return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
|
||||
}
|
||||
template <class Ret, class Fp, class A1, class A2>
|
||||
inline
|
||||
typename enable_if_c
|
||||
<
|
||||
! is_member_function_pointer<Fp>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(BOOST_THREAD_RV_REF(Fp) f, A1 a1, A2 a2)
|
||||
{
|
||||
return boost::forward<Fp>(f)(a1, a2);
|
||||
}
|
||||
template <class Ret, class Fp, class A1, class A2, class A3>
|
||||
inline
|
||||
typename enable_if_c
|
||||
<
|
||||
! is_member_function_pointer<Fp>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
|
||||
{
|
||||
return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
|
||||
}
|
||||
template <class Ret, class Fp, class A1, class A2, class A3>
|
||||
inline
|
||||
typename enable_if_c
|
||||
<
|
||||
! is_member_function_pointer<Fp>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(BOOST_THREAD_RV_REF(Fp) f, A1 a1, A2 a2, A3 a3)
|
||||
{
|
||||
return boost::forward<Fp>(f)(a1, a2, a3);
|
||||
}
|
||||
|
||||
///
|
||||
template <class Ret, class Fp>
|
||||
inline
|
||||
typename enable_if_c
|
||||
<
|
||||
! is_member_function_pointer<Fp>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(Fp const &f)
|
||||
{
|
||||
return f();
|
||||
}
|
||||
template <class Ret, class Fp, class A1>
|
||||
inline
|
||||
typename enable_if_c
|
||||
<
|
||||
! is_member_function_pointer<Fp>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(Fp const &f, BOOST_THREAD_RV_REF(A1) a1)
|
||||
inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
|
||||
{
|
||||
return f(boost::forward<A1>(a1));
|
||||
}
|
||||
template <class Ret, class Fp, class A1>
|
||||
inline
|
||||
typename enable_if_c
|
||||
typename disable_if_c
|
||||
<
|
||||
! is_member_function_pointer<Fp>::value,
|
||||
is_member_function_pointer<Fp>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(Fp const &f, A1 a1)
|
||||
invoke(BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
|
||||
{
|
||||
return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), boost::forward<A1>(a1));
|
||||
}
|
||||
|
||||
template <class Ret, class Fp, class A1, class A2>
|
||||
inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
|
||||
{
|
||||
return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
|
||||
}
|
||||
template <class Ret, class Fp, class A1, class A2>
|
||||
inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
|
||||
{
|
||||
return f(boost::forward<A1>(a1), boost::forward<A2>(a2));
|
||||
}
|
||||
template <class Ret, class Fp, class A1, class A2>
|
||||
inline
|
||||
typename disable_if_c
|
||||
<
|
||||
is_member_function_pointer<Fp>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
|
||||
{
|
||||
return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), boost::forward<A1>(a1), boost::forward<A2>(a2));
|
||||
}
|
||||
|
||||
template <class Ret, class Fp, class A1, class A2, class A3>
|
||||
inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
|
||||
{
|
||||
return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
|
||||
}
|
||||
template <class Ret, class Fp, class A1, class A2, class A3>
|
||||
inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
|
||||
{
|
||||
return f(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
|
||||
}
|
||||
template <class Ret, class Fp, class A1, class A2, class A3>
|
||||
inline
|
||||
typename disable_if_c
|
||||
<
|
||||
is_member_function_pointer<Fp>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
|
||||
{
|
||||
return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
|
||||
}
|
||||
|
||||
|
||||
template <class Ret, class Fp, class A1>
|
||||
inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1)
|
||||
{
|
||||
return boost::forward<Fp>(f)(a1);
|
||||
}
|
||||
template <class Ret, class Fp, class A1>
|
||||
inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1)
|
||||
{
|
||||
return f(a1);
|
||||
}
|
||||
template <class Ret, class Fp, class A1>
|
||||
inline
|
||||
typename disable_if_c
|
||||
<
|
||||
is_member_function_pointer<Fp>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(BOOST_THREAD_FWD_REF(Fp) f, A1 a1)
|
||||
{
|
||||
return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), a1);
|
||||
}
|
||||
|
||||
template <class Ret, class Fp, class A1, class A2>
|
||||
inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2)
|
||||
{
|
||||
return boost::forward<Fp>(f)(a1, a2);
|
||||
}
|
||||
template <class Ret, class Fp, class A1, class A2>
|
||||
inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2)
|
||||
{
|
||||
return f(a1, a2);
|
||||
}
|
||||
template <class Ret, class Fp, class A1, class A2>
|
||||
inline
|
||||
typename disable_if_c
|
||||
<
|
||||
is_member_function_pointer<Fp>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2)
|
||||
{
|
||||
return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), a1, a2);
|
||||
}
|
||||
|
||||
template <class Ret, class Fp, class A1, class A2, class A3>
|
||||
inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2, A3 a3)
|
||||
{
|
||||
return boost::forward<Fp>(f)(a1, a2, a3);
|
||||
}
|
||||
template <class Ret, class Fp, class A1, class A2, class A3>
|
||||
inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2, A3 a3)
|
||||
{
|
||||
return f(a1, a2, a3);
|
||||
}
|
||||
template <class Ret, class Fp, class A1, class A2, class A3>
|
||||
inline
|
||||
typename disable_if_c
|
||||
<
|
||||
is_member_function_pointer<Fp>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2, A3 a3)
|
||||
{
|
||||
return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), a1, a2, a3);
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
template <class Ret, class Fp>
|
||||
inline
|
||||
typename disable_if_c
|
||||
<
|
||||
is_member_function_pointer<Fp>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(Fp &f)
|
||||
{
|
||||
return f();
|
||||
}
|
||||
template <class Ret, class Fp, class A1>
|
||||
inline
|
||||
typename disable_if_c
|
||||
<
|
||||
is_member_function_pointer<Fp>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(Fp &f, BOOST_THREAD_RV_REF(A1) a1)
|
||||
{
|
||||
return f(boost::forward<A1>(a1));
|
||||
}
|
||||
template <class Ret, class Fp, class A1>
|
||||
inline
|
||||
typename disable_if_c
|
||||
<
|
||||
is_member_function_pointer<Fp>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(Fp &f, A1 a1)
|
||||
{
|
||||
return f(a1);
|
||||
}
|
||||
template <class Ret, class Fp, class A1, class A2>
|
||||
inline
|
||||
typename enable_if_c
|
||||
typename disable_if_c
|
||||
<
|
||||
! is_member_function_pointer<Fp>::value,
|
||||
is_member_function_pointer<Fp>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(Fp const &f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
|
||||
invoke(Fp &f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
|
||||
{
|
||||
return f(boost::forward<A1>(a1), boost::forward<A2>(a2));
|
||||
}
|
||||
template <class Ret, class Fp, class A1, class A2>
|
||||
inline
|
||||
typename enable_if_c
|
||||
typename disable_if_c
|
||||
<
|
||||
! is_member_function_pointer<Fp>::value,
|
||||
is_member_function_pointer<Fp>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(Fp const &f, A1 a1, A2 a2)
|
||||
invoke(Fp &f, A1 a1, A2 a2)
|
||||
{
|
||||
return f(a1, a2);
|
||||
}
|
||||
template <class Ret, class Fp, class A1, class A2, class A3>
|
||||
inline
|
||||
typename enable_if_c
|
||||
typename disable_if_c
|
||||
<
|
||||
! is_member_function_pointer<Fp>::value,
|
||||
is_member_function_pointer<Fp>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(Fp const &f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
|
||||
invoke(Fp &f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
|
||||
{
|
||||
return f(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
|
||||
}
|
||||
template <class Ret, class Fp, class A1, class A2, class A3>
|
||||
inline
|
||||
typename enable_if_c
|
||||
typename disable_if_c
|
||||
<
|
||||
! is_member_function_pointer<Fp>::value,
|
||||
is_member_function_pointer<Fp>::value,
|
||||
Ret
|
||||
>::type
|
||||
invoke(Fp const &f, A1 a1, A2 a2, A3 a3)
|
||||
invoke(Fp &f, A1 a1, A2 a2, A3 a3)
|
||||
{
|
||||
return f(a1, a2, a3);
|
||||
}
|
||||
///
|
||||
|
||||
template <class Ret>
|
||||
inline Ret
|
||||
invoke(Ret(*f)())
|
||||
{
|
||||
return f();
|
||||
}
|
||||
template <class Ret, class A1>
|
||||
inline Ret
|
||||
invoke(Ret(*f)(A1), BOOST_THREAD_RV_REF(A1) a1)
|
||||
{
|
||||
return f(boost::forward<A1>(a1));
|
||||
}
|
||||
template <class Ret, class A1, class A2>
|
||||
inline Ret
|
||||
invoke(Ret(*f)(A1, A2),
|
||||
BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
|
||||
{
|
||||
return f(boost::forward<A1>(a1), boost::forward<A2>(a2));
|
||||
}
|
||||
template <class Ret, class A1, class A2, class A3>
|
||||
inline Ret
|
||||
invoke(Ret(*f)(A1, A2, A3),
|
||||
BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
|
||||
{
|
||||
return f(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
|
||||
}
|
||||
#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
|
||||
|
||||
#endif // all
|
||||
|
||||
754
include/boost/thread/detail/invoker.hpp
Normal file
754
include/boost/thread/detail/invoker.hpp
Normal file
@@ -0,0 +1,754 @@
|
||||
// Copyright (C) 2012 Vicente J. Botet Escriba
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// 2013/04 Vicente J. Botet Escriba
|
||||
// Provide implementation up to 9 parameters when BOOST_NO_CXX11_VARIADIC_TEMPLATES is defined.
|
||||
// Make use of Boost.Move
|
||||
// Make use of Boost.Tuple (movable)
|
||||
// 2012/11 Vicente J. Botet Escriba
|
||||
// Adapt to boost libc++ implementation
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// The invoker code is based on the one from libcxx.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef BOOST_THREAD_DETAIL_INVOKER_HPP
|
||||
#define BOOST_THREAD_DETAIL_INVOKER_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <boost/utility/result_of.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/detail/invoke.hpp>
|
||||
#include <boost/thread/detail/make_tuple_indices.hpp>
|
||||
#include <boost/thread/csbl/tuple.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
|
||||
#include <boost/thread/detail/variadic_header.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
#if defined(BOOST_THREAD_PROVIDES_INVOKE) && ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && ! defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
|
||||
template <class Fp, class ... Args>
|
||||
class invoker
|
||||
{
|
||||
//typedef typename decay<Fp>::type Fpd;
|
||||
//typedef tuple<typename decay<Args>::type...> Argsd;
|
||||
|
||||
//csbl::tuple<Fpd, Argsd...> f_;
|
||||
csbl::tuple<Fp, Args...> f_;
|
||||
|
||||
public:
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE( invoker)
|
||||
//typedef typename invoke_of<_Fp, _Args...>::type Rp;
|
||||
typedef typename result_of<Fp(Args...)>::type result_type;
|
||||
|
||||
template <class F, class ... As>
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
explicit invoker(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(As)... args)
|
||||
: f_(boost::forward<F>(f), boost::forward<As>(args)...)
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker(BOOST_THREAD_RV_REF(invoker) f) : f_(boost::move(BOOST_THREAD_RV(f).f_))
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker( const invoker& f) : f_(f.f_)
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker& operator=(BOOST_THREAD_RV_REF(invoker) f)
|
||||
{
|
||||
f_ = boost::move(BOOST_THREAD_RV(f).f_);
|
||||
}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker& operator=( BOOST_THREAD_COPY_ASSIGN_REF(invoker) f)
|
||||
{
|
||||
f_ = f.f_;
|
||||
}
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
typedef typename make_tuple_indices<1+sizeof...(Args), 1>::type Index;
|
||||
return execute(Index());
|
||||
}
|
||||
private:
|
||||
template <size_t ...Indices>
|
||||
result_type
|
||||
execute(tuple_indices<Indices...>)
|
||||
{
|
||||
return invoke(boost::move(csbl::get<0>(f_)), boost::move(csbl::get<Indices>(f_))...);
|
||||
}
|
||||
};
|
||||
|
||||
template <class R, class Fp, class ... Args>
|
||||
class invoker_ret
|
||||
{
|
||||
//typedef typename decay<Fp>::type Fpd;
|
||||
//typedef tuple<typename decay<Args>::type...> Argsd;
|
||||
|
||||
//csbl::tuple<Fpd, Argsd...> f_;
|
||||
csbl::tuple<Fp, Args...> f_;
|
||||
|
||||
public:
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE( invoker_ret)
|
||||
typedef R result_type;
|
||||
|
||||
template <class F, class ... As>
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
explicit invoker_ret(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(As)... args)
|
||||
: f_(boost::forward<F>(f), boost::forward<As>(args)...)
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker_ret(BOOST_THREAD_RV_REF(invoker_ret) f) : f_(boost::move(BOOST_THREAD_RV(f).f_))
|
||||
{}
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
typedef typename make_tuple_indices<1+sizeof...(Args), 1>::type Index;
|
||||
return execute(Index());
|
||||
}
|
||||
private:
|
||||
template <size_t ...Indices>
|
||||
result_type
|
||||
execute(tuple_indices<Indices...>)
|
||||
{
|
||||
return invoke<R>(boost::move(csbl::get<0>(f_)), boost::move(csbl::get<Indices>(f_))...);
|
||||
}
|
||||
};
|
||||
//BOOST_THREAD_DCL_MOVABLE_BEG(X) invoker<Fp> BOOST_THREAD_DCL_MOVABLE_END
|
||||
#else
|
||||
|
||||
#if ! defined BOOST_MSVC
|
||||
|
||||
#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)
|
||||
#define BOOST_THREAD_RV_REF_ARG(z, n, unused) , BOOST_THREAD_RV_REF(Arg##n) arg##n
|
||||
#define BOOST_THREAD_FWD_REF_A(z, n, unused) , BOOST_THREAD_FWD_REF(A##n) arg##n
|
||||
#define BOOST_THREAD_FWD_REF_ARG(z, n, unused) , BOOST_THREAD_FWD_REF(Arg##n) arg##n
|
||||
#define BOOST_THREAD_FWD_PARAM(z, n, unused) , boost::forward<Arg##n>(arg##n)
|
||||
#define BOOST_THREAD_FWD_PARAM_A(z, n, unused) , boost::forward<A##n>(arg##n)
|
||||
#define BOOST_THREAD_DCL(z, n, unused) Arg##n v##n;
|
||||
#define BOOST_THREAD_MOVE_PARAM(z, n, unused) , v##n(boost::move(arg##n))
|
||||
#define BOOST_THREAD_FORWARD_PARAM_A(z, n, unused) , v##n(boost::forward<A##n>(arg##n))
|
||||
#define BOOST_THREAD_MOVE_RHS_PARAM(z, n, unused) , v##n(boost::move(x.v##n))
|
||||
#define BOOST_THREAD_MOVE_DCL(z, n, unused) , boost::move(v##n)
|
||||
#define BOOST_THREAD_MOVE_DCL_T(z, n, unused) BOOST_PP_COMMA_IF(n) boost::move(v##n)
|
||||
#define BOOST_THREAD_ARG_DEF(z, n, unused) , class Arg##n = tuples::null_type
|
||||
|
||||
template <class Fp, class Arg = tuples::null_type
|
||||
BOOST_PP_REPEAT(BOOST_THREAD_MAX_ARGS, BOOST_THREAD_ARG_DEF, ~)
|
||||
>
|
||||
class invoker;
|
||||
|
||||
#define BOOST_THREAD_ASYNC_FUNCT(z, n, unused) \
|
||||
template <class Fp BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class Arg) > \
|
||||
class invoker<Fp BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Arg)> \
|
||||
{ \
|
||||
Fp fp_; \
|
||||
BOOST_PP_REPEAT(n, BOOST_THREAD_DCL, ~) \
|
||||
public: \
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker) \
|
||||
typedef typename result_of<Fp(BOOST_PP_ENUM_PARAMS(n, Arg))>::type result_type; \
|
||||
\
|
||||
template <class F BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class A) > \
|
||||
BOOST_SYMBOL_VISIBLE \
|
||||
explicit invoker(BOOST_THREAD_FWD_REF(F) f \
|
||||
BOOST_PP_REPEAT(n, BOOST_THREAD_FWD_REF_A, ~) \
|
||||
) \
|
||||
: fp_(boost::forward<F>(f)) \
|
||||
BOOST_PP_REPEAT(n, BOOST_THREAD_FORWARD_PARAM_A, ~) \
|
||||
{} \
|
||||
\
|
||||
BOOST_SYMBOL_VISIBLE \
|
||||
invoker(BOOST_THREAD_RV_REF(invoker) x) \
|
||||
: fp_(boost::move(x.fp_)) \
|
||||
BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_RHS_PARAM, ~) \
|
||||
{} \
|
||||
\
|
||||
result_type operator()() { \
|
||||
return invoke(boost::move(fp_) \
|
||||
BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_DCL, ~) \
|
||||
); \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
template <class R BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class Arg) > \
|
||||
class invoker<R(*)(BOOST_PP_REPEAT(n, BOOST_THREAD_RV_REF_ARG_T, ~)) BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Arg)> \
|
||||
{ \
|
||||
typedef R(*Fp)(BOOST_PP_REPEAT(n, BOOST_THREAD_RV_REF_ARG_T, ~)); \
|
||||
Fp fp_; \
|
||||
BOOST_PP_REPEAT(n, BOOST_THREAD_DCL, ~) \
|
||||
public: \
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker) \
|
||||
typedef typename result_of<Fp(BOOST_PP_ENUM_PARAMS(n, Arg))>::type result_type; \
|
||||
\
|
||||
template <class R2 BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class A) > \
|
||||
BOOST_SYMBOL_VISIBLE \
|
||||
explicit invoker(R2(*f)(BOOST_PP_REPEAT(n, BOOST_THREAD_RV_REF_A_T, ~)) \
|
||||
BOOST_PP_REPEAT(n, BOOST_THREAD_FWD_REF_A, ~) \
|
||||
) \
|
||||
: fp_(f) \
|
||||
BOOST_PP_REPEAT(n, BOOST_THREAD_FORWARD_PARAM_A, ~) \
|
||||
{} \
|
||||
\
|
||||
BOOST_SYMBOL_VISIBLE \
|
||||
invoker(BOOST_THREAD_RV_REF(invoker) x) \
|
||||
: fp_(x.fp_) \
|
||||
BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_RHS_PARAM, ~) \
|
||||
{} \
|
||||
\
|
||||
result_type operator()() { \
|
||||
return fp_( \
|
||||
BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_DCL_T, ~) \
|
||||
); \
|
||||
} \
|
||||
};
|
||||
|
||||
BOOST_PP_REPEAT(BOOST_THREAD_MAX_ARGS, BOOST_THREAD_ASYNC_FUNCT, ~)
|
||||
|
||||
#undef BOOST_THREAD_RV_REF_ARG_T
|
||||
#undef BOOST_THREAD_RV_REF_ARG
|
||||
#undef BOOST_THREAD_FWD_REF_ARG
|
||||
#undef BOOST_THREAD_FWD_REF_A
|
||||
#undef BOOST_THREAD_FWD_PARAM
|
||||
#undef BOOST_THREAD_FWD_PARAM_A
|
||||
#undef BOOST_THREAD_DCL
|
||||
#undef BOOST_THREAD_MOVE_PARAM
|
||||
#undef BOOST_THREAD_MOVE_RHS_PARAM
|
||||
#undef BOOST_THREAD_MOVE_DCL
|
||||
#undef BOOST_THREAD_ARG_DEF
|
||||
#undef BOOST_THREAD_ASYNC_FUNCT
|
||||
|
||||
#else
|
||||
|
||||
template <class Fp,
|
||||
class T0 = tuples::null_type, class T1 = tuples::null_type, class T2 = tuples::null_type,
|
||||
class T3 = tuples::null_type, class T4 = tuples::null_type, class T5 = tuples::null_type,
|
||||
class T6 = tuples::null_type, class T7 = tuples::null_type, class T8 = tuples::null_type
|
||||
, class T9 = tuples::null_type
|
||||
>
|
||||
class invoker;
|
||||
|
||||
template <class Fp,
|
||||
class T0 , class T1 , class T2 ,
|
||||
class T3 , class T4 , class T5 ,
|
||||
class T6 , class T7 , class T8 >
|
||||
class invoker<Fp, T0, T1, T2, T3, T4, T5, T6, T7, T8>
|
||||
{
|
||||
Fp fp_;
|
||||
T0 v0_;
|
||||
T1 v1_;
|
||||
T2 v2_;
|
||||
T3 v3_;
|
||||
T4 v4_;
|
||||
T5 v5_;
|
||||
T6 v6_;
|
||||
T7 v7_;
|
||||
T8 v8_;
|
||||
//::boost::tuple<Fp, T0, T1, T2, T3, T4, T5, T6, T7, T8> f_;
|
||||
|
||||
public:
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
|
||||
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5, T6, T7, T8)>::type result_type;
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
|
||||
, BOOST_THREAD_RV_REF(T0) a0
|
||||
, BOOST_THREAD_RV_REF(T1) a1
|
||||
, BOOST_THREAD_RV_REF(T2) a2
|
||||
, BOOST_THREAD_RV_REF(T3) a3
|
||||
, BOOST_THREAD_RV_REF(T4) a4
|
||||
, BOOST_THREAD_RV_REF(T5) a5
|
||||
, BOOST_THREAD_RV_REF(T6) a6
|
||||
, BOOST_THREAD_RV_REF(T7) a7
|
||||
, BOOST_THREAD_RV_REF(T8) a8
|
||||
)
|
||||
: fp_(boost::move(f))
|
||||
, v0_(boost::move(a0))
|
||||
, v1_(boost::move(a1))
|
||||
, v2_(boost::move(a2))
|
||||
, v3_(boost::move(a3))
|
||||
, v4_(boost::move(a4))
|
||||
, v5_(boost::move(a5))
|
||||
, v6_(boost::move(a6))
|
||||
, v7_(boost::move(a7))
|
||||
, v8_(boost::move(a8))
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker(BOOST_THREAD_RV_REF(invoker) f)
|
||||
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
|
||||
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
|
||||
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
|
||||
, v2_(boost::move(BOOST_THREAD_RV(f).v2_))
|
||||
, v3_(boost::move(BOOST_THREAD_RV(f).v3_))
|
||||
, v4_(boost::move(BOOST_THREAD_RV(f).v4_))
|
||||
, v5_(boost::move(BOOST_THREAD_RV(f).v5_))
|
||||
, v6_(boost::move(BOOST_THREAD_RV(f).v6_))
|
||||
, v7_(boost::move(BOOST_THREAD_RV(f).v7_))
|
||||
, v8_(boost::move(BOOST_THREAD_RV(f).v8_))
|
||||
{}
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
return invoke(boost::move(fp_)
|
||||
, boost::move(v0_)
|
||||
, boost::move(v1_)
|
||||
, boost::move(v2_)
|
||||
, boost::move(v3_)
|
||||
, boost::move(v4_)
|
||||
, boost::move(v5_)
|
||||
, boost::move(v6_)
|
||||
, boost::move(v7_)
|
||||
, boost::move(v8_)
|
||||
);
|
||||
}
|
||||
};
|
||||
template <class Fp, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7 >
|
||||
class invoker<Fp, T0, T1, T2, T3, T4, T5, T6, T7>
|
||||
{
|
||||
Fp fp_;
|
||||
T0 v0_;
|
||||
T1 v1_;
|
||||
T2 v2_;
|
||||
T3 v3_;
|
||||
T4 v4_;
|
||||
T5 v5_;
|
||||
T6 v6_;
|
||||
T7 v7_;
|
||||
public:
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
|
||||
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5, T6, T7)>::type result_type;
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
|
||||
, BOOST_THREAD_RV_REF(T0) a0
|
||||
, BOOST_THREAD_RV_REF(T1) a1
|
||||
, BOOST_THREAD_RV_REF(T2) a2
|
||||
, BOOST_THREAD_RV_REF(T3) a3
|
||||
, BOOST_THREAD_RV_REF(T4) a4
|
||||
, BOOST_THREAD_RV_REF(T5) a5
|
||||
, BOOST_THREAD_RV_REF(T6) a6
|
||||
, BOOST_THREAD_RV_REF(T7) a7
|
||||
)
|
||||
: fp_(boost::move(f))
|
||||
, v0_(boost::move(a0))
|
||||
, v1_(boost::move(a1))
|
||||
, v2_(boost::move(a2))
|
||||
, v3_(boost::move(a3))
|
||||
, v4_(boost::move(a4))
|
||||
, v5_(boost::move(a5))
|
||||
, v6_(boost::move(a6))
|
||||
, v7_(boost::move(a7))
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker(BOOST_THREAD_RV_REF(invoker) f)
|
||||
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
|
||||
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
|
||||
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
|
||||
, v2_(boost::move(BOOST_THREAD_RV(f).v2_))
|
||||
, v3_(boost::move(BOOST_THREAD_RV(f).v3_))
|
||||
, v4_(boost::move(BOOST_THREAD_RV(f).v4_))
|
||||
, v5_(boost::move(BOOST_THREAD_RV(f).v5_))
|
||||
, v6_(boost::move(BOOST_THREAD_RV(f).v6_))
|
||||
, v7_(boost::move(BOOST_THREAD_RV(f).v7_))
|
||||
{}
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
return invoke(boost::move(fp_)
|
||||
, boost::move(v0_)
|
||||
, boost::move(v1_)
|
||||
, boost::move(v2_)
|
||||
, boost::move(v3_)
|
||||
, boost::move(v4_)
|
||||
, boost::move(v5_)
|
||||
, boost::move(v6_)
|
||||
, boost::move(v7_)
|
||||
);
|
||||
}
|
||||
};
|
||||
template <class Fp, class T0, class T1, class T2, class T3, class T4, class T5, class T6>
|
||||
class invoker<Fp, T0, T1, T2, T3, T4, T5, T6>
|
||||
{
|
||||
Fp fp_;
|
||||
T0 v0_;
|
||||
T1 v1_;
|
||||
T2 v2_;
|
||||
T3 v3_;
|
||||
T4 v4_;
|
||||
T5 v5_;
|
||||
T6 v6_;
|
||||
public:
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
|
||||
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5, T6)>::type result_type;
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
|
||||
, BOOST_THREAD_RV_REF(T0) a0
|
||||
, BOOST_THREAD_RV_REF(T1) a1
|
||||
, BOOST_THREAD_RV_REF(T2) a2
|
||||
, BOOST_THREAD_RV_REF(T3) a3
|
||||
, BOOST_THREAD_RV_REF(T4) a4
|
||||
, BOOST_THREAD_RV_REF(T5) a5
|
||||
, BOOST_THREAD_RV_REF(T6) a6
|
||||
)
|
||||
: fp_(boost::move(f))
|
||||
, v0_(boost::move(a0))
|
||||
, v1_(boost::move(a1))
|
||||
, v2_(boost::move(a2))
|
||||
, v3_(boost::move(a3))
|
||||
, v4_(boost::move(a4))
|
||||
, v5_(boost::move(a5))
|
||||
, v6_(boost::move(a6))
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker(BOOST_THREAD_RV_REF(invoker) f)
|
||||
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
|
||||
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
|
||||
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
|
||||
, v2_(boost::move(BOOST_THREAD_RV(f).v2_))
|
||||
, v3_(boost::move(BOOST_THREAD_RV(f).v3_))
|
||||
, v4_(boost::move(BOOST_THREAD_RV(f).v4_))
|
||||
, v5_(boost::move(BOOST_THREAD_RV(f).v5_))
|
||||
, v6_(boost::move(BOOST_THREAD_RV(f).v6_))
|
||||
{}
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
return invoke(boost::move(fp_)
|
||||
, boost::move(v0_)
|
||||
, boost::move(v1_)
|
||||
, boost::move(v2_)
|
||||
, boost::move(v3_)
|
||||
, boost::move(v4_)
|
||||
, boost::move(v5_)
|
||||
, boost::move(v6_)
|
||||
);
|
||||
}
|
||||
};
|
||||
template <class Fp, class T0, class T1, class T2, class T3, class T4, class T5>
|
||||
class invoker<Fp, T0, T1, T2, T3, T4, T5>
|
||||
{
|
||||
Fp fp_;
|
||||
T0 v0_;
|
||||
T1 v1_;
|
||||
T2 v2_;
|
||||
T3 v3_;
|
||||
T4 v4_;
|
||||
T5 v5_;
|
||||
public:
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
|
||||
typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5)>::type result_type;
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
|
||||
, BOOST_THREAD_RV_REF(T0) a0
|
||||
, BOOST_THREAD_RV_REF(T1) a1
|
||||
, BOOST_THREAD_RV_REF(T2) a2
|
||||
, BOOST_THREAD_RV_REF(T3) a3
|
||||
, BOOST_THREAD_RV_REF(T4) a4
|
||||
, BOOST_THREAD_RV_REF(T5) a5
|
||||
)
|
||||
: fp_(boost::move(f))
|
||||
, v0_(boost::move(a0))
|
||||
, v1_(boost::move(a1))
|
||||
, v2_(boost::move(a2))
|
||||
, v3_(boost::move(a3))
|
||||
, v4_(boost::move(a4))
|
||||
, v5_(boost::move(a5))
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker(BOOST_THREAD_RV_REF(invoker) f)
|
||||
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
|
||||
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
|
||||
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
|
||||
, v2_(boost::move(BOOST_THREAD_RV(f).v2_))
|
||||
, v3_(boost::move(BOOST_THREAD_RV(f).v3_))
|
||||
, v4_(boost::move(BOOST_THREAD_RV(f).v4_))
|
||||
, v5_(boost::move(BOOST_THREAD_RV(f).v5_))
|
||||
{}
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
return invoke(boost::move(fp_)
|
||||
, boost::move(v0_)
|
||||
, boost::move(v1_)
|
||||
, boost::move(v2_)
|
||||
, boost::move(v3_)
|
||||
, boost::move(v4_)
|
||||
, boost::move(v5_)
|
||||
);
|
||||
}
|
||||
};
|
||||
template <class Fp, class T0, class T1, class T2, class T3, class T4>
|
||||
class invoker<Fp, T0, T1, T2, T3, T4>
|
||||
{
|
||||
Fp fp_;
|
||||
T0 v0_;
|
||||
T1 v1_;
|
||||
T2 v2_;
|
||||
T3 v3_;
|
||||
T4 v4_;
|
||||
public:
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
|
||||
typedef typename result_of<Fp(T0, T1, T2, T3, T4)>::type result_type;
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
|
||||
, BOOST_THREAD_RV_REF(T0) a0
|
||||
, BOOST_THREAD_RV_REF(T1) a1
|
||||
, BOOST_THREAD_RV_REF(T2) a2
|
||||
, BOOST_THREAD_RV_REF(T3) a3
|
||||
, BOOST_THREAD_RV_REF(T4) a4
|
||||
)
|
||||
: fp_(boost::move(f))
|
||||
, v0_(boost::move(a0))
|
||||
, v1_(boost::move(a1))
|
||||
, v2_(boost::move(a2))
|
||||
, v3_(boost::move(a3))
|
||||
, v4_(boost::move(a4))
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker(BOOST_THREAD_RV_REF(invoker) f)
|
||||
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
|
||||
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
|
||||
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
|
||||
, v2_(boost::move(BOOST_THREAD_RV(f).v2_))
|
||||
, v3_(boost::move(BOOST_THREAD_RV(f).v3_))
|
||||
, v4_(boost::move(BOOST_THREAD_RV(f).v4_))
|
||||
{}
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
return invoke(boost::move(fp_)
|
||||
, boost::move(v0_)
|
||||
, boost::move(v1_)
|
||||
, boost::move(v2_)
|
||||
, boost::move(v3_)
|
||||
, boost::move(v4_)
|
||||
);
|
||||
}
|
||||
};
|
||||
template <class Fp, class T0, class T1, class T2, class T3>
|
||||
class invoker<Fp, T0, T1, T2, T3>
|
||||
{
|
||||
Fp fp_;
|
||||
T0 v0_;
|
||||
T1 v1_;
|
||||
T2 v2_;
|
||||
T3 v3_;
|
||||
public:
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
|
||||
typedef typename result_of<Fp(T0, T1, T2, T3)>::type result_type;
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
|
||||
, BOOST_THREAD_RV_REF(T0) a0
|
||||
, BOOST_THREAD_RV_REF(T1) a1
|
||||
, BOOST_THREAD_RV_REF(T2) a2
|
||||
, BOOST_THREAD_RV_REF(T3) a3
|
||||
)
|
||||
: fp_(boost::move(f))
|
||||
, v0_(boost::move(a0))
|
||||
, v1_(boost::move(a1))
|
||||
, v2_(boost::move(a2))
|
||||
, v3_(boost::move(a3))
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker(BOOST_THREAD_RV_REF(invoker) f)
|
||||
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
|
||||
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
|
||||
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
|
||||
, v2_(boost::move(BOOST_THREAD_RV(f).v2_))
|
||||
, v3_(boost::move(BOOST_THREAD_RV(f).v3_))
|
||||
{}
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
return invoke(boost::move(fp_)
|
||||
, boost::move(v0_)
|
||||
, boost::move(v1_)
|
||||
, boost::move(v2_)
|
||||
, boost::move(v3_)
|
||||
);
|
||||
}
|
||||
};
|
||||
template <class Fp, class T0, class T1, class T2>
|
||||
class invoker<Fp, T0, T1, T2>
|
||||
{
|
||||
Fp fp_;
|
||||
T0 v0_;
|
||||
T1 v1_;
|
||||
T2 v2_;
|
||||
public:
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
|
||||
typedef typename result_of<Fp(T0, T1, T2)>::type result_type;
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
|
||||
, BOOST_THREAD_RV_REF(T0) a0
|
||||
, BOOST_THREAD_RV_REF(T1) a1
|
||||
, BOOST_THREAD_RV_REF(T2) a2
|
||||
)
|
||||
: fp_(boost::move(f))
|
||||
, v0_(boost::move(a0))
|
||||
, v1_(boost::move(a1))
|
||||
, v2_(boost::move(a2))
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker(BOOST_THREAD_RV_REF(invoker) f)
|
||||
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
|
||||
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
|
||||
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
|
||||
, v2_(boost::move(BOOST_THREAD_RV(f).v2_))
|
||||
{}
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
return invoke(boost::move(fp_)
|
||||
, boost::move(v0_)
|
||||
, boost::move(v1_)
|
||||
, boost::move(v2_)
|
||||
);
|
||||
}
|
||||
};
|
||||
template <class Fp, class T0, class T1>
|
||||
class invoker<Fp, T0, T1>
|
||||
{
|
||||
Fp fp_;
|
||||
T0 v0_;
|
||||
T1 v1_;
|
||||
public:
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
|
||||
typedef typename result_of<Fp(T0, T1)>::type result_type;
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
|
||||
, BOOST_THREAD_RV_REF(T0) a0
|
||||
, BOOST_THREAD_RV_REF(T1) a1
|
||||
)
|
||||
: fp_(boost::move(f))
|
||||
, v0_(boost::move(a0))
|
||||
, v1_(boost::move(a1))
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker(BOOST_THREAD_RV_REF(invoker) f)
|
||||
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
|
||||
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
|
||||
, v1_(boost::move(BOOST_THREAD_RV(f).v1_))
|
||||
{}
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
return invoke(boost::move(fp_)
|
||||
, boost::move(v0_)
|
||||
, boost::move(v1_)
|
||||
);
|
||||
}
|
||||
};
|
||||
template <class Fp, class T0>
|
||||
class invoker<Fp, T0>
|
||||
{
|
||||
Fp fp_;
|
||||
T0 v0_;
|
||||
public:
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
|
||||
typedef typename result_of<Fp(T0)>::type result_type;
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
|
||||
, BOOST_THREAD_RV_REF(T0) a0
|
||||
)
|
||||
: fp_(boost::move(f))
|
||||
, v0_(boost::move(a0))
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker(BOOST_THREAD_RV_REF(invoker) f)
|
||||
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
|
||||
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
|
||||
{}
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
return invoke(boost::move(fp_)
|
||||
, boost::move(v0_)
|
||||
);
|
||||
}
|
||||
};
|
||||
template <class Fp>
|
||||
class invoker<Fp>
|
||||
{
|
||||
Fp fp_;
|
||||
public:
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
|
||||
typedef typename result_of<Fp()>::type result_type;
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
explicit invoker(BOOST_THREAD_FWD_REF(Fp) f)
|
||||
: fp_(boost::move(f))
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker(BOOST_THREAD_RV_REF(invoker) f)
|
||||
: fp_(boost::move(f.fp_))
|
||||
{}
|
||||
result_type operator()()
|
||||
{
|
||||
return fp_();
|
||||
}
|
||||
};
|
||||
template <class R>
|
||||
class invoker<R(*)()>
|
||||
{
|
||||
typedef R(*Fp)();
|
||||
Fp fp_;
|
||||
public:
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
|
||||
typedef typename result_of<Fp()>::type result_type;
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
explicit invoker(Fp f)
|
||||
: fp_(f)
|
||||
{}
|
||||
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
invoker(BOOST_THREAD_RV_REF(invoker) f)
|
||||
: fp_(f.fp_)
|
||||
{}
|
||||
result_type operator()()
|
||||
{
|
||||
return fp_();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#include <boost/thread/detail/variadic_footer.hpp>
|
||||
|
||||
#endif // header
|
||||
@@ -1,8 +1,9 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
// Copyright (C) 2011-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)
|
||||
//
|
||||
// See http://www.boost.org/libs/thread for documentation.
|
||||
//
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
// Copyright (C) 2011-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)
|
||||
//
|
||||
// See http://www.boost.org/libs/thread for documentation.
|
||||
//
|
||||
@@ -12,14 +13,11 @@
|
||||
#define BOOST_THREAD_DETAIL_MEMORY_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/container/allocator_traits.hpp>
|
||||
#include <boost/container/scoped_allocator.hpp>
|
||||
#include <boost/type_traits/remove_cv.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/type_traits/is_scalar.hpp>
|
||||
#include <boost/type_traits/is_pointer.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
#include <boost/thread/csbl/memory/pointer_traits.hpp>
|
||||
#include <boost/thread/csbl/memory/allocator_arg.hpp>
|
||||
#include <boost/thread/csbl/memory/allocator_traits.hpp>
|
||||
#include <boost/thread/csbl/memory/scoped_allocator.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
@@ -28,7 +26,7 @@ namespace boost
|
||||
template <class _Alloc>
|
||||
class allocator_destructor
|
||||
{
|
||||
typedef container::allocator_traits<_Alloc> alloc_traits;
|
||||
typedef csbl::allocator_traits<_Alloc> alloc_traits;
|
||||
public:
|
||||
typedef typename alloc_traits::pointer pointer;
|
||||
typedef typename alloc_traits::size_type size_type;
|
||||
@@ -46,111 +44,5 @@ namespace boost
|
||||
}
|
||||
};
|
||||
} //namespace thread_detail
|
||||
|
||||
typedef container::allocator_arg_t allocator_arg_t;
|
||||
BOOST_CONSTEXPR_OR_CONST allocator_arg_t allocator_arg = {};
|
||||
|
||||
template <class T, class Alloc>
|
||||
struct uses_allocator: public container::uses_allocator<T, Alloc>
|
||||
{
|
||||
};
|
||||
|
||||
template <class Ptr>
|
||||
struct pointer_traits
|
||||
{
|
||||
typedef Ptr pointer;
|
||||
// typedef <details> element_type;
|
||||
// typedef <details> difference_type;
|
||||
|
||||
// template <class U> using rebind = <details>;
|
||||
//
|
||||
// static pointer pointer_to(<details>);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct pointer_traits<T*>
|
||||
{
|
||||
typedef T* pointer;
|
||||
typedef T element_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
|
||||
// template <class U> using rebind = U*;
|
||||
//
|
||||
// static pointer pointer_to(<details>) noexcept;
|
||||
};
|
||||
|
||||
|
||||
namespace thread_detail {
|
||||
template <class _Ptr1, class _Ptr2,
|
||||
bool = is_same<typename remove_cv<typename pointer_traits<_Ptr1>::element_type>::type,
|
||||
typename remove_cv<typename pointer_traits<_Ptr2>::element_type>::type
|
||||
>::value
|
||||
>
|
||||
struct same_or_less_cv_qualified_imp
|
||||
: is_convertible<_Ptr1, _Ptr2> {};
|
||||
|
||||
template <class _Ptr1, class _Ptr2>
|
||||
struct same_or_less_cv_qualified_imp<_Ptr1, _Ptr2, false>
|
||||
: false_type {};
|
||||
|
||||
template <class _Ptr1, class _Ptr2, bool = is_scalar<_Ptr1>::value &&
|
||||
!is_pointer<_Ptr1>::value>
|
||||
struct same_or_less_cv_qualified
|
||||
: same_or_less_cv_qualified_imp<_Ptr1, _Ptr2> {};
|
||||
|
||||
template <class _Ptr1, class _Ptr2>
|
||||
struct same_or_less_cv_qualified<_Ptr1, _Ptr2, true>
|
||||
: false_type {};
|
||||
|
||||
}
|
||||
template <class T>
|
||||
struct BOOST_SYMBOL_VISIBLE default_delete
|
||||
{
|
||||
#ifndef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
BOOST_CONSTEXPR default_delete() = default;
|
||||
#else
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
BOOST_CONSTEXPR default_delete() BOOST_NOEXCEPT {}
|
||||
#endif
|
||||
template <class U>
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
default_delete(const default_delete<U>&,
|
||||
typename enable_if<is_convertible<U*, T*> >::type* = 0) BOOST_NOEXCEPT {}
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
void operator() (T* ptr) const BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_STATIC_ASSERT_MSG(sizeof(T) > 0, "default_delete can not delete incomplete type");
|
||||
delete ptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct BOOST_SYMBOL_VISIBLE default_delete<T[]>
|
||||
{
|
||||
public:
|
||||
#ifndef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
BOOST_CONSTEXPR default_delete() = default;
|
||||
#else
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
BOOST_CONSTEXPR default_delete() BOOST_NOEXCEPT {}
|
||||
#endif
|
||||
template <class U>
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
default_delete(const default_delete<U[]>&,
|
||||
typename enable_if<thread_detail::same_or_less_cv_qualified<U*, T*> >::type* = 0) BOOST_NOEXCEPT {}
|
||||
template <class U>
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
void operator() (U* ptr,
|
||||
typename enable_if<thread_detail::same_or_less_cv_qualified<U*, T*> >::type* = 0) const BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_STATIC_ASSERT_MSG(sizeof(T) > 0, "default_delete can not delete incomplete type");
|
||||
delete [] ptr;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
}
|
||||
#endif // BOOST_THREAD_DETAIL_MEMORY_HPP
|
||||
|
||||
@@ -9,18 +9,27 @@
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#ifndef BOOST_NO_SFINAE
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/core/enable_if.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/type_traits/remove_cv.hpp>
|
||||
#include <boost/type_traits/decay.hpp>
|
||||
#include <boost/type_traits/conditional.hpp>
|
||||
#include <boost/type_traits/remove_extent.hpp>
|
||||
#include <boost/type_traits/is_array.hpp>
|
||||
#include <boost/type_traits/is_function.hpp>
|
||||
#include <boost/type_traits/remove_cv.hpp>
|
||||
#include <boost/type_traits/add_pointer.hpp>
|
||||
#include <boost/type_traits/decay.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/thread/detail/delete.hpp>
|
||||
#include <boost/move/utility.hpp>
|
||||
#include <boost/move/traits.hpp>
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
#include <type_traits>
|
||||
#endif
|
||||
namespace boost
|
||||
{
|
||||
|
||||
@@ -71,6 +80,7 @@ namespace boost
|
||||
|
||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
|
||||
#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) BOOST_COPY_ASSIGN_REF(TYPE)
|
||||
#define BOOST_THREAD_RV_REF(TYPE) BOOST_RV_REF(TYPE)
|
||||
#define BOOST_THREAD_RV_REF_2_TEMPL_ARGS(TYPE) BOOST_RV_REF_2_TEMPL_ARGS(TYPE)
|
||||
#define BOOST_THREAD_RV_REF_BEG BOOST_RV_REF_BEG
|
||||
@@ -91,6 +101,7 @@ namespace boost
|
||||
|
||||
#elif ! defined BOOST_NO_CXX11_RVALUE_REFERENCES && defined BOOST_MSVC
|
||||
|
||||
#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) BOOST_COPY_ASSIGN_REF(TYPE)
|
||||
#define BOOST_THREAD_RV_REF(TYPE) BOOST_RV_REF(TYPE)
|
||||
#define BOOST_THREAD_RV_REF_2_TEMPL_ARGS(TYPE) BOOST_RV_REF_2_TEMPL_ARGS(TYPE)
|
||||
#define BOOST_THREAD_RV_REF_BEG BOOST_RV_REF_BEG
|
||||
@@ -112,6 +123,7 @@ namespace boost
|
||||
#else
|
||||
|
||||
#if defined BOOST_THREAD_USES_MOVE
|
||||
#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) BOOST_COPY_ASSIGN_REF(TYPE)
|
||||
#define BOOST_THREAD_RV_REF(TYPE) BOOST_RV_REF(TYPE)
|
||||
#define BOOST_THREAD_RV_REF_2_TEMPL_ARGS(TYPE) BOOST_RV_REF_2_TEMPL_ARGS(TYPE)
|
||||
#define BOOST_THREAD_RV_REF_BEG BOOST_RV_REF_BEG
|
||||
@@ -131,6 +143,7 @@ namespace boost
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) const TYPE&
|
||||
#define BOOST_THREAD_RV_REF(TYPE) boost::detail::thread_move_t< TYPE >
|
||||
#define BOOST_THREAD_RV_REF_BEG boost::detail::thread_move_t<
|
||||
#define BOOST_THREAD_RV_REF_END >
|
||||
@@ -189,6 +202,8 @@ namespace detail
|
||||
|
||||
#define BOOST_THREAD_MOVABLE(TYPE)
|
||||
|
||||
#define BOOST_THREAD_COPYABLE(TYPE)
|
||||
|
||||
#else
|
||||
|
||||
#if defined BOOST_THREAD_USES_MOVE
|
||||
@@ -211,6 +226,11 @@ namespace detail
|
||||
return *static_cast<const ::boost::rv<TYPE>* >(this); \
|
||||
}\
|
||||
|
||||
#define BOOST_THREAD_COPYABLE(TYPE) \
|
||||
TYPE& operator=(TYPE &t)\
|
||||
{ this->operator=(static_cast<const ::boost::rv<TYPE> &>(const_cast<const TYPE &>(t))); return *this;}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_THREAD_MOVABLE(TYPE) \
|
||||
@@ -224,21 +244,94 @@ namespace detail
|
||||
return x; \
|
||||
} \
|
||||
|
||||
#define BOOST_THREAD_COPYABLE(TYPE)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define BOOST_THREAD_MOVABLE_ONLY(TYPE) \
|
||||
BOOST_THREAD_NO_COPYABLE(TYPE) \
|
||||
BOOST_THREAD_MOVABLE(TYPE) \
|
||||
typedef int boost_move_no_copy_constructor_or_assign; \
|
||||
|
||||
|
||||
#define BOOST_THREAD_COPYABLE_AND_MOVABLE(TYPE) \
|
||||
BOOST_THREAD_MOVABLE(TYPE) \
|
||||
BOOST_THREAD_COPYABLE(TYPE) \
|
||||
BOOST_THREAD_MOVABLE(TYPE) \
|
||||
|
||||
|
||||
|
||||
namespace boost
|
||||
{ namespace thread_detail
|
||||
{
|
||||
namespace thread_detail
|
||||
{
|
||||
|
||||
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
#elif defined BOOST_THREAD_USES_MOVE
|
||||
template <class T>
|
||||
struct is_rv
|
||||
: ::boost::move_detail::is_rv<T>
|
||||
{};
|
||||
|
||||
#else
|
||||
template <class T>
|
||||
struct is_rv
|
||||
: ::boost::integral_constant<bool, false>
|
||||
{};
|
||||
|
||||
template <class T>
|
||||
struct is_rv< ::boost::detail::thread_move_t<T> >
|
||||
: ::boost::integral_constant<bool, true>
|
||||
{};
|
||||
|
||||
template <class T>
|
||||
struct is_rv< const ::boost::detail::thread_move_t<T> >
|
||||
: ::boost::integral_constant<bool, true>
|
||||
{};
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
template <class Tp>
|
||||
struct remove_reference : boost::remove_reference<Tp> {};
|
||||
template <class Tp>
|
||||
struct decay : boost::decay<Tp> {};
|
||||
#else
|
||||
template <class Tp>
|
||||
struct remove_reference
|
||||
{
|
||||
typedef Tp type;
|
||||
};
|
||||
template <class Tp>
|
||||
struct remove_reference<Tp&>
|
||||
{
|
||||
typedef Tp type;
|
||||
};
|
||||
template <class Tp>
|
||||
struct remove_reference< rv<Tp> > {
|
||||
typedef Tp type;
|
||||
};
|
||||
|
||||
template <class Tp>
|
||||
struct decay
|
||||
{
|
||||
private:
|
||||
typedef typename boost::move_detail::remove_rvalue_reference<Tp>::type Up0;
|
||||
typedef typename boost::remove_reference<Up0>::type Up;
|
||||
public:
|
||||
typedef typename conditional
|
||||
<
|
||||
is_array<Up>::value,
|
||||
typename remove_extent<Up>::type*,
|
||||
typename conditional
|
||||
<
|
||||
is_function<Up>::value,
|
||||
typename add_pointer<Up>::type,
|
||||
typename remove_cv<Up>::type
|
||||
>::type
|
||||
>::type type;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
template <class T>
|
||||
typename decay<T>::type
|
||||
|
||||
234
include/boost/thread/detail/nullary_function.hpp
Normal file
234
include/boost/thread/detail/nullary_function.hpp
Normal file
@@ -0,0 +1,234 @@
|
||||
// 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/09 Vicente J. Botet Escriba
|
||||
// Adapt to boost from CCIA C++11 implementation
|
||||
// Make use of Boost.Move
|
||||
|
||||
#ifndef BOOST_THREAD_DETAIL_NULLARY_FUNCTION_HPP
|
||||
#define BOOST_THREAD_DETAIL_NULLARY_FUNCTION_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/thread/detail/memory.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/csbl/memory/shared_ptr.hpp>
|
||||
#include <boost/type_traits/decay.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename F>
|
||||
class nullary_function;
|
||||
template <>
|
||||
class nullary_function<void()>
|
||||
{
|
||||
struct impl_base
|
||||
{
|
||||
virtual void call()=0;
|
||||
virtual ~impl_base()
|
||||
{
|
||||
}
|
||||
};
|
||||
csbl::shared_ptr<impl_base> impl;
|
||||
template <typename F>
|
||||
struct impl_type: impl_base
|
||||
{
|
||||
F f;
|
||||
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
impl_type(F &f_)
|
||||
: f(f_)
|
||||
{}
|
||||
#endif
|
||||
impl_type(BOOST_THREAD_RV_REF(F) f_)
|
||||
: f(boost::move(f_))
|
||||
{}
|
||||
|
||||
void call()
|
||||
{
|
||||
f();
|
||||
}
|
||||
};
|
||||
struct impl_type_ptr: impl_base
|
||||
{
|
||||
void (*f)();
|
||||
impl_type_ptr(void (*f_)())
|
||||
: f(f_)
|
||||
{}
|
||||
void call()
|
||||
{
|
||||
f();
|
||||
}
|
||||
};
|
||||
public:
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE(nullary_function)
|
||||
|
||||
explicit nullary_function(void (*f)()):
|
||||
impl(new impl_type_ptr(f))
|
||||
{}
|
||||
|
||||
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
template<typename F>
|
||||
explicit nullary_function(F& f):
|
||||
impl(new impl_type<F>(f))
|
||||
{}
|
||||
#endif
|
||||
template<typename F>
|
||||
nullary_function(BOOST_THREAD_RV_REF(F) f):
|
||||
impl(new impl_type<typename decay<F>::type>(thread_detail::decay_copy(boost::forward<F>(f))))
|
||||
{}
|
||||
|
||||
nullary_function()
|
||||
: impl()
|
||||
{
|
||||
}
|
||||
nullary_function(nullary_function const& other) BOOST_NOEXCEPT :
|
||||
impl(other.impl)
|
||||
{
|
||||
}
|
||||
nullary_function(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT :
|
||||
#if defined BOOST_NO_CXX11_SMART_PTR
|
||||
impl(BOOST_THREAD_RV(other).impl)
|
||||
{
|
||||
BOOST_THREAD_RV(other).impl.reset();
|
||||
}
|
||||
#else
|
||||
impl(boost::move(other.impl))
|
||||
{
|
||||
}
|
||||
#endif
|
||||
~nullary_function()
|
||||
{
|
||||
}
|
||||
|
||||
nullary_function& operator=(BOOST_THREAD_COPY_ASSIGN_REF(nullary_function) other) BOOST_NOEXCEPT
|
||||
{
|
||||
impl=other.impl;
|
||||
return *this;
|
||||
}
|
||||
nullary_function& operator=(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT
|
||||
{
|
||||
#if defined BOOST_NO_CXX11_SMART_PTR
|
||||
impl=BOOST_THREAD_RV(other).impl;
|
||||
BOOST_THREAD_RV(other).impl.reset();
|
||||
#else
|
||||
impl = boost::move(other.impl);
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void operator()()
|
||||
{ if (impl) impl->call();}
|
||||
|
||||
};
|
||||
|
||||
template <typename R>
|
||||
class nullary_function<R()>
|
||||
{
|
||||
struct impl_base
|
||||
{
|
||||
virtual R call()=0;
|
||||
virtual ~impl_base()
|
||||
{
|
||||
}
|
||||
};
|
||||
csbl::shared_ptr<impl_base> impl;
|
||||
template <typename F>
|
||||
struct impl_type: impl_base
|
||||
{
|
||||
F f;
|
||||
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
impl_type(F &f_)
|
||||
: f(f_)
|
||||
{}
|
||||
#endif
|
||||
impl_type(BOOST_THREAD_RV_REF(F) f_)
|
||||
: f(boost::move(f_))
|
||||
{}
|
||||
|
||||
R call()
|
||||
{
|
||||
return f();
|
||||
}
|
||||
};
|
||||
struct impl_type_ptr: impl_base
|
||||
{
|
||||
R (*f)();
|
||||
impl_type_ptr(R (*f_)())
|
||||
: f(f_)
|
||||
{}
|
||||
|
||||
R call()
|
||||
{
|
||||
return f();
|
||||
}
|
||||
};
|
||||
public:
|
||||
BOOST_THREAD_COPYABLE_AND_MOVABLE(nullary_function)
|
||||
|
||||
nullary_function(R (*f)()):
|
||||
impl(new impl_type_ptr(f))
|
||||
{}
|
||||
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
template<typename F>
|
||||
nullary_function(F& f):
|
||||
impl(new impl_type<F>(f))
|
||||
{}
|
||||
#endif
|
||||
template<typename F>
|
||||
nullary_function(BOOST_THREAD_RV_REF(F) f):
|
||||
impl(new impl_type<typename decay<F>::type>(thread_detail::decay_copy(boost::forward<F>(f))))
|
||||
{}
|
||||
|
||||
nullary_function(nullary_function const& other) BOOST_NOEXCEPT :
|
||||
impl(other.impl)
|
||||
{
|
||||
}
|
||||
nullary_function(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT :
|
||||
#if defined BOOST_NO_CXX11_SMART_PTR
|
||||
impl(BOOST_THREAD_RV(other).impl)
|
||||
{
|
||||
BOOST_THREAD_RV(other).impl.reset();
|
||||
}
|
||||
#else
|
||||
impl(boost::move(other.impl))
|
||||
{
|
||||
}
|
||||
#endif
|
||||
nullary_function()
|
||||
: impl()
|
||||
{
|
||||
}
|
||||
~nullary_function()
|
||||
{
|
||||
}
|
||||
|
||||
nullary_function& operator=(BOOST_THREAD_COPY_ASSIGN_REF(nullary_function) other) BOOST_NOEXCEPT
|
||||
{
|
||||
impl=other.impl;
|
||||
return *this;
|
||||
}
|
||||
nullary_function& operator=(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT
|
||||
{
|
||||
#if defined BOOST_NO_CXX11_SMART_PTR
|
||||
impl=BOOST_THREAD_RV(other).impl;
|
||||
BOOST_THREAD_RV(other).impl.reset();
|
||||
#else
|
||||
impl = boost::move(other.impl);
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
R operator()()
|
||||
{ if (impl) return impl->call(); else return R();}
|
||||
|
||||
};
|
||||
}
|
||||
//BOOST_THREAD_DCL_MOVABLE_BEG(F) detail::nullary_function<F> BOOST_THREAD_DCL_MOVABLE_END
|
||||
}
|
||||
|
||||
#endif // header
|
||||
@@ -4,9 +4,10 @@
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// (C) Copyright 2007-2010 Anthony Williams
|
||||
// (C) Copyright 20011-2012 Vicente J. Botet Escriba
|
||||
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/predef/platform.h>
|
||||
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#ifndef BOOST_NO_IOSTREAM
|
||||
@@ -24,12 +25,12 @@
|
||||
#include <boost/assert.hpp>
|
||||
#include <list>
|
||||
#include <algorithm>
|
||||
#include <boost/ref.hpp>
|
||||
#include <boost/core/ref.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <stdlib.h>
|
||||
#include <memory>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/core/enable_if.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/io/ios_state.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
@@ -64,11 +65,9 @@ namespace boost
|
||||
{
|
||||
public:
|
||||
BOOST_THREAD_NO_COPYABLE(thread_data)
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
thread_data(BOOST_THREAD_RV_REF(F) f_, BOOST_THREAD_RV_REF(ArgTypes)... args_):
|
||||
fp(boost::forward<F>(f_), boost::forward<ArgTypes>(args_)...)
|
||||
{}
|
||||
#endif
|
||||
template <std::size_t ...Indices>
|
||||
void run2(tuple_indices<Indices...>)
|
||||
{
|
||||
@@ -174,7 +173,7 @@ namespace boost
|
||||
private:
|
||||
bool start_thread_noexcept();
|
||||
bool start_thread_noexcept(const attributes& attr);
|
||||
public:
|
||||
//public:
|
||||
void start_thread()
|
||||
{
|
||||
if (!start_thread_noexcept())
|
||||
@@ -293,7 +292,8 @@ namespace boost
|
||||
template <class F>
|
||||
explicit thread(F f
|
||||
, typename disable_if_c<
|
||||
boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F)>::value
|
||||
boost::thread_detail::is_rv<F>::value // todo ass a thread_detail::is_rv
|
||||
//boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F)>::value
|
||||
//|| is_same<typename decay<F>::type, thread>::value
|
||||
, dummy* >::type=0
|
||||
):
|
||||
@@ -303,7 +303,8 @@ namespace boost
|
||||
}
|
||||
template <class F>
|
||||
thread(attributes const& attrs, F f
|
||||
, typename disable_if<boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F) >, dummy* >::type=0
|
||||
, typename disable_if<boost::thread_detail::is_rv<F>, dummy* >::type=0
|
||||
//, typename disable_if<boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F) >, dummy* >::type=0
|
||||
):
|
||||
thread_info(make_thread_info(f))
|
||||
{
|
||||
@@ -334,7 +335,7 @@ namespace boost
|
||||
start_thread(attrs);
|
||||
}
|
||||
#endif
|
||||
thread(BOOST_THREAD_RV_REF(thread) x)
|
||||
thread(BOOST_THREAD_RV_REF(thread) x) BOOST_NOEXCEPT
|
||||
{
|
||||
thread_info=BOOST_THREAD_RV(x).thread_info;
|
||||
BOOST_THREAD_RV(x).thread_info.reset();
|
||||
@@ -466,11 +467,20 @@ namespace boost
|
||||
inline void join();
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
#if defined(BOOST_THREAD_PLATFORM_WIN32)
|
||||
template <class Rep, class Period>
|
||||
bool try_join_for(const chrono::duration<Rep, Period>& rel_time)
|
||||
{
|
||||
chrono::milliseconds rel_time2= chrono::ceil<chrono::milliseconds>(rel_time);
|
||||
return do_try_join_until(rel_time2.count());
|
||||
}
|
||||
#else
|
||||
template <class Rep, class Period>
|
||||
bool try_join_for(const chrono::duration<Rep, Period>& rel_time)
|
||||
{
|
||||
return try_join_until(chrono::steady_clock::now() + rel_time);
|
||||
}
|
||||
#endif
|
||||
template <class Clock, class Duration>
|
||||
bool try_join_until(const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
@@ -546,6 +556,7 @@ namespace boost
|
||||
void detach();
|
||||
|
||||
static unsigned hardware_concurrency() BOOST_NOEXCEPT;
|
||||
static unsigned physical_concurrency() BOOST_NOEXCEPT;
|
||||
|
||||
#define BOOST_THREAD_DEFINES_THREAD_NATIVE_HANDLE
|
||||
typedef detail::thread_data_base::native_handle_type native_handle_type;
|
||||
@@ -749,10 +760,10 @@ namespace boost
|
||||
#endif
|
||||
void thread::join() {
|
||||
if (this_thread::get_id() == get_id())
|
||||
boost::throw_exception(thread_resource_error(system::errc::resource_deadlock_would_occur, "boost thread: trying joining itself"));
|
||||
boost::throw_exception(thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost thread: trying joining itself"));
|
||||
|
||||
BOOST_THREAD_VERIFY_PRECONDITION( join_noexcept(),
|
||||
thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable")
|
||||
thread_resource_error(static_cast<int>(system::errc::invalid_argument), "boost thread: thread not joinable")
|
||||
);
|
||||
}
|
||||
|
||||
@@ -763,7 +774,7 @@ namespace boost
|
||||
#endif
|
||||
{
|
||||
if (this_thread::get_id() == get_id())
|
||||
boost::throw_exception(thread_resource_error(system::errc::resource_deadlock_would_occur, "boost thread: trying joining itself"));
|
||||
boost::throw_exception(thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost thread: trying joining itself"));
|
||||
bool res;
|
||||
if (do_try_join_until_noexcept(timeout, res))
|
||||
{
|
||||
@@ -772,7 +783,7 @@ namespace boost
|
||||
else
|
||||
{
|
||||
BOOST_THREAD_THROW_ELSE_RETURN(
|
||||
(thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable")),
|
||||
(thread_resource_error(static_cast<int>(system::errc::invalid_argument), "boost thread: thread not joinable")),
|
||||
false
|
||||
);
|
||||
}
|
||||
@@ -826,6 +837,19 @@ namespace boost
|
||||
};
|
||||
|
||||
void BOOST_THREAD_DECL add_thread_exit_function(thread_exit_function_base*);
|
||||
struct shared_state_base;
|
||||
#if defined(BOOST_THREAD_PLATFORM_WIN32)
|
||||
inline void make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
|
||||
{
|
||||
detail::thread_data_base* const current_thread_data(detail::get_current_thread_data());
|
||||
if(current_thread_data)
|
||||
{
|
||||
current_thread_data->make_ready_at_thread_exit(as);
|
||||
}
|
||||
}
|
||||
#else
|
||||
void BOOST_THREAD_DECL make_ready_at_thread_exit(shared_ptr<shared_state_base> as);
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace this_thread
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace boost
|
||||
if(thrd)
|
||||
{
|
||||
BOOST_THREAD_ASSERT_PRECONDITION( ! is_thread_in(thrd) ,
|
||||
thread_resource_error(system::errc::resource_deadlock_would_occur, "boost::thread_group: trying to add a duplicated thread")
|
||||
thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost::thread_group: trying to add a duplicated thread")
|
||||
);
|
||||
|
||||
boost::lock_guard<shared_mutex> guard(m);
|
||||
@@ -106,7 +106,7 @@ namespace boost
|
||||
void join_all()
|
||||
{
|
||||
BOOST_THREAD_ASSERT_PRECONDITION( ! is_this_thread_in() ,
|
||||
thread_resource_error(system::errc::resource_deadlock_would_occur, "boost::thread_group: trying joining itself")
|
||||
thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost::thread_group: trying joining itself")
|
||||
);
|
||||
boost::shared_lock<shared_mutex> guard(m);
|
||||
|
||||
|
||||
10
include/boost/thread/detail/variadic_footer.hpp
Normal file
10
include/boost/thread/detail/variadic_footer.hpp
Normal file
@@ -0,0 +1,10 @@
|
||||
// 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)
|
||||
|
||||
|
||||
#if defined BOOST_NO_CXX11_VARIADIC_TEMPLATES
|
||||
|
||||
|
||||
#endif
|
||||
19
include/boost/thread/detail/variadic_header.hpp
Normal file
19
include/boost/thread/detail/variadic_header.hpp
Normal file
@@ -0,0 +1,19 @@
|
||||
// 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)
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
//#if defined BOOST_NO_CXX11_VARIADIC_TEMPLATES
|
||||
|
||||
#include <boost/preprocessor/facilities/intercept.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
|
||||
|
||||
#ifndef BOOST_THREAD_MAX_ARGS
|
||||
#define BOOST_THREAD_MAX_ARGS 9
|
||||
#endif
|
||||
|
||||
//#endif
|
||||
|
||||
23
include/boost/thread/detail/work.hpp
Normal file
23
include/boost/thread/detail/work.hpp
Normal file
@@ -0,0 +1,23 @@
|
||||
// (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
|
||||
44
include/boost/thread/exceptional_ptr.hpp
Normal file
44
include/boost/thread/exceptional_ptr.hpp
Normal file
@@ -0,0 +1,44 @@
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// (C) Copyright 2014 Vicente J. Botet Escriba
|
||||
|
||||
#ifndef BOOST_THREAD_EXCEPTIONAL_PTR_HPP
|
||||
#define BOOST_THREAD_EXCEPTIONAL_PTR_HPP
|
||||
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/exception_ptr.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
struct exceptional_ptr {
|
||||
exception_ptr ptr_;
|
||||
|
||||
exceptional_ptr() : ptr_() {}
|
||||
explicit exceptional_ptr(exception_ptr ex) : ptr_(ex) {}
|
||||
template <class E>
|
||||
explicit exceptional_ptr(BOOST_FWD_REF(E) ex) : ptr_(boost::copy_exception(boost::forward<E>(ex))) {}
|
||||
};
|
||||
|
||||
template <class E>
|
||||
inline exceptional_ptr make_exceptional(BOOST_FWD_REF(E) ex) {
|
||||
return exceptional_ptr(boost::forward<E>(ex));
|
||||
}
|
||||
|
||||
inline exceptional_ptr make_exceptional(exception_ptr ex)
|
||||
{
|
||||
return exceptional_ptr(ex);
|
||||
}
|
||||
|
||||
inline exceptional_ptr make_exceptional()
|
||||
{
|
||||
return exceptional_ptr();
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
@@ -124,7 +124,7 @@ namespace boost
|
||||
typedef thread_exception base_type;
|
||||
public:
|
||||
thread_resource_error()
|
||||
: base_type(system::errc::resource_unavailable_try_again, "boost::thread_resource_error")
|
||||
: base_type(static_cast<int>(system::errc::resource_unavailable_try_again), "boost::thread_resource_error")
|
||||
{}
|
||||
|
||||
thread_resource_error( int ev )
|
||||
@@ -152,7 +152,7 @@ namespace boost
|
||||
typedef thread_exception base_type;
|
||||
public:
|
||||
unsupported_thread_option()
|
||||
: base_type(system::errc::invalid_argument, "boost::unsupported_thread_option")
|
||||
: base_type(static_cast<int>(system::errc::invalid_argument), "boost::unsupported_thread_option")
|
||||
{}
|
||||
|
||||
unsupported_thread_option( int ev )
|
||||
@@ -176,7 +176,7 @@ namespace boost
|
||||
typedef thread_exception base_type;
|
||||
public:
|
||||
invalid_thread_argument()
|
||||
: base_type(system::errc::invalid_argument, "boost::invalid_thread_argument")
|
||||
: base_type(static_cast<int>(system::errc::invalid_argument), "boost::invalid_thread_argument")
|
||||
{}
|
||||
|
||||
invalid_thread_argument( int ev )
|
||||
@@ -200,7 +200,7 @@ namespace boost
|
||||
typedef thread_exception base_type;
|
||||
public:
|
||||
thread_permission_error()
|
||||
: base_type(system::errc::permission_denied, "boost::thread_permission_error")
|
||||
: base_type(static_cast<int>(system::errc::permission_denied), "boost::thread_permission_error")
|
||||
{}
|
||||
|
||||
thread_permission_error( int ev )
|
||||
|
||||
15
include/boost/thread/executor.hpp
Normal file
15
include/boost/thread/executor.hpp
Normal file
@@ -0,0 +1,15 @@
|
||||
// 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/09 Vicente J. Botet Escriba
|
||||
// Adapt to boost from CCIA C++11 implementation
|
||||
|
||||
#ifndef BOOST_THREAD_EXECUTOR_HPP
|
||||
#define BOOST_THREAD_EXECUTOR_HPP
|
||||
|
||||
#include <boost/thread/executors/executor.hpp>
|
||||
#include <boost/thread/executors/executor_adaptor.hpp>
|
||||
|
||||
#endif
|
||||
317
include/boost/thread/executors/basic_thread_pool.hpp
Normal file
317
include/boost/thread/executors/basic_thread_pool.hpp
Normal file
@@ -0,0 +1,317 @@
|
||||
// Copyright (C) 2013-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)
|
||||
//
|
||||
// 2013/09 Vicente J. Botet Escriba
|
||||
// Adapt to boost from CCIA C++11 implementation
|
||||
// first implementation of a simple pool thread using a vector of threads and a sync_queue.
|
||||
|
||||
#ifndef BOOST_THREAD_EXECUTORS_BASIC_THREAD_POOL_HPP
|
||||
#define BOOST_THREAD_EXECUTORS_BASIC_THREAD_POOL_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#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/executors/work.hpp>
|
||||
#include <boost/thread/csbl/vector.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace executors
|
||||
{
|
||||
class basic_thread_pool
|
||||
{
|
||||
public:
|
||||
/// type-erasure to store the works to do
|
||||
typedef executors::work work;
|
||||
private:
|
||||
/// the kind of stored threads are scoped threads to ensure that the threads are joined.
|
||||
/// A move aware vector type
|
||||
typedef scoped_thread<> thread_t;
|
||||
typedef csbl::vector<thread_t> thread_vector;
|
||||
|
||||
/// the thread safe work queue
|
||||
sync_queue<work > work_queue;
|
||||
/// A move aware vector
|
||||
thread_vector threads;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Effects: try to execute one task.
|
||||
* Returns: whether a task has been executed.
|
||||
* Throws: whatever the current task constructor throws or the task() throws.
|
||||
*/
|
||||
bool try_executing_one()
|
||||
{
|
||||
work task;
|
||||
try
|
||||
{
|
||||
if (work_queue.try_pull_front(task) == queue_op_status::success)
|
||||
{
|
||||
task();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
catch (std::exception& )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Effects: schedule one task or yields
|
||||
* Throws: whatever the current task constructor throws or the task() throws.
|
||||
*/
|
||||
void schedule_one_or_yield()
|
||||
{
|
||||
if ( ! try_executing_one())
|
||||
{
|
||||
this_thread::yield();
|
||||
}
|
||||
}
|
||||
private:
|
||||
|
||||
/**
|
||||
* The main loop of the worker threads
|
||||
*/
|
||||
void worker_thread()
|
||||
{
|
||||
try
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
work task;
|
||||
queue_op_status st = work_queue.wait_pull_front(task);
|
||||
if (st == queue_op_status::closed) return;
|
||||
task();
|
||||
}
|
||||
}
|
||||
catch (std::exception& )
|
||||
{
|
||||
return;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
template <class AtThreadEntry>
|
||||
void worker_thread1(AtThreadEntry& at_thread_entry)
|
||||
{
|
||||
at_thread_entry(*this);
|
||||
worker_thread();
|
||||
}
|
||||
#endif
|
||||
void worker_thread2(void(*at_thread_entry)(basic_thread_pool&))
|
||||
{
|
||||
at_thread_entry(*this);
|
||||
worker_thread();
|
||||
}
|
||||
template <class AtThreadEntry>
|
||||
void worker_thread3(BOOST_THREAD_FWD_REF(AtThreadEntry) at_thread_entry)
|
||||
{
|
||||
at_thread_entry(*this);
|
||||
worker_thread();
|
||||
}
|
||||
static void do_nothing_at_thread_entry(basic_thread_pool&) {}
|
||||
|
||||
public:
|
||||
/// basic_thread_pool is not copyable.
|
||||
BOOST_THREAD_NO_COPYABLE(basic_thread_pool)
|
||||
|
||||
/**
|
||||
* \b Effects: creates a thread pool that runs closures on \c thread_count threads.
|
||||
*
|
||||
* \b Throws: Whatever exception is thrown while initializing the needed resources.
|
||||
*/
|
||||
basic_thread_pool(unsigned const thread_count = thread::hardware_concurrency())
|
||||
{
|
||||
try
|
||||
{
|
||||
threads.reserve(thread_count);
|
||||
for (unsigned i = 0; i < thread_count; ++i)
|
||||
{
|
||||
#if 1
|
||||
thread th (&basic_thread_pool::worker_thread, this);
|
||||
threads.push_back(thread_t(boost::move(th)));
|
||||
#else
|
||||
threads.push_back(thread_t(&basic_thread_pool::worker_thread, this)); // do not compile
|
||||
#endif
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
close();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* \b Effects: creates a thread pool that runs closures on \c thread_count threads
|
||||
* and executes the at_thread_entry function at the entry of each created thread. .
|
||||
*
|
||||
* \b Throws: Whatever exception is thrown while initializing the needed resources.
|
||||
*/
|
||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
template <class AtThreadEntry>
|
||||
basic_thread_pool( unsigned const thread_count, AtThreadEntry& at_thread_entry)
|
||||
{
|
||||
try
|
||||
{
|
||||
threads.reserve(thread_count);
|
||||
for (unsigned i = 0; i < thread_count; ++i)
|
||||
{
|
||||
thread th (&basic_thread_pool::worker_thread1<AtThreadEntry>, this, at_thread_entry);
|
||||
threads.push_back(thread_t(boost::move(th)));
|
||||
//threads.push_back(thread_t(&basic_thread_pool::worker_thread, this)); // do not compile
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
close();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
basic_thread_pool( unsigned const thread_count, void(*at_thread_entry)(basic_thread_pool&))
|
||||
{
|
||||
try
|
||||
{
|
||||
threads.reserve(thread_count);
|
||||
for (unsigned i = 0; i < thread_count; ++i)
|
||||
{
|
||||
thread th (&basic_thread_pool::worker_thread2, this, at_thread_entry);
|
||||
threads.push_back(thread_t(boost::move(th)));
|
||||
//threads.push_back(thread_t(&basic_thread_pool::worker_thread, this)); // do not compile
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
close();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
template <class AtThreadEntry>
|
||||
basic_thread_pool( unsigned const thread_count, BOOST_THREAD_FWD_REF(AtThreadEntry) at_thread_entry)
|
||||
{
|
||||
try
|
||||
{
|
||||
threads.reserve(thread_count);
|
||||
for (unsigned i = 0; i < thread_count; ++i)
|
||||
{
|
||||
thread th (&basic_thread_pool::worker_thread3<AtThreadEntry>, this, boost::forward<AtThreadEntry>(at_thread_entry));
|
||||
threads.push_back(thread_t(boost::move(th)));
|
||||
//threads.push_back(thread_t(&basic_thread_pool::worker_thread, this)); // do not compile
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
close();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* \b Effects: Destroys the thread pool.
|
||||
*
|
||||
* \b Synchronization: The completion of all the closures happen before the completion of the \c basic_thread_pool destructor.
|
||||
*/
|
||||
~basic_thread_pool()
|
||||
{
|
||||
// signal to all the worker threads that there will be no more submissions.
|
||||
close();
|
||||
// joins all the threads as the threads were scoped_threads
|
||||
}
|
||||
|
||||
/**
|
||||
* \b Effects: join all the threads.
|
||||
*/
|
||||
void join()
|
||||
{
|
||||
for (unsigned i = 0; i < threads.size(); ++i)
|
||||
{
|
||||
threads[i].join();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \b Effects: close the \c basic_thread_pool for submissions.
|
||||
* The worker threads will work until there is no more closures to run.
|
||||
*/
|
||||
void close()
|
||||
{
|
||||
work_queue.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* \b Returns: whether the pool is closed for submissions.
|
||||
*/
|
||||
bool closed()
|
||||
{
|
||||
return work_queue.closed();
|
||||
}
|
||||
|
||||
/**
|
||||
* \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 at some point in the future.
|
||||
* If invoked closure throws an exception the \c basic_thread_pool will call \c std::terminate, as is the case with threads.
|
||||
*
|
||||
* \b Synchronization: completion of \c closure on a particular thread happens before destruction of thread's thread local variables.
|
||||
*
|
||||
* \b Throws: \c sync_queue_is_closed if the thread pool 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)
|
||||
{
|
||||
work_queue.push_back(work(closure));
|
||||
}
|
||||
#endif
|
||||
void submit(void (*closure)())
|
||||
{
|
||||
work_queue.push_back(work(closure));
|
||||
}
|
||||
|
||||
template <typename Closure>
|
||||
void submit(BOOST_THREAD_RV_REF(Closure) closure)
|
||||
{
|
||||
work_queue.push_back(work(boost::forward<Closure>(closure)));
|
||||
}
|
||||
|
||||
/**
|
||||
* \b Requires: This must be called from an scheduled task.
|
||||
*
|
||||
* \b Effects: reschedule functions until pred()
|
||||
*/
|
||||
template <typename Pred>
|
||||
bool reschedule_until(Pred const& pred)
|
||||
{
|
||||
do {
|
||||
if ( ! try_executing_one())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} while (! pred());
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
using executors::basic_thread_pool;
|
||||
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
147
include/boost/thread/executors/executor.hpp
Normal file
147
include/boost/thread/executors/executor.hpp
Normal file
@@ -0,0 +1,147 @@
|
||||
// Copyright (C) 2013,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)
|
||||
//
|
||||
// 2013/09 Vicente J. Botet Escriba
|
||||
// Adapt to boost from CCIA C++11 implementation
|
||||
|
||||
#ifndef BOOST_THREAD_EXECUTORS_EXECUTOR_HPP
|
||||
#define BOOST_THREAD_EXECUTORS_EXECUTOR_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/thread/detail/delete.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/executors/work.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace executors
|
||||
{
|
||||
class executor
|
||||
{
|
||||
public:
|
||||
/// type-erasure to store the works to do
|
||||
typedef executors::work work;
|
||||
|
||||
/// executor is not copyable.
|
||||
BOOST_THREAD_NO_COPYABLE(executor)
|
||||
executor() {}
|
||||
|
||||
/**
|
||||
* \par Effects
|
||||
* Destroys the executor.
|
||||
*
|
||||
* \par Synchronization
|
||||
* The completion of all the closures happen before the completion of the executor destructor.
|
||||
*/
|
||||
virtual ~executor() {};
|
||||
|
||||
/**
|
||||
* \par Effects
|
||||
* Close the \c executor for submissions.
|
||||
* The worker threads will work until there is no more closures to run.
|
||||
*/
|
||||
virtual void close() = 0;
|
||||
|
||||
/**
|
||||
* \par Returns
|
||||
* Whether the pool is closed for submissions.
|
||||
*/
|
||||
virtual bool closed() = 0;
|
||||
|
||||
/**
|
||||
* \par Effects
|
||||
* The specified closure will be scheduled for execution at some point in the future.
|
||||
* If invoked closure throws an exception the executor will call std::terminate, as is the case with threads.
|
||||
*
|
||||
* \par Synchronization
|
||||
* Ccompletion of closure on a particular thread happens before destruction of thread's thread local variables.
|
||||
*
|
||||
* \par Throws
|
||||
* \c sync_queue_is_closed if the thread pool is closed.
|
||||
* Whatever exception that can be throw while storing the closure.
|
||||
*/
|
||||
virtual void submit(BOOST_THREAD_RV_REF(work) closure) = 0;
|
||||
// virtual void submit(work& closure) = 0;
|
||||
|
||||
/**
|
||||
* \par Requires
|
||||
* \c Closure is a model of Callable(void()) and a model of CopyConstructible/MoveConstructible.
|
||||
*
|
||||
* \par Effects
|
||||
* The specified closure will be scheduled for execution at some point in the future.
|
||||
* If invoked closure throws an exception the thread pool will call std::terminate, as is the case with threads.
|
||||
*
|
||||
* \par Synchronization
|
||||
* Completion of closure on a particular thread happens before destruction of thread's thread local variables.
|
||||
*
|
||||
* \par Throws
|
||||
* \c sync_queue_is_closed if the thread pool 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)
|
||||
{
|
||||
work w ((closure));
|
||||
submit(boost::move(w));
|
||||
}
|
||||
#endif
|
||||
void submit(void (*closure)())
|
||||
{
|
||||
work w ((closure));
|
||||
submit(boost::move(w));
|
||||
}
|
||||
|
||||
template <typename Closure>
|
||||
void submit(BOOST_THREAD_RV_REF(Closure) closure)
|
||||
{
|
||||
work w = boost::move(closure);
|
||||
submit(boost::move(w));
|
||||
}
|
||||
|
||||
/**
|
||||
* \par Effects
|
||||
* Try to execute one task.
|
||||
*
|
||||
* \par Returns
|
||||
* Whether a task has been executed.
|
||||
*
|
||||
* \par Throws
|
||||
* Whatever the current task constructor throws or the task() throws.
|
||||
*/
|
||||
virtual bool try_executing_one() = 0;
|
||||
|
||||
/**
|
||||
* \par Requires
|
||||
* This must be called from an scheduled task.
|
||||
*
|
||||
* \par Effects
|
||||
* Reschedule functions until pred()
|
||||
*/
|
||||
template <typename Pred>
|
||||
bool reschedule_until(Pred const& pred)
|
||||
{
|
||||
do {
|
||||
//schedule_one_or_yield();
|
||||
if ( ! try_executing_one())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} while (! pred());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
using executors::executor;
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
137
include/boost/thread/executors/executor_adaptor.hpp
Normal file
137
include/boost/thread/executors/executor_adaptor.hpp
Normal file
@@ -0,0 +1,137 @@
|
||||
// Copyright (C) 2013,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)
|
||||
//
|
||||
// 2013/09 Vicente J. Botet Escriba
|
||||
// Adapt to boost from CCIA C++11 implementation
|
||||
|
||||
#ifndef BOOST_THREAD_EXECUTORS_EXECUTOR_ADAPTOR_HPP
|
||||
#define BOOST_THREAD_EXECUTORS_EXECUTOR_ADAPTOR_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/thread/executors/executor.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace executors
|
||||
{
|
||||
/**
|
||||
* Polymorphic adaptor of a model of Executor to an executor.
|
||||
*/
|
||||
template <typename Executor>
|
||||
class executor_adaptor : public executor
|
||||
{
|
||||
Executor ex;
|
||||
public:
|
||||
/// type-erasure to store the works to do
|
||||
typedef executor::work work;
|
||||
|
||||
/// executor is not copyable.
|
||||
BOOST_THREAD_NO_COPYABLE(executor_adaptor)
|
||||
|
||||
/**
|
||||
* executor_adaptor constructor
|
||||
*/
|
||||
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template <typename ...Args>
|
||||
executor_adaptor(BOOST_THREAD_RV_REF(Args) ... args) : ex(boost::forward<Args>(args)...) {}
|
||||
#else
|
||||
/**
|
||||
* executor_adaptor constructor
|
||||
*/
|
||||
executor_adaptor() : ex() {}
|
||||
|
||||
template <typename A1>
|
||||
executor_adaptor(
|
||||
BOOST_THREAD_FWD_REF(A1) a1
|
||||
) :
|
||||
ex(
|
||||
boost::forward<A1>(a1)
|
||||
) {}
|
||||
template <typename A1, typename A2>
|
||||
executor_adaptor(
|
||||
BOOST_THREAD_FWD_REF(A1) a1,
|
||||
BOOST_THREAD_FWD_REF(A2) a2
|
||||
) :
|
||||
ex(
|
||||
boost::forward<A1>(a1),
|
||||
boost::forward<A2>(a2)
|
||||
) {}
|
||||
template <typename A1, typename A2, typename A3>
|
||||
executor_adaptor(
|
||||
BOOST_THREAD_FWD_REF(A1) a1,
|
||||
BOOST_THREAD_FWD_REF(A2) a2,
|
||||
BOOST_THREAD_FWD_REF(A3) a3
|
||||
) :
|
||||
ex(
|
||||
boost::forward<A1>(a1),
|
||||
boost::forward<A2>(a2),
|
||||
boost::forward<A3>(a3)
|
||||
) {}
|
||||
#endif
|
||||
Executor& underlying_executor() { return ex; }
|
||||
|
||||
/**
|
||||
* \b Effects: close the \c executor for submissions.
|
||||
* The worker threads will work until there is no more closures to run.
|
||||
*/
|
||||
void close() { ex.close(); }
|
||||
|
||||
/**
|
||||
* \b Returns: whether the pool is closed for submissions.
|
||||
*/
|
||||
bool closed() { return ex.closed(); }
|
||||
|
||||
/**
|
||||
* \b Effects: The specified closure will be scheduled for execution at some point in the future.
|
||||
* If invoked closure throws an exception the executor will call std::terminate, as is the case with threads.
|
||||
*
|
||||
* \b Synchronization: completion of closure on a particular thread happens before destruction of thread's thread local variables.
|
||||
*
|
||||
* \b Throws: \c sync_queue_is_closed if the thread pool is closed.
|
||||
* Whatever exception that can be throw while storing the closure.
|
||||
*/
|
||||
void submit(BOOST_THREAD_RV_REF(work) closure) {
|
||||
return ex.submit(boost::move(closure));
|
||||
}
|
||||
// void submit(work & closure) {
|
||||
// return ex.submit(closure);
|
||||
// }
|
||||
|
||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
template <typename Closure>
|
||||
void submit(Closure & closure)
|
||||
{
|
||||
submit(work(closure));
|
||||
}
|
||||
#endif
|
||||
void submit(void (*closure)())
|
||||
{
|
||||
submit(work(closure));
|
||||
}
|
||||
|
||||
template <typename Closure>
|
||||
void submit(BOOST_THREAD_RV_REF(Closure) closure)
|
||||
{
|
||||
submit(work(boost::forward<Closure>(closure)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Effects: try to execute one task.
|
||||
* Returns: whether a task has been executed.
|
||||
* Throws: whatever the current task constructor throws or the task() throws.
|
||||
*/
|
||||
bool try_executing_one() { return ex.try_executing_one(); }
|
||||
|
||||
};
|
||||
}
|
||||
using executors::executor_adaptor;
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
211
include/boost/thread/executors/generic_executor_ref.hpp
Normal file
211
include/boost/thread/executors/generic_executor_ref.hpp
Normal file
@@ -0,0 +1,211 @@
|
||||
// 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_GENERIC_EXECUTOR_REF_HPP
|
||||
#define BOOST_THREAD_EXECUTORS_GENERIC_EXECUTOR_REF_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/thread/detail/delete.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/executors/executor.hpp>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace executors
|
||||
{
|
||||
|
||||
template <class Executor>
|
||||
class executor_ref : public executor
|
||||
{
|
||||
Executor& ex;
|
||||
public:
|
||||
/// type-erasure to store the works to do
|
||||
typedef executors::work work;
|
||||
|
||||
/// executor is not copyable.
|
||||
BOOST_THREAD_NO_COPYABLE(executor_ref)
|
||||
executor_ref(Executor& ex) : ex(ex) {}
|
||||
|
||||
/**
|
||||
* \par Effects
|
||||
* Destroys the executor.
|
||||
*
|
||||
* \par Synchronization
|
||||
* The completion of all the closures happen before the completion of the executor destructor.
|
||||
*/
|
||||
~executor_ref() {};
|
||||
|
||||
/**
|
||||
* \par Effects
|
||||
* Close the \c executor for submissions.
|
||||
* The worker threads will work until there is no more closures to run.
|
||||
*/
|
||||
void close() { ex.close(); }
|
||||
|
||||
/**
|
||||
* \par Returns
|
||||
* Whether the pool is closed for submissions.
|
||||
*/
|
||||
bool closed() { return ex.closed(); }
|
||||
|
||||
/**
|
||||
* \par Effects
|
||||
* The specified closure will be scheduled for execution at some point in the future.
|
||||
* If invoked closure throws an exception the executor will call std::terminate, as is the case with threads.
|
||||
*
|
||||
* \par Synchronization
|
||||
* Ccompletion of closure on a particular thread happens before destruction of thread's thread local variables.
|
||||
*
|
||||
* \par Throws
|
||||
* \c sync_queue_is_closed if the thread pool is closed.
|
||||
* Whatever exception that can be throw while storing the closure.
|
||||
*/
|
||||
void submit(BOOST_THREAD_RV_REF(work) closure) {
|
||||
ex.submit(boost::move(closure));
|
||||
}
|
||||
// void submit(work& closure) {
|
||||
// ex.submit(closure);
|
||||
// }
|
||||
|
||||
|
||||
/**
|
||||
* \par Effects
|
||||
* Try to execute one task.
|
||||
*
|
||||
* \par Returns
|
||||
* Whether a task has been executed.
|
||||
*
|
||||
* \par Throws
|
||||
* Whatever the current task constructor throws or the task() throws.
|
||||
*/
|
||||
bool try_executing_one() { return ex.try_executing_one(); }
|
||||
|
||||
};
|
||||
|
||||
class generic_executor_ref
|
||||
{
|
||||
shared_ptr<executor> ex;
|
||||
public:
|
||||
/// type-erasure to store the works to do
|
||||
typedef executors::work work;
|
||||
|
||||
template<typename Executor>
|
||||
generic_executor_ref(Executor& ex)
|
||||
//: ex(make_shared<executor_ref<Executor> >(ex)) // todo check why this doesn't works with C++03
|
||||
: ex( new executor_ref<Executor>(ex) )
|
||||
{
|
||||
}
|
||||
|
||||
//generic_executor_ref(generic_executor_ref const& other) noexcept {}
|
||||
//generic_executor_ref& operator=(generic_executor_ref const& other) noexcept {}
|
||||
|
||||
|
||||
/**
|
||||
* \par Effects
|
||||
* Close the \c executor for submissions.
|
||||
* The worker threads will work until there is no more closures to run.
|
||||
*/
|
||||
void close() { ex->close(); }
|
||||
|
||||
/**
|
||||
* \par Returns
|
||||
* Whether the pool is closed for submissions.
|
||||
*/
|
||||
bool closed() { return ex->closed(); }
|
||||
|
||||
void submit(BOOST_THREAD_RV_REF(work) closure)
|
||||
{
|
||||
ex->submit(boost::forward<work>(closure));
|
||||
}
|
||||
|
||||
/**
|
||||
* \par Requires
|
||||
* \c Closure is a model of Callable(void()) and a model of CopyConstructible/MoveConstructible.
|
||||
*
|
||||
* \par Effects
|
||||
* The specified closure will be scheduled for execution at some point in the future.
|
||||
* If invoked closure throws an exception the thread pool will call std::terminate, as is the case with threads.
|
||||
*
|
||||
* \par Synchronization
|
||||
* Completion of closure on a particular thread happens before destruction of thread's thread local variables.
|
||||
*
|
||||
* \par Throws
|
||||
* \c sync_queue_is_closed if the thread pool 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)
|
||||
{
|
||||
work w ((closure));
|
||||
submit(boost::move(w));
|
||||
}
|
||||
#endif
|
||||
void submit(void (*closure)())
|
||||
{
|
||||
work w ((closure));
|
||||
submit(boost::move(w));
|
||||
}
|
||||
|
||||
template <typename Closure>
|
||||
void submit(BOOST_THREAD_RV_REF(Closure) closure)
|
||||
{
|
||||
work w = boost::move(closure);
|
||||
submit(boost::move(w));
|
||||
}
|
||||
|
||||
// size_t num_pending_closures() const
|
||||
// {
|
||||
// return ex->num_pending_closures();
|
||||
// }
|
||||
|
||||
/**
|
||||
* \par Effects
|
||||
* Try to execute one task.
|
||||
*
|
||||
* \par Returns
|
||||
* Whether a task has been executed.
|
||||
*
|
||||
* \par Throws
|
||||
* Whatever the current task constructor throws or the task() throws.
|
||||
*/
|
||||
bool try_executing_one() { return ex->try_executing_one(); }
|
||||
|
||||
/**
|
||||
* \par Requires
|
||||
* This must be called from an scheduled task.
|
||||
*
|
||||
* \par Effects
|
||||
* reschedule functions until pred()
|
||||
*/
|
||||
template <typename Pred>
|
||||
bool reschedule_until(Pred const& pred)
|
||||
{
|
||||
do {
|
||||
//schedule_one_or_yield();
|
||||
if ( ! try_executing_one())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} while (! pred());
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
using executors::executor_ref;
|
||||
using executors::generic_executor_ref;
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
131
include/boost/thread/executors/inline_executor.hpp
Normal file
131
include/boost/thread/executors/inline_executor.hpp
Normal file
@@ -0,0 +1,131 @@
|
||||
// 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)
|
||||
//
|
||||
// 2013/11 Vicente J. Botet Escriba
|
||||
// first implementation of a simple serial scheduler.
|
||||
|
||||
#ifndef BOOST_THREAD_INLINE_EXECUTOR_HPP
|
||||
#define BOOST_THREAD_INLINE_EXECUTOR_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/detail/delete.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/executors/work.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace executors
|
||||
{
|
||||
class inline_executor
|
||||
{
|
||||
public:
|
||||
/// type-erasure to store the works to do
|
||||
typedef executors::work work;
|
||||
bool closed_;
|
||||
/**
|
||||
* Effects: try to execute one task.
|
||||
* Returns: whether a task has been executed.
|
||||
* Throws: whatever the current task constructor throws or the task() throws.
|
||||
*/
|
||||
bool try_executing_one()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
/// inline_executor is not copyable.
|
||||
BOOST_THREAD_NO_COPYABLE(inline_executor)
|
||||
|
||||
/**
|
||||
* \b Effects: creates a inline executor that runs closures immediately.
|
||||
*
|
||||
* \b Throws: Nothing.
|
||||
*/
|
||||
inline_executor()
|
||||
: closed_(false)
|
||||
{
|
||||
}
|
||||
/**
|
||||
* \b Effects: Destroys the inline executor.
|
||||
*
|
||||
* \b Synchronization: The completion of all the closures happen before the completion of the \c inline_executor destructor.
|
||||
*/
|
||||
~inline_executor()
|
||||
{
|
||||
// signal to all the worker thread that there will be no more submissions.
|
||||
close();
|
||||
}
|
||||
|
||||
/**
|
||||
* \b Effects: close the \c inline_executor for submissions.
|
||||
* The loop will work until there is no more closures to run.
|
||||
*/
|
||||
void close()
|
||||
{
|
||||
closed_ = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* \b Returns: whether the pool is closed for submissions.
|
||||
*/
|
||||
bool closed()
|
||||
{
|
||||
return closed_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \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 at some point in the future.
|
||||
* If invoked closure throws an exception the \c inline_executor will call \c std::terminate, as is the case with threads.
|
||||
*
|
||||
* \b Synchronization: completion of \c closure on a particular thread happens before destruction of thread's thread local variables.
|
||||
*
|
||||
* \b Throws: \c sync_queue_is_closed if the thread pool 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)
|
||||
{
|
||||
if (closed()) return;
|
||||
closure();
|
||||
}
|
||||
#endif
|
||||
void submit(void (*closure)())
|
||||
{
|
||||
if (closed()) return;
|
||||
closure();
|
||||
}
|
||||
|
||||
template <typename Closure>
|
||||
void submit(BOOST_THREAD_FWD_REF(Closure) closure)
|
||||
{
|
||||
if (closed()) return;
|
||||
closure();
|
||||
}
|
||||
|
||||
/**
|
||||
* \b Requires: This must be called from an scheduled task.
|
||||
*
|
||||
* \b Effects: reschedule functions until pred()
|
||||
*/
|
||||
template <typename Pred>
|
||||
bool reschedule_until(Pred const& )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
using executors::inline_executor;
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
204
include/boost/thread/executors/loop_executor.hpp
Normal file
204
include/boost/thread/executors/loop_executor.hpp
Normal file
@@ -0,0 +1,204 @@
|
||||
// Copyright (C) 2013,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)
|
||||
//
|
||||
// 2013/11 Vicente J. Botet Escriba
|
||||
// first implementation of a simple user scheduler.
|
||||
// 2013/11 Vicente J. Botet Escriba
|
||||
// rename loop_executor.
|
||||
|
||||
#ifndef BOOST_THREAD_EXECUTORS_LOOP_EXECUTOR_HPP
|
||||
#define BOOST_THREAD_EXECUTORS_LOOP_EXECUTOR_HPP
|
||||
|
||||
#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/executors/work.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace executors
|
||||
{
|
||||
|
||||
class loop_executor
|
||||
{
|
||||
public:
|
||||
/// type-erasure to store the works to do
|
||||
typedef executors::work work;
|
||||
private:
|
||||
/// the thread safe work queue
|
||||
sync_queue<work > work_queue;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Effects: try to execute one task.
|
||||
* Returns: whether a task has been executed.
|
||||
* Throws: whatever the current task constructor throws or the task() throws.
|
||||
*/
|
||||
bool try_executing_one()
|
||||
{
|
||||
work task;
|
||||
try
|
||||
{
|
||||
if (work_queue.try_pull_front(task) == queue_op_status::success)
|
||||
{
|
||||
task();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
catch (std::exception& )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
private:
|
||||
/**
|
||||
* Effects: schedule one task or yields
|
||||
* Throws: whatever the current task constructor throws or the task() throws.
|
||||
*/
|
||||
void schedule_one_or_yield()
|
||||
{
|
||||
if ( ! try_executing_one())
|
||||
{
|
||||
this_thread::yield();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The main loop of the worker thread
|
||||
*/
|
||||
void worker_thread()
|
||||
{
|
||||
while (!closed())
|
||||
{
|
||||
schedule_one_or_yield();
|
||||
}
|
||||
while (try_executing_one())
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
/// loop_executor is not copyable.
|
||||
BOOST_THREAD_NO_COPYABLE(loop_executor)
|
||||
|
||||
/**
|
||||
* \b Effects: creates a thread pool that runs closures using one of its closure-executing methods.
|
||||
*
|
||||
* \b Throws: Whatever exception is thrown while initializing the needed resources.
|
||||
*/
|
||||
loop_executor()
|
||||
{
|
||||
}
|
||||
/**
|
||||
* \b Effects: Destroys the thread pool.
|
||||
*
|
||||
* \b Synchronization: The completion of all the closures happen before the completion of the \c loop_executor destructor.
|
||||
*/
|
||||
~loop_executor()
|
||||
{
|
||||
// signal to all the worker thread that there will be no more submissions.
|
||||
close();
|
||||
}
|
||||
|
||||
/**
|
||||
* loop
|
||||
*/
|
||||
void loop() { worker_thread(); }
|
||||
/**
|
||||
* \b Effects: close the \c loop_executor for submissions.
|
||||
* The loop will work until there is no more closures to run.
|
||||
*/
|
||||
void close()
|
||||
{
|
||||
work_queue.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* \b Returns: whether the pool is closed for submissions.
|
||||
*/
|
||||
bool closed()
|
||||
{
|
||||
return work_queue.closed();
|
||||
}
|
||||
|
||||
/**
|
||||
* \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 at some point in the future.
|
||||
* If invoked closure throws an exception the \c loop_executor will call \c std::terminate, as is the case with threads.
|
||||
*
|
||||
* \b Synchronization: completion of \c closure on a particular thread happens before destruction of thread's thread local variables.
|
||||
*
|
||||
* \b Throws: \c sync_queue_is_closed if the thread pool 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)
|
||||
{
|
||||
work_queue.push_back(work(closure));
|
||||
}
|
||||
#endif
|
||||
void submit(void (*closure)())
|
||||
{
|
||||
work_queue.push_back(work(closure));
|
||||
}
|
||||
|
||||
template <typename Closure>
|
||||
void submit(BOOST_THREAD_RV_REF(Closure) closure)
|
||||
{
|
||||
work_queue.push_back(work(boost::forward<Closure>(closure)));
|
||||
}
|
||||
|
||||
/**
|
||||
* \b Requires: This must be called from an scheduled task.
|
||||
*
|
||||
* \b Effects: reschedule functions until pred()
|
||||
*/
|
||||
template <typename Pred>
|
||||
bool reschedule_until(Pred const& pred)
|
||||
{
|
||||
do {
|
||||
if ( ! try_executing_one())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} while (! pred());
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* run queued closures
|
||||
*/
|
||||
void run_queued_closures()
|
||||
{
|
||||
sync_queue<work>::underlying_queue_type q = work_queue.underlying_queue();
|
||||
while (! q.empty())
|
||||
{
|
||||
work& task = q.front();
|
||||
task();
|
||||
q.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
using executors::loop_executor;
|
||||
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
214
include/boost/thread/executors/serial_executor.hpp
Normal file
214
include/boost/thread/executors/serial_executor.hpp
Normal file
@@ -0,0 +1,214 @@
|
||||
// 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/11 Vicente J. Botet Escriba
|
||||
// first implementation of a simple serial scheduler.
|
||||
|
||||
#ifndef BOOST_THREAD_SERIAL_EXECUTOR_HPP
|
||||
#define BOOST_THREAD_SERIAL_EXECUTOR_HPP
|
||||
|
||||
#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/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
|
||||
{
|
||||
public:
|
||||
/// type-erasure to store the works to do
|
||||
typedef executors::work work;
|
||||
private:
|
||||
typedef scoped_thread<> thread_t;
|
||||
|
||||
/// the thread safe work queue
|
||||
sync_queue<work > work_queue;
|
||||
generic_executor_ref ex;
|
||||
thread_t thr;
|
||||
|
||||
struct try_executing_one_task {
|
||||
work& task;
|
||||
boost::promise<void> &p;
|
||||
try_executing_one_task(work& task, boost::promise<void> &p)
|
||||
: task(task), p(p) {}
|
||||
void operator()() {
|
||||
task(); // if task() throws promise is not set but as the the program terminates and should terminate there is no need to use try-catch here.
|
||||
p.set_value();
|
||||
}
|
||||
};
|
||||
public:
|
||||
/**
|
||||
* \par Returns
|
||||
* The underlying executor wrapped on a generic executor reference.
|
||||
*/
|
||||
generic_executor_ref underlying_executor() BOOST_NOEXCEPT { return ex; }
|
||||
|
||||
/**
|
||||
* Effects: try to execute one task.
|
||||
* Returns: whether a task has been executed.
|
||||
* Throws: whatever the current task constructor throws or the task() throws.
|
||||
*/
|
||||
bool try_executing_one()
|
||||
{
|
||||
work task;
|
||||
try
|
||||
{
|
||||
if (work_queue.try_pull_front(task) == queue_op_status::success)
|
||||
{
|
||||
boost::promise<void> p;
|
||||
try_executing_one_task tmp(task,p);
|
||||
ex.submit(tmp);
|
||||
// ex.submit([&task, &p]()
|
||||
// {
|
||||
// task(); // if task() throws promise is not set but as the the program terminates and should terminate there is no need to use try-catch here.
|
||||
// p.set_value();
|
||||
// });
|
||||
p.get_future().wait();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
catch (std::exception& )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
private:
|
||||
/**
|
||||
* Effects: schedule one task or yields
|
||||
* Throws: whatever the current task constructor throws or the task() throws.
|
||||
*/
|
||||
void schedule_one_or_yield()
|
||||
{
|
||||
if ( ! try_executing_one())
|
||||
{
|
||||
this_thread::yield();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The main loop of the worker thread
|
||||
*/
|
||||
void worker_thread()
|
||||
{
|
||||
while (!closed())
|
||||
{
|
||||
schedule_one_or_yield();
|
||||
}
|
||||
while (try_executing_one())
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
/// serial_executor is not copyable.
|
||||
BOOST_THREAD_NO_COPYABLE(serial_executor)
|
||||
|
||||
/**
|
||||
* \b Effects: creates a thread pool that runs closures using one of its closure-executing methods.
|
||||
*
|
||||
* \b Throws: Whatever exception is thrown while initializing the needed resources.
|
||||
*/
|
||||
template <class Executor>
|
||||
serial_executor(Executor& ex)
|
||||
: ex(ex), thr(&serial_executor::worker_thread, this)
|
||||
{
|
||||
}
|
||||
/**
|
||||
* \b Effects: Destroys the thread pool.
|
||||
*
|
||||
* \b Synchronization: The completion of all the closures happen before the completion of the \c serial_executor destructor.
|
||||
*/
|
||||
~serial_executor()
|
||||
{
|
||||
// signal to all the worker thread that there will be no more submissions.
|
||||
close();
|
||||
}
|
||||
|
||||
/**
|
||||
* \b Effects: close the \c serial_executor for submissions.
|
||||
* The loop will work until there is no more closures to run.
|
||||
*/
|
||||
void close()
|
||||
{
|
||||
work_queue.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* \b Returns: whether the pool is closed for submissions.
|
||||
*/
|
||||
bool closed()
|
||||
{
|
||||
return work_queue.closed();
|
||||
}
|
||||
|
||||
/**
|
||||
* \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 at some point in the future.
|
||||
* If invoked closure throws an exception the \c serial_executor will call \c std::terminate, as is the case with threads.
|
||||
*
|
||||
* \b Synchronization: completion of \c closure on a particular thread happens before destruction of thread's thread local variables.
|
||||
*
|
||||
* \b Throws: \c sync_queue_is_closed if the thread pool 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)
|
||||
{
|
||||
work_queue.push_back(work(closure));
|
||||
}
|
||||
#endif
|
||||
void submit(void (*closure)())
|
||||
{
|
||||
work_queue.push_back(work(closure));
|
||||
}
|
||||
|
||||
template <typename Closure>
|
||||
void submit(BOOST_THREAD_RV_REF(Closure) closure)
|
||||
{
|
||||
work_queue.push_back(work(boost::forward<Closure>(closure)));
|
||||
}
|
||||
|
||||
/**
|
||||
* \b Requires: This must be called from an scheduled task.
|
||||
*
|
||||
* \b Effects: reschedule functions until pred()
|
||||
*/
|
||||
template <typename Pred>
|
||||
bool reschedule_until(Pred const& pred)
|
||||
{
|
||||
do {
|
||||
if ( ! try_executing_one())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} while (! pred());
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
using executors::serial_executor;
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
136
include/boost/thread/executors/thread_executor.hpp
Normal file
136
include/boost/thread/executors/thread_executor.hpp
Normal file
@@ -0,0 +1,136 @@
|
||||
// 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)
|
||||
//
|
||||
// 2014/01 Vicente J. Botet Escriba
|
||||
// first implementation of a thread_executor.
|
||||
|
||||
#ifndef BOOST_THREAD_THREAD_EXECUTOR_HPP
|
||||
#define BOOST_THREAD_THREAD_EXECUTOR_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/detail/delete.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/thread/executors/work.hpp>
|
||||
#include <boost/thread/executors/executor.hpp>
|
||||
#include <boost/thread/thread_only.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace executors
|
||||
{
|
||||
class thread_executor
|
||||
{
|
||||
public:
|
||||
/// type-erasure to store the works to do
|
||||
typedef executors::work work;
|
||||
bool closed_;
|
||||
/**
|
||||
* Effects: try to execute one task.
|
||||
* Returns: whether a task has been executed.
|
||||
* Throws: whatever the current task constructor throws or the task() throws.
|
||||
*/
|
||||
bool try_executing_one()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
/// thread_executor is not copyable.
|
||||
BOOST_THREAD_NO_COPYABLE(thread_executor)
|
||||
|
||||
/**
|
||||
* \b Effects: creates a inline executor that runs closures immediately.
|
||||
*
|
||||
* \b Throws: Nothing.
|
||||
*/
|
||||
thread_executor()
|
||||
: closed_(false)
|
||||
{
|
||||
}
|
||||
/**
|
||||
* \b Effects: Destroys the inline executor.
|
||||
*
|
||||
* \b Synchronization: The completion of all the closures happen before the completion of the \c thread_executor destructor.
|
||||
*/
|
||||
~thread_executor()
|
||||
{
|
||||
// signal to all the worker thread that there will be no more submissions.
|
||||
close();
|
||||
}
|
||||
|
||||
/**
|
||||
* \b Effects: close the \c thread_executor for submissions.
|
||||
* The loop will work until there is no more closures to run.
|
||||
*/
|
||||
void close()
|
||||
{
|
||||
closed_ = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* \b Returns: whether the pool is closed for submissions.
|
||||
*/
|
||||
bool closed()
|
||||
{
|
||||
return closed_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \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 at some point in the future.
|
||||
* If invoked closure throws an exception the \c thread_executor will call \c std::terminate, as is the case with threads.
|
||||
*
|
||||
* \b Synchronization: completion of \c closure on a particular thread happens before destruction of thread's thread local variables.
|
||||
*
|
||||
* \b Throws: \c sync_queue_is_closed if the thread pool 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)
|
||||
{
|
||||
if (closed()) return;
|
||||
thread th(closure);
|
||||
th.detach();
|
||||
}
|
||||
#endif
|
||||
void submit(void (*closure)())
|
||||
{
|
||||
if (closed()) return;
|
||||
thread th(closure);
|
||||
th.detach();
|
||||
}
|
||||
|
||||
template <typename Closure>
|
||||
void submit(BOOST_THREAD_FWD_REF(Closure) closure)
|
||||
{
|
||||
if (closed()) return;
|
||||
thread th(boost::forward<Closure>(closure));
|
||||
th.detach();
|
||||
}
|
||||
|
||||
/**
|
||||
* \b Requires: This must be called from an scheduled task.
|
||||
*
|
||||
* \b Effects: reschedule functions until pred()
|
||||
*/
|
||||
template <typename Pred>
|
||||
bool reschedule_until(Pred const&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
using executors::thread_executor;
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
43
include/boost/thread/executors/work.hpp
Normal file
43
include/boost/thread/executors/work.hpp
Normal file
@@ -0,0 +1,43 @@
|
||||
// (C) Copyright 2013,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_WORK_HPP
|
||||
#define BOOST_THREAD_EXECUTORS_WORK_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#if ! defined BOOST_THREAD_EXECUTORS_WORK_ACCEPTS_MOVABLE \
|
||||
&& ! defined BOOST_THREAD_EXECUTORS_WORK_DONT_ACCEPT_MOVABLE
|
||||
#define BOOST_THREAD_EXECUTORS_WORK_ACCEPTS_MOVABLE
|
||||
//#define BOOST_THREAD_EXECUTORS_WORK_DONT_ACCEPT_MOVABLE
|
||||
#endif
|
||||
|
||||
#if defined BOOST_THREAD_EXECUTORS_WORK_ACCEPTS_MOVABLE
|
||||
|
||||
#include <boost/thread/detail/nullary_function.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace executors
|
||||
{
|
||||
typedef detail::nullary_function<void()> work;
|
||||
}
|
||||
} // namespace boost
|
||||
|
||||
#else
|
||||
#include <boost/thread/csbl/functional.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace executors
|
||||
{
|
||||
typedef csbl::function<void()> work;
|
||||
}
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
||||
#endif // BOOST_THREAD_EXECUTORS_WORK_HPP
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/utility/swap.hpp>
|
||||
#include <boost/core/swap.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
@@ -97,7 +97,7 @@ namespace boost
|
||||
/// move assignment
|
||||
externally_locked& operator=(BOOST_THREAD_RV_REF(externally_locked) rhs) // BOOST_NOEXCEPT
|
||||
{
|
||||
obj_=move(rhs.obj_);
|
||||
obj_=move(BOOST_THREAD_RV(rhs).obj_);
|
||||
mtx_=rhs.mtx_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,7 +9,7 @@
|
||||
#define BOOST_THREAD_FUTURE_ERROR_CODE_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/detail/scoped_enum_emulation.hpp>
|
||||
#include <boost/core/scoped_enum.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <boost/type_traits/integral_constant.hpp>
|
||||
|
||||
@@ -29,11 +29,11 @@ namespace boost
|
||||
namespace system
|
||||
{
|
||||
template <>
|
||||
struct BOOST_SYMBOL_VISIBLE is_error_code_enum<future_errc> : public true_type {};
|
||||
struct BOOST_SYMBOL_VISIBLE is_error_code_enum< ::boost::future_errc> : public true_type {};
|
||||
|
||||
#ifdef BOOST_NO_CXX11_SCOPED_ENUMS
|
||||
template <>
|
||||
struct BOOST_SYMBOL_VISIBLE is_error_code_enum<future_errc::enum_type> : public true_type { };
|
||||
struct BOOST_SYMBOL_VISIBLE is_error_code_enum< ::boost::future_errc::enum_type> : public true_type { };
|
||||
#endif
|
||||
} // system
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace boost
|
||||
error_condition
|
||||
make_error_condition(future_errc e) BOOST_NOEXCEPT
|
||||
{
|
||||
return error_condition(underlying_cast<int>(e), future_category());
|
||||
return error_condition(underlying_cast<int>(e), boost::future_category());
|
||||
}
|
||||
} // system
|
||||
} // boost
|
||||
|
||||
@@ -23,28 +23,40 @@ namespace boost
|
||||
{
|
||||
class latch
|
||||
{
|
||||
/// @Requires: count_.value_ must be greater than 0
|
||||
/// Effect: Decrement the count. Unlocks the lock notify anyone waiting if we reached zero.
|
||||
/// Returns: true if count_.value_ reached the value 0.
|
||||
/// @Requires: count_ must be greater than 0
|
||||
/// 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)
|
||||
/// pre_condition (count_.value_ > 0)
|
||||
/// pre_condition (count_ > 0)
|
||||
{
|
||||
BOOST_ASSERT(count_.value_ > 0);
|
||||
if (--count_.value_ == 0)
|
||||
BOOST_ASSERT(count_ > 0);
|
||||
if (--count_ == 0)
|
||||
{
|
||||
count_.cond_.notify_all();
|
||||
lk.unlock();
|
||||
++generation_;
|
||||
//lk.unlock();
|
||||
cond_.notify_all();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/// Effect: Decrement the count is > 0. Unlocks the lock notify anyone waiting if we reached zero.
|
||||
/// Returns: true if count_ is 0.
|
||||
/// @ThreadSafe ensured by the @c lk parameter
|
||||
bool try_count_down(unique_lock<mutex> &lk)
|
||||
{
|
||||
if (count_ > 0)
|
||||
{
|
||||
return count_down(lk);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public:
|
||||
BOOST_THREAD_NO_COPYABLE( latch)
|
||||
|
||||
/// Constructs a latch with a given count.
|
||||
latch(std::size_t count) :
|
||||
count_(count)
|
||||
count_(count), generation_(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -60,7 +72,8 @@ namespace boost
|
||||
void wait()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mutex_);
|
||||
count_.cond_.wait(lk, detail::counter_is_zero(count_));
|
||||
std::size_t generation(generation_);
|
||||
cond_.wait(lk, detail::not_equal(generation, generation_));
|
||||
}
|
||||
|
||||
/// @return true if the internal counter is already 0, false otherwise
|
||||
@@ -76,7 +89,8 @@ namespace boost
|
||||
cv_status wait_for(const chrono::duration<Rep, Period>& rel_time)
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mutex_);
|
||||
return count_.cond_.wait_for(lk, rel_time, detail::counter_is_zero(count_))
|
||||
std::size_t generation(generation_);
|
||||
return cond_.wait_for(lk, rel_time, detail::not_equal(generation, generation_))
|
||||
? cv_status::no_timeout
|
||||
: cv_status::timeout;
|
||||
}
|
||||
@@ -87,7 +101,8 @@ namespace boost
|
||||
cv_status wait_until(const chrono::time_point<Clock, Duration>& abs_time)
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mutex_);
|
||||
return count_.cond_.wait_until(lk, abs_time, detail::counter_is_zero(count_))
|
||||
std::size_t generation(generation_);
|
||||
return cond_.wait_until(lk, abs_time, detail::not_equal(generation, generation_))
|
||||
? cv_status::no_timeout
|
||||
: cv_status::timeout;
|
||||
}
|
||||
@@ -99,6 +114,13 @@ namespace boost
|
||||
boost::unique_lock<boost::mutex> lk(mutex_);
|
||||
count_down(lk);
|
||||
}
|
||||
/// Effect: Decrement the count if it is > 0 and notify anyone waiting if we reached zero.
|
||||
/// Returns: true if count_ was 0 or reached 0.
|
||||
bool try_count_down()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mutex_);
|
||||
return try_count_down(lk);
|
||||
}
|
||||
void signal()
|
||||
{
|
||||
count_down();
|
||||
@@ -110,11 +132,12 @@ namespace boost
|
||||
void count_down_and_wait()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(mutex_);
|
||||
std::size_t generation(generation_);
|
||||
if (count_down(lk))
|
||||
{
|
||||
return;
|
||||
}
|
||||
count_.cond_.wait(lk, detail::counter_is_zero(count_));
|
||||
cond_.wait(lk, detail::not_equal(generation, generation_));
|
||||
}
|
||||
void sync()
|
||||
{
|
||||
@@ -132,7 +155,9 @@ namespace boost
|
||||
|
||||
private:
|
||||
mutex mutex_;
|
||||
detail::counter count_;
|
||||
condition_variable cond_;
|
||||
std::size_t count_;
|
||||
std::size_t generation_;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
@@ -336,12 +336,12 @@ namespace boost
|
||||
if (m == 0)
|
||||
{
|
||||
boost::throw_exception(
|
||||
boost::lock_error(system::errc::operation_not_permitted, "boost unique_lock has no mutex"));
|
||||
boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
|
||||
}
|
||||
if (owns_lock())
|
||||
{
|
||||
boost::throw_exception(
|
||||
boost::lock_error(system::errc::resource_deadlock_would_occur, "boost unique_lock owns already the mutex"));
|
||||
boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex"));
|
||||
}
|
||||
m->lock();
|
||||
is_locked = true;
|
||||
@@ -351,12 +351,12 @@ namespace boost
|
||||
if (m == 0)
|
||||
{
|
||||
boost::throw_exception(
|
||||
boost::lock_error(system::errc::operation_not_permitted, "boost unique_lock has no mutex"));
|
||||
boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
|
||||
}
|
||||
if (owns_lock())
|
||||
{
|
||||
boost::throw_exception(
|
||||
boost::lock_error(system::errc::resource_deadlock_would_occur, "boost unique_lock owns already the mutex"));
|
||||
boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex"));
|
||||
}
|
||||
is_locked = m->try_lock();
|
||||
return is_locked;
|
||||
@@ -367,11 +367,11 @@ namespace boost
|
||||
{
|
||||
if(m==0)
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost unique_lock has no mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
|
||||
}
|
||||
if(owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost unique_lock owns already the mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex"));
|
||||
}
|
||||
is_locked=m->timed_lock(relative_time);
|
||||
return is_locked;
|
||||
@@ -381,11 +381,11 @@ namespace boost
|
||||
{
|
||||
if(m==0)
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost unique_lock has no mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
|
||||
}
|
||||
if(owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost unique_lock owns already the mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex"));
|
||||
}
|
||||
is_locked=m->timed_lock(absolute_time);
|
||||
return is_locked;
|
||||
@@ -394,11 +394,11 @@ namespace boost
|
||||
{
|
||||
if(m==0)
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost unique_lock has no mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
|
||||
}
|
||||
if(owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost unique_lock owns already the mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex"));
|
||||
}
|
||||
is_locked=m->timed_lock(absolute_time);
|
||||
return is_locked;
|
||||
@@ -411,11 +411,11 @@ namespace boost
|
||||
{
|
||||
if(m==0)
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost unique_lock has no mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
|
||||
}
|
||||
if(owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost unique_lock owns already the mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex"));
|
||||
}
|
||||
is_locked=m->try_lock_for(rel_time);
|
||||
return is_locked;
|
||||
@@ -425,11 +425,11 @@ namespace boost
|
||||
{
|
||||
if(m==0)
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost unique_lock has no mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
|
||||
}
|
||||
if(owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost unique_lock owns already the mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex"));
|
||||
}
|
||||
is_locked=m->try_lock_until(abs_time);
|
||||
return is_locked;
|
||||
@@ -441,12 +441,12 @@ namespace boost
|
||||
if (m == 0)
|
||||
{
|
||||
boost::throw_exception(
|
||||
boost::lock_error(system::errc::operation_not_permitted, "boost unique_lock has no mutex"));
|
||||
boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
|
||||
}
|
||||
if (!owns_lock())
|
||||
{
|
||||
boost::throw_exception(
|
||||
boost::lock_error(system::errc::operation_not_permitted, "boost unique_lock doesn't own the mutex"));
|
||||
boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock doesn't own the mutex"));
|
||||
}
|
||||
m->unlock();
|
||||
is_locked = false;
|
||||
@@ -636,11 +636,11 @@ namespace boost
|
||||
{
|
||||
if(m==0)
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
|
||||
}
|
||||
if(owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost shared_lock owns already the mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex"));
|
||||
}
|
||||
m->lock_shared();
|
||||
is_locked=true;
|
||||
@@ -649,11 +649,11 @@ namespace boost
|
||||
{
|
||||
if(m==0)
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
|
||||
}
|
||||
if(owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost shared_lock owns already the mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex"));
|
||||
}
|
||||
is_locked=m->try_lock_shared();
|
||||
return is_locked;
|
||||
@@ -663,11 +663,11 @@ namespace boost
|
||||
{
|
||||
if(m==0)
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
|
||||
}
|
||||
if(owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost shared_lock owns already the mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex"));
|
||||
}
|
||||
is_locked=m->timed_lock_shared(target_time);
|
||||
return is_locked;
|
||||
@@ -677,11 +677,11 @@ namespace boost
|
||||
{
|
||||
if(m==0)
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
|
||||
}
|
||||
if(owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost shared_lock owns already the mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex"));
|
||||
}
|
||||
is_locked=m->timed_lock_shared(target_time);
|
||||
return is_locked;
|
||||
@@ -693,11 +693,11 @@ namespace boost
|
||||
{
|
||||
if(m==0)
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
|
||||
}
|
||||
if(owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost shared_lock owns already the mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex"));
|
||||
}
|
||||
is_locked=m->try_lock_shared_for(rel_time);
|
||||
return is_locked;
|
||||
@@ -707,11 +707,11 @@ namespace boost
|
||||
{
|
||||
if(m==0)
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
|
||||
}
|
||||
if(owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost shared_lock owns already the mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex"));
|
||||
}
|
||||
is_locked=m->try_lock_shared_until(abs_time);
|
||||
return is_locked;
|
||||
@@ -721,11 +721,11 @@ namespace boost
|
||||
{
|
||||
if(m==0)
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
|
||||
}
|
||||
if(!owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock doesn't own the mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock doesn't own the mutex"));
|
||||
}
|
||||
m->unlock_shared();
|
||||
is_locked=false;
|
||||
@@ -934,12 +934,12 @@ namespace boost
|
||||
if (m == 0)
|
||||
{
|
||||
boost::throw_exception(
|
||||
boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex"));
|
||||
boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
|
||||
}
|
||||
if (owns_lock())
|
||||
{
|
||||
boost::throw_exception(
|
||||
boost::lock_error(system::errc::resource_deadlock_would_occur, "boost upgrade_lock owns already the mutex"));
|
||||
boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost upgrade_lock owns already the mutex"));
|
||||
}
|
||||
m->lock_upgrade();
|
||||
is_locked = true;
|
||||
@@ -949,12 +949,12 @@ namespace boost
|
||||
if (m == 0)
|
||||
{
|
||||
boost::throw_exception(
|
||||
boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex"));
|
||||
boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
|
||||
}
|
||||
if (owns_lock())
|
||||
{
|
||||
boost::throw_exception(
|
||||
boost::lock_error(system::errc::resource_deadlock_would_occur, "boost upgrade_lock owns already the mutex"));
|
||||
boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost upgrade_lock owns already the mutex"));
|
||||
}
|
||||
is_locked = m->try_lock_upgrade();
|
||||
return is_locked;
|
||||
@@ -964,12 +964,12 @@ namespace boost
|
||||
if (m == 0)
|
||||
{
|
||||
boost::throw_exception(
|
||||
boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex"));
|
||||
boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
|
||||
}
|
||||
if (!owns_lock())
|
||||
{
|
||||
boost::throw_exception(
|
||||
boost::lock_error(system::errc::operation_not_permitted, "boost upgrade_lock doesn't own the mutex"));
|
||||
boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost upgrade_lock doesn't own the mutex"));
|
||||
}
|
||||
m->unlock_upgrade();
|
||||
is_locked = false;
|
||||
@@ -980,11 +980,11 @@ namespace boost
|
||||
{
|
||||
if(m==0)
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
|
||||
}
|
||||
if(owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost shared_lock owns already the mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex"));
|
||||
}
|
||||
is_locked=m->try_lock_upgrade_for(rel_time);
|
||||
return is_locked;
|
||||
@@ -994,11 +994,11 @@ namespace boost
|
||||
{
|
||||
if(m==0)
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
|
||||
}
|
||||
if(owns_lock())
|
||||
{
|
||||
boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost shared_lock owns already the mutex"));
|
||||
boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex"));
|
||||
}
|
||||
is_locked=m->try_lock_upgrade_until(abs_time);
|
||||
return is_locked;
|
||||
@@ -1112,6 +1112,10 @@ namespace boost
|
||||
{
|
||||
return exclusive.owns_lock();
|
||||
}
|
||||
Mutex* mutex() const BOOST_NOEXCEPT
|
||||
{
|
||||
return exclusive.mutex();
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) upgrade_to_unique_lock<Mutex> BOOST_THREAD_DCL_MOVABLE_END
|
||||
@@ -1187,7 +1191,7 @@ private unique_lock<Mutex>
|
||||
{
|
||||
return base::owns_lock();
|
||||
}
|
||||
Mutex* mutex() const
|
||||
Mutex* mutex() const BOOST_NOEXCEPT
|
||||
{
|
||||
return base::mutex();
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user