mirror of
https://github.com/boostorg/smart_ptr.git
synced 2025-10-23 04:41:40 +02:00
Compare commits
1474 Commits
boost-1.19
...
feature/pe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
02cc561248 | ||
|
|
066b398114 | ||
|
|
9c43c69c14 | ||
|
|
eb8998cd91 | ||
|
|
0ddfab493c | ||
|
|
a2732e207a | ||
|
|
5be7523ebe | ||
|
|
2320dafc03 | ||
|
|
7ab4093f46 | ||
|
|
296c203135 | ||
|
|
2dd35e5fbc | ||
|
|
977544feda | ||
|
|
54b5498208 | ||
|
|
da81452f1f | ||
|
|
7b9a969215 | ||
|
|
91cd83e5bf | ||
|
|
2fdb8c4b0a | ||
|
|
e806b53433 | ||
|
|
e0c7bd9a7e | ||
|
|
766ab05a12 | ||
|
|
05cbefd28e | ||
|
|
bfbdf4f45f | ||
|
|
169c0cd52a | ||
|
|
7d70691a16 | ||
|
|
90c27d7cfa | ||
|
|
43d1fe12c5 | ||
|
|
a2749dddb4 | ||
|
|
a71e62146c | ||
|
|
274ec17836 | ||
|
|
a7341070f1 | ||
|
|
a6323354cd | ||
|
|
f788448101 | ||
|
|
283f2d2a11 | ||
|
|
034f94617d | ||
|
|
6a5f67b3a2 | ||
|
|
dcd3c8ef80 | ||
|
|
bb2a453ff6 | ||
|
|
e56eec70ca | ||
|
|
60c26acab8 | ||
|
|
00f6b5dcb0 | ||
|
|
6195ae1eb0 | ||
|
|
30291c406a | ||
|
|
610f19f247 | ||
|
|
876d40a9ab | ||
|
|
e4d642c46a | ||
|
|
3dffa64f58 | ||
|
|
af92bd89ef | ||
|
|
4742143605 | ||
|
|
872bf10347 | ||
|
|
c0ae9b3728 | ||
|
|
1298c2e8e5 | ||
|
|
d593061b15 | ||
|
|
5072045f12 | ||
|
|
442e179920 | ||
|
|
9544a8cb91 | ||
|
|
5823d6bcc9 | ||
|
|
f56e609757 | ||
|
|
8df63a3d0e | ||
|
|
4b6cb1223b | ||
|
|
719e819570 | ||
|
|
a571b3a250 | ||
|
|
f17c5e8e3b | ||
|
|
e306b30dcf | ||
|
|
b6b49ef591 | ||
|
|
2122c7753c | ||
|
|
7c76fb385d | ||
|
|
372fac679b | ||
|
|
e3adcaed1e | ||
|
|
016e682af6 | ||
|
|
78e095d761 | ||
|
|
eb8a91cb46 | ||
|
|
513cd15378 | ||
|
|
7bfa6a1f3d | ||
|
|
8120bb44cb | ||
|
|
18974ea2db | ||
|
|
2a4aca403a | ||
|
|
4d0d81477c | ||
|
|
1725e26f70 | ||
|
|
47fffaf11c | ||
|
|
7f0323a347 | ||
|
|
6d8ea0f0c4 | ||
|
|
d10299159a | ||
|
|
adcab0e313 | ||
|
|
4fbb9ff076 | ||
|
|
8ccb36dfcf | ||
|
|
fde2e91443 | ||
|
|
aa1341a6a2 | ||
|
|
053779f3ee | ||
|
|
51d8167fbf | ||
|
|
5f95fe9848 | ||
|
|
599d0bbba9 | ||
|
|
f769217ca8 | ||
|
|
5d5d28a92e | ||
|
|
85fd341402 | ||
|
|
eac6411867 | ||
|
|
97ef7970e8 | ||
|
|
4baa21dd5e | ||
|
|
d0a89a81f0 | ||
|
|
ab2b977e4a | ||
|
|
f380d4466c | ||
|
|
2932ca4203 | ||
|
|
660d26c2c3 | ||
|
|
a095084492 | ||
|
|
a314765b94 | ||
|
|
02eba55685 | ||
|
|
9c2c991291 | ||
|
|
2e57ddb953 | ||
|
|
f6c3508aee | ||
|
|
b7cca00408 | ||
|
|
7e50abb9ec | ||
|
|
e7360779b0 | ||
|
|
456da93897 | ||
|
|
04f0847af4 | ||
|
|
29a08cdff6 | ||
|
|
6d3af760f6 | ||
|
|
a9f39d2b94 | ||
|
|
4e2f236116 | ||
|
|
4eb53db537 | ||
|
|
a2b6ba85f3 | ||
|
|
e37cd4154f | ||
|
|
8563fc5c4e | ||
|
|
67fab5c9ec | ||
|
|
f16fbdce26 | ||
|
|
c3b3835a58 | ||
|
|
d1600b8abc | ||
|
|
5885763287 | ||
|
|
9bb12692b3 | ||
|
|
773ef80f5d | ||
|
|
704de2bd67 | ||
|
|
1caa233faa | ||
|
|
605d4a2789 | ||
|
|
6ab9b93088 | ||
|
|
4129bb6a5c | ||
|
|
3b64e5ecb3 | ||
|
|
4025698fe8 | ||
|
|
2d7ab197a7 | ||
|
|
5877b08490 | ||
|
|
ffe5b46f75 | ||
|
|
4abc74fe28 | ||
|
|
12a646c607 | ||
|
|
937a3e0e93 | ||
|
|
258fa75a7e | ||
|
|
93d0d69f5e | ||
|
|
f173f9c0fb | ||
|
|
6a5942f55f | ||
|
|
293a4ee009 | ||
|
|
8e3aa3a565 | ||
|
|
78bebd5166 | ||
|
|
a47cf35b0f | ||
|
|
8d0afb670f | ||
|
|
77a35856c6 | ||
|
|
693109361e | ||
|
|
6735806863 | ||
|
|
b0dc300154 | ||
|
|
adc998469a | ||
|
|
4252ed31de | ||
|
|
279372a784 | ||
|
|
b77b7cfd62 | ||
|
|
2553a71b79 | ||
|
|
5dfcd2a6e4 | ||
|
|
6f30b395e4 | ||
|
|
014318a1ba | ||
|
|
d2c8eea08d | ||
|
|
4e0d47302b | ||
|
|
765840cd71 | ||
|
|
cb4a878fa8 | ||
|
|
57a585ed46 | ||
|
|
949338ff18 | ||
|
|
50fbbe91d8 | ||
|
|
e88227b506 | ||
|
|
410f2ce8d4 | ||
|
|
4e2e758f58 | ||
|
|
9cb8ee086f | ||
|
|
a054a570c1 | ||
|
|
219dc523ec | ||
|
|
5da882293d | ||
|
|
868a870a59 | ||
|
|
10c6233029 | ||
|
|
bcfe1be681 | ||
|
|
966786e7f9 | ||
|
|
087471a232 | ||
|
|
06bd43d5b5 | ||
|
|
1758d44e4c | ||
|
|
1c13ec0888 | ||
|
|
cc7eb56f51 | ||
|
|
eb64ae8daa | ||
|
|
a3c8c2125a | ||
|
|
3aa419463c | ||
|
|
e4ba116d7e | ||
|
|
864a0c80dd | ||
|
|
be736e5088 | ||
|
|
48294c483f | ||
|
|
13e73d6a78 | ||
|
|
20a517cc3d | ||
|
|
65d412c840 | ||
|
|
d031d4719f | ||
|
|
c1979bcaf5 | ||
|
|
0adb1fb212 | ||
|
|
7410cb1733 | ||
|
|
2d087d0003 | ||
|
|
ca7a01a593 | ||
|
|
314a6634d4 | ||
|
|
6cbc1e6775 | ||
|
|
81e1cfe301 | ||
|
|
eb8aa36854 | ||
|
|
e210c5728d | ||
|
|
4046186a2d | ||
|
|
01b73a8bfa | ||
|
|
c85abde6b0 | ||
|
|
e9523962ae | ||
|
|
4e5d067ba8 | ||
|
|
827206ec57 | ||
|
|
0cdad6421d | ||
|
|
f7f7e0183d | ||
|
|
f901988e57 | ||
|
|
22d150a1a9 | ||
|
|
fb17bf685e | ||
|
|
052ebd1946 | ||
|
|
028bb2cee8 | ||
|
|
9fe6885078 | ||
|
|
6e5a382b6b | ||
|
|
87272703c2 | ||
|
|
1c097b5764 | ||
|
|
014181e1f9 | ||
|
|
0b9547ddad | ||
|
|
b104d85d95 | ||
|
|
e92d79c0a6 | ||
|
|
2b5869882a | ||
|
|
1f86907a3d | ||
|
|
685b40cc1b | ||
|
|
dcfb8489c6 | ||
|
|
6218c52c1a | ||
|
|
c2b6e96cd7 | ||
|
|
b062d84d36 | ||
|
|
68fb786d4d | ||
|
|
f7275b7f45 | ||
|
|
edf02ab0f9 | ||
|
|
5b316e6e90 | ||
|
|
7ed8583a9c | ||
|
|
6474847481 | ||
|
|
75003f734f | ||
|
|
79e6fcdd61 | ||
|
|
4341446e04 | ||
|
|
9c18322e85 | ||
|
|
49095c3236 | ||
|
|
fff61ab5d6 | ||
|
|
aef27128f2 | ||
|
|
c1d72af0a4 | ||
|
|
0e78e219f5 | ||
|
|
2e469dd7f3 | ||
|
|
d9296befa8 | ||
|
|
f321ce404f | ||
|
|
67d897a533 | ||
|
|
e462f17c2d | ||
|
|
b8390aeffb | ||
|
|
9dafc01024 | ||
|
|
7d51c868eb | ||
|
|
0b0b7af05b | ||
|
|
7bd389c95e | ||
|
|
1cae5c5696 | ||
|
|
369fdbe38d | ||
|
|
43b37d4f28 | ||
|
|
a048cfb56d | ||
|
|
070a3a9f1a | ||
|
|
d03ef3db5c | ||
|
|
6d97c2b89e | ||
|
|
7484d4da41 | ||
|
|
2964ed2379 | ||
|
|
a7668291d2 | ||
|
|
ffc48e63d8 | ||
|
|
bcc9e50a54 | ||
|
|
8812114601 | ||
|
|
5b817ba04d | ||
|
|
6db55f7dfd | ||
|
|
61de342adc | ||
|
|
7f760526ab | ||
|
|
478a819cb5 | ||
|
|
902ca6fdf3 | ||
|
|
074882976f | ||
|
|
c1820b4a27 | ||
|
|
8096b7d324 | ||
|
|
bdcab9df47 | ||
|
|
8f99919102 | ||
|
|
27898b0823 | ||
|
|
47ee1e09e9 | ||
|
|
4dda1b5fbb | ||
|
|
585de501da | ||
|
|
420626d6d9 | ||
|
|
ab99c8f7aa | ||
|
|
0eb6ad145d | ||
|
|
1d314c5668 | ||
|
|
5b7d3c08ab | ||
|
|
f770e53989 | ||
|
|
c4d07defcd | ||
|
|
65e616c90b | ||
|
|
f90b418460 | ||
|
|
bd2474e7f3 | ||
|
|
a88d8b5b29 | ||
|
|
213c00aed7 | ||
|
|
52d976fde2 | ||
|
|
a6031ff8e2 | ||
|
|
239fe204de | ||
|
|
e75fa9329b | ||
|
|
3b16e1cc3e | ||
|
|
392b3c76f0 | ||
|
|
dea4e8129d | ||
|
|
0dfb4dad0f | ||
|
|
aec76051f8 | ||
|
|
8f2e6d04de | ||
|
|
8d9c4df71a | ||
|
|
b18f68324f | ||
|
|
aeadd6aeff | ||
|
|
3c47079f4d | ||
|
|
ca9cb71e86 | ||
|
|
ba98b8c33f | ||
|
|
3160cbb2e3 | ||
|
|
bfa3752ad7 | ||
|
|
e9010baaf5 | ||
|
|
b530ffcae5 | ||
|
|
7f42d987e7 | ||
|
|
469015992a | ||
|
|
33b18c7da0 | ||
|
|
596adfc69a | ||
|
|
e99e722fa5 | ||
|
|
7ef8fa4a19 | ||
|
|
9081dc5573 | ||
|
|
0043228495 | ||
|
|
6bdd3fde65 | ||
|
|
3568e093bb | ||
|
|
acb29ad6f3 | ||
|
|
d2c1ed0ed5 | ||
|
|
0085752a56 | ||
|
|
d7ad42724d | ||
|
|
83d3f07b0d | ||
|
|
994f39f9b0 | ||
|
|
f45dd4d955 | ||
|
|
b4abcdb016 | ||
|
|
25cf644f60 | ||
|
|
71ef7850ab | ||
|
|
40c0ddcbd6 | ||
|
|
687d31b7c8 | ||
|
|
fac6fbe3cf | ||
|
|
d3b9ee7d24 | ||
|
|
650537da60 | ||
|
|
324347b9ec | ||
|
|
79e675c727 | ||
|
|
6ef791c715 | ||
|
|
15ed558a29 | ||
|
|
106ada7770 | ||
|
|
9f70f6619f | ||
|
|
494c0cd2c0 | ||
|
|
8c058dfeee | ||
|
|
0807efa91a | ||
|
|
bea0fc4a37 | ||
|
|
3f21bac34f | ||
|
|
7beb91fd0e | ||
|
|
d1bb87d34e | ||
|
|
7570340d70 | ||
|
|
b42acf77b3 | ||
|
|
1f9c63c34f | ||
|
|
f8524c42a8 | ||
|
|
52fbf70879 | ||
|
|
fb59cd574e | ||
|
|
c749052162 | ||
|
|
970e88897c | ||
|
|
609de5d711 | ||
|
|
d641b9c436 | ||
|
|
3bb4e4d2df | ||
|
|
5ab9a77d50 | ||
|
|
b80ffbeb3d | ||
|
|
5f8c2a7ee0 | ||
|
|
94634cb853 | ||
|
|
17a07a228e | ||
|
|
d4bc4c9733 | ||
|
|
1d7f6b9bfd | ||
|
|
d718d21d6b | ||
|
|
39b14fa0d6 | ||
|
|
19147212a9 | ||
|
|
53928bcc12 | ||
|
|
9e568dad6e | ||
|
|
ebd1788f2c | ||
|
|
3e2ac10e94 | ||
|
|
61075bb9df | ||
|
|
3e61a63f60 | ||
|
|
a7fbb0a841 | ||
|
|
1e9e2ed6aa | ||
|
|
bdc19dee01 | ||
|
|
3aa720714d | ||
|
|
94a04e57fb | ||
|
|
776b33ec09 | ||
|
|
5595622c3e | ||
|
|
2ae3e4ba44 | ||
|
|
b5498d944e | ||
|
|
8fac3c9f2f | ||
|
|
a14515a364 | ||
|
|
190c06e25d | ||
|
|
62a8a9d6cc | ||
|
|
48401806f4 | ||
|
|
02de302774 | ||
|
|
80597b379e | ||
|
|
840e9fc96e | ||
|
|
70367e848e | ||
|
|
e8daeaee1c | ||
|
|
3b9ae9fd5f | ||
|
|
20fedcff2c | ||
|
|
de38a735ea | ||
|
|
ce52fb1045 | ||
|
|
6b787f1cec | ||
|
|
2185c4f005 | ||
|
|
6d5f554baa | ||
|
|
f3279d24b4 | ||
|
|
c87b6e8af8 | ||
|
|
aaded4f85c | ||
|
|
eb1a002e34 | ||
|
|
3304a56101 | ||
|
|
181f38682f | ||
|
|
5b1a8412c3 | ||
|
|
e52905cf3c | ||
|
|
b7f99ceba6 | ||
|
|
a7ade6f062 | ||
|
|
097d2e9bf9 | ||
|
|
d44a78d671 | ||
|
|
582eb63cb3 | ||
|
|
181b449a57 | ||
|
|
da8de3e95b | ||
|
|
6c27833099 | ||
|
|
83e6e00456 | ||
|
|
522f6c1869 | ||
|
|
cd8de9d4a6 | ||
|
|
e26542272d | ||
|
|
e13beef5df | ||
|
|
8298952a12 | ||
|
|
821925c536 | ||
|
|
427124543b | ||
|
|
46f00ea993 | ||
|
|
4473bf8ec2 | ||
|
|
7a7ac4512e | ||
|
|
38b6334e36 | ||
|
|
7af503d3bb | ||
|
|
4db7219c32 | ||
|
|
3f17244225 | ||
|
|
ca93749614 | ||
|
|
05d5a4e9a0 | ||
|
|
970a179ac2 | ||
|
|
a06123eb87 | ||
|
|
fd543d3292 | ||
|
|
df90496583 | ||
|
|
20ead68473 | ||
|
|
79cde147c9 | ||
|
|
abbe975e8f | ||
|
|
8ba0730686 | ||
|
|
686efe100b | ||
|
|
acb880d8c2 | ||
|
|
1712b87cb6 | ||
|
|
f8943703f8 | ||
|
|
a42dda0af4 | ||
|
|
9b9b6d3ca6 | ||
|
|
d875a68ceb | ||
|
|
8cb2c56556 | ||
|
|
290fe82a43 | ||
|
|
94824c807f | ||
|
|
334654de06 | ||
|
|
0ab0e6eecc | ||
|
|
effc9f73d6 | ||
|
|
99762e7dde | ||
|
|
add539142b | ||
|
|
e067fd2cfd | ||
|
|
212528860a | ||
|
|
711c36958a | ||
|
|
7104e7dc7e | ||
|
|
254bda34b7 | ||
|
|
3fd53ced83 | ||
|
|
75de3dbcf1 | ||
|
|
7faec4265b | ||
|
|
c81d0806e4 | ||
|
|
a74329794c | ||
|
|
71756350d9 | ||
|
|
f65c57d9d2 | ||
|
|
b1fc261fe6 | ||
|
|
aedcf3ccda | ||
|
|
a1a5999a38 | ||
|
|
8afd3bee69 | ||
|
|
2a56c73924 | ||
|
|
720ce12a25 | ||
|
|
2be09db523 | ||
|
|
de10be8560 | ||
|
|
7b71068b52 | ||
|
|
6b562cb5b1 | ||
|
|
3d2c230623 | ||
|
|
553c7994ba | ||
|
|
280aadfcdb | ||
|
|
59ac922a1c | ||
|
|
8de3e84021 | ||
|
|
bd4f9c239a | ||
|
|
528195233b | ||
|
|
8c49f5a637 | ||
|
|
0bab2cc658 | ||
|
|
88f0a98d71 | ||
|
|
96d82e0275 | ||
|
|
40387ef654 | ||
|
|
d28b0d07fc | ||
|
|
1c83d65701 | ||
|
|
1d41a328f7 | ||
|
|
b1beb11a45 | ||
|
|
bf3e9cc7af | ||
|
|
506239bef5 | ||
|
|
d6841e6d71 | ||
|
|
56ae9f86c1 | ||
|
|
1a74757cfa | ||
|
|
07e222217b | ||
|
|
71c9165119 | ||
|
|
f32669400c | ||
|
|
b550e028f5 | ||
|
|
ed2eaddc5d | ||
|
|
d523c3423e | ||
|
|
1968d17d2f | ||
|
|
e1e99c5ba3 | ||
|
|
d586469d60 | ||
|
|
fbb851097f | ||
|
|
75add10b1d | ||
|
|
71b2f87e35 | ||
|
|
c759321782 | ||
|
|
3e625c07e8 | ||
|
|
7ff1c65494 | ||
|
|
75cab39801 | ||
|
|
38cb523713 | ||
|
|
5f1d4eae4f | ||
|
|
adc0cdddff | ||
|
|
dcfa031de7 | ||
|
|
8c9e8b5556 | ||
|
|
d9333e5375 | ||
|
|
3d279e6c6d | ||
|
|
c003fba3a0 | ||
|
|
0c29e86728 | ||
|
|
016af907bd | ||
|
|
0337743c8c | ||
|
|
208bfd78f9 | ||
|
|
2c32bf91b7 | ||
|
|
b7ee788845 | ||
|
|
a56378ee35 | ||
|
|
443302306e | ||
|
|
f5402a937e | ||
|
|
fe04bea979 | ||
|
|
8fbb5e9e7f | ||
|
|
0401afc106 | ||
|
|
b69ca7aaa5 | ||
|
|
dffbf7c931 | ||
|
|
5dabdf635c | ||
|
|
3dbde36076 | ||
|
|
97a9aac5f0 | ||
|
|
bd5b684fd3 | ||
|
|
6ede4ec4c6 | ||
|
|
aab1328e06 | ||
|
|
451c71c1bd | ||
|
|
6341b8802a | ||
|
|
e274885fd2 | ||
|
|
82fe5f5095 | ||
|
|
8c50214e3f | ||
|
|
21198d07fd | ||
|
|
b4c8cf3958 | ||
|
|
77aeaee7a7 | ||
|
|
677a0777d2 | ||
|
|
7c7250379b | ||
|
|
142eb95986 | ||
|
|
d9f24f882e | ||
|
|
0fd3947e19 | ||
|
|
43bc30e576 | ||
|
|
e0ec2a0aaa | ||
|
|
5320981cbb | ||
|
|
d676bac36a | ||
|
|
ec1c6ed414 | ||
|
|
ce36b11fd5 | ||
|
|
eee70bdcab | ||
|
|
97eed20d9b | ||
|
|
6b6b63ef37 | ||
|
|
1bdabdb96b | ||
|
|
0876e67ac7 | ||
|
|
fdcb2572a3 | ||
|
|
71d99e89e9 | ||
|
|
2dc506f4bc | ||
|
|
7161dc5842 | ||
|
|
ec97270c01 | ||
|
|
b7a759f00f | ||
|
|
4f2392ffa5 | ||
|
|
80a06c8883 | ||
|
|
d0a458616f | ||
|
|
def81b1941 | ||
|
|
4f276715ce | ||
|
|
a47bbfe95c | ||
|
|
90fe855f1b | ||
|
|
991436303d | ||
|
|
b274ed4cc3 | ||
|
|
870a989fcf | ||
|
|
5f7a5a5912 | ||
|
|
82db88f4fa | ||
|
|
c8df85434e | ||
|
|
68517b43bd | ||
|
|
72ac0e8bfd | ||
|
|
6c7578e206 | ||
|
|
3149446fe8 | ||
|
|
b11d734f73 | ||
|
|
6f5f8babf4 | ||
|
|
7d7f32c3a9 | ||
|
|
cb697fe9cb | ||
|
|
8422135bf2 | ||
|
|
fd60899dfb | ||
|
|
a11ab16010 | ||
|
|
9b9cad3f5b | ||
|
|
7ce5b6b2a9 | ||
|
|
7e3ae44bc2 | ||
|
|
57dc400fbf | ||
|
|
5f485c2952 | ||
|
|
260af64027 | ||
|
|
f837c7f56c | ||
|
|
54fb49a5be | ||
|
|
c23bd41c44 | ||
|
|
a64cc5c41c | ||
|
|
e1f170cd49 | ||
|
|
52a5c422a1 | ||
|
|
d46e3c7cbd | ||
|
|
5008957bd0 | ||
|
|
6d73b4aa54 | ||
|
|
540149f019 | ||
|
|
9f5822f427 | ||
|
|
d229ae870c | ||
|
|
3ac6dbbf08 | ||
|
|
af5141d492 | ||
|
|
975d04ac62 | ||
|
|
90e74511f7 | ||
|
|
f27b780724 | ||
|
|
51ab46a07d | ||
|
|
e8595a05af | ||
|
|
154a274916 | ||
|
|
2b033ce05d | ||
|
|
63a05a3576 | ||
|
|
aede0039bf | ||
|
|
72e5fb6fd7 | ||
|
|
f91e7e9ce7 | ||
|
|
7fef3bb40b | ||
|
|
ad658fa5ec | ||
|
|
83b3b703e0 | ||
|
|
7806737b52 | ||
|
|
87e5debdc2 | ||
|
|
db78d9b2be | ||
|
|
630e4f49f3 | ||
|
|
a68db557e8 | ||
|
|
4de3f36839 | ||
|
|
4e46cb0609 | ||
|
|
73153d5797 | ||
|
|
d7fa365843 | ||
|
|
6e0ee30543 | ||
|
|
fed15ad8c5 | ||
|
|
bba3b446bd | ||
|
|
4c8a558982 | ||
|
|
a41b81f1c8 | ||
|
|
c103ace77a | ||
|
|
04f456f86d | ||
|
|
3a188af8d6 | ||
|
|
b701ed0225 | ||
|
|
5e9bb19688 | ||
|
|
a4f853bfbc | ||
|
|
832ed079b9 | ||
|
|
d9b29beebe | ||
|
|
182452e057 | ||
|
|
5f69684c8f | ||
|
|
70ffd2921f | ||
|
|
00aee2c7dc | ||
|
|
85d8056368 | ||
|
|
106832df66 | ||
|
|
2549b818c5 | ||
|
|
be06392771 | ||
|
|
56b0853887 | ||
|
|
f5e6e4063e | ||
|
|
8767b9580e | ||
|
|
0e6ddb843e | ||
|
|
14be9eb90f | ||
|
|
fa91b7d020 | ||
|
|
382fb54a52 | ||
|
|
e4f24e4d3d | ||
|
|
7d1c527ac0 | ||
|
|
fc20a29c99 | ||
|
|
0dc1faa6d3 | ||
|
|
7b9354fcf3 | ||
|
|
a7d96b4762 | ||
|
|
6eefc6bf81 | ||
|
|
172afff6ca | ||
|
|
9355404d10 | ||
|
|
d61e675caf | ||
|
|
240c66e633 | ||
|
|
6df3a0295e | ||
|
|
e497aec58a | ||
|
|
2d56e85174 | ||
|
|
579b347267 | ||
|
|
82e178f043 | ||
|
|
3178d38137 | ||
|
|
46d119c385 | ||
|
|
e39fcad839 | ||
|
|
e5950adc43 | ||
|
|
de6dc3a26e | ||
|
|
06c4dacaf2 | ||
|
|
72095a4804 | ||
|
|
dcc1713c59 | ||
|
|
32a28ec462 | ||
|
|
f6d5257597 | ||
|
|
ef817e91d2 | ||
|
|
43b43aa83a | ||
|
|
d3a549e93a | ||
|
|
e8be24c003 | ||
|
|
c55ffa1cab | ||
|
|
66f34142be | ||
|
|
63834f7233 | ||
|
|
049d0698b7 | ||
|
|
5ba3312519 | ||
|
|
bb700870c0 | ||
|
|
6a218a5ef2 | ||
|
|
e36689bd5e | ||
|
|
1c070b3a32 | ||
|
|
647f67aabf | ||
|
|
c14369aac9 | ||
|
|
7ab4f6ce92 | ||
|
|
bbf0245248 | ||
|
|
619b168614 | ||
|
|
4ba8d879f1 | ||
|
|
c28bef2e9b | ||
|
|
5f0155cca6 | ||
|
|
db542de908 | ||
|
|
5fc6fe474b | ||
|
|
d42ce87557 | ||
|
|
67f5e9825e | ||
|
|
fd52dbc411 | ||
|
|
6e269872df | ||
|
|
ecceb710de | ||
|
|
9863467152 | ||
|
|
b306c9751f | ||
|
|
6b0d96af96 | ||
|
|
c03bfd0b4d | ||
|
|
8093967da7 | ||
|
|
7a4ad75f5d | ||
|
|
f390d9e265 | ||
|
|
ea22982865 | ||
|
|
09e77bc8df | ||
|
|
b3f2ebedbc | ||
|
|
1209531fe0 | ||
|
|
6c2ed927e4 | ||
|
|
7a733263da | ||
|
|
08e5894510 | ||
|
|
3551d17566 | ||
|
|
32fe0b8f26 | ||
|
|
2d3cc0db7d | ||
|
|
188602581d | ||
|
|
88c2baa20b | ||
|
|
1adf546ddb | ||
|
|
5e5ff387fa | ||
|
|
ea55019260 | ||
|
|
500913db6d | ||
|
|
19283a3548 | ||
|
|
cfd4152291 | ||
|
|
f5adfb0963 | ||
|
|
8597433028 | ||
|
|
4da0e2b7fc | ||
|
|
2346941b15 | ||
|
|
39ff002d2e | ||
|
|
fceea2e584 | ||
|
|
b17205ded7 | ||
|
|
d74c09dd5a | ||
|
|
97d32745aa | ||
|
|
c7b6e56b30 | ||
|
|
7835914d83 | ||
|
|
98b92fa83a | ||
|
|
392885a56a | ||
|
|
b4594eab3b | ||
|
|
ddfcc5f417 | ||
|
|
3f458c68f4 | ||
|
|
79b229adcd | ||
|
|
94b6487ca1 | ||
|
|
cf769b94a7 | ||
|
|
215771c83d | ||
|
|
2805ae9362 | ||
|
|
7adb1cc1ec | ||
|
|
da9524d637 | ||
|
|
6b2556edfb | ||
|
|
cb0797acf0 | ||
|
|
e8103f9774 | ||
|
|
71eb435412 | ||
|
|
4a2dad1574 | ||
|
|
babc72757d | ||
|
|
c19cbc1892 | ||
|
|
d065e4d971 | ||
|
|
777b86a661 | ||
|
|
aae5440854 | ||
|
|
227d2e3255 | ||
|
|
8bf183b373 | ||
|
|
5017da2514 | ||
|
|
3b0b10d06d | ||
|
|
25e11b20d3 | ||
|
|
fa513340d7 | ||
|
|
0e90213746 | ||
|
|
980070e63f | ||
|
|
5bdde37414 | ||
|
|
2aaa913b11 | ||
|
|
58a46f4e55 | ||
|
|
8cc50a5ce9 | ||
|
|
2731957b5b | ||
|
|
fe06c120b9 | ||
|
|
c1f41aa925 | ||
|
|
ffa3327817 | ||
|
|
999c284109 | ||
|
|
d512eaaa0f | ||
|
|
730980f3ee | ||
|
|
3d50db11b9 | ||
|
|
aa7562c3e5 | ||
|
|
c57245d710 | ||
|
|
945c013a12 | ||
|
|
df544871d7 | ||
|
|
89190ca17e | ||
|
|
5d9312239c | ||
|
|
93b5cace12 | ||
|
|
e50c849ab3 | ||
|
|
dbea328b8b | ||
|
|
c06ba497a3 | ||
|
|
734b5d1354 | ||
|
|
0467af1b83 | ||
|
|
dc5406aa5a | ||
|
|
6e873de0fa | ||
|
|
322bcd7efa | ||
|
|
bb72e0a092 | ||
|
|
d8eb2fc105 | ||
|
|
e7d3987cfb | ||
|
|
6662ae7242 | ||
|
|
2ba7b6b99b | ||
|
|
a30e291022 | ||
|
|
0b6cab9f2f | ||
|
|
8c15401ea7 | ||
|
|
03ae5cdbc6 | ||
|
|
0c22e55f3e | ||
|
|
10dcb8db7c | ||
|
|
f2d4b67a48 | ||
|
|
16084637a6 | ||
|
|
3e447c919c | ||
|
|
b0f72d7b3d | ||
|
|
4c98df7c57 | ||
|
|
c2048732d8 | ||
|
|
5979c1d4bd | ||
|
|
1029ae0ea5 | ||
|
|
27a312228c | ||
|
|
3090f6f4af | ||
|
|
2c29f1e5a9 | ||
|
|
40073ef64f | ||
|
|
b9970eda45 | ||
|
|
df364f37f2 | ||
|
|
9147489b4c | ||
|
|
33ba2c4722 | ||
|
|
d1348ea05e | ||
|
|
faf212f4aa | ||
|
|
57a5441ebf | ||
|
|
90db9a6435 | ||
|
|
017ab7e2ee | ||
|
|
1c208ad3ea | ||
|
|
5fc9bf5bc5 | ||
|
|
c846d230f0 | ||
|
|
e4cb5e131f | ||
|
|
fbe4ddf4a2 | ||
|
|
288fb7efcf | ||
|
|
7b097467d6 | ||
|
|
9d9e6350f2 | ||
|
|
7cb040edb0 | ||
|
|
d6ac116b71 | ||
|
|
7e9664396a | ||
|
|
b4b415553c | ||
|
|
f76a8d95d8 | ||
|
|
8abc8889d1 | ||
|
|
c5b47e2136 | ||
|
|
7c0815c567 | ||
|
|
210288f02e | ||
|
|
cf7b6904e8 | ||
|
|
b978919dd1 | ||
|
|
1086aff971 | ||
|
|
445e8d1728 | ||
|
|
545745d649 | ||
|
|
634866c28a | ||
|
|
b18b47770d | ||
|
|
69aa01ec00 | ||
|
|
e3d2f2ee6b | ||
|
|
593093e46d | ||
|
|
9196247dea | ||
|
|
53d5d086ea | ||
|
|
1426b0bbdd | ||
|
|
4fabf9b352 | ||
|
|
a2fc6e12da | ||
|
|
c3b51e201b | ||
|
|
d71cc6ab08 | ||
|
|
825786d59a | ||
|
|
37f10d500d | ||
|
|
0d77fd0678 | ||
|
|
6ca6d3ce6f | ||
|
|
cfc82854d3 | ||
|
|
3c84388186 | ||
|
|
a46d405778 | ||
|
|
2e53b1eb38 | ||
|
|
b9d77d877e | ||
|
|
1f50e3abe4 | ||
|
|
37c9a235a5 | ||
|
|
7083e76666 | ||
|
|
7aac2f3263 | ||
|
|
458dffdab9 | ||
|
|
697f338510 | ||
|
|
f7919f0b9f | ||
|
|
f4386409d9 | ||
|
|
ae34be773f | ||
|
|
1b91c1dbea | ||
|
|
ba349679f3 | ||
|
|
577528812a | ||
|
|
e78efdbb96 | ||
|
|
a3b84f8586 | ||
|
|
3824a6b156 | ||
|
|
b0fd8a6b08 | ||
|
|
4f5062004a | ||
|
|
f040bed751 | ||
|
|
2f8945a885 | ||
|
|
2bd0778778 | ||
|
|
eec640bfd7 | ||
|
|
754fd941ee | ||
|
|
b691be0af9 | ||
|
|
fa597b877e | ||
|
|
d0a9d76494 | ||
|
|
979e76b7e0 | ||
|
|
c97eebabf7 | ||
|
|
030a848c5f | ||
|
|
18bfaea996 | ||
|
|
502de325ee | ||
|
|
9f49538b37 | ||
|
|
2ee5eb70f3 | ||
|
|
32eb028e13 | ||
|
|
e824e23ec2 | ||
|
|
e94f64039d | ||
|
|
63b17c24ea | ||
|
|
f5cc79f58d | ||
|
|
8a421c2098 | ||
|
|
28d7e348c1 | ||
|
|
5fa1cbf6e1 | ||
|
|
fc12543814 | ||
|
|
9f30442d1e | ||
|
|
a4293f9dfa | ||
|
|
4b4a62513f | ||
|
|
0368a37fde | ||
|
|
28de0cb1e3 | ||
|
|
3dacec8e1d | ||
|
|
a1b4fc8d95 | ||
|
|
5758e51948 | ||
|
|
287d329276 | ||
|
|
d34d638998 | ||
|
|
6f2bdddfa0 | ||
|
|
9227371881 | ||
|
|
e88dd9fc77 | ||
|
|
77971c6ff5 | ||
|
|
1742c37942 | ||
|
|
fa3c56747d | ||
|
|
fbc6919eae | ||
|
|
31e06b4a1d | ||
|
|
dc3ffc5f4b | ||
|
|
0610947c4a | ||
|
|
22f1b092c9 | ||
|
|
9c55fbc6c2 | ||
|
|
5a2771e585 | ||
|
|
dad59f3325 | ||
|
|
bad394b1e9 | ||
|
|
f93110620a | ||
|
|
6be1e3fceb | ||
|
|
cf91287732 | ||
|
|
68c939ec5a | ||
|
|
a378c8c278 | ||
|
|
905a3711db | ||
|
|
ed32efcc51 | ||
|
|
eb0ff40d62 | ||
|
|
ad1b344405 | ||
|
|
0da6902267 | ||
|
|
10f6ff8b77 | ||
|
|
13f91c15f0 | ||
|
|
a2c5208b8e | ||
|
|
55583ac749 | ||
|
|
c40b306647 | ||
|
|
d9b9921d23 | ||
|
|
6f91ea87c3 | ||
|
|
ed79000ea8 | ||
|
|
6e804e64b8 | ||
|
|
395766e2d3 | ||
|
|
774332f85a | ||
|
|
f5990cab65 | ||
|
|
6175baf858 | ||
|
|
2fb567b3f2 | ||
|
|
2b25579338 | ||
|
|
a97cd2d0cc | ||
|
|
e3b9389a24 | ||
|
|
6ba78f76f6 | ||
|
|
8c7954a53a | ||
|
|
556b9fe563 | ||
|
|
77ab953171 | ||
|
|
991b02b03e | ||
|
|
31d0c48f18 | ||
|
|
1b49f08cb8 | ||
|
|
034c12d244 | ||
|
|
f884c53bd6 | ||
|
|
07b4c17980 | ||
|
|
1bc4f16ff8 | ||
|
|
774a8d330c | ||
|
|
0fd94d6d56 | ||
|
|
866590ee97 | ||
|
|
2a92df56f2 | ||
|
|
a9cd84f43d | ||
|
|
366472fc35 | ||
|
|
2bfe13c9c4 | ||
|
|
83e2510ce5 | ||
|
|
31685fe551 | ||
|
|
05e050abe0 | ||
|
|
d261079616 | ||
|
|
d52878df88 | ||
|
|
4b0490c0ae | ||
|
|
2f1b1acc7a | ||
|
|
f0f9f72be6 | ||
|
|
efdc390bc9 | ||
|
|
d13f1d8694 | ||
|
|
83c43617af | ||
|
|
da323af72d | ||
|
|
0c4aaef77c | ||
|
|
440fcb7ba0 | ||
|
|
18a6c1add8 | ||
|
|
357d3c4d54 | ||
|
|
4bb747fb27 | ||
|
|
f13591ef2b | ||
|
|
e3422efec6 | ||
|
|
a01e4c3f83 | ||
|
|
6f8dc5923c | ||
|
|
7dc6b3d810 | ||
|
|
2251b1d2df | ||
|
|
8b3907ae81 | ||
|
|
77f2d3f614 | ||
|
|
93545d5cf2 | ||
|
|
9e92c6354c | ||
|
|
e12ed6864b | ||
|
|
b541145a60 | ||
|
|
ca344809ba | ||
|
|
7802c695ef | ||
|
|
71fa2cd658 | ||
|
|
04be979670 | ||
|
|
35f2af947c | ||
|
|
3a578ac7c1 | ||
|
|
9365853fde | ||
|
|
16828c9c0a | ||
|
|
2fe899cdfe | ||
|
|
b45d011d5a | ||
|
|
4094c23537 | ||
|
|
f85a1bf406 | ||
|
|
dbd62686a3 | ||
|
|
e4f638025c | ||
|
|
d8296b3933 | ||
|
|
b4885a1dd6 | ||
|
|
748b1baee8 | ||
|
|
4880292c07 | ||
|
|
6b25c57712 | ||
|
|
373c52efa3 | ||
|
|
acb6824ef7 | ||
|
|
316d00c3fc | ||
|
|
515be965bd | ||
|
|
6ef32e1627 | ||
|
|
2452705117 | ||
|
|
bb076d67e6 | ||
|
|
b08789b784 | ||
|
|
5df69a8946 | ||
|
|
dc6a8f0696 | ||
|
|
af7d4fabad | ||
|
|
d17a096407 | ||
|
|
d7448b5746 | ||
|
|
f22516d650 | ||
|
|
b30aa1468a | ||
|
|
5b17f88f0e | ||
|
|
1c2d780f9e | ||
|
|
2eb3991630 | ||
|
|
3a4dc43924 | ||
|
|
a055d9829e | ||
|
|
f596092bac | ||
|
|
4ba016d29e | ||
|
|
7ca6d86bdc | ||
|
|
b2a3c9e59d | ||
|
|
60ae24f4ae | ||
|
|
dba6ebbb01 | ||
|
|
d2194e3b24 | ||
|
|
5ab6b24856 | ||
|
|
e6f6ec9fa3 | ||
|
|
f854829d86 | ||
|
|
7b5beeedde | ||
|
|
9e41d1f194 | ||
|
|
f49a2fb1e1 | ||
|
|
87c6b6b403 | ||
|
|
9db307eda5 | ||
|
|
5a85c1f0f2 | ||
|
|
f5ce4dbc4c | ||
|
|
b2354d0a5e | ||
|
|
e0ca42bb88 | ||
|
|
bca336bf35 | ||
|
|
6646d8acd2 | ||
|
|
c66f0aeecc | ||
|
|
ecb41cb150 | ||
|
|
ed8db8b5f2 | ||
|
|
4ba37fce95 | ||
|
|
94db735438 | ||
|
|
5b57eff9b8 | ||
|
|
f980da560a | ||
|
|
ffba68221b | ||
|
|
4d45e5b9b5 | ||
|
|
86d3f0aba7 | ||
|
|
66a25bd4a9 | ||
|
|
745dbedbaa | ||
|
|
26f83e75ef | ||
|
|
ce72827dc7 | ||
|
|
6e8f075d42 | ||
|
|
ae6c180be8 | ||
|
|
54e12d03fd | ||
|
|
469578e976 | ||
|
|
97118668e2 | ||
|
|
1c3813ce52 | ||
|
|
b440e85452 | ||
|
|
d889751bc0 | ||
|
|
0609322489 | ||
|
|
b215e34650 | ||
|
|
2f70e81b73 | ||
|
|
6284a1abef | ||
|
|
c464a07ab1 | ||
|
|
41d4167533 | ||
|
|
4a98c2931c | ||
|
|
75bc821afd | ||
|
|
ebc0af9147 | ||
|
|
db0969d97b | ||
|
|
39551bdc1a | ||
|
|
6412de1dd5 | ||
|
|
8d2f7fc5ef | ||
|
|
7c477960d3 | ||
|
|
7e5d7011e6 | ||
|
|
ffd73c39b3 | ||
|
|
4fcee64483 | ||
|
|
75cd88112c | ||
|
|
203764eb51 | ||
|
|
6e120f4bf1 | ||
|
|
747c9a1d3e | ||
|
|
7ce5b55f5c | ||
|
|
e38d0daaab | ||
|
|
f3e94d8ca0 | ||
|
|
c36e023162 | ||
|
|
00f744bf1e | ||
|
|
24d1e6f8dd | ||
|
|
ae0a48d544 | ||
|
|
e427716dc2 | ||
|
|
8c256502cc | ||
|
|
a86b2f7fbf | ||
|
|
a196f39cd0 | ||
|
|
90b5a3736a | ||
|
|
2d25f8f036 | ||
|
|
3771707bb7 | ||
|
|
239bb6d966 | ||
|
|
25ca855127 | ||
|
|
0127c06692 | ||
|
|
9edd3beebc | ||
|
|
92a027fbeb | ||
|
|
7880720bc1 | ||
|
|
235994873f | ||
|
|
7bfddbccf6 | ||
|
|
c6a4e93a05 | ||
|
|
ff7e027648 | ||
|
|
08f517b5b0 | ||
|
|
6b3f961542 | ||
|
|
0db2a88403 | ||
|
|
afc17037de | ||
|
|
0cee41d47e | ||
|
|
eb3d3464db | ||
|
|
8d2aeea3a8 | ||
|
|
675d09723a | ||
|
|
24c23b8064 | ||
|
|
880c2e1062 | ||
|
|
357f57d147 | ||
|
|
8bacee46eb | ||
|
|
4e4ec29fc9 | ||
|
|
df1d8b27df | ||
|
|
76722e125f | ||
|
|
d24f6d3b97 | ||
|
|
6ab6b66601 | ||
|
|
559056c856 | ||
|
|
13c128f98f | ||
|
|
3ebc9b8f0b | ||
|
|
361a7c3fd0 | ||
|
|
faa675ad6a | ||
|
|
319836fe78 | ||
|
|
d0656015ad | ||
|
|
f1a9148a43 | ||
|
|
1942b64751 | ||
|
|
a0eb5daf75 | ||
|
|
6046a099ba | ||
|
|
e0ee037e2d | ||
|
|
13657c8bda | ||
|
|
52587aaa05 | ||
|
|
0669d41076 | ||
|
|
8f2beee8e9 | ||
|
|
3adfc7842c | ||
|
|
613e684b30 | ||
|
|
bfc0225cda | ||
|
|
a67e505cf5 | ||
|
|
adec862262 | ||
|
|
c6bf857f8b | ||
|
|
14024e2598 | ||
|
|
34953d8a45 | ||
|
|
09a0ba8c75 | ||
|
|
b0eb65b433 | ||
|
|
c830315dff | ||
|
|
b07447aa6e | ||
|
|
42a739b357 | ||
|
|
7d59d29ad1 | ||
|
|
5616a1a872 | ||
|
|
e5c1e12a66 | ||
|
|
8f317492ee | ||
|
|
c81be1e2e7 | ||
|
|
1bc58ea861 | ||
|
|
27be736b8f | ||
|
|
ef51f6a1de | ||
|
|
6b00a55542 | ||
|
|
858cefbfe8 | ||
|
|
c7abff0099 | ||
|
|
cb6cb636f7 | ||
|
|
366d2666d4 | ||
|
|
9c67a59d43 | ||
|
|
7361e476b8 | ||
|
|
e1bd18f6a6 | ||
|
|
1346982b80 | ||
|
|
c48f05dcb4 | ||
|
|
53cc52127b | ||
|
|
7fb399b3bb | ||
|
|
93d69af60a | ||
|
|
09c8685181 | ||
|
|
15d6b2aace | ||
|
|
feff6e40ea | ||
|
|
26a93f224e | ||
|
|
96f572b19b | ||
|
|
d6c4633e89 | ||
|
|
106a6d58d4 | ||
|
|
debd953d8f | ||
|
|
f2c5439644 | ||
|
|
b4ec0e90fb | ||
|
|
2d4eb92401 | ||
|
|
192970b3b8 | ||
|
|
7c36a640ae | ||
|
|
794de98cd1 | ||
|
|
dcdbaf1e57 | ||
|
|
6dbec7621d | ||
|
|
889cb6bee6 | ||
|
|
11cddbbb45 | ||
|
|
77c629b6e4 | ||
|
|
d091ee85c0 | ||
|
|
bc00d5fa1a | ||
|
|
e760759414 | ||
|
|
deab8ca1bb | ||
|
|
300f8f7b9a | ||
|
|
d7c841484a | ||
|
|
f4dce1cb88 | ||
|
|
b400d34bec | ||
|
|
8f0bdd48f8 | ||
|
|
6d6bcc7be9 | ||
|
|
851d87a1bb | ||
|
|
34f423f811 | ||
|
|
190893a1ce | ||
|
|
4244992d4d | ||
|
|
4b502993b5 | ||
|
|
a24ec3988a | ||
|
|
23f7532a9f | ||
|
|
a790191bc5 | ||
|
|
86e9a322ba | ||
|
|
98fa979aef | ||
|
|
be0267f9a3 | ||
|
|
44afc7e5cd | ||
|
|
d2c7febd26 | ||
|
|
ddf1f0fdcc | ||
|
|
cd41426fe9 | ||
|
|
89ea2156bc | ||
|
|
fabd6e5755 | ||
|
|
b60de38d28 | ||
|
|
2dbfc89d4e | ||
|
|
abb0d9e725 | ||
|
|
d030182e87 | ||
|
|
bd39e2eded | ||
|
|
d04757128c | ||
|
|
868062e81d | ||
|
|
6bd66fe054 | ||
|
|
c5bae28eeb | ||
|
|
78a47d7619 | ||
|
|
8eaf187dbd | ||
|
|
d36a215554 | ||
|
|
8448bbf0b9 | ||
|
|
1dee6e0229 | ||
|
|
e3f2329c14 | ||
|
|
3e616752c9 | ||
|
|
987a7d32fb | ||
|
|
fafd9a863b | ||
|
|
51e9783a21 | ||
|
|
eee96e8059 | ||
|
|
1ef2a5b059 | ||
|
|
c5f7c973d9 | ||
|
|
572a97d3c4 | ||
|
|
a3d87ff623 | ||
|
|
468f63261a | ||
|
|
e60c1f9b49 | ||
|
|
72bcb8ff46 | ||
|
|
12b1871136 | ||
|
|
9632464c45 | ||
|
|
1311731e24 | ||
|
|
980307a90a | ||
|
|
1f9908be69 | ||
|
|
0aaca2fffe | ||
|
|
5dd2c62132 | ||
|
|
fadc0716ce | ||
|
|
ea285b4231 | ||
|
|
8d6517484c | ||
|
|
66a8e8b3c1 | ||
|
|
c697e2ef21 | ||
|
|
2e53e2e5d7 | ||
|
|
8283ec826b | ||
|
|
e32b2adfda | ||
|
|
e555d33695 | ||
|
|
de68e6ed1e | ||
|
|
804b1483c7 | ||
|
|
4b200e9847 | ||
|
|
f34866e8a5 | ||
|
|
45c799f40c | ||
|
|
11a046f628 | ||
|
|
b632f1ef20 | ||
|
|
7f30268b10 | ||
|
|
7504eff5af | ||
|
|
8752c00ebf | ||
|
|
d0c5e83def | ||
|
|
f6b7ff4b34 | ||
|
|
2314f20c4e | ||
|
|
ff7410cad2 | ||
|
|
57c0ad44f3 | ||
|
|
ae60bcaffb | ||
|
|
f2f616a95c | ||
|
|
a8bb455df7 | ||
|
|
9dcbc46225 | ||
|
|
024f918b86 | ||
|
|
0f05f41306 | ||
|
|
4ea6decc7d | ||
|
|
f79b8cb7ae | ||
|
|
275cb77378 | ||
|
|
b916445dd8 | ||
|
|
c02fee7013 | ||
|
|
e77889679f | ||
|
|
b9dceb2340 | ||
|
|
e84eb3f1ba | ||
|
|
92999be436 | ||
|
|
bd4f575567 | ||
|
|
09016db3c3 | ||
|
|
c2ee5172b0 | ||
|
|
8436c4d271 | ||
|
|
a09c2e556f | ||
|
|
e650c7ff16 | ||
|
|
c06b4206f2 | ||
|
|
89435a6287 | ||
|
|
5328674c2d | ||
|
|
927fe73093 | ||
|
|
053aa108e3 | ||
|
|
b5e5c35696 | ||
|
|
77ad156c52 | ||
|
|
018c401e47 | ||
|
|
f586d3f83e | ||
|
|
3f0ebd4c71 | ||
|
|
33077bda71 | ||
|
|
547888d507 | ||
|
|
af6fe18c9d | ||
|
|
dca9628be3 | ||
|
|
d84fa738ef | ||
|
|
a322dc54dc | ||
|
|
951c2b7e83 | ||
|
|
23f68a5657 | ||
|
|
ecb0b4478b | ||
|
|
70255d46bb | ||
|
|
4653c3673b | ||
|
|
11eacab70e | ||
|
|
110c0021e2 | ||
|
|
4c5e355a0b | ||
|
|
fbc9028313 | ||
|
|
9b800d4f84 | ||
|
|
513752eee5 | ||
|
|
9eb1ba7e9f | ||
|
|
fb5b1a20d2 | ||
|
|
b89945d36a | ||
|
|
220f35a0f1 | ||
|
|
72f83165e0 | ||
|
|
c17f8c36c1 | ||
|
|
8e604a9da9 | ||
|
|
3e0233a26c | ||
|
|
aa98e2b37e | ||
|
|
7b53c0040c | ||
|
|
e6605637f8 | ||
|
|
6dfe0896e3 | ||
|
|
9f295cbb48 | ||
|
|
76c19e6111 | ||
|
|
6e6a2a013a | ||
|
|
2482e00224 | ||
|
|
7981b647c3 | ||
|
|
875bab352c | ||
|
|
862dc0001f | ||
|
|
adc3ec3851 | ||
|
|
5a6cd1cf3e | ||
|
|
5e2f514140 | ||
|
|
309e6dd82e | ||
|
|
6c5d296722 | ||
|
|
b1a1ab99aa | ||
|
|
1b69c14f45 | ||
|
|
cd8dea78e6 | ||
|
|
d77b35f333 | ||
|
|
6f7b927641 | ||
|
|
d2e20cf56c | ||
|
|
a6126b1370 | ||
|
|
87f0accb23 | ||
|
|
7add76dae8 | ||
|
|
2a2f10fddd | ||
|
|
0dd3285d56 | ||
|
|
f9782387d9 | ||
|
|
e1567707b1 | ||
|
|
08df55159b | ||
|
|
c29cc62d66 | ||
|
|
6ed07733cb | ||
|
|
ee3d3bd1e1 | ||
|
|
758954a93f | ||
|
|
590757e2b2 | ||
|
|
ddd6d54426 | ||
|
|
1a7cd887e4 | ||
|
|
d3c76575f9 | ||
|
|
b224270cc0 | ||
|
|
8b5b780c2c | ||
|
|
39c10f739d | ||
|
|
4fdc84f29e | ||
|
|
a8efe20862 | ||
|
|
58c5711b47 | ||
|
|
5d564a2f01 | ||
|
|
09c1476063 | ||
|
|
f255439ece | ||
|
|
b104e9ae78 | ||
|
|
4f964ce6ad | ||
|
|
11ec515378 | ||
|
|
1a9b1dd123 | ||
|
|
a93dfc1837 | ||
|
|
c5846378ab | ||
|
|
aea7d0c9c8 | ||
|
|
65c3f2dc85 | ||
|
|
5fbc553611 | ||
|
|
c41b060618 | ||
|
|
c17921c417 | ||
|
|
94287044ba | ||
|
|
7c09884eac | ||
|
|
a90a157ea6 | ||
|
|
ac8d0f5505 | ||
|
|
8f23f07740 | ||
|
|
3b183163c9 | ||
|
|
55a377b446 | ||
|
|
2d342f0ddf | ||
|
|
060ea4a573 | ||
|
|
6a12efb77b | ||
|
|
e57d3f4bc1 | ||
|
|
16902b1f4f | ||
|
|
cb1b1b7cc0 | ||
|
|
26fe4c4078 | ||
|
|
4e832788bf | ||
|
|
db43d160b4 | ||
|
|
1412e40490 | ||
|
|
00c5642eb4 | ||
|
|
d3347b6d08 | ||
|
|
ed7e13da9f | ||
|
|
90b7ec19d1 | ||
|
|
468c41041b |
414
.travis.yml
Normal file
414
.travis.yml
Normal file
@@ -0,0 +1,414 @@
|
||||
# Copyright 2016-2020 Peter Dimov
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
|
||||
|
||||
language: cpp
|
||||
|
||||
dist: xenial
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- develop
|
||||
- /feature\/.*/
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- BOGUS_JOB=true
|
||||
|
||||
matrix:
|
||||
|
||||
exclude:
|
||||
- env: BOGUS_JOB=true
|
||||
|
||||
include:
|
||||
- os: linux
|
||||
arch: arm64
|
||||
compiler: g++
|
||||
env: TOOLSET=gcc COMPILER=g++ CXXSTD=03,11,14
|
||||
|
||||
- os: linux
|
||||
arch: ppc64le
|
||||
compiler: g++
|
||||
env: TOOLSET=gcc COMPILER=g++ CXXSTD=03,11,14
|
||||
|
||||
- os: linux
|
||||
arch: s390x
|
||||
compiler: g++
|
||||
env: TOOLSET=gcc COMPILER=g++ CXXSTD=03,11,14
|
||||
|
||||
- os: linux
|
||||
compiler: g++-4.4
|
||||
env: TOOLSET=gcc COMPILER=g++-4.4 CXXSTD=98,0x
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-4.4
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-4.6
|
||||
env: TOOLSET=gcc COMPILER=g++-4.6 CXXSTD=03,0x
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-4.6
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-4.7
|
||||
env: TOOLSET=gcc COMPILER=g++-4.7 CXXSTD=03,11
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-4.7
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-4.8
|
||||
env: TOOLSET=gcc COMPILER=g++-4.8 CXXSTD=03,11
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-4.8
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- os: linux
|
||||
compiler: g++-4.9
|
||||
env: TOOLSET=gcc COMPILER=g++-4.9 CXXSTD=03,11
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-4.9
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-5
|
||||
env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=03,11,14,1z
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-5
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-6
|
||||
env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=03,11,14,1z
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-6
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-7
|
||||
env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=03,11,14,17
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-7
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-8
|
||||
env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=03,11,14
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-8
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-8
|
||||
env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=17,2a
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-8
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-9
|
||||
env: TOOLSET=gcc COMPILER=g++-9 CXXSTD=03,11,14
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-9
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-9
|
||||
env: TOOLSET=gcc COMPILER=g++-9 CXXSTD=17,2a
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-9
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-7
|
||||
env: UBSAN=1 TOOLSET=gcc COMPILER=g++-7 CXXSTD=03,11,14,17 UBSAN_OPTIONS=print_stacktrace=1 LINKFLAGS=-fuse-ld=gold
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-7
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
dist: trusty
|
||||
compiler: /usr/bin/clang++
|
||||
env: TOOLSET=clang COMPILER=/usr/bin/clang++ CXXSTD=03,11
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.3
|
||||
|
||||
- os: linux
|
||||
dist: trusty
|
||||
compiler: /usr/bin/clang++
|
||||
env: TOOLSET=clang COMPILER=/usr/bin/clang++ CXXSTD=03,11
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.4
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.5
|
||||
env: TOOLSET=clang COMPILER=clang++-3.5 CXXSTD=03,11
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.5
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.6
|
||||
env: TOOLSET=clang COMPILER=clang++-3.6 CXXSTD=03,11,14,1z
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.6
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.7
|
||||
env: TOOLSET=clang COMPILER=clang++-3.7 CXXSTD=03,11,14,1z
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.7
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.8
|
||||
env: TOOLSET=clang COMPILER=clang++-3.8 CXXSTD=03,11,14,1z
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.8
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.9
|
||||
env: TOOLSET=clang COMPILER=clang++-3.9 CXXSTD=03,11,14,1z
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.9
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-4.0
|
||||
env: TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=03,11,14,1z
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-4.0
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-5.0
|
||||
env: TOOLSET=clang COMPILER=clang++-5.0 CXXSTD=03,11,14,1z
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-5.0
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-6.0
|
||||
env: TOOLSET=clang COMPILER=clang++-6.0 CXXSTD=03,11,14,17,2a
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-6.0
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-7
|
||||
env: TOOLSET=clang COMPILER=clang++-7 CXXSTD=03,11,14,17,2a
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-7
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-xenial-7
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-8
|
||||
env: TOOLSET=clang COMPILER=clang++-8 CXXSTD=03,11,14,17,2a
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-8
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-xenial-8
|
||||
|
||||
- os: linux
|
||||
dist: xenial
|
||||
compiler: clang++-9
|
||||
env: TOOLSET=clang COMPILER=clang++-9 CXXSTD=03,11,14,17,2a
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-9
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main'
|
||||
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
|
||||
|
||||
- os: linux
|
||||
dist: xenial
|
||||
compiler: clang++-10
|
||||
env: TOOLSET=clang COMPILER=clang++-10 CXXSTD=03,11,14,17,2a
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-10
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-10 main'
|
||||
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-8
|
||||
env: UBSAN=1 TOOLSET=clang COMPILER=clang++-8 CXXSTD=03,11,14,17,2a UBSAN_OPTIONS=print_stacktrace=1
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-8
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-xenial-8
|
||||
|
||||
- os: linux
|
||||
dist: trusty
|
||||
compiler: clang++-libc++
|
||||
env: TOOLSET=clang COMPILER=clang++-libc++ CXXSTD=03,11,14,1z
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libc++-dev
|
||||
|
||||
- os: linux
|
||||
dist: trusty
|
||||
compiler: clang++-libc++
|
||||
env: UBSAN=1 TOOLSET=clang COMPILER=clang++-libc++ CXXSTD=03,11,14,1z UBSAN_OPTIONS=print_stacktrace=1
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libc++-dev
|
||||
|
||||
- os: osx
|
||||
compiler: clang++
|
||||
env: TOOLSET=clang COMPILER=clang++ CXXSTD=03,11,14,1z
|
||||
|
||||
- os: osx
|
||||
compiler: clang++
|
||||
env: UBSAN=1 TOOLSET=clang COMPILER=clang++ CXXSTD=03,11,14,1z UBSAN_OPTIONS=print_stacktrace=1
|
||||
|
||||
- os: linux
|
||||
env: CMAKE_TEST=1
|
||||
script:
|
||||
- mkdir __build__ && cd __build__
|
||||
- cmake -DBOOST_ENABLE_CMAKE=1 -DBoost_VERBOSE=1 -DBOOST_INCLUDE_LIBRARIES=smart_ptr -DBUILD_TESTING=ON ..
|
||||
- ctest --output-on-failure -R boost_smart_ptr
|
||||
|
||||
- os: linux
|
||||
compiler: g++
|
||||
env: CMAKE_SUBDIR_TEST=1
|
||||
script:
|
||||
- cd libs/smart_ptr/test/cmake_subdir_test && mkdir __build__ && cd __build__
|
||||
- cmake ..
|
||||
- cmake --build .
|
||||
- cmake --build . --target check
|
||||
|
||||
- os: linux
|
||||
env: CMAKE_INSTALL_TEST=1
|
||||
script:
|
||||
- mkdir __build__ && cd __build__
|
||||
- cmake -DBOOST_ENABLE_CMAKE=1 -DBoost_VERBOSE=1 -DBOOST_INCLUDE_LIBRARIES=smart_ptr -DBUILD_TESTING=OFF -DCMAKE_INSTALL_PREFIX=~/.local ..
|
||||
- cmake --build . --target install
|
||||
- cd ../libs/smart_ptr/test/cmake_install_test && mkdir __build__ && cd __build__
|
||||
- cmake -DCMAKE_INSTALL_PREFIX=~/.local ..
|
||||
- cmake --build .
|
||||
- cmake --build . --target check
|
||||
|
||||
install:
|
||||
- BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true
|
||||
- cd ..
|
||||
- git clone -b $BOOST_BRANCH https://github.com/boostorg/boost.git boost-root
|
||||
- cd boost-root
|
||||
- git submodule init libs/align
|
||||
- git submodule init libs/assert
|
||||
- git submodule init libs/atomic
|
||||
- git submodule init libs/config
|
||||
- git submodule init libs/container_hash
|
||||
- git submodule init libs/core
|
||||
- git submodule init libs/move
|
||||
- git submodule init libs/predef
|
||||
- git submodule init libs/static_assert
|
||||
- git submodule init libs/throw_exception
|
||||
- git submodule init libs/type_traits
|
||||
- git submodule init libs/detail
|
||||
- git submodule init libs/integer
|
||||
- git submodule init tools/build
|
||||
- git submodule init libs/headers
|
||||
- git submodule init tools/boost_install
|
||||
- git submodule init tools/cmake
|
||||
- git submodule init libs/preprocessor
|
||||
- git submodule update # no --jobs 3 on non-amd64
|
||||
- cp -r $TRAVIS_BUILD_DIR/* libs/smart_ptr
|
||||
- ./bootstrap.sh
|
||||
- ./b2 headers
|
||||
|
||||
script:
|
||||
- |-
|
||||
echo "using $TOOLSET : : $COMPILER ;" > ~/user-config.jam
|
||||
- ./b2 -j3 libs/smart_ptr/test toolset=$TOOLSET cxxstd=$CXXSTD variant=debug,release ${UBSAN:+cxxflags=-fsanitize=undefined cxxflags=-fno-sanitize-recover=undefined linkflags=-fsanitize=undefined debug-symbols=on} ${LINKFLAGS:+linkflags=$LINKFLAGS}
|
||||
|
||||
notifications:
|
||||
email:
|
||||
on_success: always
|
||||
36
CMakeLists.txt
Normal file
36
CMakeLists.txt
Normal file
@@ -0,0 +1,36 @@
|
||||
# Copyright 2018-2020 Peter Dimov
|
||||
# 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
|
||||
|
||||
cmake_minimum_required(VERSION 3.5...3.16)
|
||||
|
||||
project(boost_smart_ptr VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)
|
||||
|
||||
add_library(boost_smart_ptr INTERFACE)
|
||||
add_library(Boost::smart_ptr ALIAS boost_smart_ptr)
|
||||
|
||||
target_include_directories(boost_smart_ptr INTERFACE include)
|
||||
|
||||
target_link_libraries(boost_smart_ptr
|
||||
INTERFACE
|
||||
Boost::assert
|
||||
Boost::config
|
||||
Boost::core
|
||||
Boost::move
|
||||
Boost::static_assert
|
||||
Boost::throw_exception
|
||||
Boost::type_traits
|
||||
)
|
||||
|
||||
if(BOOST_SUPERPROJECT_VERSION)
|
||||
|
||||
include(BoostInstall)
|
||||
boost_install(TARGETS boost_smart_ptr HEADER_DIRECTORY include/)
|
||||
|
||||
endif()
|
||||
|
||||
if(BUILD_TESTING)
|
||||
|
||||
add_subdirectory(test)
|
||||
|
||||
endif()
|
||||
6
README.md
Normal file
6
README.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Boost.SmartPtr
|
||||
|
||||
Branch | Travis | Appveyor
|
||||
---------|--------|---------
|
||||
Develop | [](https://travis-ci.org/boostorg/smart_ptr) | [](https://ci.appveyor.com/project/pdimov/smart-ptr)
|
||||
Master | [](https://travis-ci.org/boostorg/smart_ptr) | [](https://ci.appveyor.com/project/pdimov/smart-ptr)
|
||||
84
appveyor.yml
Normal file
84
appveyor.yml
Normal file
@@ -0,0 +1,84 @@
|
||||
# Copyright 2016-2019 Peter Dimov
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
|
||||
|
||||
version: 1.0.{build}-{branch}
|
||||
|
||||
shallow_clone: true
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- develop
|
||||
- /feature\/.*/
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
TOOLSET: msvc-9.0,msvc-10.0,msvc-11.0
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
TOOLSET: msvc-12.0,msvc-14.0
|
||||
ADDRMD: 32,64
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
TOOLSET: msvc-14.1
|
||||
CXXSTD: 14,17
|
||||
ADDRMD: 32,64
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
TOOLSET: clang-win
|
||||
CXXSTD: 14,17
|
||||
ADDRMD: 64
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
TOOLSET: msvc-14.2
|
||||
CXXSTD: 14,17
|
||||
ADDRMD: 32,64
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
ADDPATH: C:\cygwin\bin;
|
||||
TOOLSET: gcc
|
||||
CXXSTD: 03,11,14,1z
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
ADDPATH: C:\cygwin64\bin;
|
||||
TOOLSET: gcc
|
||||
CXXSTD: 03,11,14,1z
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
ADDPATH: C:\mingw\bin;
|
||||
TOOLSET: gcc
|
||||
CXXSTD: 03,11,14,1z
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
ADDPATH: C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin;
|
||||
TOOLSET: gcc
|
||||
CXXSTD: 03,11,14,1z
|
||||
|
||||
install:
|
||||
- set BOOST_BRANCH=develop
|
||||
- if "%APPVEYOR_REPO_BRANCH%" == "master" set BOOST_BRANCH=master
|
||||
- cd ..
|
||||
- git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
- cd boost-root
|
||||
- git submodule init libs/align
|
||||
- git submodule init libs/assert
|
||||
- git submodule init libs/atomic
|
||||
- git submodule init libs/config
|
||||
- git submodule init libs/container_hash
|
||||
- git submodule init libs/core
|
||||
- git submodule init libs/move
|
||||
- git submodule init libs/predef
|
||||
- git submodule init libs/static_assert
|
||||
- git submodule init libs/throw_exception
|
||||
- git submodule init libs/type_traits
|
||||
- git submodule init libs/detail
|
||||
- git submodule init libs/integer
|
||||
- git submodule init tools/build
|
||||
- git submodule init libs/headers
|
||||
- git submodule init tools/boost_install
|
||||
- git submodule update --jobs 3
|
||||
- xcopy /s /e /q %APPVEYOR_BUILD_FOLDER% libs\smart_ptr\
|
||||
- cmd /c bootstrap
|
||||
- b2 -d0 headers
|
||||
|
||||
build: off
|
||||
|
||||
test_script:
|
||||
- PATH=%ADDPATH%%PATH%
|
||||
- if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD%
|
||||
- if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD%
|
||||
- b2 -j3 libs/smart_ptr/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release
|
||||
2
doc/.gitignore
vendored
Normal file
2
doc/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/html/
|
||||
/pdf/
|
||||
24
doc/Jamfile
Normal file
24
doc/Jamfile
Normal file
@@ -0,0 +1,24 @@
|
||||
# Copyright 2017 Peter Dimov
|
||||
#
|
||||
# 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
|
||||
|
||||
import asciidoctor ;
|
||||
|
||||
html smart_ptr.html : smart_ptr.adoc ;
|
||||
|
||||
install html_ : smart_ptr.html : <location>html ;
|
||||
|
||||
pdf smart_ptr.pdf : smart_ptr.adoc ;
|
||||
explicit smart_ptr.pdf ;
|
||||
|
||||
install pdf_ : smart_ptr.pdf : <location>pdf ;
|
||||
explicit pdf_ ;
|
||||
|
||||
###############################################################################
|
||||
alias boostdoc ;
|
||||
explicit boostdoc ;
|
||||
alias boostrelease : html_ ;
|
||||
explicit boostrelease ;
|
||||
6
doc/smart_ptr-docinfo-footer.html
Normal file
6
doc/smart_ptr-docinfo-footer.html
Normal file
@@ -0,0 +1,6 @@
|
||||
<style>
|
||||
|
||||
*:not(pre)>code { background: none; color: #600000; }
|
||||
table tr.even, table tr.alt, table tr:nth-of-type(even) { background: none; }
|
||||
|
||||
</style>
|
||||
82
doc/smart_ptr.adoc
Normal file
82
doc/smart_ptr.adoc
Normal file
@@ -0,0 +1,82 @@
|
||||
////
|
||||
Copyright 2017 Peter Dimov
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
|
||||
See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt
|
||||
////
|
||||
|
||||
# Boost.SmartPtr: The Smart Pointer Library
|
||||
Greg Colvin, Beman Dawes, Peter Dimov, Glen Fernandes
|
||||
:toc: left
|
||||
:toclevels: 2
|
||||
:idprefix:
|
||||
:listing-caption: Code Example
|
||||
:docinfo: private-footer
|
||||
|
||||
:leveloffset: +1
|
||||
|
||||
include::smart_ptr/introduction.adoc[]
|
||||
|
||||
include::smart_ptr/changelog.adoc[]
|
||||
|
||||
include::smart_ptr/scoped_ptr.adoc[]
|
||||
|
||||
include::smart_ptr/scoped_array.adoc[]
|
||||
|
||||
include::smart_ptr/shared_ptr.adoc[]
|
||||
|
||||
include::smart_ptr/weak_ptr.adoc[]
|
||||
|
||||
include::smart_ptr/make_shared.adoc[]
|
||||
|
||||
include::smart_ptr/enable_shared_from_this.adoc[]
|
||||
|
||||
include::smart_ptr/enable_shared_from.adoc[]
|
||||
|
||||
include::smart_ptr/make_unique.adoc[]
|
||||
|
||||
include::smart_ptr/allocate_unique.adoc[]
|
||||
|
||||
include::smart_ptr/intrusive_ptr.adoc[]
|
||||
|
||||
include::smart_ptr/intrusive_ref_counter.adoc[]
|
||||
|
||||
include::smart_ptr/local_shared_ptr.adoc[]
|
||||
|
||||
include::smart_ptr/make_local_shared.adoc[]
|
||||
|
||||
include::smart_ptr/pointer_cast.adoc[]
|
||||
|
||||
include::smart_ptr/pointer_to_other.adoc[]
|
||||
|
||||
include::smart_ptr/atomic_shared_ptr.adoc[]
|
||||
|
||||
// appendix
|
||||
include::smart_ptr/techniques.adoc[]
|
||||
|
||||
// appendix
|
||||
include::smart_ptr/history.adoc[]
|
||||
|
||||
// appendix, deprecated
|
||||
include::smart_ptr/shared_array.adoc[]
|
||||
|
||||
:leveloffset: -1
|
||||
|
||||
[[copyright]]
|
||||
[appendix]
|
||||
## Copyright and License
|
||||
|
||||
This documentation is
|
||||
|
||||
* Copyright 1999 Greg Colvin
|
||||
* Copyright 1999 Beman Dawes
|
||||
* Copyright 2002 Darin Adler
|
||||
* Copyright 2003-2017 Peter Dimov
|
||||
* Copyright 2005, 2006 Ion Gaztañaga
|
||||
* Copyright 2008 Frank Mori Hess
|
||||
* Copyright 2012-2017 Glen Fernandes
|
||||
* Copyright 2013 Andrey Semashev
|
||||
|
||||
and is distributed under the http://www.boost.org/LICENSE_1_0.txt[Boost Software License, Version 1.0].
|
||||
318
doc/smart_ptr/allocate_unique.adoc
Normal file
318
doc/smart_ptr/allocate_unique.adoc
Normal file
@@ -0,0 +1,318 @@
|
||||
////
|
||||
Copyright 2019 Glen Joseph Fernandes (glenjofe@gmail.com)
|
||||
|
||||
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
|
||||
////
|
||||
|
||||
[#allocate_unique]
|
||||
# allocate_unique: Creating unique_ptr
|
||||
:toc:
|
||||
:toc-title:
|
||||
:idprefix: allocate_unique_
|
||||
|
||||
## Description
|
||||
|
||||
The `allocate_unique` family of function templates provide convenient and safe
|
||||
ways to obtain a `std::unique_ptr` that manages a new object created using an
|
||||
allocator.
|
||||
|
||||
## Rationale
|
||||
|
||||
The {cpp}14 standard introduced `std::make_unique` which used operator `new` to
|
||||
create new objects. However, there is no convenient facility in the standard
|
||||
library to use an allocator for the creation of the objects managed by
|
||||
`std::unique_ptr`. Users writing allocator aware code have often requested an
|
||||
`allocate_unique` factory function. This function is to `std::unique_ptr` what
|
||||
`std::allocate_shared` is to `std::shared_ptr`.
|
||||
|
||||
## Synopsis
|
||||
|
||||
`allocate_unique` is defined in `<boost/smart_ptr/allocate_unique.hpp>`.
|
||||
|
||||
[subs=+quotes]
|
||||
```
|
||||
namespace boost {
|
||||
template<class T, class A>
|
||||
class alloc_deleter;
|
||||
|
||||
template<class T, class A>
|
||||
using alloc_noinit_deleter = alloc_deleter<T, noinit_adaptor<A>>;
|
||||
|
||||
`// T is not an array`
|
||||
template<class T, class A, class... Args>
|
||||
std::unique_ptr<T, alloc_deleter<T, A>>
|
||||
allocate_unique(const A& a, Args&&... args);
|
||||
|
||||
`// T is not an array`
|
||||
template<class T, class A>
|
||||
std::unique_ptr<T, alloc_deleter<T, A>>
|
||||
allocate_unique(const A& a, type_identity_t<T>&& v);
|
||||
|
||||
`// T is an array of unknown bounds`
|
||||
template<class T, class A>
|
||||
std::unique_ptr<T, alloc_deleter<T, A>>
|
||||
allocate_unique(const A& a, std::size_t n);
|
||||
|
||||
`// T is an array of known bounds`
|
||||
template<class T, class A>
|
||||
std::unique_ptr<remove_extent_t<T>[], alloc_deleter<T, A>>
|
||||
allocate_unique(const A& a);
|
||||
|
||||
`// T is an array of unknown bounds`
|
||||
template<class T, class A>
|
||||
std::unique_ptr<T, alloc_deleter<T, A>>
|
||||
allocate_unique(const A& a, std::size_t n, const remove_extent_t<T>& v);
|
||||
|
||||
`// T is an array of known bounds`
|
||||
template<class T, class A>
|
||||
std::unique_ptr<remove_extent_t<T>[], alloc_deleter<T, A>>
|
||||
allocate_unique(const A& a, const remove_extent_t<T>& v);
|
||||
|
||||
`// T is not an array`
|
||||
template<class T, class A>
|
||||
std::unique_ptr<T, alloc_noinit_deleter<T, A>>
|
||||
allocate_unique_noinit(const A& a);
|
||||
|
||||
`// T is an array of unknown bounds`
|
||||
template<class T, class A>
|
||||
std::unique_ptr<T, alloc_noinit_deleter<T, A>>
|
||||
allocate_unique_noinit(const A& a, std::size_t n);
|
||||
|
||||
`// T is an array of known bounds`
|
||||
template<class T, class A>
|
||||
std::unique_ptr<remove_extent_t<T>[], alloc_noinit_deleter<T, A>>
|
||||
allocate_unique_noinit(const A& a);
|
||||
}
|
||||
```
|
||||
|
||||
## Common Requirements
|
||||
|
||||
The common requirements that apply to all `allocate_unique` and
|
||||
`allocate_unique_noinit` overloads, unless specified otherwise, are described
|
||||
below.
|
||||
|
||||
Requires:: `A` shall be an _allocator_. The copy constructor and destructor
|
||||
of `A` shall not throw exceptions.
|
||||
|
||||
Effects:: Allocates memory for an object of type `T` or `n` objects of `U`
|
||||
(if `T` is an array type of the form `U[]` and `n` is determined by
|
||||
arguments, as specified by the concrete overload). The object is initialized
|
||||
from arguments as specified by the concrete overload. Uses a rebound copy of
|
||||
`a` (for an unspecified `value_type`) to allocate memory. If an exception is
|
||||
thrown, the functions have no effect.
|
||||
|
||||
Returns:: A `std::unique_ptr` instance that stores and owns the address of the
|
||||
newly constructed object.
|
||||
|
||||
Postconditions:: `r.get() != 0`, where `r` is the return value.
|
||||
|
||||
Throws:: An exception thrown from `A::allocate`, or from the initialization of
|
||||
the object.
|
||||
|
||||
Remarks::
|
||||
* When an object of an array type is specified to be initialized to a value of
|
||||
the same type `v`, this shall be interpreted to mean that each array element
|
||||
of the object is initialized to the corresponding element from `v`.
|
||||
* When an object of an array type is specified to be value-initialized, this
|
||||
shall be interpreted to mean that each array element of the object is
|
||||
value-initialized.
|
||||
* When a (sub)object of non-array type `U` is specified to be initialized to a
|
||||
value `v`, or constructed from `args\...`, `allocate_unique` shall perform this
|
||||
initialization via the expression
|
||||
`std::allocator_traits<A2>::construct(a2, p, expr)` (where `_expr_` is `v` or
|
||||
`std::forward<Args>(args)\...)` respectively), `p` points to storage suitable
|
||||
to hold an object of type `U`, and `a2` of type `A2` is a potentially rebound
|
||||
copy of `a`.
|
||||
* When a (sub)object of non-array type `U` is specified to be
|
||||
default-initialized, `allocate_unique_noinit` shall perform this initialization
|
||||
via the expression `::new(p) U`, where `p` has type `void*` and points to
|
||||
storage suitable to hold an object of type `U`.
|
||||
* When a (sub)object of non-array type `U` is specified to be
|
||||
value-initialized, `allocate_unique` shall perform this initialization via the
|
||||
expression `std::allocator_traits<A2>::construct(a2, p)`, where `p` points to
|
||||
storage suitable to hold an object of type `U` and `a2` of type `A2` is a
|
||||
potentially rebound copy of `a`.
|
||||
* Array elements are initialized in ascending order of their addresses.
|
||||
* When the lifetime of the object managed by the return value ends, or when the
|
||||
initialization of an array element throws an exception, the initialized
|
||||
elements should be destroyed in the reverse order of their construction.
|
||||
|
||||
## Free Functions
|
||||
|
||||
```
|
||||
template<class T, class A, class... Args>
|
||||
std::unique_ptr<T, alloc_deleter<T, A>>
|
||||
allocate_unique(const A& a, Args&&... args);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Constraints:: `T` is not an array.
|
||||
Returns:: A `std::unique_ptr` to an object of type `T`, constructed from
|
||||
`args\...`.
|
||||
Examples::
|
||||
* `auto p = allocate_unique<int>(a);`
|
||||
* `auto p = allocate_unique<std::vector<int>>(a, 16, 1);`
|
||||
|
||||
```
|
||||
template<class T, class A>
|
||||
std::unique_ptr<T, alloc_deleter<T, A>>
|
||||
allocate_unique(const A& a, type_identity_t<T>&& v);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Constraints:: `T` is not an array.
|
||||
Returns:: A `std::unique_ptr` to an object of type `T`, constructed from `v`.
|
||||
Example:: `auto p = allocate_unique<std::vector<int>>(a, {1, 2});`
|
||||
|
||||
```
|
||||
template<class T, class A>
|
||||
std::unique_ptr<T, alloc_deleter<T, A>>
|
||||
allocate_unique(const A& a, std::size_t n);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Constraints:: `T` is an array of unknown bounds.
|
||||
Returns:: A `std::unique_ptr` to a sequence of `n` value-initialized objects of
|
||||
type `remove_extent_t<T>`.
|
||||
Examples::
|
||||
* `auto p = allocate_unique<double[]>(a, 1024);`
|
||||
* `auto p = allocate_unique<double[][2][2]>(a, 6);`
|
||||
|
||||
```
|
||||
template<class T, class A>
|
||||
std::unique_ptr<remove_extent_t<T>[], alloc_deleter<T, A>>
|
||||
allocate_unique(const A& a);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Constraints:: `T` is an array of known bounds.
|
||||
Returns:: A `std::unique_ptr` to a sequence of `extent_v<T>` value-initialized
|
||||
objects of type `remove_extent_t<T>`.
|
||||
Examples::
|
||||
* `auto p = allocate_unique<double[1024]>(a);`
|
||||
* `auto p = allocate_unique<double[6][2][2]>(a);`
|
||||
|
||||
```
|
||||
template<class T, class A>
|
||||
std::unique_ptr<T, alloc_deleter<T, A>>
|
||||
allocate_unique(const A& a, std::size_t n, const remove_extent_t<T>& v);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Constraints:: `T` is an array of unknown bounds.
|
||||
Returns:: A `std::unique_ptr` to a sequence of `n` objects of type
|
||||
`remove_extent_t<T>`, each initialized to `v`.
|
||||
Examples::
|
||||
* `auto p = allocate_unique<double[]>(a, 1024, 1.0);`
|
||||
* `auto p = allocate_unique<double[][2]>(a, 6, {1.0, 0.0});`
|
||||
* `auto p = allocate_unique<std::vector<int>[]>(a, 4, {1, 2});`
|
||||
|
||||
```
|
||||
template<class T, class A>
|
||||
std::unique_ptr<remove_extent_t<T>[], alloc_deleter<T, A>>
|
||||
allocate_unique(const A& a, const remove_extent_t<T>& v);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Constraints:: `T` is an array of known bounds.
|
||||
Returns:: A `std::unique_ptr` to a sequence of `extent_v<T>` objects of type
|
||||
`remove_extent_t<T>`, each initialized to `v`.
|
||||
Examples::
|
||||
* `auto p = allocate_unique<double[1024]>(a, 1.0);`
|
||||
* `auto p = allocate_unique<double[6][2]>(a, {1.0, 0.0});`
|
||||
* `auto p = allocate_unique<std::vector<int>[4]>(a, {1, 2});`
|
||||
|
||||
```
|
||||
template<class T, class A>
|
||||
std::unique_ptr<T, alloc_noinit_deleter<T, A>>
|
||||
allocate_unique_noinit(const A& a);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Constraints:: `T` is not an array.
|
||||
Returns:: A `std::unique_ptr` to a default-initialized object of type `T`.
|
||||
Example:: `auto p = allocate_unique_noinit<double>(a);`
|
||||
|
||||
```
|
||||
template<class T, class A>
|
||||
std::unique_ptr<T, alloc_noinit_deleter<T, A>>
|
||||
allocate_unique_noinit(const A& a, std::size_t n);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Constraints:: `T` is an array of unknown bounds.
|
||||
Returns:: A `std::unique_ptr` to a sequence of `n` default-initialized objects
|
||||
of type `remove_extent_t<T>`.
|
||||
Example:: `auto p = allocate_unique_noinit<double[]>(a, 1024);`
|
||||
|
||||
```
|
||||
template<class T, class A>
|
||||
std::unique_ptr<remove_extent_t<T>, alloc_noinit_deleter<T, A>>
|
||||
allocate_unique_noinit(const A& a);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Constraints:: `T` is an array of known bounds.
|
||||
Returns:: A `std::unique_ptr` to a sequence of `extent_v<T>`
|
||||
default-initialized objects of type `remove_extent_t<T>`.
|
||||
Example:: `auto p = allocate_unique_noinit<double[1024]>(a);`
|
||||
|
||||
## Deleter
|
||||
|
||||
Class template `alloc_deleter` is the deleter used by the `allocate_unique`
|
||||
functions.
|
||||
|
||||
### Synopsis
|
||||
|
||||
[subs=+quotes]
|
||||
```
|
||||
template<class T, class A>
|
||||
class alloc_deleter {
|
||||
public:
|
||||
using pointer = `unspecified`;
|
||||
|
||||
explicit alloc_deleter(const A& a) noexcept;
|
||||
|
||||
void operator()(pointer p);
|
||||
};
|
||||
```
|
||||
|
||||
### Members
|
||||
|
||||
[subs=+quotes]
|
||||
```
|
||||
using pointer = `unspecified`;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
A type that satisfies _NullablePointer_.
|
||||
|
||||
```
|
||||
explicit alloc_deleter(const A& a) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Initializes the stored allocator from `a`.
|
||||
|
||||
```
|
||||
void operator()(pointer p);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Destroys the objects and deallocates the storage referenced by `p`,
|
||||
using the stored allocator.
|
||||
170
doc/smart_ptr/atomic_shared_ptr.adoc
Normal file
170
doc/smart_ptr/atomic_shared_ptr.adoc
Normal file
@@ -0,0 +1,170 @@
|
||||
////
|
||||
Copyright 2017 Peter Dimov
|
||||
|
||||
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
|
||||
////
|
||||
|
||||
[#atomic_shared_ptr]
|
||||
# atomic_shared_ptr
|
||||
:toc:
|
||||
:toc-title:
|
||||
:idprefix: atomic_shared_ptr_
|
||||
|
||||
## Description
|
||||
|
||||
The class template `atomic_shared_ptr<T>` implements the interface of `std::atomic`
|
||||
for a contained value of type `shared_ptr<T>`. Concurrent access to `atomic_shared_ptr`
|
||||
is not a data race.
|
||||
|
||||
## Synopsis
|
||||
|
||||
`atomic_shared_ptr` is defined in `<boost/smart_ptr/atomic_shared_ptr.hpp>`.
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
|
||||
template<class T> class atomic_shared_ptr {
|
||||
private:
|
||||
|
||||
shared_ptr<T> p_; // exposition only
|
||||
|
||||
atomic_shared_ptr(const atomic_shared_ptr&) = delete;
|
||||
atomic_shared_ptr& operator=(const atomic_shared_ptr&) = delete;
|
||||
|
||||
public:
|
||||
|
||||
constexpr atomic_shared_ptr() noexcept;
|
||||
atomic_shared_ptr( shared_ptr<T> p ) noexcept;
|
||||
|
||||
atomic_shared_ptr& operator=( shared_ptr<T> r ) noexcept;
|
||||
|
||||
bool is_lock_free() const noexcept;
|
||||
|
||||
shared_ptr<T> load( int = 0 ) const noexcept;
|
||||
operator shared_ptr<T>() const noexcept;
|
||||
|
||||
void store( shared_ptr<T> r, int = 0 ) noexcept;
|
||||
|
||||
shared_ptr<T> exchange( shared_ptr<T> r, int = 0 ) noexcept;
|
||||
|
||||
bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) noexcept;
|
||||
bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) noexcept;
|
||||
bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) noexcept;
|
||||
bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) noexcept;
|
||||
|
||||
bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) noexcept;
|
||||
bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) noexcept;
|
||||
bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) noexcept;
|
||||
bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) noexcept;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Members
|
||||
|
||||
```
|
||||
constexpr atomic_shared_ptr() noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Default-initializes `p_`.
|
||||
|
||||
```
|
||||
atomic_shared_ptr( shared_ptr<T> p ) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Initializes `p_` to `p`.
|
||||
|
||||
```
|
||||
atomic_shared_ptr& operator=( shared_ptr<T> r ) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: `p_.swap(r)`.
|
||||
Returns:: `*this`.
|
||||
|
||||
```
|
||||
bool is_lock_free() const noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `false`.
|
||||
|
||||
NOTE: This implementation is not lock-free.
|
||||
|
||||
```
|
||||
shared_ptr<T> load( int = 0 ) const noexcept;
|
||||
```
|
||||
```
|
||||
operator shared_ptr<T>() const noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `p_`.
|
||||
|
||||
NOTE: The `int` argument is intended to be of type `memory_order`, but is ignored.
|
||||
This implementation is lock-based and therefore always sequentially consistent.
|
||||
|
||||
```
|
||||
void store( shared_ptr<T> r, int = 0 ) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: `p_.swap(r)`.
|
||||
|
||||
```
|
||||
shared_ptr<T> exchange( shared_ptr<T> r, int = 0 ) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: `p_.swap(r)`.
|
||||
Returns:: The old value of `p_`.
|
||||
|
||||
```
|
||||
bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) noexcept;
|
||||
```
|
||||
```
|
||||
bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) noexcept;
|
||||
```
|
||||
```
|
||||
bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) noexcept;
|
||||
```
|
||||
```
|
||||
bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: If `p_` is equivalent to `v`, assigns `w` to `p_`, otherwise assigns `p_` to `v`.
|
||||
Returns:: `true` if `p_` was equivalent to `v`, `false` otherwise.
|
||||
Remarks:: Two `shared_ptr` instances are equivalent if they store the same pointer value and _share ownership_.
|
||||
|
||||
```
|
||||
bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) noexcept;
|
||||
```
|
||||
```
|
||||
bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) noexcept;
|
||||
```
|
||||
```
|
||||
bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) noexcept;
|
||||
```
|
||||
```
|
||||
bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: If `p_` is equivalent to `v`, assigns `std::move(w)` to `p_`, otherwise assigns `p_` to `v`.
|
||||
Returns:: `true` if `p_` was equivalent to `v`, `false` otherwise.
|
||||
Remarks:: The old value of `w` is not preserved in either case.
|
||||
29
doc/smart_ptr/changelog.adoc
Normal file
29
doc/smart_ptr/changelog.adoc
Normal file
@@ -0,0 +1,29 @@
|
||||
////
|
||||
Copyright 2019 Peter Dimov
|
||||
|
||||
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
|
||||
////
|
||||
|
||||
[#changelog]
|
||||
# Revision History
|
||||
:toc:
|
||||
:toc-title:
|
||||
:idprefix: changelog_
|
||||
|
||||
## Changes in 1.72.0
|
||||
|
||||
* Added `allocate_unique`
|
||||
|
||||
## Changes in 1.71.0
|
||||
|
||||
* Added aliasing constructors to `weak_ptr`
|
||||
* Added `weak_ptr<T>::empty()`
|
||||
* Added `enable_shared_from`, `shared_from`, and `weak_from`
|
||||
|
||||
## Changes in 1.65.0
|
||||
|
||||
* Added `atomic_shared_ptr`
|
||||
* Added `local_shared_ptr`, `make_local_shared`
|
||||
89
doc/smart_ptr/enable_shared_from.adoc
Normal file
89
doc/smart_ptr/enable_shared_from.adoc
Normal file
@@ -0,0 +1,89 @@
|
||||
////
|
||||
Copyright 2002, 2003, 2015, 2017, 2019 Peter Dimov
|
||||
|
||||
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
|
||||
////
|
||||
|
||||
[#enable_shared_from]
|
||||
# enable_shared_from
|
||||
:toc:
|
||||
:toc-title:
|
||||
:idprefix: enable_shared_from_
|
||||
|
||||
## Description
|
||||
|
||||
`enable_shared_from` is used as a base class that allows a `shared_ptr` or a
|
||||
`weak_ptr` to be obtained given a raw pointer to the object, by using the
|
||||
functions `shared_from` and `weak_from`.
|
||||
|
||||
`enable_shared_from` differs from `enable_shared_from_this<T>` by the fact
|
||||
that it's not a template, and is its recommended replacement for new code.
|
||||
|
||||
## Example
|
||||
|
||||
```
|
||||
#include <boost/smart_ptr/enable_shared_from.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <cassert>
|
||||
|
||||
class Y: public boost::enable_shared_from
|
||||
{
|
||||
public:
|
||||
|
||||
boost::shared_ptr<Y> f()
|
||||
{
|
||||
return boost::shared_from( this );
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
boost::shared_ptr<Y> p(new Y);
|
||||
boost::shared_ptr<Y> q = p->f();
|
||||
assert(p == q);
|
||||
assert(!(p < q || q < p)); // p and q must share ownership
|
||||
}
|
||||
```
|
||||
|
||||
## Synopsis
|
||||
|
||||
`enable_shared_from` is defined in `<boost/smart_ptr/enable_shared_from.hpp>`.
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
|
||||
class enable_shared_from: public enable_shared_from_this<enable_shared_from>
|
||||
{
|
||||
};
|
||||
|
||||
template<class T> shared_ptr<T> shared_from( T * p );
|
||||
template<class T> weak_ptr<T> weak_from( T * p ) noexcept;
|
||||
}
|
||||
```
|
||||
|
||||
## Functions
|
||||
|
||||
```
|
||||
template<class T> shared_ptr<T> shared_from( T * p );
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `shared_ptr<T>( p\->enable_shared_from::shared_from_this(), p )`.
|
||||
|
||||
NOTE: Throws `bad_weak_ptr` when `p` is not owned by a `shared_ptr`.
|
||||
|
||||
```
|
||||
template<class T> weak_ptr<T> weak_from( T * p ) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `weak_ptr<T>( p\->enable_shared_from::weak_from_this(), p )`.
|
||||
|
||||
NOTE: Unlike `shared_from(this)`, `weak_from(this)` is valid in a destructor
|
||||
and returns a `weak_ptr` that is `expired()` but still shares ownership
|
||||
with other `weak_ptr` instances (if any) that refer to the object.
|
||||
148
doc/smart_ptr/enable_shared_from_this.adoc
Normal file
148
doc/smart_ptr/enable_shared_from_this.adoc
Normal file
@@ -0,0 +1,148 @@
|
||||
////
|
||||
Copyright 2002, 2003, 2015, 2017 Peter Dimov
|
||||
|
||||
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
|
||||
////
|
||||
|
||||
[#enable_shared_from_this]
|
||||
# enable_shared_from_this
|
||||
:toc:
|
||||
:toc-title:
|
||||
:idprefix: enable_shared_from_this_
|
||||
|
||||
## Description
|
||||
|
||||
The class template `enable_shared_from_this` is used as a base class that allows
|
||||
a `shared_ptr` or a `weak_ptr` to the current object to be obtained from within a
|
||||
member function.
|
||||
|
||||
`enable_shared_from_this<T>` defines two member functions called `shared_from_this`
|
||||
that return a `shared_ptr<T>` and `shared_ptr<T const>`, depending on constness, to
|
||||
`this`. It also defines two member functions called `weak_from_this` that return a
|
||||
corresponding `weak_ptr`.
|
||||
|
||||
## Example
|
||||
|
||||
```
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <cassert>
|
||||
|
||||
class Y: public boost::enable_shared_from_this<Y>
|
||||
{
|
||||
public:
|
||||
|
||||
boost::shared_ptr<Y> f()
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
boost::shared_ptr<Y> p(new Y);
|
||||
boost::shared_ptr<Y> q = p->f();
|
||||
assert(p == q);
|
||||
assert(!(p < q || q < p)); // p and q must share ownership
|
||||
}
|
||||
```
|
||||
|
||||
## Synopsis
|
||||
|
||||
`enable_shared_from_this` is defined in `<boost/smart_ptr/enable_shared_from_this.hpp>`.
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
|
||||
template<class T> class enable_shared_from_this {
|
||||
private:
|
||||
|
||||
// exposition only
|
||||
weak_ptr<T> weak_this_;
|
||||
|
||||
protected:
|
||||
|
||||
enable_shared_from_this() = default;
|
||||
~enable_shared_from_this() = default;
|
||||
|
||||
enable_shared_from_this(const enable_shared_from_this&) noexcept;
|
||||
enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept;
|
||||
|
||||
public:
|
||||
|
||||
shared_ptr<T> shared_from_this();
|
||||
shared_ptr<T const> shared_from_this() const;
|
||||
|
||||
weak_ptr<T> weak_from_this() noexcept;
|
||||
weak_ptr<T const> weak_from_this() const noexcept;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Members
|
||||
|
||||
```
|
||||
enable_shared_from_this(enable_shared_from_this const &) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Default-constructs `weak_this_`.
|
||||
|
||||
NOTE: `weak_this_` is _not_ copied from the argument.
|
||||
|
||||
```
|
||||
enable_shared_from_this& operator=(enable_shared_from_this const &) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `*this`.
|
||||
|
||||
NOTE: `weak_this_` is unchanged.
|
||||
|
||||
```
|
||||
template<class T> shared_ptr<T> shared_from_this();
|
||||
```
|
||||
```
|
||||
template<class T> shared_ptr<T const> shared_from_this() const;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `shared_ptr<T>(weak_this_)`.
|
||||
|
||||
NOTE: These members throw `bad_weak_ptr` when `*this` is not owned by a `shared_ptr`.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
`weak_this_` is initialized by `shared_ptr` to a copy of itself when it's constructed by a pointer to `*this`.
|
||||
For example, in the following code:
|
||||
```
|
||||
class Y: public boost::enable_shared_from_this<Y> {};
|
||||
|
||||
int main()
|
||||
{
|
||||
boost::shared_ptr<Y> p(new Y);
|
||||
}
|
||||
```
|
||||
the construction of `p` will automatically initialize `p\->weak_this_` to `p`.
|
||||
====
|
||||
|
||||
```
|
||||
template<class T> weak_ptr<T> weak_from_this() noexcept;
|
||||
```
|
||||
```
|
||||
template<class T> weak_ptr<T const> weak_from_this() const noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `weak_this_`.
|
||||
|
||||
NOTE: Unlike `shared_from_this()`, `weak_from_this()` is valid in a destructor
|
||||
and returns a `weak_ptr` that is `expired()` but still shares ownership
|
||||
with other `weak_ptr` instances (if any) that refer to the object.
|
||||
117
doc/smart_ptr/history.adoc
Normal file
117
doc/smart_ptr/history.adoc
Normal file
@@ -0,0 +1,117 @@
|
||||
////
|
||||
Copyright 1999 Greg Colvin and Beman Dawes
|
||||
Copyright 2002 Darin Adler
|
||||
Copyright 2017 Peter Dimov
|
||||
|
||||
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
|
||||
////
|
||||
|
||||
[[history]]
|
||||
[appendix]
|
||||
# History and Acknowledgments
|
||||
:idprefix: history_
|
||||
|
||||
## Summer 1994
|
||||
|
||||
Greg Colvin http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1994/N0555.pdf[proposed]
|
||||
to the {cpp} Standards Committee classes named `auto_ptr` and `counted_ptr` which were very
|
||||
similar to what we now call `scoped_ptr` and `shared_ptr`. In one of the very few cases
|
||||
where the Library Working Group's recommendations were not followed by the full committee,
|
||||
`counted_ptr` was rejected and surprising transfer-of-ownership semantics were added to `auto_ptr`.
|
||||
|
||||
## October 1998
|
||||
|
||||
Beman Dawes proposed reviving the original semantics under the names `safe_ptr` and `counted_ptr`,
|
||||
meeting of Per Andersson, Matt Austern, Greg Colvin, Sean Corfield, Pete Becker, Nico Josuttis,
|
||||
Dietmar Kühl, Nathan Myers, Chichiang Wan and Judy Ward. During the discussion, the four new class
|
||||
names were finalized, it was decided that there was no need to exactly follow the `std::auto_ptr`
|
||||
interface, and various function signatures and semantics were finalized.
|
||||
|
||||
Over the next three months, several implementations were considered for `shared_ptr`, and discussed
|
||||
on the http://www.boost.org/[boost.org] mailing list. The implementation questions revolved around
|
||||
the reference count which must be kept, either attached to the pointed to object, or detached elsewhere.
|
||||
Each of those variants have themselves two major variants:
|
||||
|
||||
* Direct detached: the `shared_ptr` contains a pointer to the object, and a pointer to the count.
|
||||
* Indirect detached: the `shared_ptr` contains a pointer to a helper object, which in turn contains a pointer to the object and the count.
|
||||
* Embedded attached: the count is a member of the object pointed to.
|
||||
* Placement attached: the count is attached via operator new manipulations.
|
||||
|
||||
Each implementation technique has advantages and disadvantages. We went so far as to run various timings
|
||||
of the direct and indirect approaches, and found that at least on Intel Pentium chips there was very little
|
||||
measurable difference. Kevlin Henney provided a paper he wrote on "Counted Body Techniques." Dietmar Kühl
|
||||
suggested an elegant partial template specialization technique to allow users to choose which implementation
|
||||
they preferred, and that was also experimented with.
|
||||
|
||||
But Greg Colvin and Jerry Schwarz argued that "parameterization will discourage users", and in the end we choose
|
||||
to supply only the direct implementation.
|
||||
|
||||
## May 1999
|
||||
|
||||
In April and May, 1999, Valentin Bonnard and David Abrahams made a number of suggestions resulting in numerous improvements.
|
||||
|
||||
## September 1999
|
||||
|
||||
Luis Coelho provided `shared_ptr::swap` and `shared_array::swap`.
|
||||
|
||||
## November 1999
|
||||
|
||||
Darin Adler provided `operator ==`, `operator !=`, and `std::swap` and `std::less` specializations for shared types.
|
||||
|
||||
## May 2001
|
||||
|
||||
Vladimir Prus suggested requiring a complete type on destruction. Refinement evolved in discussions including Dave Abrahams,
|
||||
Greg Colvin, Beman Dawes, Rainer Deyke, Peter Dimov, John Maddock, Vladimir Prus, Shankar Sai, and others.
|
||||
|
||||
## January 2002
|
||||
|
||||
Peter Dimov reworked all four classes, adding features, fixing bugs, splitting them into four separate headers, and adding
|
||||
`weak_ptr`.
|
||||
|
||||
## March 2003
|
||||
|
||||
Peter Dimov, Beman Dawes and Greg Colvin http://open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1450.html[proposed] `shared_ptr`
|
||||
and `weak_ptr` for inclusion in the Standard Library via the first Library Technical Report (known as TR1). The proposal was
|
||||
accepted and eventually went on to become a part of the {cpp} standard in its 2011 iteration.
|
||||
|
||||
## July 2007
|
||||
|
||||
Peter Dimov and Beman Dawes http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2351.htm[proposed] a number of enhancements
|
||||
to `shared_ptr` as it was entering the working paper that eventually became the {cpp}11 standard.
|
||||
|
||||
## November 2012
|
||||
|
||||
Glen Fernandes provided implementations of `make_shared` and `allocate_shared` for arrays. They achieve a single allocation
|
||||
for an array that can be initialized with constructor arguments or initializer lists as well as overloads for default initialization
|
||||
and no value initialization.
|
||||
|
||||
Peter Dimov aided this development by extending `shared_ptr` to support arrays via the syntax `shared_ptr<T[]>` and `shared_ptr<T[N]>`.
|
||||
|
||||
## April 2013
|
||||
|
||||
Peter Dimov http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3640.html[proposed] the extension of `shared_ptr` to support
|
||||
arrays for inclusion into the standard, and it was accepted.
|
||||
|
||||
## February 2014
|
||||
|
||||
Glen Fernandes updated `make_shared` and `allocate_shared` to conform to the specification in {cpp} standard paper
|
||||
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3870.html[N3870], and implemented `make_unique` for arrays and objects.
|
||||
|
||||
Peter Dimov and Glen Fernandes updated the scalar and array implementations, respectively, to resolve {cpp} standard library defect 2070.
|
||||
|
||||
## February 2017
|
||||
|
||||
Glen Fernandes rewrote `allocate_shared` and `make_shared` for arrays for a more optimal and more maintainable implementation.
|
||||
|
||||
## June 2017
|
||||
|
||||
Peter Dimov and Glen Fernandes rewrote the documentation in Asciidoc format.
|
||||
|
||||
Peter Dimov added `atomic_shared_ptr` and `local_shared_ptr`.
|
||||
|
||||
## August 2019
|
||||
|
||||
Glen Fernandes implemented `allocate_unique` for scalars and arrays.
|
||||
52
doc/smart_ptr/introduction.adoc
Normal file
52
doc/smart_ptr/introduction.adoc
Normal file
@@ -0,0 +1,52 @@
|
||||
////
|
||||
Copyright 1999 Greg Colvin and Beman Dawes
|
||||
Copyright 2002 Darin Adler
|
||||
Copyright 2017 Peter Dimov
|
||||
|
||||
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
|
||||
////
|
||||
|
||||
[#introduction]
|
||||
# Introduction
|
||||
:toc:
|
||||
:toc-title:
|
||||
:idprefix: intro_
|
||||
|
||||
Smart pointers are objects which store pointers to dynamically allocated (heap) objects.
|
||||
They behave much like built-in {cpp} pointers except that they automatically delete the object
|
||||
pointed to at the appropriate time. Smart pointers are particularly useful in the face of
|
||||
exceptions as they ensure proper destruction of dynamically allocated objects. They can also be
|
||||
used to keep track of dynamically allocated objects shared by multiple owners.
|
||||
|
||||
Conceptually, smart pointers are seen as owning the object pointed to, and thus responsible for
|
||||
deletion of the object when it is no longer needed. As such, they are examples of the "resource
|
||||
acquisition is initialization" idiom described in Bjarne Stroustrup's "The C++ Programming Language",
|
||||
3rd edition, Section 14.4, Resource Management.
|
||||
|
||||
This library provides six smart pointer class templates:
|
||||
|
||||
* `<<scoped_ptr,scoped_ptr>>`, used to contain ownership of a dynamically allocated object to the current scope;
|
||||
* `<<scoped_array,scoped_array>>`, which provides scoped ownership for a dynamically allocated array;
|
||||
* `<<shared_ptr,shared_ptr>>`, a versatile tool for managing shared ownership of an object or array;
|
||||
* `<<weak_ptr,weak_ptr>>`, a non-owning observer to a shared_ptr-managed object that can be promoted temporarily to shared_ptr;
|
||||
* `<<intrusive_ptr,intrusive_ptr>>`, a pointer to objects with an embedded reference count;
|
||||
* `<<local_shared_ptr,local_shared_ptr>>`, providing shared ownership within a single thread.
|
||||
|
||||
`shared_ptr` and `weak_ptr` are part of the {cpp} standard since its 2011 iteration.
|
||||
|
||||
In addition, the library contains the following supporting utility functions and classes:
|
||||
|
||||
* `<<make_shared,make_shared>>`, a factory function for creating objects that returns a `shared_ptr`;
|
||||
* `<<make_unique,make_unique>>`, a factory function returning `std::unique_ptr`;
|
||||
* `<<allocate_unique,allocate_unique>>`, a factory function for creating objects using an allocator that returns a `std::unique_ptr`;
|
||||
* `<<enable_shared_from_this,enable_shared_from_this>>`, a helper base class that enables the acquisition of a `shared_ptr` pointing to `this`;
|
||||
* `<<pointer_to_other,pointer_to_other>>`, a helper trait for converting one smart pointer type to another;
|
||||
* `<<pointer_cast,static_pointer_cast>>` and companions, generic smart pointer casts;
|
||||
* `<<intrusive_ref_counter,intrusive_ref_counter>>`, a helper base class containing a reference count.
|
||||
* `<<atomic_shared_ptr,atomic_shared_ptr>>`, a helper class implementing the interface of `std::atomic` for a value of type `shared_ptr`.
|
||||
|
||||
As a general rule, the destructor or `operator delete` for an object managed by pointers in the library
|
||||
are not allowed to throw exceptions.
|
||||
478
doc/smart_ptr/intrusive_ptr.adoc
Normal file
478
doc/smart_ptr/intrusive_ptr.adoc
Normal file
@@ -0,0 +1,478 @@
|
||||
////
|
||||
Copyright 2003-2005, 2013, 2017 Peter Dimov
|
||||
|
||||
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
|
||||
////
|
||||
|
||||
[#intrusive_ptr]
|
||||
# intrusive_ptr: Managing Objects with Embedded Counts
|
||||
:toc:
|
||||
:toc-title:
|
||||
:idprefix: intrusive_ptr_
|
||||
|
||||
## Description
|
||||
|
||||
The `intrusive_ptr` class template stores a pointer to an object with an embedded reference count.
|
||||
Every new `intrusive_ptr` instance increments the reference count by using an unqualified call to the
|
||||
function `intrusive_ptr_add_ref`, passing it the pointer as an argument. Similarly, when an `intrusive_ptr`
|
||||
is destroyed, it calls `intrusive_ptr_release`; this function is responsible for destroying the object when
|
||||
its reference count drops to zero. The user is expected to provide suitable definitions of these two functions.
|
||||
On compilers that support argument-dependent lookup, `intrusive_ptr_add_ref` and `intrusive_ptr_release` should
|
||||
be defined in the namespace that corresponds to their parameter; otherwise, the definitions need to go in namespace
|
||||
`boost`. The library provides a helper base class template `<<intrusive_ref_counter,intrusive_ref_counter>>` which
|
||||
may help adding support for `intrusive_ptr` to user types.
|
||||
|
||||
The class template is parameterized on `T`, the type of the object pointed to. `intrusive_ptr<T>` can be implicitly
|
||||
converted to `intrusive_ptr<U>` whenever `T*` can be implicitly converted to `U*`.
|
||||
|
||||
The main reasons to use `intrusive_ptr` are:
|
||||
|
||||
* Some existing frameworks or OSes provide objects with embedded reference counts;
|
||||
* The memory footprint of `intrusive_ptr` is the same as the corresponding raw pointer;
|
||||
* `intrusive_ptr<T>` can be constructed from an arbitrary raw pointer of type `T*`.
|
||||
|
||||
As a general rule, if it isn't obvious whether `intrusive_ptr` better fits your needs than `shared_ptr`, try a `shared_ptr`-based design first.
|
||||
|
||||
## Synopsis
|
||||
|
||||
`intrusive_ptr` is defined in `<boost/smart_ptr/intrusive_ptr.hpp>`.
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
|
||||
template<class T> class intrusive_ptr {
|
||||
public:
|
||||
|
||||
typedef T element_type;
|
||||
|
||||
intrusive_ptr() noexcept;
|
||||
intrusive_ptr(T * p, bool add_ref = true);
|
||||
|
||||
intrusive_ptr(intrusive_ptr const & r);
|
||||
template<class Y> intrusive_ptr(intrusive_ptr<Y> const & r);
|
||||
|
||||
intrusive_ptr(intrusive_ptr && r);
|
||||
template<class Y> intrusive_ptr(intrusive_ptr<Y> && r);
|
||||
|
||||
~intrusive_ptr();
|
||||
|
||||
intrusive_ptr & operator=(intrusive_ptr const & r);
|
||||
template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r);
|
||||
intrusive_ptr & operator=(T * r);
|
||||
|
||||
intrusive_ptr & operator=(intrusive_ptr && r);
|
||||
template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> && r);
|
||||
|
||||
void reset();
|
||||
void reset(T * r);
|
||||
void reset(T * r, bool add_ref);
|
||||
|
||||
T & operator*() const noexcept;
|
||||
T * operator->() const noexcept;
|
||||
T * get() const noexcept;
|
||||
T * detach() noexcept;
|
||||
|
||||
explicit operator bool () const noexcept;
|
||||
|
||||
void swap(intrusive_ptr & b) noexcept;
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept;
|
||||
|
||||
template<class T, class U>
|
||||
bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept;
|
||||
|
||||
template<class T, class U>
|
||||
bool operator==(intrusive_ptr<T> const & a, U * b) noexcept;
|
||||
|
||||
template<class T, class U>
|
||||
bool operator!=(intrusive_ptr<T> const & a, U * b) noexcept;
|
||||
|
||||
template<class T, class U>
|
||||
bool operator==(T * a, intrusive_ptr<U> const & b) noexcept;
|
||||
|
||||
template<class T, class U>
|
||||
bool operator!=(T * a, intrusive_ptr<U> const & b) noexcept;
|
||||
|
||||
template<class T>
|
||||
bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) noexcept;
|
||||
|
||||
template<class T> void swap(intrusive_ptr<T> & a, intrusive_ptr<T> & b) noexcept;
|
||||
|
||||
template<class T> T * get_pointer(intrusive_ptr<T> const & p) noexcept;
|
||||
|
||||
template<class T, class U>
|
||||
intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & r) noexcept;
|
||||
|
||||
template<class T, class U>
|
||||
intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & r) noexcept;
|
||||
|
||||
template<class T, class U>
|
||||
intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & r) noexcept;
|
||||
|
||||
template<class E, class T, class Y>
|
||||
std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os,
|
||||
intrusive_ptr<Y> const & p);
|
||||
}
|
||||
```
|
||||
|
||||
## Members
|
||||
|
||||
### element_type
|
||||
|
||||
```
|
||||
typedef T element_type;
|
||||
```
|
||||
|
||||
Provides the type of the template parameter T.
|
||||
|
||||
### constructors
|
||||
|
||||
```
|
||||
intrusive_ptr() noexcept;
|
||||
```
|
||||
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Postconditions:: `get() == 0`.
|
||||
|
||||
```
|
||||
intrusive_ptr(T * p, bool add_ref = true);
|
||||
```
|
||||
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: `if(p != 0 && add_ref) intrusive_ptr_add_ref(p);`.
|
||||
Postconditions:: `get() == p`.
|
||||
|
||||
```
|
||||
intrusive_ptr(intrusive_ptr const & r);
|
||||
```
|
||||
```
|
||||
template<class Y> intrusive_ptr(intrusive_ptr<Y> const & r);
|
||||
```
|
||||
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: `T * p = r.get(); if(p != 0) intrusive_ptr_add_ref(p);`.
|
||||
Postconditions:: `get() == r.get()`.
|
||||
|
||||
```
|
||||
intrusive_ptr(intrusive_ptr && r);
|
||||
```
|
||||
```
|
||||
template<class Y> intrusive_ptr(intrusive_ptr<Y> && r);
|
||||
```
|
||||
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Postconditions:: `get()` equals the old value of `r.get()`. `r.get() == 0`.
|
||||
|
||||
### destructor
|
||||
|
||||
```
|
||||
~intrusive_ptr();
|
||||
```
|
||||
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: `if(get() != 0) intrusive_ptr_release(get());`.
|
||||
|
||||
### assignment
|
||||
|
||||
```
|
||||
intrusive_ptr & operator=(intrusive_ptr const & r);
|
||||
```
|
||||
```
|
||||
template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r);
|
||||
```
|
||||
```
|
||||
intrusive_ptr & operator=(T * r);
|
||||
```
|
||||
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Equivalent to `intrusive_ptr(r).swap(*this)`.
|
||||
Returns:: `*this`.
|
||||
|
||||
```
|
||||
intrusive_ptr & operator=(intrusive_ptr && r);
|
||||
```
|
||||
```
|
||||
template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> && r);
|
||||
```
|
||||
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Equivalent to `intrusive_ptr(std::move(r)).swap(*this)`.
|
||||
Returns:: `*this`.
|
||||
|
||||
### reset
|
||||
|
||||
```
|
||||
void reset();
|
||||
```
|
||||
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Equivalent to `intrusive_ptr().swap(*this)`.
|
||||
|
||||
```
|
||||
void reset(T * r);
|
||||
```
|
||||
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Equivalent to `intrusive_ptr(r).swap(*this)`.
|
||||
|
||||
```
|
||||
void reset(T * r, bool add_ref);
|
||||
```
|
||||
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Equivalent to `intrusive_ptr(r, add_ref).swap(*this)`.
|
||||
|
||||
### indirection
|
||||
|
||||
```
|
||||
T & operator*() const noexcept;
|
||||
```
|
||||
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Requirements:: `get() != 0`.
|
||||
Returns:: `*get()`.
|
||||
|
||||
```
|
||||
T * operator->() const noexcept;
|
||||
```
|
||||
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Requirements:: `get() != 0`.
|
||||
Returns:: `get()`.
|
||||
|
||||
### get
|
||||
|
||||
```
|
||||
T * get() const noexcept;
|
||||
```
|
||||
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: the stored pointer.
|
||||
|
||||
### detach
|
||||
|
||||
```
|
||||
T * detach() noexcept;
|
||||
```
|
||||
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: the stored pointer.
|
||||
Postconditions:: `get() == 0`.
|
||||
|
||||
NOTE: The returned pointer has an elevated reference count. This allows conversion of an `intrusive_ptr`
|
||||
back to a raw pointer, without the performance overhead of acquiring and dropping an extra reference.
|
||||
It can be viewed as the complement of the non-reference-incrementing constructor.
|
||||
|
||||
CAUTION: Using `detach` escapes the safety of automatic reference counting provided by `intrusive_ptr`.
|
||||
It should by used only where strictly necessary (such as when interfacing to an existing API), and when
|
||||
the implications are thoroughly understood.
|
||||
|
||||
### conversions
|
||||
|
||||
```
|
||||
explicit operator bool () const noexcept;
|
||||
```
|
||||
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `get() != 0`.
|
||||
|
||||
NOTE: This conversion operator allows `intrusive_ptr` objects to be used in boolean contexts,
|
||||
like `if (p && p\->valid()) {}`.
|
||||
|
||||
NOTE: On C++03 compilers, the return value is of an unspecified type.
|
||||
|
||||
### swap
|
||||
|
||||
```
|
||||
void swap(intrusive_ptr & b) noexcept;
|
||||
```
|
||||
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Exchanges the contents of the two smart pointers.
|
||||
|
||||
## Free Functions
|
||||
|
||||
### comparison
|
||||
|
||||
```
|
||||
template<class T, class U>
|
||||
bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept;
|
||||
```
|
||||
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `a.get() == b.get()`.
|
||||
|
||||
```
|
||||
template<class T, class U>
|
||||
bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept;
|
||||
```
|
||||
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `a.get() != b.get()`.
|
||||
|
||||
```
|
||||
template<class T, class U>
|
||||
bool operator==(intrusive_ptr<T> const & a, U * b) noexcept;
|
||||
```
|
||||
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `a.get() == b`.
|
||||
|
||||
```
|
||||
template<class T, class U>
|
||||
bool operator!=(intrusive_ptr<T> const & a, U * b) noexcept;
|
||||
```
|
||||
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `a.get() != b`.
|
||||
|
||||
```
|
||||
template<class T, class U>
|
||||
bool operator==(T * a, intrusive_ptr<U> const & b) noexcept;
|
||||
```
|
||||
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `a == b.get()`.
|
||||
|
||||
```
|
||||
template<class T, class U>
|
||||
bool operator!=(T * a, intrusive_ptr<U> const & b) noexcept;
|
||||
```
|
||||
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `a != b.get()`.
|
||||
|
||||
```
|
||||
template<class T>
|
||||
bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) noexcept;
|
||||
```
|
||||
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `std::less<T *>()(a.get(), b.get())`.
|
||||
|
||||
NOTE: Allows `intrusive_ptr` objects to be used as keys in associative containers.
|
||||
|
||||
### swap
|
||||
|
||||
```
|
||||
template<class T> void swap(intrusive_ptr<T> & a, intrusive_ptr<T> & b) noexcept;
|
||||
```
|
||||
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Equivalent to `a.swap(b)`.
|
||||
|
||||
### get_pointer
|
||||
|
||||
```
|
||||
template<class T> T * get_pointer(intrusive_ptr<T> const & p) noexcept;
|
||||
```
|
||||
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `p.get()`.
|
||||
|
||||
NOTE: Provided as an aid to generic programming. Used by `mem_fn`.
|
||||
|
||||
### static_pointer_cast
|
||||
|
||||
```
|
||||
template<class T, class U>
|
||||
intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & r) noexcept;
|
||||
```
|
||||
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `intrusive_ptr<T>(static_cast<T*>(r.get()))`.
|
||||
|
||||
### const_pointer_cast
|
||||
|
||||
```
|
||||
template<class T, class U>
|
||||
intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & r) noexcept;
|
||||
```
|
||||
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `intrusive_ptr<T>(const_cast<T*>(r.get()))`.
|
||||
|
||||
### dynamic_pointer_cast
|
||||
|
||||
```
|
||||
template<class T, class U>
|
||||
intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & r) noexcept;
|
||||
```
|
||||
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `intrusive_ptr<T>(dynamic_cast<T*>(r.get()))`.
|
||||
|
||||
### operator<<
|
||||
|
||||
```
|
||||
template<class E, class T, class Y>
|
||||
std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os,
|
||||
intrusive_ptr<Y> const & p);
|
||||
```
|
||||
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: `os << p.get();`.
|
||||
Returns:: `os`.
|
||||
153
doc/smart_ptr/intrusive_ref_counter.adoc
Normal file
153
doc/smart_ptr/intrusive_ref_counter.adoc
Normal file
@@ -0,0 +1,153 @@
|
||||
////
|
||||
Copyright 2017 Peter Dimov
|
||||
Copyright 2013 Andrey Semashev
|
||||
|
||||
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
|
||||
////
|
||||
|
||||
[#intrusive_ref_counter]
|
||||
# intrusive_ref_counter
|
||||
:toc:
|
||||
:toc-title:
|
||||
:idprefix: intrusive_ref_counter_
|
||||
|
||||
## Description
|
||||
|
||||
The `intrusive_ref_counter` class template implements a reference counter for
|
||||
a derived user's class that is intended to be used with `intrusive_ptr`. The
|
||||
base class has associated `intrusive_ptr_add_ref` and `intrusive_ptr_release`
|
||||
functions which modify the reference counter as needed and destroy the user's
|
||||
object when the counter drops to zero.
|
||||
|
||||
The class template is parameterized on `Derived` and `CounterPolicy`
|
||||
parameters. The first parameter is the user's class that derives from
|
||||
`intrusive_ref_counter`. This type is needed in order to destroy the object
|
||||
correctly when there are no references to it left.
|
||||
|
||||
The second parameter is a policy that defines the nature of the reference
|
||||
counter. The library provides two such policies: `thread_unsafe_counter` and
|
||||
`thread_safe_counter`. The former instructs the `intrusive_ref_counter` base
|
||||
class to use a counter only suitable for a single-threaded use. Pointers to a
|
||||
single object that uses this kind of reference counter must not be used in
|
||||
different threads. The latter policy makes the reference counter thread-safe,
|
||||
unless the target platform doesn't support threading. Since in modern systems
|
||||
support for threading is common, the default counter policy is
|
||||
`thread_safe_counter`.
|
||||
|
||||
## Synopsis
|
||||
|
||||
`intrusive_ref_counter` is defined in
|
||||
`<boost/smart_ptr/intrusive_ref_counter.hpp>`.
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
struct thread_unsafe_counter;
|
||||
struct thread_safe_counter;
|
||||
|
||||
template<class Derived, class CounterPolicy = thread_safe_counter>
|
||||
class intrusive_ref_counter {
|
||||
public:
|
||||
intrusive_ref_counter() noexcept;
|
||||
intrusive_ref_counter(const intrusive_ref_counter& v) noexcept;
|
||||
|
||||
intrusive_ref_counter& operator=(const intrusive_ref_counter& v) noexcept;
|
||||
|
||||
unsigned int use_count() const noexcept;
|
||||
|
||||
protected:
|
||||
~intrusive_ref_counter() = default;
|
||||
};
|
||||
|
||||
template<class Derived, class CounterPolicy>
|
||||
void intrusive_ptr_add_ref(
|
||||
const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept;
|
||||
|
||||
template<class Derived, class CounterPolicy>
|
||||
void intrusive_ptr_release(
|
||||
const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept;
|
||||
}
|
||||
```
|
||||
|
||||
## Members
|
||||
|
||||
### Constructors
|
||||
|
||||
```
|
||||
intrusive_ref_counter() noexcept;
|
||||
```
|
||||
```
|
||||
intrusive_ref_counter(const intrusive_ref_counter&) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Postconditions:: `use_count() == 0`.
|
||||
|
||||
NOTE: The pointer to the constructed object is expected to be passed to
|
||||
`intrusive_ptr` constructor, assignment operator or `reset` method, which
|
||||
would increment the reference counter.
|
||||
|
||||
### Destructor
|
||||
|
||||
```
|
||||
~intrusive_ref_counter();
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Destroys the counter object.
|
||||
|
||||
NOTE: The destructor is protected so that the object can only be destroyed
|
||||
through the `Derived` class.
|
||||
|
||||
### Assignment
|
||||
|
||||
```
|
||||
intrusive_ref_counter& operator=(const intrusive_ref_counter& v) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Does nothing, reference counter is not modified.
|
||||
|
||||
### use_count
|
||||
|
||||
```
|
||||
unsigned int use_count() const noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: The current value of the reference counter.
|
||||
|
||||
NOTE: The returned value may not be actual in multi-threaded applications.
|
||||
|
||||
## Free Functions
|
||||
|
||||
### intrusive_ptr_add_ref
|
||||
|
||||
```
|
||||
template<class Derived, class CounterPolicy>
|
||||
void intrusive_ptr_add_ref(
|
||||
const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Increments the reference counter.
|
||||
|
||||
### intrusive_ptr_release
|
||||
|
||||
```
|
||||
template<class Derived, class CounterPolicy>
|
||||
void intrusive_ptr_release(
|
||||
const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Decrements the reference counter. If the reference counter reaches
|
||||
0, calls `delete static_cast<const Derived*>(p)`.
|
||||
718
doc/smart_ptr/local_shared_ptr.adoc
Normal file
718
doc/smart_ptr/local_shared_ptr.adoc
Normal file
@@ -0,0 +1,718 @@
|
||||
////
|
||||
Copyright 2017 Peter Dimov
|
||||
|
||||
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
|
||||
////
|
||||
|
||||
[#local_shared_ptr]
|
||||
# local_shared_ptr: Shared Ownership within a Single Thread
|
||||
:toc:
|
||||
:toc-title:
|
||||
:idprefix: local_shared_ptr_
|
||||
|
||||
## Description
|
||||
|
||||
`local_shared_ptr` is nearly identical to `shared_ptr`, with the only difference of note being that its reference count is
|
||||
updated with non-atomic operations. As such, a `local_shared_ptr` and all its copies must reside in (be local to) a single
|
||||
thread (hence the name.)
|
||||
|
||||
`local_shared_ptr` can be converted to `shared_ptr` and vice versa. Creating a `local_shared_ptr` from a `shared_ptr` creates
|
||||
a new local reference count; this means that two `local_shared_ptr` instances, both created from the same `shared_ptr`, refer
|
||||
to the same object but don't share the same count, and as such, can safely be used by two different threads.
|
||||
|
||||
.Two local_shared_ptr instances created from a shared_ptr
|
||||
```
|
||||
shared_ptr<X> p1( new X );
|
||||
|
||||
local_shared_ptr<X> p2( p1 ); // p2.local_use_count() == 1
|
||||
local_shared_ptr<X> p3( p1 ); // p3.local_use_count() also 1
|
||||
```
|
||||
|
||||
Creating the second `local_shared_ptr` from the first one, however, does lead to the two sharing the same count:
|
||||
|
||||
.A local_shared_ptr created from another local_shared_ptr
|
||||
```
|
||||
shared_ptr<X> p1( new X );
|
||||
|
||||
local_shared_ptr<X> p2( p1 ); // p2.local_use_count() == 1
|
||||
local_shared_ptr<X> p3( p2 ); // p3.local_use_count() == 2
|
||||
```
|
||||
|
||||
Two `shared_ptr` instances created from the same `local_shared_ptr` do share ownership:
|
||||
|
||||
.Two shared_ptr instances created from a local_shared_ptr
|
||||
```
|
||||
local_shared_ptr<X> p1( new X );
|
||||
|
||||
shared_ptr<X> p2( p1 ); // p2.use_count() == 2
|
||||
shared_ptr<X> p3( p1 ); // p3.use_count() == 3
|
||||
```
|
||||
|
||||
Here `p2.use_count()` is 2, because `p1` holds a reference, too.
|
||||
|
||||
One can think of `local_shared_ptr<T>` as `shared_ptr<shared_ptr<T>>`, with the outer `shared_ptr` using non-atomic operations for
|
||||
its count. Converting from `local_shared_ptr` to `shared_ptr` gives you a copy of the inner `shared_ptr`; converting from `shared_ptr`
|
||||
wraps it into an outer `shared_ptr` with a non-atomic use count (conceptually speaking) and returns the result.
|
||||
|
||||
## Synopsis
|
||||
|
||||
`local_shared_ptr` is defined in `<boost/smart_ptr/local_shared_ptr.hpp>`.
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
|
||||
template<class T> class local_shared_ptr {
|
||||
public:
|
||||
|
||||
typedef /*see below*/ element_type;
|
||||
|
||||
// constructors
|
||||
|
||||
constexpr local_shared_ptr() noexcept;
|
||||
constexpr local_shared_ptr(std::nullptr_t) noexcept;
|
||||
|
||||
template<class Y> explicit local_shared_ptr(Y * p);
|
||||
|
||||
template<class Y, class D> local_shared_ptr(Y * p, D d);
|
||||
template<class D> local_shared_ptr(std::nullptr_t p, D d);
|
||||
|
||||
template<class Y, class D, class A> local_shared_ptr(Y * p, D d, A a);
|
||||
template<class D, class A> local_shared_ptr(std::nullptr_t p, D d, A a);
|
||||
|
||||
local_shared_ptr(local_shared_ptr const & r) noexcept;
|
||||
template<class Y> local_shared_ptr(local_shared_ptr<Y> const & r) noexcept;
|
||||
|
||||
local_shared_ptr(local_shared_ptr && r) noexcept;
|
||||
template<class Y> local_shared_ptr(local_shared_ptr<Y> && r) noexcept;
|
||||
|
||||
template<class Y> local_shared_ptr( shared_ptr<Y> const & r );
|
||||
template<class Y> local_shared_ptr( shared_ptr<Y> && r );
|
||||
|
||||
template<class Y> local_shared_ptr(local_shared_ptr<Y> const & r, element_type * p) noexcept;
|
||||
template<class Y> local_shared_ptr(local_shared_ptr<Y> && r, element_type * p) noexcept;
|
||||
|
||||
template<class Y, class D> local_shared_ptr(std::unique_ptr<Y, D> && r);
|
||||
|
||||
// destructor
|
||||
|
||||
~local_shared_ptr() noexcept;
|
||||
|
||||
// assignment
|
||||
|
||||
local_shared_ptr & operator=(local_shared_ptr const & r) noexcept;
|
||||
template<class Y> local_shared_ptr & operator=(local_shared_ptr<Y> const & r) noexcept;
|
||||
|
||||
local_shared_ptr & operator=(local_shared_ptr const && r) noexcept;
|
||||
template<class Y> local_shared_ptr & operator=(local_shared_ptr<Y> const && r) noexcept;
|
||||
|
||||
template<class Y, class D> local_shared_ptr & operator=(std::unique_ptr<Y, D> && r);
|
||||
|
||||
local_shared_ptr & operator=(std::nullptr_t) noexcept;
|
||||
|
||||
// reset
|
||||
|
||||
void reset() noexcept;
|
||||
|
||||
template<class Y> void reset(Y * p);
|
||||
template<class Y, class D> void reset(Y * p, D d);
|
||||
template<class Y, class D, class A> void reset(Y * p, D d, A a);
|
||||
|
||||
template<class Y> void reset(local_shared_ptr<Y> const & r, element_type * p) noexcept;
|
||||
template<class Y> void reset(local_shared_ptr<Y> && r, element_type * p) noexcept;
|
||||
|
||||
// accessors
|
||||
|
||||
T & operator*() const noexcept; // only valid when T is not an array type
|
||||
T * operator->() const noexcept; // only valid when T is not an array type
|
||||
|
||||
// only valid when T is an array type
|
||||
element_type & operator[](std::ptrdiff_t i) const noexcept;
|
||||
|
||||
element_type * get() const noexcept;
|
||||
|
||||
long local_use_count() const noexcept;
|
||||
|
||||
// conversions
|
||||
|
||||
explicit operator bool() const noexcept;
|
||||
|
||||
template<class Y> operator shared_ptr<Y>() const noexcept;
|
||||
template<class Y> operator weak_ptr<Y>() const noexcept;
|
||||
|
||||
// swap
|
||||
|
||||
void swap(local_shared_ptr & b) noexcept;
|
||||
|
||||
// owner_before
|
||||
|
||||
template<class Y> bool owner_before(local_shared_ptr<Y> const & rhs) const noexcept;
|
||||
};
|
||||
|
||||
// comparisons
|
||||
|
||||
template<class T, class U>
|
||||
bool operator==(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
|
||||
template<class T, class U>
|
||||
bool operator==(local_shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
|
||||
template<class T, class U>
|
||||
bool operator==(shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
|
||||
|
||||
template<class T, class U>
|
||||
bool operator!=(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
|
||||
template<class T, class U>
|
||||
bool operator!=(local_shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
|
||||
template<class T, class U>
|
||||
bool operator!=(shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
|
||||
|
||||
template<class T> bool operator==(local_shared_ptr<T> const & p, std::nullptr_t) noexcept;
|
||||
template<class T> bool operator==(std::nullptr_t, local_shared_ptr<T> const & p) noexcept;
|
||||
|
||||
template<class T> bool operator!=(local_shared_ptr<T> const & p, std::nullptr_t) noexcept;
|
||||
template<class T> bool operator!=(std::nullptr_t, local_shared_ptr<T> const & p) noexcept;
|
||||
|
||||
template<class T, class U>
|
||||
bool operator<(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
|
||||
|
||||
// swap
|
||||
|
||||
template<class T> void swap(local_shared_ptr<T> & a, local_shared_ptr<T> & b) noexcept;
|
||||
|
||||
// get_pointer
|
||||
|
||||
template<class T>
|
||||
typename local_shared_ptr<T>::element_type *
|
||||
get_pointer(local_shared_ptr<T> const & p) noexcept;
|
||||
|
||||
// casts
|
||||
|
||||
template<class T, class U>
|
||||
local_shared_ptr<T> static_pointer_cast(local_shared_ptr<U> const & r) noexcept;
|
||||
|
||||
template<class T, class U>
|
||||
local_shared_ptr<T> const_pointer_cast(local_shared_ptr<U> const & r) noexcept;
|
||||
|
||||
template<class T, class U>
|
||||
local_shared_ptr<T> dynamic_pointer_cast(local_shared_ptr<U> const & r) noexcept;
|
||||
|
||||
template<class T, class U>
|
||||
local_shared_ptr<T> reinterpret_pointer_cast(local_shared_ptr<U> const & r) noexcept;
|
||||
|
||||
// stream I/O
|
||||
|
||||
template<class E, class T, class Y>
|
||||
std::basic_ostream<E, T> &
|
||||
operator<< (std::basic_ostream<E, T> & os, local_shared_ptr<Y> const & p);
|
||||
|
||||
// get_deleter
|
||||
|
||||
template<class D, class T> D * get_deleter(local_shared_ptr<T> const & p) noexcept;
|
||||
}
|
||||
```
|
||||
|
||||
## Members
|
||||
|
||||
### element_type
|
||||
```
|
||||
typedef ... element_type;
|
||||
```
|
||||
`element_type` is `T` when `T` is not an array type, and `U` when `T` is `U[]` or `U[N]`.
|
||||
|
||||
### default constructor
|
||||
```
|
||||
constexpr local_shared_ptr() noexcept;
|
||||
```
|
||||
```
|
||||
constexpr local_shared_ptr(std::nullptr_t) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Constructs an empty `local_shared_ptr`.
|
||||
Postconditions:: `local_use_count() == 0 && get() == 0`.
|
||||
|
||||
### pointer constructor
|
||||
```
|
||||
template<class Y> explicit local_shared_ptr(Y * p);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Constructs a `local_shared_ptr` that owns `shared_ptr<T>( p )`.
|
||||
|
||||
Postconditions:: `local_use_count() == 1 && get() == p`.
|
||||
|
||||
Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained.
|
||||
|
||||
### constructors taking a deleter
|
||||
```
|
||||
template<class Y, class D> local_shared_ptr(Y * p, D d);
|
||||
```
|
||||
```
|
||||
template<class D> local_shared_ptr(std::nullptr_t p, D d);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Constructs a `local_shared_ptr` that owns `shared_ptr<T>( p, d )`.
|
||||
|
||||
Postconditions:: `local_use_count() == 1 && get() == p`.
|
||||
|
||||
Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained.
|
||||
|
||||
```
|
||||
template<class Y, class D, class A> local_shared_ptr(Y * p, D d, A a);
|
||||
```
|
||||
```
|
||||
template<class D, class A> local_shared_ptr(std::nullptr_t p, D d, A a);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Constructs a `local_shared_ptr` that owns `shared_ptr<T>( p, d, a )`.
|
||||
|
||||
Postconditions:: `local_use_count() == 1 && get() == p`.
|
||||
|
||||
Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained.
|
||||
|
||||
### copy and converting constructors
|
||||
```
|
||||
local_shared_ptr(local_shared_ptr const & r) noexcept;
|
||||
```
|
||||
```
|
||||
template<class Y> local_shared_ptr(local_shared_ptr<Y> const & r) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Requires:: `Y*` should be convertible to `T*`.
|
||||
|
||||
Effects:: If `r` is empty, constructs an empty `local_shared_ptr`; otherwise, constructs a `local_shared_ptr` that shares ownership with `r`.
|
||||
|
||||
Postconditions:: `get() == r.get() && local_use_count() == r.local_use_count()`.
|
||||
|
||||
### move constructors
|
||||
```
|
||||
local_shared_ptr(local_shared_ptr && r) noexcept;
|
||||
```
|
||||
```
|
||||
template<class Y> local_shared_ptr(local_shared_ptr<Y> && r) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Requires:: `Y*` should be convertible to `T*`.
|
||||
|
||||
Effects:: Move-constructs a `local_shared_ptr` from `r`.
|
||||
|
||||
Postconditions:: `*this` contains the old value of `r`. `r` is empty and `r.get() == 0`.
|
||||
|
||||
### shared_ptr constructor
|
||||
```
|
||||
template<class Y> local_shared_ptr( shared_ptr<Y> const & r );
|
||||
```
|
||||
```
|
||||
template<class Y> local_shared_ptr( shared_ptr<Y> && r );
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Constructs a `local_shared_ptr` that owns `r`.
|
||||
|
||||
Postconditions:: `local_use_count() == 1`. `get()` returns the old value of `r.get()`.
|
||||
|
||||
Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained.
|
||||
|
||||
### aliasing constructor
|
||||
```
|
||||
template<class Y> local_shared_ptr(local_shared_ptr<Y> const & r, element_type * p) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: constructs a `local_shared_ptr` that shares ownership with `r` and stores `p`.
|
||||
|
||||
Postconditions:: `get() == p && local_use_count() == r.local_use_count()`.
|
||||
|
||||
### aliasing move constructor
|
||||
```
|
||||
template<class Y> local_shared_ptr(local_shared_ptr<Y> && r, element_type * p) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Move-constructs a `local_shared_ptr` from `r`, while storing `p` instead.
|
||||
|
||||
Postconditions:: `get() == p` and `local_use_count()` equals the old count of `r`. `r` is empty and `r.get() == 0`.
|
||||
|
||||
### unique_ptr constructor
|
||||
```
|
||||
template<class Y, class D> local_shared_ptr(std::unique_ptr<Y, D> && r);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Requires:: `Y*` should be convertible to `T*`.
|
||||
|
||||
Effects::
|
||||
- When `r.get() == 0`, equivalent to `local_shared_ptr()`;
|
||||
- Otherwise, constructs a `local_shared_ptr` that owns `shared_ptr<T>( std::move(r) )`.
|
||||
|
||||
Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained.
|
||||
|
||||
Exception safety:: If an exception is thrown, the constructor has no effect.
|
||||
|
||||
### destructor
|
||||
```
|
||||
~local_shared_ptr() noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects::
|
||||
- If `*this` is empty, or shares ownership with another `local_shared_ptr` instance (`local_use_count() > 1`), there are no side effects.
|
||||
- Otherwise, destroys the owned `shared_ptr`.
|
||||
|
||||
### assignment
|
||||
```
|
||||
local_shared_ptr & operator=(local_shared_ptr const & r) noexcept;
|
||||
```
|
||||
```
|
||||
template<class Y> local_shared_ptr & operator=(local_shared_ptr<Y> const & r) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Equivalent to `local_shared_ptr(r).swap(*this)`.
|
||||
Returns:: `*this`.
|
||||
|
||||
```
|
||||
local_shared_ptr & operator=(local_shared_ptr && r) noexcept;
|
||||
```
|
||||
```
|
||||
template<class Y> local_shared_ptr & operator=(local_shared_ptr<Y> && r) noexcept;
|
||||
```
|
||||
```
|
||||
template<class Y, class D> local_shared_ptr & operator=(std::unique_ptr<Y, D> && r);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Equivalent to `local_shared_ptr(std::move(r)).swap(*this)`.
|
||||
Returns:: `*this`.
|
||||
|
||||
```
|
||||
local_shared_ptr & operator=(std::nullptr_t) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Equivalent to `local_shared_ptr().swap(*this)`.
|
||||
Returns:: `*this`.
|
||||
|
||||
### reset
|
||||
```
|
||||
void reset() noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Equivalent to `local_shared_ptr().swap(*this)`.
|
||||
|
||||
```
|
||||
template<class Y> void reset(Y * p);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Equivalent to `local_shared_ptr(p).swap(*this)`.
|
||||
|
||||
```
|
||||
template<class Y, class D> void reset(Y * p, D d);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Equivalent to `local_shared_ptr(p, d).swap(*this)`.
|
||||
|
||||
```
|
||||
template<class Y, class D, class A> void reset(Y * p, D d, A a);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Equivalent to `local_shared_ptr(p, d, a).swap(*this)`.
|
||||
|
||||
```
|
||||
template<class Y> void reset(local_shared_ptr<Y> const & r, element_type * p) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Equivalent to `local_shared_ptr(r, p).swap(*this)`.
|
||||
|
||||
```
|
||||
template<class Y> void reset(local_shared_ptr<Y> && r, element_type * p) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Equivalent to `local_shared_ptr(std::move(r), p).swap(*this)`.
|
||||
|
||||
### indirection
|
||||
```
|
||||
T & operator*() const noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Requires:: `T` should not be an array type.
|
||||
Returns:: `*get()`.
|
||||
|
||||
```
|
||||
T * operator->() const noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Requires:: `T` should not be an array type.
|
||||
Returns:: `get()`.
|
||||
|
||||
```
|
||||
element_type & operator[](std::ptrdiff_t i) const noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Requires:: `T` should be an array type. The stored pointer must not be 0. `i >= 0`. If `T` is `U[N]`, `i < N`.
|
||||
Returns:: `get()[i]`.
|
||||
|
||||
### get
|
||||
|
||||
```
|
||||
element_type * get() const noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: The stored pointer.
|
||||
|
||||
### local_use_count
|
||||
```
|
||||
long local_use_count() const noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: The number of `local_shared_ptr` objects, `*this` included, that share ownership with `*this`, or 0 when `*this` is empty.
|
||||
|
||||
### conversions
|
||||
```
|
||||
explicit operator bool() const noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `get() != 0`.
|
||||
|
||||
NOTE: On C++03 compilers, the return value is of an unspecified type.
|
||||
|
||||
```
|
||||
template<class Y> operator shared_ptr<Y>() const noexcept;
|
||||
```
|
||||
```
|
||||
template<class Y> operator weak_ptr<Y>() const noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Requires:: `T*` should be convertible to `Y*`.
|
||||
Returns:: a copy of the owned `shared_ptr`.
|
||||
|
||||
### swap
|
||||
```
|
||||
void swap(local_shared_ptr & b) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Exchanges the contents of the two smart pointers.
|
||||
|
||||
### owner_before
|
||||
```
|
||||
template<class Y> bool owner_before(local_shared_ptr<Y> const & rhs) const noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: See the description of `operator<`.
|
||||
|
||||
## Free Functions
|
||||
|
||||
### comparison
|
||||
```
|
||||
template<class T, class U>
|
||||
bool operator==(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
|
||||
```
|
||||
```
|
||||
template<class T, class U>
|
||||
bool operator==(local_shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
|
||||
```
|
||||
```
|
||||
template<class T, class U>
|
||||
bool operator==(shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `a.get() == b.get()`.
|
||||
|
||||
```
|
||||
template<class T, class U>
|
||||
bool operator!=(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
|
||||
```
|
||||
```
|
||||
template<class T, class U>
|
||||
bool operator!=(local_shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
|
||||
```
|
||||
```
|
||||
template<class T, class U>
|
||||
bool operator!=(shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `a.get() != b.get()`.
|
||||
|
||||
```
|
||||
template<class T> bool operator==(local_shared_ptr<T> const & p, std::nullptr_t) noexcept;
|
||||
```
|
||||
```
|
||||
template<class T> bool operator==(std::nullptr_t, local_shared_ptr<T> const & p) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `p.get() == 0`.
|
||||
|
||||
```
|
||||
template<class T> bool operator!=(local_shared_ptr<T> const & p, std::nullptr_t) noexcept;
|
||||
```
|
||||
```
|
||||
template<class T> bool operator!=(std::nullptr_t, local_shared_ptr<T> const & p) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `p.get() != 0`.
|
||||
|
||||
```
|
||||
template<class T, class U>
|
||||
bool operator<(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: An unspecified value such that
|
||||
- `operator<` is a strict weak ordering as described in section [lib.alg.sorting] of the {cpp} standard;
|
||||
- under the equivalence relation defined by `operator<`, `!(a < b) && !(b < a)`, two `local_shared_ptr` instances
|
||||
are equivalent if and only if they share ownership or are both empty.
|
||||
|
||||
NOTE: Allows `local_shared_ptr` objects to be used as keys in associative containers.
|
||||
|
||||
NOTE: The rest of the comparison operators are omitted by design.
|
||||
|
||||
### swap
|
||||
```
|
||||
template<class T> void swap(local_shared_ptr<T> & a, local_shared_ptr<T> & b) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Equivalent to `a.swap(b)`.
|
||||
|
||||
### get_pointer
|
||||
```
|
||||
template<class T>
|
||||
typename local_shared_ptr<T>::element_type *
|
||||
get_pointer(local_shared_ptr<T> const & p) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `p.get()`.
|
||||
|
||||
NOTE: Provided as an aid to generic programming. Used by `mem_fn`.
|
||||
|
||||
### static_pointer_cast
|
||||
```
|
||||
template<class T, class U>
|
||||
local_shared_ptr<T> static_pointer_cast(local_shared_ptr<U> const & r) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Requires:: The expression `static_cast<T*>( (U*)0 )` must be well-formed.
|
||||
Returns:: `local_shared_ptr<T>( r, static_cast<typename local_shared_ptr<T>::element_type*>(r.get()) )`.
|
||||
|
||||
CAUTION: The seemingly equivalent expression `local_shared_ptr<T>(static_cast<T*>(r.get()))` will eventually
|
||||
result in undefined behavior, attempting to delete the same object twice.
|
||||
|
||||
### const_pointer_cast
|
||||
```
|
||||
template<class T, class U>
|
||||
local_shared_ptr<T> const_pointer_cast(local_shared_ptr<U> const & r) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Requires:: The expression `const_cast<T*>( (U*)0 )` must be well-formed.
|
||||
Returns:: `local_shared_ptr<T>( r, const_cast<typename local_shared_ptr<T>::element_type*>(r.get()) )`.
|
||||
|
||||
### dynamic_pointer_cast
|
||||
```
|
||||
template<class T, class U>
|
||||
local_shared_ptr<T> dynamic_pointer_cast(local_shared_ptr<U> const & r) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Requires:: The expression `dynamic_cast<T*>( (U*)0 )` must be well-formed.
|
||||
Returns::
|
||||
- When `dynamic_cast<typename local_shared_ptr<T>::element_type*>(r.get())` returns a nonzero value `p`, `local_shared_ptr<T>(r, p)`;
|
||||
- Otherwise, `local_shared_ptr<T>()`.
|
||||
|
||||
### reinterpret_pointer_cast
|
||||
```
|
||||
template<class T, class U>
|
||||
local_shared_ptr<T> reinterpret_pointer_cast(local_shared_ptr<U> const & r) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Requires:: The expression `reinterpret_cast<T*>( (U*)0 )` must be well-formed.
|
||||
Returns:: `local_shared_ptr<T>( r, reinterpret_cast<typename local_shared_ptr<T>::element_type*>(r.get()) )`.
|
||||
|
||||
### operator<<
|
||||
```
|
||||
template<class E, class T, class Y>
|
||||
std::basic_ostream<E, T> &
|
||||
operator<< (std::basic_ostream<E, T> & os, local_shared_ptr<Y> const & p);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: `os << p.get();`.
|
||||
Returns:: `os`.
|
||||
|
||||
### get_deleter
|
||||
```
|
||||
template<class D, class T>
|
||||
D * get_deleter(local_shared_ptr<T> const & p) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: If `*this` owns a `shared_ptr` instance `p`, `get_deleter<D>( p )`, otherwise 0.
|
||||
81
doc/smart_ptr/make_local_shared.adoc
Normal file
81
doc/smart_ptr/make_local_shared.adoc
Normal file
@@ -0,0 +1,81 @@
|
||||
////
|
||||
Copyright 2017 Glen Joseph Fernandes (glenjofe@gmail.com)
|
||||
|
||||
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
|
||||
////
|
||||
|
||||
[#make_local_shared]
|
||||
# make_local_shared: Creating local_shared_ptr
|
||||
:toc:
|
||||
:toc-title:
|
||||
:idprefix: make_local_shared_
|
||||
|
||||
## Description
|
||||
|
||||
The function templates `make_local_shared` and `allocate_local_shared` provide
|
||||
convenient, safe and efficient ways to create `local_shared_ptr` objects. They
|
||||
are analogous to `make_shared` and `allocate_shared` for `shared_ptr`.
|
||||
|
||||
## Synopsis
|
||||
|
||||
`make_local_shared` and `allocate_local_shared` are defined in
|
||||
`<boost/smart_ptr/make_local_shared.hpp>`.
|
||||
|
||||
[subs=+quotes]
|
||||
```
|
||||
namespace boost {
|
||||
`// T is not an array`
|
||||
template<class T, class... Args>
|
||||
local_shared_ptr<T> make_local_shared(Args&&... args);
|
||||
template<class T, class A, class... Args>
|
||||
local_shared_ptr<T> allocate_local_shared(const A& a, Args&&... args);
|
||||
|
||||
`// T is an array of unknown bounds`
|
||||
template<class T>
|
||||
local_shared_ptr<T> make_local_shared(std::size_t n);
|
||||
template<class T, class A>
|
||||
local_shared_ptr<T> allocate_local_shared(const A& a, std::size_t n);
|
||||
|
||||
`// T is an array of known bounds`
|
||||
template<class T>
|
||||
local_shared_ptr<T> make_local_shared();
|
||||
template<class T, class A>
|
||||
local_shared_ptr<T> allocate_local_shared(const A& a);
|
||||
|
||||
`// T is an array of unknown bounds`
|
||||
template<class T>
|
||||
local_shared_ptr<T> make_local_shared(std::size_t n,
|
||||
const remove_extent_t<T>& v);
|
||||
template<class T, class A>
|
||||
local_shared_ptr<T> allocate_local_shared(const A& a, std::size_t n,
|
||||
const remove_extent_t<T>& v);
|
||||
|
||||
`// T is an array of known bounds`
|
||||
template<class T>
|
||||
local_shared_ptr<T> make_local_shared(const remove_extent_t<T>& v);
|
||||
template<class T, class A>
|
||||
local_shared_ptr<T> allocate_local_shared(const A& a,
|
||||
const remove_extent_t<T>& v);
|
||||
|
||||
`// T is not an array of known bounds`
|
||||
template<class T>
|
||||
local_shared_ptr<T> make_local_shared_noinit();
|
||||
template<class T, class A>
|
||||
local_shared_ptr<T> allocate_local_shared_noinit(const A& a);
|
||||
|
||||
`// T is an array of unknown bounds`
|
||||
template<class T>
|
||||
local_shared_ptr<T> make_local_shared_noinit(std::size_t n);
|
||||
template<class T, class A>
|
||||
local_shared_ptr<T> allocate_local_shared_noinit(const A& a,
|
||||
std::size_t n);
|
||||
}
|
||||
```
|
||||
|
||||
## Description
|
||||
|
||||
The requirements and effects of these functions are the same as `make_shared`
|
||||
and `allocate_shared`, except that a `local_shared_ptr` is returned.
|
||||
296
doc/smart_ptr/make_shared.adoc
Normal file
296
doc/smart_ptr/make_shared.adoc
Normal file
@@ -0,0 +1,296 @@
|
||||
////
|
||||
Copyright 2017 Peter Dimov
|
||||
Copyright 2017 Glen Joseph Fernandes (glenjofe@gmail.com)
|
||||
|
||||
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
|
||||
////
|
||||
|
||||
[#make_shared]
|
||||
# make_shared: Creating shared_ptr
|
||||
:toc:
|
||||
:toc-title:
|
||||
:idprefix: make_shared_
|
||||
|
||||
## Description
|
||||
|
||||
The function templates `make_shared` and `allocate_shared` provide convenient,
|
||||
safe and efficient ways to create `shared_ptr` objects.
|
||||
|
||||
## Rationale
|
||||
|
||||
Consistent use of `shared_ptr` can eliminate the need to use an explicit
|
||||
`delete`, but alone it provides no support in avoiding explicit `new`. There
|
||||
were repeated requests from users for a factory function that creates an
|
||||
object of a given type and returns a `shared_ptr` to it. Besides convenience
|
||||
and style, such a function is also exception safe and considerably faster
|
||||
because it can use a single allocation for both the object and its
|
||||
corresponding control block, eliminating a significant portion of
|
||||
`shared_ptr` construction overhead. This eliminates one of the major
|
||||
efficiency complaints about `shared_ptr`.
|
||||
|
||||
The family of overloaded function templates, `make_shared` and
|
||||
`allocate_shared`, were provided to address this need. `make_shared` uses the
|
||||
global `operator new` to allocate memory, whereas `allocate_shared` uses an
|
||||
user-supplied allocator, allowing finer control.
|
||||
|
||||
The rationale for choosing the name `make_shared` is that the expression
|
||||
`make_shared<Widget>()` can be read aloud and conveys the intended meaning.
|
||||
|
||||
Originally the Boost function templates `allocate_shared` and `make_shared`
|
||||
were provided for scalar objects only. There was a need to have efficient
|
||||
allocation of array objects. One criticism of class template `shared_array`
|
||||
was always the lack of a utility like `make_shared` that uses only a single
|
||||
allocation. When `shared_ptr` was enhanced to support array types, additional
|
||||
overloads of `allocate_shared` and `make_shared` were provided for array
|
||||
types.
|
||||
|
||||
## Synopsis
|
||||
|
||||
`make_shared` and `allocate_shared` are defined in
|
||||
`<boost/smart_ptr/make_shared.hpp>`.
|
||||
|
||||
[subs=+quotes]
|
||||
```
|
||||
namespace boost {
|
||||
`// T is not an array`
|
||||
template<class T, class... Args>
|
||||
shared_ptr<T> make_shared(Args&&... args);
|
||||
template<class T, class A, class... Args>
|
||||
shared_ptr<T> allocate_shared(const A& a, Args&&... args);
|
||||
|
||||
`// T is an array of unknown bounds`
|
||||
template<class T>
|
||||
shared_ptr<T> make_shared(std::size_t n);
|
||||
template<class T, class A>
|
||||
shared_ptr<T> allocate_shared(const A& a, std::size_t n);
|
||||
|
||||
`// T is an array of known bounds`
|
||||
template<class T>
|
||||
shared_ptr<T> make_shared();
|
||||
template<class T, class A>
|
||||
shared_ptr<T> allocate_shared(const A& a);
|
||||
|
||||
`// T is an array of unknown bounds`
|
||||
template<class T> shared_ptr<T>
|
||||
make_shared(std::size_t n, const remove_extent_t<T>& v);
|
||||
template<class T, class A> shared_ptr<T>
|
||||
allocate_shared(const A& a, std::size_t n, const remove_extent_t<T>& v);
|
||||
|
||||
`// T is an array of known bounds`
|
||||
template<class T>
|
||||
shared_ptr<T> make_shared(const remove_extent_t<T>& v);
|
||||
template<class T, class A>
|
||||
shared_ptr<T> allocate_shared(const A& a, const remove_extent_t<T>& v);
|
||||
|
||||
`// T is not an array of unknown bounds`
|
||||
template<class T>
|
||||
shared_ptr<T> make_shared_noinit();
|
||||
template<class T, class A>
|
||||
shared_ptr<T> allocate_shared_noinit(const A& a);
|
||||
|
||||
`// T is an array of unknown bounds`
|
||||
template<class T>
|
||||
shared_ptr<T> make_shared_noinit(std::size_t n);
|
||||
template<class T, class A>
|
||||
shared_ptr<T> allocate_shared_noinit(const A& a, std::size_t n);
|
||||
}
|
||||
```
|
||||
|
||||
## Common Requirements
|
||||
|
||||
The common requirements that apply to all `make_shared` and `allocate_shared`
|
||||
overloads, unless specified otherwise, are described below.
|
||||
|
||||
Requires:: `A` shall be an _allocator_. The copy constructor and destructor
|
||||
of `A` shall not throw exceptions.
|
||||
|
||||
Effects:: Allocates memory for an object of type `T` or `n` objects of `U`
|
||||
(if `T` is an array type of the form `U[]` and `n` is determined by
|
||||
arguments, as specified by the concrete overload). The object is initialized
|
||||
from arguments as specified by the concrete overload. Uses a rebound copy of
|
||||
`a` (for an unspecified `value_type`) to allocate memory. If an exception is
|
||||
thrown, the functions have no effect.
|
||||
|
||||
Returns:: A `shared_ptr` instance that stores and owns the address of the
|
||||
newly constructed object.
|
||||
|
||||
Postconditions:: `r.get() != 0` and `r.use_count() == 1`, where `r`
|
||||
is the return value.
|
||||
|
||||
Throws:: `std::bad_alloc`, an exception thrown from `A::allocate`, or from the
|
||||
initialization of the object.
|
||||
|
||||
Remarks::
|
||||
* Performs no more than one memory allocation. This provides efficiency
|
||||
equivalent to an intrusive smart pointer.
|
||||
* When an object of an array type is specified to be initialized to a value of
|
||||
the same type `v`, this shall be interpreted to mean that each array element
|
||||
of the object is initialized to the corresponding element from `v`.
|
||||
* When an object of an array type is specified to be value-initialized, this
|
||||
shall be interpreted to mean that each array element of the object is
|
||||
value-initialized.
|
||||
* When a (sub)object of non-array type `U` is specified to be initialized to
|
||||
a value `v`, or constructed from `args\...`, `make_shared` shall perform
|
||||
this initialization via the expression `::new(p) U(expr)` (where
|
||||
`_expr_` is `v` or `std::forward<Args>(args)\...)` respectively) and `p`
|
||||
has type `void*` and points to storage suitable to hold an object of type
|
||||
`U`.
|
||||
* When a (sub)object of non-array type `U` is specified to be initialized to
|
||||
a value `v`, or constructed from `args\...`, `allocate_shared` shall
|
||||
perform this initialization via the expression
|
||||
`std::allocator_traits<A2>::construct(a2, p, expr)` (where
|
||||
`_expr_` is `v` or `std::forward<Args>(args)\...)` respectively), `p`
|
||||
points to storage suitable to hold an object of type `U`, and `a2` of
|
||||
type `A2` is a potentially rebound copy of `a`.
|
||||
* When a (sub)object of non-array type `U` is specified to be
|
||||
default-initialized, `make_shared_noinit` and `allocate_shared_noinit` shall
|
||||
perform this initialization via the expression `::new(p) U`, where
|
||||
`p` has type `void*` and points to storage suitable to hold an object of
|
||||
type `U`.
|
||||
* When a (sub)object of non-array type `U` is specified to be
|
||||
value-initialized, `make_shared` shall perform this initialization via the
|
||||
expression `::new(p) U()`, where `p` has type `void*` and points to
|
||||
storage suitable to hold an object of type `U`.
|
||||
* When a (sub)object of non-array type `U` is specified to be
|
||||
value-initialized, `allocate_shared` shall perform this initialization via the
|
||||
expression `std::allocator_traits<A2>::construct(a2, p)`, where
|
||||
`p` points to storage suitable to hold an object of type `U` and `a2` of
|
||||
type `A2` is a potentially rebound copy of `a`.
|
||||
* Array elements are initialized in ascending order of their addresses.
|
||||
* When the lifetime of the object managed by the return value ends, or when
|
||||
the initialization of an array element throws an exception, the initialized
|
||||
elements should be destroyed in the reverse order of their construction.
|
||||
|
||||
NOTE: These functions will typically allocate more memory than the total size
|
||||
of the element objects to allow for internal bookkeeping structures such as
|
||||
the reference counts.
|
||||
|
||||
## Free Functions
|
||||
|
||||
```
|
||||
template<class T, class... Args>
|
||||
shared_ptr<T> make_shared(Args&&... args);
|
||||
```
|
||||
```
|
||||
template<class T, class A, class... Args>
|
||||
shared_ptr<T> allocate_shared(const A& a, Args&&... args);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Constraints:: `T` is not an array.
|
||||
Returns:: A `shared_ptr` to an object of type `T`, constructed from
|
||||
`args\...`.
|
||||
Examples::
|
||||
* `auto p = make_shared<int>();`
|
||||
* `auto p = make_shared<std::vector<int> >(16, 1);`
|
||||
|
||||
```
|
||||
template<class T>
|
||||
shared_ptr<T> make_shared(std::size_t n);
|
||||
```
|
||||
```
|
||||
template<class T, class A>
|
||||
shared_ptr<T> allocate_shared(const A& a, std::size_t n);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Constraints:: `T` is an array of unknown bounds.
|
||||
Returns:: A `shared_ptr` to a sequence of `n` value-initialized objects of
|
||||
type `remove_extent_t<T>`.
|
||||
Examples::
|
||||
* `auto p = make_shared<double[]>(1024);`
|
||||
* `auto p = make_shared<double[][2][2]>(6);`
|
||||
|
||||
```
|
||||
template<class T>
|
||||
shared_ptr<T> make_shared();
|
||||
```
|
||||
```
|
||||
template<class T, class A>
|
||||
shared_ptr<T> allocate_shared(const A& a);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Constraints:: `T` is an array of known bounds.
|
||||
Returns:: A `shared_ptr` to a sequence of `extent_v<T>` value-initialized
|
||||
objects of type `remove_extent_t<T>`.
|
||||
Examples::
|
||||
* `auto p = make_shared<double[1024]>();`
|
||||
* `auto p = make_shared<double[6][2][2]>();`
|
||||
|
||||
```
|
||||
template<class T> shared_ptr<T>
|
||||
make_shared(std::size_t n, const remove_extent_t<T>& v);
|
||||
```
|
||||
```
|
||||
template<class T, class A> shared_ptr<T>
|
||||
allocate_shared(const A& a, std::size_t n, const remove_extent_t<T>& v);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Constraints:: `T` is an array of unknown bounds.
|
||||
Returns:: A `shared_ptr` to a sequence of `n` objects of type
|
||||
`remove_extent_t<T>`, each initialized to `v`.
|
||||
Examples::
|
||||
* `auto p = make_shared<double[]>(1024, 1.0);`
|
||||
* `auto p = make_shared<double[][2]>(6, {1.0, 0.0});`
|
||||
* `auto p = make_shared<std::vector<int>[]>(4, {1, 2});`
|
||||
|
||||
```
|
||||
template<class T>
|
||||
shared_ptr<T> make_shared(const remove_extent_t<T>& v);
|
||||
```
|
||||
```
|
||||
template<class T, class A>
|
||||
shared_ptr<T> allocate_shared(const A& a, const remove_extent_t<T>& v);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Constraints:: `T` is an array of known bounds.
|
||||
Returns:: A `shared_ptr` to a sequence of `extent_v<T>` objects of type
|
||||
`remove_extent_t<T>`, each initialized to `v`.
|
||||
Examples::
|
||||
* `auto p = make_shared<double[1024]>(1.0);`
|
||||
* `auto p = make_shared<double[6][2]>({1.0, 0.0});`
|
||||
* `auto p = make_shared<std::vector<int>[4]>({1, 2});`
|
||||
|
||||
```
|
||||
template<class T>
|
||||
shared_ptr<T> make_shared_noinit();
|
||||
```
|
||||
```
|
||||
template<class T, class A>
|
||||
shared_ptr<T> allocate_shared_noinit(const A& a);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Constraints:: `T` is not an array, or is an array of known bounds.
|
||||
Returns:: A `shared_ptr` to a default-initialized object of type `T`, or a
|
||||
sequence of `extent_v<T>` default-initialized objects of type
|
||||
`remove_extent_t<T>`, respectively.
|
||||
Example:: `auto p = make_shared_noinit<double[1024]>();`
|
||||
|
||||
```
|
||||
template<class T>
|
||||
shared_ptr<T> make_shared_noinit(std::size_t n);
|
||||
```
|
||||
```
|
||||
template<class T, class A>
|
||||
shared_ptr<T> allocate_shared_noinit(const A& a, std::size_t n);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Constraints:: `T` is an array of unknown bounds.
|
||||
Returns:: A `shared_ptr` to a sequence of `_n_` default-initialized objects
|
||||
of type `remove_extent_t<T>`.
|
||||
Example:: `auto p = make_shared_noinit<double[]>(1024);`
|
||||
120
doc/smart_ptr/make_unique.adoc
Normal file
120
doc/smart_ptr/make_unique.adoc
Normal file
@@ -0,0 +1,120 @@
|
||||
////
|
||||
Copyright 2017 Peter Dimov
|
||||
Copyright 2017 Glen Joseph Fernandes (glenjofe@gmail.com)
|
||||
|
||||
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
|
||||
////
|
||||
|
||||
[#make_unique]
|
||||
# make_unique: Creating unique_ptr
|
||||
:toc:
|
||||
:toc-title:
|
||||
:idprefix: make_unique_
|
||||
|
||||
## Description
|
||||
|
||||
The `make_unique` function templates provide convenient and safe ways to
|
||||
create `std::unique_ptr` objects.
|
||||
|
||||
## Rationale
|
||||
|
||||
The {cpp}11 standard introduced `std::unique_ptr` but did not provide any
|
||||
`make_unique` utility like `std::make_shared` that provided the same
|
||||
exception safety and facility to avoid writing `new` expressions. Before it
|
||||
was implemented by some standard library vendors (and prior to the {cpp}14
|
||||
standard introducing `std::make_unique`), this library provided it due to
|
||||
requests from users.
|
||||
|
||||
This library also provides additional overloads of `make_unique` for
|
||||
default-initialization, when users do not need or want to incur the expense
|
||||
of value-initialization. The {cpp} standard does not yet provide this
|
||||
feature with `std::make_unique`.
|
||||
|
||||
## Synopsis
|
||||
|
||||
`make_unique` is defined in `<boost/smart_ptr/make_unique.hpp>`.
|
||||
|
||||
[subs=+quotes]
|
||||
```
|
||||
namespace boost {
|
||||
`// T is not an array`
|
||||
template<class T, class... Args>
|
||||
std::unique_ptr<T> make_unique(Args&&... args);
|
||||
|
||||
`// T is not an array`
|
||||
template<class T>
|
||||
std::unique_ptr<T> make_unique(type_identity_t<T>&& v);
|
||||
|
||||
`// T is an array of unknown bounds`
|
||||
template<class T>
|
||||
std::unique_ptr<T> make_unique(std::size_t n);
|
||||
|
||||
`// T is not an array`
|
||||
template<class T>
|
||||
std::unique_ptr<T> make_unique_noinit();
|
||||
|
||||
`// T is an array of unknown bounds`
|
||||
template<class T>
|
||||
std::unique_ptr<T> make_unique_noinit(std::size_t n);
|
||||
}
|
||||
```
|
||||
|
||||
## Free Functions
|
||||
|
||||
```
|
||||
template<class T, class... Args>
|
||||
std::unique_ptr<T> make_unique(Args&&... args);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Constraints:: `T` is not an array.
|
||||
Returns:: `std::unique_ptr<T>(new T(std::forward<Args>(args)\...)`.
|
||||
Example:: `auto p = make_unique<int>();`
|
||||
|
||||
```
|
||||
template<class T>
|
||||
std::unique_ptr<T> make_unique(type_identity_t<T>&& v);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Constraints:: `T` is not an array.
|
||||
Returns:: `std::unique_ptr<T>(new T(std::move(v))`.
|
||||
Example:: `auto p = make_unique<std::vector<int> >({1, 2});`
|
||||
|
||||
```
|
||||
template<class T>
|
||||
std::unique_ptr<T> make_unique(std::size_t n);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Constraints:: `T` is an array of unknown bounds.
|
||||
Returns:: `std::unique_ptr<T>(new remove_extent_t<T>[n]())`.
|
||||
Example:: `auto p = make_unique<double[]>(1024);`
|
||||
|
||||
```
|
||||
template<class T>
|
||||
std::unique_ptr<T> make_unique_noinit();
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Constraints:: `T` is not an array.
|
||||
Returns:: `std::unique_ptr<T>(new T)`.
|
||||
Example:: `auto p = make_unique_noinit<std::array<double, 1024> >();`
|
||||
|
||||
```
|
||||
template<class T>
|
||||
std::unique_ptr<T> make_unique_noinit(std::size_t n);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Constraints:: `T` is an array of unknown bounds.
|
||||
Returns:: `std::unique_ptr<T>(new remove_extent_t<T>[n])`.
|
||||
Example:: `auto p = make_unique_noinit<double[]>(1024);`
|
||||
237
doc/smart_ptr/pointer_cast.adoc
Normal file
237
doc/smart_ptr/pointer_cast.adoc
Normal file
@@ -0,0 +1,237 @@
|
||||
////
|
||||
Copyright 2017 Peter Dimov
|
||||
|
||||
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
|
||||
////
|
||||
|
||||
[#pointer_cast]
|
||||
# Generic Pointer Casts
|
||||
:toc:
|
||||
:toc-title:
|
||||
:idprefix: pointer_cast_
|
||||
|
||||
## Description
|
||||
|
||||
The pointer cast function templates (`static_pointer_cast`,
|
||||
`dynamic_pointer_cast`, `const_pointer_cast`, and `reinterpret_pointer_cast`)
|
||||
provide a way to write generic pointer castings for raw pointers,
|
||||
`std::shared_ptr` and `std::unique_ptr`.
|
||||
|
||||
There is test and example code in
|
||||
link:../../test/pointer_cast_test.cpp[pointer_cast_test.cpp]
|
||||
|
||||
## Rationale
|
||||
|
||||
Boost smart pointers usually overload those functions to provide a mechanism
|
||||
to emulate pointers casts. For example, `shared_ptr<T>` implements a static
|
||||
pointer cast this way:
|
||||
|
||||
```
|
||||
template<class T, class U>
|
||||
shared_ptr<T> static_pointer_cast(const shared_ptr<U>& p);
|
||||
```
|
||||
|
||||
Pointer cast functions templates are overloads of `static_pointer_cast`,
|
||||
`dynamic_pointer_cast`, `const_pointer_cast`, and `reinterpret_pointer_cast`
|
||||
for raw pointers, `std::shared_ptr` and `std::unique_ptr`. This way when
|
||||
developing pointer type independent classes, for example, memory managers or
|
||||
shared memory compatible classes, the same code can be used for raw and smart
|
||||
pointers.
|
||||
|
||||
## Synopsis
|
||||
|
||||
The generic pointer casts are defined in `<boost/pointer_cast.hpp>`.
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
template<class T, class U> T* static_pointer_cast(U* p) noexcept;
|
||||
template<class T, class U> T* dynamic_pointer_cast(U* p) noexcept;
|
||||
template<class T, class U> T* const_pointer_cast(U* p) noexcept;
|
||||
template<class T, class U> T* reinterpret_pointer_cast(U* p) noexcept;
|
||||
|
||||
template<class T, class U> std::shared_ptr<T>
|
||||
static_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
||||
template<class T, class U> std::shared_ptr<T>
|
||||
dynamic_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
||||
template<class T, class U> std::shared_ptr<T>
|
||||
const_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
||||
template<class T, class U> std::shared_ptr<T>
|
||||
reinterpret_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
||||
|
||||
template<class T, class U> std::unique_ptr<T>
|
||||
static_pointer_cast(std::unique_ptr<U>&& p) noexcept;
|
||||
template<class T, class U> std::unique_ptr<T>
|
||||
dynamic_pointer_cast(std::unique_ptr<U>&& p) noexcept;
|
||||
template<class T, class U> std::unique_ptr<T>
|
||||
const_pointer_cast(std::unique_ptr<U>&& p) noexcept;
|
||||
template<class T, class U> std::unique_ptr<T>
|
||||
reinterpret_pointer_cast(std::unique_ptr<U>&& p) noexcept;
|
||||
}
|
||||
```
|
||||
|
||||
## Free Functions
|
||||
|
||||
### static_pointer_cast
|
||||
```
|
||||
template<class T, class U> T* static_pointer_cast(U* p) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `static_cast<T*>(p)`
|
||||
|
||||
```
|
||||
template<class T, class U> std::shared_ptr<T>
|
||||
static_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `std::static_pointer_cast<T>(p)`
|
||||
|
||||
```
|
||||
template<class T, class U> std::unique_ptr<T>
|
||||
static_pointer_cast(std::unique_ptr<U>&& p) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Requires:: The expression `static_cast<T*>((U*)0)` must be well-formed.
|
||||
Returns:: `std::unique_ptr<T>(static_cast<typename
|
||||
std::unique_ptr<T>::element_type*>(p.release()))`.
|
||||
|
||||
CAUTION: The seemingly equivalent expression
|
||||
`std::unique_ptr<T>(static_cast<T*>(p.get()))` will eventually result in
|
||||
undefined behavior, attempting to delete the same object twice.
|
||||
|
||||
### dynamic_pointer_cast
|
||||
|
||||
```
|
||||
template<class T, class U> T* dynamic_pointer_cast(U* p) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `dynamic_cast<T*>(p)`
|
||||
|
||||
```
|
||||
template<class T, class U> std::shared_ptr<T>
|
||||
dynamic_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `std::dynamic_pointer_cast<T>(p)`
|
||||
|
||||
```
|
||||
template<class T, class U> std::unique_ptr<T>
|
||||
dynamic_pointer_cast(std::unique_ptr<U>&& p) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Requires::
|
||||
* The expression `static_cast<T*>((U*)0)` must be well-formed.
|
||||
* `T` must have a virtual destructor.
|
||||
Returns::
|
||||
* When `dynamic_cast<typename std::unique_ptr<T>::element_type*>(p.get())`
|
||||
returns a non-zero value, `std::unique_ptr<T>(dynamic_cast<typename
|
||||
std::unique_ptr<T>::element_type*>(p.release()));`.
|
||||
* Otherwise, `std::unique_ptr<T>()`.
|
||||
|
||||
### const_pointer_cast
|
||||
|
||||
```
|
||||
template<class T, class U> T* const_pointer_cast(U* p) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `const_cast<T*>(p)`
|
||||
|
||||
```
|
||||
template<class T, class U> std::shared_ptr<T>
|
||||
const_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `std::const_pointer_cast<T>(p)`
|
||||
|
||||
```
|
||||
template<class T, class U> std::unique_ptr<T>
|
||||
const_pointer_cast(std::unique_ptr<U>&& p) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Requires:: The expression `const_cast<T*>((U*)0)` must be well-formed.
|
||||
Returns:: `std::unique_ptr<T>(const_cast<typename
|
||||
std::unique_ptr<T>::element_type*>(p.release()))`.
|
||||
|
||||
### reinterpret_pointer_cast
|
||||
|
||||
```
|
||||
template<class T, class U> T* reinterpret_pointer_cast(U* p) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `reinterpret_cast<T*>(p)`
|
||||
|
||||
```
|
||||
template<class T, class U> std::shared_ptr<T>
|
||||
reinterpret_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `std::reinterpret_pointer_cast<T>(p)`
|
||||
|
||||
```
|
||||
template<class T, class U> std::unique_ptr<T>
|
||||
reinterpret_pointer_cast(std::unique_ptr<U>&& p) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Requires:: The expression `reinterpret_cast<T*>((U*)0)` must be well-formed.
|
||||
Returns:: `std::unique_ptr<T>(reinterpret_cast<typename
|
||||
std::unique_ptr<T>::element_type*>(p.release()))`.
|
||||
|
||||
## Example
|
||||
|
||||
The following example demonstrates how the generic pointer casts help us
|
||||
create pointer independent code.
|
||||
|
||||
```
|
||||
#include <boost/pointer_cast.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
class base {
|
||||
public:
|
||||
virtual ~base() { }
|
||||
};
|
||||
|
||||
class derived : public base { };
|
||||
|
||||
template<class Ptr>
|
||||
void check_if_it_is_derived(const Ptr& ptr)
|
||||
{
|
||||
assert(boost::dynamic_pointer_cast<derived>(ptr) != 0);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
base* ptr = new derived;
|
||||
boost::shared_ptr<base> sptr(new derived);
|
||||
|
||||
check_if_it_is_derived(ptr);
|
||||
check_if_it_is_derived(sptr);
|
||||
|
||||
delete ptr;
|
||||
}
|
||||
```
|
||||
114
doc/smart_ptr/pointer_to_other.adoc
Normal file
114
doc/smart_ptr/pointer_to_other.adoc
Normal file
@@ -0,0 +1,114 @@
|
||||
////
|
||||
Copyright 2005, 2006 Ion Gaztañaga
|
||||
Copyright 2005, 2006, 2017 Peter Dimov
|
||||
|
||||
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
|
||||
////
|
||||
|
||||
[#pointer_to_other]
|
||||
# pointer_to_other
|
||||
:toc:
|
||||
:toc-title:
|
||||
:idprefix: pointer_to_other_
|
||||
|
||||
## Description
|
||||
|
||||
The `pointer_to_other` utility provides a way, given a source pointer type, to obtain a pointer of the same type
|
||||
to another pointee type.
|
||||
|
||||
There is test/example code in link:../../test/pointer_to_other_test.cpp[pointer_to_other_test.cpp].
|
||||
|
||||
## Rationale
|
||||
|
||||
When building pointer independent classes, like memory managers, allocators, or containers, there is often a need to
|
||||
define pointers generically, so that if a template parameter represents a pointer (for example, a raw or smart pointer
|
||||
to an `int`), we can define another pointer of the same type to another pointee (a raw or smart pointer to a `float`.)
|
||||
|
||||
```
|
||||
template <class IntPtr> class FloatPointerHolder
|
||||
{
|
||||
// Let's define a pointer to a float
|
||||
|
||||
typedef typename boost::pointer_to_other
|
||||
<IntPtr, float>::type float_ptr_t;
|
||||
|
||||
float_ptr_t float_ptr;
|
||||
};
|
||||
```
|
||||
|
||||
## Synopsis
|
||||
|
||||
`pointer_to_other` is defined in `<boost/smart_ptr/pointer_to_other.hpp>`.
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
|
||||
template<class T, class U> struct pointer_to_other;
|
||||
|
||||
template<class T, class U,
|
||||
template <class> class Sp>
|
||||
struct pointer_to_other< Sp<T>, U >
|
||||
{
|
||||
typedef Sp<U> type;
|
||||
};
|
||||
|
||||
template<class T, class T2, class U,
|
||||
template <class, class> class Sp>
|
||||
struct pointer_to_other< Sp<T, T2>, U >
|
||||
{
|
||||
typedef Sp<U, T2> type;
|
||||
};
|
||||
|
||||
template<class T, class T2, class T3, class U,
|
||||
template <class, class, class> class Sp>
|
||||
struct pointer_to_other< Sp<T, T2, T3>, U >
|
||||
{
|
||||
typedef Sp<U, T2, T3> type;
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
struct pointer_to_other< T*, U >
|
||||
{
|
||||
typedef U* type;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
If these definitions are not correct for a specific smart pointer, we can define a specialization of `pointer_to_other`.
|
||||
|
||||
## Example
|
||||
|
||||
```
|
||||
// Let's define a memory allocator that can
|
||||
// work with raw and smart pointers
|
||||
|
||||
#include <boost/pointer_to_other.hpp>
|
||||
|
||||
template <class VoidPtr>
|
||||
class memory_allocator
|
||||
{
|
||||
// Predefine a memory_block
|
||||
|
||||
struct block;
|
||||
|
||||
// Define a pointer to a memory_block from a void pointer
|
||||
// If VoidPtr is void *, block_ptr_t is block*
|
||||
// If VoidPtr is smart_ptr<void>, block_ptr_t is smart_ptr<block>
|
||||
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPtr, block>::type block_ptr_t;
|
||||
|
||||
struct block
|
||||
{
|
||||
std::size_t size;
|
||||
block_ptr_t next_block;
|
||||
};
|
||||
|
||||
block_ptr_t free_blocks;
|
||||
};
|
||||
```
|
||||
|
||||
As we can see, using `pointer_to_other` we can create pointer independent code.
|
||||
175
doc/smart_ptr/scoped_array.adoc
Normal file
175
doc/smart_ptr/scoped_array.adoc
Normal file
@@ -0,0 +1,175 @@
|
||||
////
|
||||
Copyright 1999 Greg Colvin and Beman Dawes
|
||||
Copyright 2002 Darin Adler
|
||||
Copyright 2002-2005, 2017 Peter Dimov
|
||||
|
||||
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
|
||||
////
|
||||
|
||||
[#scoped_array]
|
||||
# scoped_array: Scoped Array Ownership
|
||||
:toc:
|
||||
:toc-title:
|
||||
:idprefix: scoped_array_
|
||||
|
||||
## Description
|
||||
|
||||
The `scoped_array` class template stores a pointer to a dynamically allocated array.
|
||||
(Dynamically allocated arrays are allocated with the {cpp} `new[]` expression.) The array
|
||||
pointed to is guaranteed to be deleted, either on destruction of the `scoped_array`,
|
||||
or via an explicit `reset`.
|
||||
|
||||
The `scoped_array` template is a simple solution for simple needs. It supplies a basic
|
||||
"resource acquisition is initialization" facility, without shared-ownership or
|
||||
transfer-of-ownership semantics. Both its name and enforcement of semantics
|
||||
(by being noncopyable) signal its intent to retain ownership solely within the current scope.
|
||||
Because it is noncopyable, it is safer than `shared_ptr<T[]>` for pointers which should not be copied.
|
||||
|
||||
Because `scoped_array` is so simple, in its usual implementation every operation is as fast as a
|
||||
built-in array pointer and it has no more space overhead that a built-in array pointer.
|
||||
|
||||
It cannot be used in {cpp} standard library containers. See `shared_ptr<T[]>` if `scoped_array`
|
||||
does not meet your needs.
|
||||
|
||||
It cannot correctly hold a pointer to a single object. See `scoped_ptr` for that usage.
|
||||
|
||||
`std::vector` is an alternative to `scoped_array` that is a bit heavier duty but far more flexible.
|
||||
`boost::array` is an alternative that does not use dynamic allocation.
|
||||
|
||||
The class template is parameterized on `T`, the type of the object pointed to.
|
||||
|
||||
## Synopsis
|
||||
|
||||
`scoped_array` is defined in `<boost/smart_ptr/scoped_array.hpp>`.
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
|
||||
template<class T> class scoped_array {
|
||||
private:
|
||||
|
||||
scoped_array(scoped_array const &);
|
||||
scoped_array & operator=(scoped_array const &);
|
||||
|
||||
void operator==( scoped_array const& ) const;
|
||||
void operator!=( scoped_array const& ) const;
|
||||
|
||||
public:
|
||||
|
||||
typedef T element_type;
|
||||
|
||||
explicit scoped_array(T * p = 0) noexcept;
|
||||
~scoped_array() noexcept;
|
||||
|
||||
void reset(T * p = 0) noexcept;
|
||||
|
||||
T & operator[](std::ptrdiff_t i) const noexcept;
|
||||
T * get() const noexcept;
|
||||
|
||||
explicit operator bool () const noexcept;
|
||||
|
||||
void swap(scoped_array & b) noexcept;
|
||||
};
|
||||
|
||||
template<class T> void swap(scoped_array<T> & a, scoped_array<T> & b) noexcept;
|
||||
|
||||
template<class T>
|
||||
bool operator==( scoped_array<T> const & p, std::nullptr_t ) noexcept;
|
||||
template<class T>
|
||||
bool operator==( std::nullptr_t, scoped_array<T> const & p ) noexcept;
|
||||
|
||||
template<class T>
|
||||
bool operator!=( scoped_array<T> const & p, std::nullptr_t ) noexcept;
|
||||
template<class T>
|
||||
bool operator!=( std::nullptr_t, scoped_array<T> const & p ) noexcept;
|
||||
}
|
||||
```
|
||||
|
||||
## Members
|
||||
|
||||
### element_type
|
||||
|
||||
typedef T element_type;
|
||||
|
||||
Provides the type of the stored pointer.
|
||||
|
||||
### constructors
|
||||
|
||||
explicit scoped_array(T * p = 0) noexcept;
|
||||
|
||||
Constructs a `scoped_array`, storing a copy of `p`, which must have been
|
||||
allocated via a {cpp} `new[]` expression or be 0. `T` is not required be a complete type.
|
||||
|
||||
### destructor
|
||||
|
||||
~scoped_array() noexcept;
|
||||
|
||||
Deletes the array pointed to by the stored pointer. Note that `delete[]` on a pointer with
|
||||
a value of 0 is harmless. `T` must be complete, and `delete[]` on the stored pointer must
|
||||
not throw exceptions.
|
||||
|
||||
### reset
|
||||
|
||||
void reset(T * p = 0) noexcept;
|
||||
|
||||
Deletes the array pointed to by the stored pointer and then stores a copy of `p`,
|
||||
which must have been allocated via a {cpp} `new[]` expression or be 0. `T` must be complete,
|
||||
and `delete[]` on the stored pointer must not throw exceptions.
|
||||
|
||||
### subscripting
|
||||
|
||||
T & operator[](std::ptrdiff_t i) const noexcept;
|
||||
|
||||
Returns a reference to element `i` of the array pointed to by the stored pointer.
|
||||
Behavior is undefined and almost certainly undesirable if the stored pointer is 0,
|
||||
or if `i` is less than 0 or is greater than or equal to the number of elements in
|
||||
the array.
|
||||
|
||||
### get
|
||||
|
||||
T * get() const noexcept;
|
||||
|
||||
Returns the stored pointer. `T` need not be a complete type.
|
||||
|
||||
### conversions
|
||||
|
||||
explicit operator bool () const noexcept;
|
||||
|
||||
Returns `get() != 0`.
|
||||
|
||||
NOTE: On C++03 compilers, the return value is of an unspecified type.
|
||||
|
||||
### swap
|
||||
|
||||
void swap(scoped_array & b) noexcept;
|
||||
|
||||
Exchanges the contents of the two smart pointers. `T` need not be a complete type.
|
||||
|
||||
## Free Functions
|
||||
|
||||
### swap
|
||||
|
||||
template<class T> void swap(scoped_array<T> & a, scoped_array<T> & b) noexcept;
|
||||
|
||||
Equivalent to `a.swap(b)`.
|
||||
|
||||
### comparisons
|
||||
|
||||
template<class T>
|
||||
bool operator==( scoped_array<T> const & p, std::nullptr_t ) noexcept;
|
||||
|
||||
template<class T>
|
||||
bool operator==( std::nullptr_t, scoped_array<T> const & p ) noexcept;
|
||||
|
||||
Returns `p.get() == nullptr`.
|
||||
|
||||
template<class T>
|
||||
bool operator!=( scoped_array<T> const & p, std::nullptr_t ) noexcept;
|
||||
|
||||
template<class T>
|
||||
bool operator!=( std::nullptr_t, scoped_array<T> const & p ) noexcept;
|
||||
|
||||
Returns `p.get() != nullptr`.
|
||||
234
doc/smart_ptr/scoped_ptr.adoc
Normal file
234
doc/smart_ptr/scoped_ptr.adoc
Normal file
@@ -0,0 +1,234 @@
|
||||
////
|
||||
Copyright 2017 Peter Dimov
|
||||
|
||||
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
|
||||
////
|
||||
|
||||
[#scoped_ptr]
|
||||
# scoped_ptr: Scoped Object Ownership
|
||||
:toc:
|
||||
:toc-title:
|
||||
:idprefix: scoped_ptr_
|
||||
|
||||
## Description
|
||||
|
||||
The `scoped_ptr` class template stores a pointer to a dynamically allocated object.
|
||||
(Dynamically allocated objects are allocated with the {cpp} `new` expression.) The
|
||||
object pointed to is guaranteed to be deleted, either on destruction of the `scoped_ptr`,
|
||||
or via an explicit `reset`. See the <<scoped_ptr_example,example>>.
|
||||
|
||||
`scoped_ptr` is a simple solution for simple needs. It supplies a basic "resource acquisition
|
||||
is initialization" facility, without shared-ownership or transfer-of-ownership semantics.
|
||||
Both its name and enforcement of semantics (by being noncopyable) signal its intent to retain
|
||||
ownership solely within the current scope. Because it is noncopyable, it is safer than `shared_ptr`
|
||||
for pointers which should not be copied.
|
||||
|
||||
Because `scoped_ptr` is simple, in its usual implementation every operation is as fast as for a
|
||||
built-in pointer and it has no more space overhead that a built-in pointer.
|
||||
|
||||
`scoped_ptr` cannot be used in {cpp} Standard Library containers. Use `shared_ptr` or `std::unique_ptr`
|
||||
if you need a smart pointer that can.
|
||||
|
||||
`scoped_ptr` cannot correctly hold a pointer to a dynamically allocated array. See `scoped_array` for that usage.
|
||||
|
||||
The class template is parameterized on `T`, the type of the object pointed to. Destroying `T` must not thow exceptions,
|
||||
and `T` must be complete at the point `scoped_ptr<T>::~scoped_ptr` is instantiated.
|
||||
|
||||
## Synopsis
|
||||
|
||||
`scoped_ptr` is defined in `<boost/smart_ptr/scoped_ptr.hpp>`.
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
|
||||
template<class T> class scoped_ptr {
|
||||
private:
|
||||
|
||||
scoped_ptr(scoped_ptr const&);
|
||||
scoped_ptr& operator=(scoped_ptr const&);
|
||||
|
||||
void operator==(scoped_ptr const&) const;
|
||||
void operator!=(scoped_ptr const&) const;
|
||||
|
||||
public:
|
||||
|
||||
typedef T element_type;
|
||||
|
||||
explicit scoped_ptr(T * p = 0) noexcept;
|
||||
~scoped_ptr() noexcept;
|
||||
|
||||
void reset(T * p = 0) noexcept;
|
||||
|
||||
T & operator*() const noexcept;
|
||||
T * operator->() const noexcept;
|
||||
T * get() const noexcept;
|
||||
|
||||
explicit operator bool() const noexcept;
|
||||
|
||||
void swap(scoped_ptr & b) noexcept;
|
||||
};
|
||||
|
||||
template<class T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) noexcept;
|
||||
|
||||
template<class T>
|
||||
bool operator==( scoped_ptr<T> const & p, std::nullptr_t ) noexcept;
|
||||
template<class T>
|
||||
bool operator==( std::nullptr_t, scoped_ptr<T> const & p ) noexcept;
|
||||
|
||||
template<class T>
|
||||
bool operator!=( scoped_ptr<T> const & p, std::nullptr_t ) noexcept;
|
||||
template<class T>
|
||||
bool operator!=( std::nullptr_t, scoped_ptr<T> const & p ) noexcept;
|
||||
}
|
||||
```
|
||||
|
||||
## Members
|
||||
|
||||
### element_type
|
||||
|
||||
typedef T element_type;
|
||||
|
||||
Provides the type of the stored pointer.
|
||||
|
||||
### constructor
|
||||
|
||||
explicit scoped_ptr(T * p = 0) noexcept;
|
||||
|
||||
Constructs a `scoped_ptr`, storing a copy of `p`, which must have been allocated via a
|
||||
{cpp} `new` expression or be 0. `T` is not required be a complete type.
|
||||
|
||||
### destructor
|
||||
|
||||
~scoped_ptr() noexcept;
|
||||
|
||||
Destroys the object pointed to by the stored pointer, if any, as if by using
|
||||
`delete this\->get()`. `T` must be a complete type.
|
||||
|
||||
### reset
|
||||
|
||||
void reset(T * p = 0) noexcept;
|
||||
|
||||
Deletes the object pointed to by the stored pointer and then stores a copy of
|
||||
`p`, which must have been allocated via a {cpp} `new` expression or be 0.
|
||||
|
||||
Since the previous object needs to be deleted, `T` must be a complete type.
|
||||
|
||||
### indirection
|
||||
|
||||
T & operator*() const noexcept;
|
||||
|
||||
Returns a reference to the object pointed to by the stored pointer. Behavior is undefined if the stored pointer is 0.
|
||||
|
||||
T * operator->() const noexcept;
|
||||
|
||||
Returns the stored pointer. Behavior is undefined if the stored pointer is 0.
|
||||
|
||||
### get
|
||||
|
||||
T * get() const noexcept;
|
||||
|
||||
Returns the stored pointer. `T` need not be a complete type.
|
||||
|
||||
### conversions
|
||||
|
||||
explicit operator bool () const noexcept; // never throws
|
||||
|
||||
Returns `get() != 0`.
|
||||
|
||||
NOTE: On C++03 compilers, the return value is of an unspecified type.
|
||||
|
||||
### swap
|
||||
|
||||
void swap(scoped_ptr & b) noexcept;
|
||||
|
||||
Exchanges the contents of the two smart pointers. `T` need not be a complete type.
|
||||
|
||||
## Free Functions
|
||||
|
||||
### swap
|
||||
|
||||
template<class T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) noexcept;
|
||||
|
||||
Equivalent to `a.swap(b)`.
|
||||
|
||||
### comparisons
|
||||
|
||||
template<class T> bool operator==( scoped_ptr<T> const & p, std::nullptr_t ) noexcept;
|
||||
|
||||
template<class T> bool operator==( std::nullptr_t, scoped_ptr<T> const & p ) noexcept;
|
||||
|
||||
Returns `p.get() == nullptr`.
|
||||
|
||||
template<class T> bool operator!=( scoped_ptr<T> const & p, std::nullptr_t ) noexcept;
|
||||
|
||||
template<class T> bool operator!=( std::nullptr_t, scoped_ptr<T> const & p ) noexcept;
|
||||
|
||||
Returns `p.get() != nullptr`.
|
||||
|
||||
## Example
|
||||
|
||||
Here's an example that uses `scoped_ptr`.
|
||||
|
||||
```
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <iostream>
|
||||
|
||||
struct Shoe { ~Shoe() { std::cout << "Buckle my shoe\n"; } };
|
||||
|
||||
class MyClass {
|
||||
boost::scoped_ptr<int> ptr;
|
||||
public:
|
||||
MyClass() : ptr(new int) { *ptr = 0; }
|
||||
int add_one() { return ++*ptr; }
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
boost::scoped_ptr<Shoe> x(new Shoe);
|
||||
MyClass my_instance;
|
||||
std::cout << my_instance.add_one() << '\n';
|
||||
std::cout << my_instance.add_one() << '\n';
|
||||
}
|
||||
```
|
||||
|
||||
The example program produces the beginning of a child's nursery rhyme:
|
||||
|
||||
```
|
||||
1
|
||||
2
|
||||
Buckle my shoe
|
||||
```
|
||||
|
||||
## Rationale
|
||||
|
||||
The primary reason to use `scoped_ptr` rather than `std::auto_ptr` or `std::unique_ptr` is to let readers of your code
|
||||
know that you intend "resource acquisition is initialization" to be applied only for the current scope, and have no intent to transfer ownership.
|
||||
|
||||
A secondary reason to use `scoped_ptr` is to prevent a later maintenance programmer from adding a function that transfers
|
||||
ownership by returning the `auto_ptr`, because the maintenance programmer saw `auto_ptr`, and assumed ownership could safely be transferred.
|
||||
|
||||
Think of `bool` vs `int`. We all know that under the covers `bool` is usually just an `int`. Indeed, some argued against including bool in the {cpp}
|
||||
standard because of that. But by coding `bool` rather than `int`, you tell your readers what your intent is. Same with `scoped_ptr`; by using it you are signaling intent.
|
||||
|
||||
It has been suggested that `scoped_ptr<T>` is equivalent to `std::auto_ptr<T> const`. Ed Brey pointed out, however, that `reset` will not work on a `std::auto_ptr<T> const`.
|
||||
|
||||
## Handle/Body Idiom
|
||||
|
||||
One common usage of `scoped_ptr` is to implement a handle/body (also called pimpl) idiom which avoids exposing the body (implementation) in the header file.
|
||||
|
||||
The `link:../../example/scoped_ptr_example_test.cpp[scoped_ptr_example_test.cpp]` sample program includes a header file,
|
||||
`link:../../example/scoped_ptr_example.hpp[scoped_ptr_example.hpp]`, which uses a `scoped_ptr<>` to an incomplete type to hide the
|
||||
implementation. The instantiation of member functions which require a complete type occurs in the `link:../../example/scoped_ptr_example.cpp[scoped_ptr_example.cpp]`
|
||||
implementation file.
|
||||
|
||||
## Frequently Asked Questions
|
||||
|
||||
[qanda]
|
||||
Why doesn't `scoped_ptr` have a `release()` member?::
|
||||
|
||||
When reading source code, it is valuable to be able to draw conclusions about program behavior based on the types being used. If `scoped_ptr` had a `release()` member,
|
||||
it would become possible to transfer ownership of the held pointer, weakening its role as a way of limiting resource lifetime to a given context. Use `std::auto_ptr` where
|
||||
transfer of ownership is required. (supplied by Dave Abrahams)
|
||||
298
doc/smart_ptr/shared_array.adoc
Normal file
298
doc/smart_ptr/shared_array.adoc
Normal file
@@ -0,0 +1,298 @@
|
||||
////
|
||||
Copyright 2017 Peter Dimov
|
||||
|
||||
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
|
||||
////
|
||||
|
||||
[[shared_array]]
|
||||
[appendix]
|
||||
# shared_array (deprecated)
|
||||
:toc:
|
||||
:toc-title:
|
||||
:idprefix: shared_array_
|
||||
|
||||
NOTE: This facility is deprecated because a `shared_ptr` to `T[]` or `T[N]`
|
||||
is now available, and is superior in every regard.
|
||||
|
||||
## Description
|
||||
|
||||
The `shared_array` class template stores a pointer to a dynamically allocated
|
||||
array. (Dynamically allocated array are allocated with the C++ `new[]`
|
||||
expression.) The object pointed to is guaranteed to be deleted when the last
|
||||
`shared_array` pointing to it is destroyed or reset.
|
||||
|
||||
Every `shared_array` meets the _CopyConstructible_ and _Assignable_
|
||||
requirements of the {cpp} Standard Library, and so can be used in standard
|
||||
library containers. Comparison operators are supplied so that shared_array
|
||||
works with the standard library's associative containers.
|
||||
|
||||
Normally, a `shared_array` cannot correctly hold a pointer to an object that
|
||||
has been allocated with the non-array form of `new`. See `shared_ptr` for that
|
||||
usage.
|
||||
|
||||
Because the implementation uses reference counting, cycles of `shared_array`
|
||||
instances will not be reclaimed. For example, if `main` holds a shared_array
|
||||
to `A`, which directly or indirectly holds a shared_array back to `A`, the use
|
||||
count of `A` will be 2. Destruction of the original `shared_array` will leave
|
||||
`A` dangling with a use count of 1.
|
||||
|
||||
A `shared_ptr` to a `std::vector` is an alternative to a `shared_array` that
|
||||
is a bit heavier duty but far more flexible.
|
||||
|
||||
The class template is parameterized on `T`, the type of the object pointed to.
|
||||
`shared_array` and most of its member functions place no requirements on `T`;
|
||||
it is allowed to be an incomplete type, or `void`. Member functions that do
|
||||
place additional requirements (constructors, reset) are explicitly documented
|
||||
below.
|
||||
|
||||
## Synopsis
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
|
||||
template<class T> class shared_array {
|
||||
public:
|
||||
typedef T element_type;
|
||||
|
||||
explicit shared_array(T* p = 0);
|
||||
template<class D> shared_array(T* p, D d);
|
||||
shared_array(const shared_array& v) noexcept;
|
||||
|
||||
~shared_array() noexcept;
|
||||
|
||||
shared_array& operator=(const shared_array& v) noexcept;
|
||||
|
||||
void reset(T* p = 0);
|
||||
template<class D> void reset(T* p, D d);
|
||||
|
||||
T& operator[](std::ptrdiff_t n) const noexcept;
|
||||
T* get() const noexcept;
|
||||
|
||||
bool unique() const noexcept;
|
||||
long use_count() const noexcept;
|
||||
|
||||
explicit operator bool() const noexcept;
|
||||
|
||||
void swap(shared_array<T>& v) noexcept;
|
||||
};
|
||||
|
||||
template<class T> bool
|
||||
operator==(const shared_array<T>& a, const shared_array<T>& b) noexcept;
|
||||
template<class T> bool
|
||||
operator!=(const shared_array<T>& a, const shared_array<T>& b) noexcept;
|
||||
template<class T> bool
|
||||
operator<(const shared_array<T>& a, const shared_array<T>& b) noexcept;
|
||||
|
||||
template<class T>
|
||||
void swap(shared_array<T>& a, shared_array<T>& b) noexcept;
|
||||
}
|
||||
```
|
||||
|
||||
## Members
|
||||
|
||||
### element_type
|
||||
|
||||
```
|
||||
typedef T element_type;
|
||||
```
|
||||
Type:: Provides the type of the stored pointer.
|
||||
|
||||
### Constructors
|
||||
|
||||
```
|
||||
explicit shared_array(T* p = 0);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Constructs a `shared_array`, storing a copy of `p`, which must be a
|
||||
pointer to an array that was allocated via a C++ `new[]` expression or be 0.
|
||||
Afterwards, the use count is 1 (even if `p == 0`; see `~shared_array`).
|
||||
Requires:: `T` is a complete type.
|
||||
Throws:: `std::bad_alloc`. If an exception is thrown, `delete[] p` is called.
|
||||
|
||||
```
|
||||
template<class D> shared_array(T* p, D d);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Constructs a `shared_array`, storing a copy of `p` and of `d`.
|
||||
Afterwards, the use count is 1. When the the time comes to delete the array
|
||||
pointed to by `p`, the object `d` is used in the statement `d(p)`.
|
||||
Requires::
|
||||
* `T` is a complete type.
|
||||
* The copy constructor and destructor of `D` must not throw.
|
||||
* Invoking the object `d` with parameter `p` must not throw.
|
||||
Throws:: `std::bad_alloc`. If an exception is thrown, `d(p)` is called.
|
||||
|
||||
```
|
||||
shared_array(const shared_array& v) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Constructs a `shared_array`, as if by storing a copy of the pointer
|
||||
stored in `v`. Afterwards, the use count for all copies is 1 more than the
|
||||
initial use count.
|
||||
Requires:: `T` is a complete type.
|
||||
|
||||
### Destructor
|
||||
|
||||
```
|
||||
~shared_array() noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Decrements the use count. Then, if the use count is 0, deletes the
|
||||
array pointed to by the stored pointer. Note that `delete[]` on a pointer with
|
||||
a value of 0 is harmless.
|
||||
|
||||
### Assignment
|
||||
|
||||
```
|
||||
shared_array& operator=(const shared_array& v) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Constructs a new `shared_array` as described above, then replaces
|
||||
this `shared_array` with the new one, destroying the replaced object.
|
||||
Requires:: `T` is a complete type.
|
||||
Returns:: `*this`.
|
||||
|
||||
### reset
|
||||
|
||||
```
|
||||
void reset(T* p = 0);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Constructs a new `shared_array` as described above, then replaces
|
||||
this `shared_array` with the new one, destroying the replaced object.
|
||||
Requires:: `T` is a complete type.
|
||||
Throws:: `std::bad_alloc`. If an exception is thrown, `delete[] p` is called.
|
||||
|
||||
```
|
||||
template<class D> void reset(T* p, D d);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Constructs a new `shared_array` as described above, then replaces
|
||||
this `shared_array` with the new one, destroying the replaced object.
|
||||
Requires::
|
||||
* `T` is a complete type.
|
||||
* The copy constructor of `D` must not throw.
|
||||
Throws:: `std::bad_alloc`. If an exception is thrown, `d(p)` is called.
|
||||
|
||||
### Indexing
|
||||
|
||||
```
|
||||
T& operator[](std::ptrdiff_t n) const noexcept;
|
||||
```
|
||||
Returns:: A reference to element `n` of the array pointed to by the stored
|
||||
pointer. Behavior is undefined and almost certainly undesirable if the stored
|
||||
pointer is 0, or if `n` is less than 0 or is greater than or equal to the
|
||||
number of elements in the array.
|
||||
Requires:: `T` is a complete type.
|
||||
|
||||
### get
|
||||
|
||||
```
|
||||
T* get() const noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: The stored pointer.
|
||||
|
||||
### unique
|
||||
|
||||
```
|
||||
bool unique() const noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `true` if no other `shared_array` is sharing ownership of the
|
||||
stored pointer, `false` otherwise.
|
||||
|
||||
### use_count
|
||||
|
||||
```
|
||||
long use_count() const noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: The number of `shared_array` objects sharing ownership of the
|
||||
stored pointer.
|
||||
|
||||
### Conversions
|
||||
|
||||
```
|
||||
explicit operator bool() const noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `get() != 0`.
|
||||
Requires:: `T` is a complete type.
|
||||
|
||||
### swap
|
||||
|
||||
```
|
||||
void swap(shared_array<T>& b) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Exchanges the contents of the two smart pointers.
|
||||
|
||||
## Free Functions
|
||||
|
||||
### Comparison
|
||||
|
||||
```
|
||||
template<class T> bool
|
||||
operator==(const shared_array<T>& a, const shared_array<T>& b) noexcept;
|
||||
```
|
||||
```
|
||||
template<class T> bool
|
||||
operator!=(const shared_array<T>& a, const shared_array<T>& b) noexcept;
|
||||
```
|
||||
```
|
||||
template<class T> bool
|
||||
operator<(const shared_array<T>& a, const shared_array<T>& b) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: The result of comparing the stored pointers of the two smart
|
||||
pointers.
|
||||
|
||||
NOTE: The `operator<` overload is provided to define an ordering so that
|
||||
`shared_array` objects can be used in associative containers such as
|
||||
`std::map`. The implementation uses `std::less<T*>` to perform the comparison.
|
||||
This ensures that the comparison is handled correctly, since the standard
|
||||
mandates that relational operations on pointers are unspecified (5.9
|
||||
[expr.rel] paragraph 2) but `std::less` on pointers is well-defined (20.3.3
|
||||
[lib.comparisons] paragraph 8).
|
||||
|
||||
### swap
|
||||
|
||||
```
|
||||
template<class T>
|
||||
void swap(shared_array<T>& a, shared_array<T>& b) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `a.swap(b)`.
|
||||
Requires:: `T` is a complete type.
|
||||
1034
doc/smart_ptr/shared_ptr.adoc
Normal file
1034
doc/smart_ptr/shared_ptr.adoc
Normal file
File diff suppressed because it is too large
Load Diff
768
doc/smart_ptr/techniques.adoc
Normal file
768
doc/smart_ptr/techniques.adoc
Normal file
@@ -0,0 +1,768 @@
|
||||
////
|
||||
Copyright 2003, 2017 Peter Dimov
|
||||
|
||||
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
|
||||
////
|
||||
|
||||
[[techniques]]
|
||||
[appendix]
|
||||
# Smart Pointer Programming Techniques
|
||||
:toc:
|
||||
:toc-title:
|
||||
:idprefix: techniques_
|
||||
|
||||
[#techniques_incomplete]
|
||||
## Using incomplete classes for implementation hiding
|
||||
|
||||
A proven technique (that works in C, too) for separating interface from implementation is to use a pointer to an incomplete class as an opaque handle:
|
||||
|
||||
```
|
||||
class FILE;
|
||||
|
||||
FILE * fopen(char const * name, char const * mode);
|
||||
void fread(FILE * f, void * data, size_t size);
|
||||
void fclose(FILE * f);
|
||||
```
|
||||
|
||||
|
||||
It is possible to express the above interface using `shared_ptr`, eliminating the need to manually call `fclose`:
|
||||
|
||||
```
|
||||
class FILE;
|
||||
|
||||
shared_ptr<FILE> fopen(char const * name, char const * mode);
|
||||
void fread(shared_ptr<FILE> f, void * data, size_t size);
|
||||
```
|
||||
|
||||
This technique relies on `shared_ptr`’s ability to execute a custom deleter, eliminating the explicit call to `fclose`, and on the fact that `shared_ptr<X>` can be copied and destroyed when `X` is incomplete.
|
||||
|
||||
## The "Pimpl" idiom
|
||||
|
||||
A {cpp} specific variation of the incomplete class pattern is the "Pimpl" idiom. The incomplete class is not exposed to the user; it is hidden behind a forwarding facade. `shared_ptr` can be used to implement a "Pimpl":
|
||||
|
||||
```
|
||||
// file.hpp:
|
||||
|
||||
class file
|
||||
{
|
||||
private:
|
||||
|
||||
class impl;
|
||||
shared_ptr<impl> pimpl_;
|
||||
|
||||
public:
|
||||
|
||||
file(char const * name, char const * mode);
|
||||
|
||||
// compiler generated members are fine and useful
|
||||
|
||||
void read(void * data, size_t size);
|
||||
};
|
||||
|
||||
// file.cpp:
|
||||
|
||||
#include "file.hpp"
|
||||
|
||||
class file::impl
|
||||
{
|
||||
private:
|
||||
|
||||
impl(impl const &);
|
||||
impl & operator=(impl const &);
|
||||
|
||||
// private data
|
||||
|
||||
public:
|
||||
|
||||
impl(char const * name, char const * mode) { ... }
|
||||
~impl() { ... }
|
||||
void read(void * data, size_t size) { ... }
|
||||
};
|
||||
|
||||
file::file(char const * name, char const * mode): pimpl_(new impl(name, mode))
|
||||
{
|
||||
}
|
||||
|
||||
void file::read(void * data, size_t size)
|
||||
{
|
||||
pimpl_->read(data, size);
|
||||
}
|
||||
```
|
||||
|
||||
The key thing to note here is that the compiler-generated copy constructor, assignment operator, and destructor all have a sensible meaning. As a result, `file` is `CopyConstructible` and `Assignable`, allowing its use in standard containers.
|
||||
|
||||
## Using abstract classes for implementation hiding
|
||||
|
||||
Another widely used C++ idiom for separating inteface and implementation is to use abstract base classes and factory functions.
|
||||
The abstract classes are sometimes called "interfaces" and the pattern is known as "interface-based programming". Again,
|
||||
`shared_ptr` can be used as the return type of the factory functions:
|
||||
|
||||
```
|
||||
// X.hpp:
|
||||
|
||||
class X
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void f() = 0;
|
||||
virtual void g() = 0;
|
||||
|
||||
protected:
|
||||
|
||||
~X() {}
|
||||
};
|
||||
|
||||
shared_ptr<X> createX();
|
||||
|
||||
// X.cpp:
|
||||
|
||||
class X_impl: public X
|
||||
{
|
||||
private:
|
||||
|
||||
X_impl(X_impl const &);
|
||||
X_impl & operator=(X_impl const &);
|
||||
|
||||
public:
|
||||
|
||||
virtual void f()
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
virtual void g()
|
||||
{
|
||||
// ...
|
||||
}
|
||||
};
|
||||
|
||||
shared_ptr<X> createX()
|
||||
{
|
||||
shared_ptr<X> px(new X_impl);
|
||||
return px;
|
||||
}
|
||||
```
|
||||
|
||||
A key property of `shared_ptr` is that the allocation, construction, deallocation, and destruction details are captured at the point of construction, inside the factory function.
|
||||
|
||||
Note the protected and nonvirtual destructor in the example above. The client code cannot, and does not need to, delete a pointer to `X`; the `shared_ptr<X>` instance returned from `createX` will correctly call `~X_impl`.
|
||||
|
||||
## Preventing `delete px.get()`
|
||||
|
||||
It is often desirable to prevent client code from deleting a pointer that is being managed by `shared_ptr`. The previous technique showed one possible approach, using a protected destructor. Another alternative is to use a private deleter:
|
||||
|
||||
```
|
||||
class X
|
||||
{
|
||||
private:
|
||||
|
||||
~X();
|
||||
|
||||
class deleter;
|
||||
friend class deleter;
|
||||
|
||||
class deleter
|
||||
{
|
||||
public:
|
||||
|
||||
void operator()(X * p) { delete p; }
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
static shared_ptr<X> create()
|
||||
{
|
||||
shared_ptr<X> px(new X, X::deleter());
|
||||
return px;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## Encapsulating allocation details, wrapping factory functions
|
||||
|
||||
`shared_ptr` can be used in creating {cpp} wrappers over existing C style library interfaces that return raw pointers from their factory functions
|
||||
to encapsulate allocation details. As an example, consider this interface, where `CreateX` might allocate `X` from its own private heap, `~X` may
|
||||
be inaccessible, or `X` may be incomplete:
|
||||
|
||||
X * CreateX();
|
||||
void DestroyX(X *);
|
||||
|
||||
The only way to reliably destroy a pointer returned by `CreateX` is to call `DestroyX`.
|
||||
|
||||
Here is how a `shared_ptr`-based wrapper may look like:
|
||||
|
||||
shared_ptr<X> createX()
|
||||
{
|
||||
shared_ptr<X> px(CreateX(), DestroyX);
|
||||
return px;
|
||||
}
|
||||
|
||||
Client code that calls `createX` still does not need to know how the object has been allocated, but now the destruction is automatic.
|
||||
|
||||
[#techniques_static]
|
||||
## Using a shared_ptr to hold a pointer to a statically allocated object
|
||||
|
||||
Sometimes it is desirable to create a `shared_ptr` to an already existing object, so that the `shared_ptr` does not attempt to destroy the
|
||||
object when there are no more references left. As an example, the factory function:
|
||||
|
||||
shared_ptr<X> createX();
|
||||
|
||||
in certain situations may need to return a pointer to a statically allocated `X` instance.
|
||||
|
||||
The solution is to use a custom deleter that does nothing:
|
||||
|
||||
```
|
||||
struct null_deleter
|
||||
{
|
||||
void operator()(void const *) const
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static X x;
|
||||
|
||||
shared_ptr<X> createX()
|
||||
{
|
||||
shared_ptr<X> px(&x, null_deleter());
|
||||
return px;
|
||||
}
|
||||
```
|
||||
|
||||
The same technique works for any object known to outlive the pointer.
|
||||
|
||||
## Using a shared_ptr to hold a pointer to a COM Object
|
||||
|
||||
Background: COM objects have an embedded reference count and two member functions that manipulate it. `AddRef()` increments the count.
|
||||
`Release()` decrements the count and destroys itself when the count drops to zero.
|
||||
|
||||
It is possible to hold a pointer to a COM object in a `shared_ptr`:
|
||||
|
||||
shared_ptr<IWhatever> make_shared_from_COM(IWhatever * p)
|
||||
{
|
||||
p->AddRef();
|
||||
shared_ptr<IWhatever> pw(p, mem_fn(&IWhatever::Release));
|
||||
return pw;
|
||||
}
|
||||
|
||||
Note, however, that `shared_ptr` copies created from `pw` will not "register" in the embedded count of the COM object;
|
||||
they will share the single reference created in `make_shared_from_COM`. Weak pointers created from `pw` will be invalidated when the last
|
||||
`shared_ptr` is destroyed, regardless of whether the COM object itself is still alive.
|
||||
|
||||
As link:../../../../libs/bind/mem_fn.html#Q3[explained] in the `mem_fn` documentation, you need to `#define BOOST_MEM_FN_ENABLE_STDCALL` first.
|
||||
|
||||
[#techniques_intrusive]
|
||||
## Using a shared_ptr to hold a pointer to an object with an embedded reference count
|
||||
|
||||
This is a generalization of the above technique. The example assumes that the object implements the two functions required by `<<intrusive_ptr,intrusive_ptr>>`,
|
||||
`intrusive_ptr_add_ref` and `intrusive_ptr_release`:
|
||||
|
||||
```
|
||||
template<class T> struct intrusive_deleter
|
||||
{
|
||||
void operator()(T * p)
|
||||
{
|
||||
if(p) intrusive_ptr_release(p);
|
||||
}
|
||||
};
|
||||
|
||||
shared_ptr<X> make_shared_from_intrusive(X * p)
|
||||
{
|
||||
if(p) intrusive_ptr_add_ref(p);
|
||||
shared_ptr<X> px(p, intrusive_deleter<X>());
|
||||
return px;
|
||||
}
|
||||
```
|
||||
|
||||
## Using a shared_ptr to hold another shared ownership smart pointer
|
||||
|
||||
One of the design goals of `shared_ptr` is to be used in library interfaces. It is possible to encounter a situation where a library takes a
|
||||
`shared_ptr` argument, but the object at hand is being managed by a different reference counted or linked smart pointer.
|
||||
|
||||
It is possible to exploit `shared_ptr`’s custom deleter feature to wrap this existing smart pointer behind a `shared_ptr` facade:
|
||||
|
||||
```
|
||||
template<class P> struct smart_pointer_deleter
|
||||
{
|
||||
private:
|
||||
|
||||
P p_;
|
||||
|
||||
public:
|
||||
|
||||
smart_pointer_deleter(P const & p): p_(p)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(void const *)
|
||||
{
|
||||
p_.reset();
|
||||
}
|
||||
|
||||
P const & get() const
|
||||
{
|
||||
return p_;
|
||||
}
|
||||
};
|
||||
|
||||
shared_ptr<X> make_shared_from_another(another_ptr<X> qx)
|
||||
{
|
||||
shared_ptr<X> px(qx.get(), smart_pointer_deleter< another_ptr<X> >(qx));
|
||||
return px;
|
||||
}
|
||||
```
|
||||
|
||||
One subtle point is that deleters are not allowed to throw exceptions, and the above example as written assumes that `p_.reset()` doesn't throw.
|
||||
If this is not the case, `p_.reset();` should be wrapped in a `try {} catch(...) {}` block that ignores exceptions. In the (usually unlikely) event
|
||||
when an exception is thrown and ignored, `p_` will be released when the lifetime of the deleter ends. This happens when all references, including
|
||||
weak pointers, are destroyed or reset.
|
||||
|
||||
Another twist is that it is possible, given the above `shared_ptr` instance, to recover the original smart pointer, using `<<shared_ptr_get_deleter,get_deleter>>`:
|
||||
|
||||
```
|
||||
void extract_another_from_shared(shared_ptr<X> px)
|
||||
{
|
||||
typedef smart_pointer_deleter< another_ptr<X> > deleter;
|
||||
|
||||
if(deleter const * pd = get_deleter<deleter>(px))
|
||||
{
|
||||
another_ptr<X> qx = pd->get();
|
||||
}
|
||||
else
|
||||
{
|
||||
// not one of ours
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
[#techniques_from_raw]
|
||||
## Obtaining a shared_ptr from a raw pointer
|
||||
|
||||
Sometimes it is necessary to obtain a `shared_ptr` given a raw pointer to an object that is already managed by another `shared_ptr` instance. Example:
|
||||
|
||||
void f(X * p)
|
||||
{
|
||||
shared_ptr<X> px(???);
|
||||
}
|
||||
|
||||
Inside `f`, we'd like to create a `shared_ptr` to `*p`.
|
||||
|
||||
In the general case, this problem has no solution. One approach is to modify `f` to take a `shared_ptr`, if possible:
|
||||
|
||||
void f(shared_ptr<X> px);
|
||||
|
||||
The same transformation can be used for nonvirtual member functions, to convert the implicit `this`:
|
||||
|
||||
void X::f(int m);
|
||||
|
||||
would become a free function with a `shared_ptr` first argument:
|
||||
|
||||
void f(shared_ptr<X> this_, int m);
|
||||
|
||||
If `f` cannot be changed, but `X` uses intrusive counting, use `<<techniques_intrusive,make_shared_from_intrusive>>` described above. Or, if it's known that the `shared_ptr` created in `f` will never outlive the object, use <<techniques_static,a null deleter>>.
|
||||
|
||||
## Obtaining a shared_ptr (weak_ptr) to this in a constructor
|
||||
|
||||
Some designs require objects to register themselves on construction with a central authority. When the registration routines take a `shared_ptr`, this leads to the question how could a constructor obtain a `shared_ptr` to `this`:
|
||||
|
||||
```
|
||||
class X
|
||||
{
|
||||
public:
|
||||
|
||||
X()
|
||||
{
|
||||
shared_ptr<X> this_(???);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
In the general case, the problem cannot be solved. The `X` instance being constructed can be an automatic variable or a static variable; it can be created on the heap:
|
||||
|
||||
shared_ptr<X> px(new X);
|
||||
|
||||
but at construction time, `px` does not exist yet, and it is impossible to create another `shared_ptr` instance that shares ownership with it.
|
||||
|
||||
Depending on context, if the inner `shared_ptr this_` doesn't need to keep the object alive, use a `null_deleter` as explained <<techniques_static,here>> and <<techniques_weak_without_shared,here>>.
|
||||
If `X` is supposed to always live on the heap, and be managed by a `shared_ptr`, use a static factory function:
|
||||
|
||||
```
|
||||
class X
|
||||
{
|
||||
private:
|
||||
|
||||
X() { ... }
|
||||
|
||||
public:
|
||||
|
||||
static shared_ptr<X> create()
|
||||
{
|
||||
shared_ptr<X> px(new X);
|
||||
// use px as 'this_'
|
||||
return px;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## Obtaining a shared_ptr to this
|
||||
|
||||
Sometimes it is needed to obtain a `shared_ptr` from `this` in a virtual member function under the assumption that `this` is already managed by a `shared_ptr`.
|
||||
The transformations <<techniques_from_raw,described in the previous technique>> cannot be applied.
|
||||
|
||||
A typical example:
|
||||
|
||||
```
|
||||
class X
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void f() = 0;
|
||||
|
||||
protected:
|
||||
|
||||
~X() {}
|
||||
};
|
||||
|
||||
class Y
|
||||
{
|
||||
public:
|
||||
|
||||
virtual shared_ptr<X> getX() = 0;
|
||||
|
||||
protected:
|
||||
|
||||
~Y() {}
|
||||
};
|
||||
|
||||
// --
|
||||
|
||||
class impl: public X, public Y
|
||||
{
|
||||
public:
|
||||
|
||||
impl() { ... }
|
||||
|
||||
virtual void f() { ... }
|
||||
|
||||
virtual shared_ptr<X> getX()
|
||||
{
|
||||
shared_ptr<X> px(???);
|
||||
return px;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
The solution is to keep a weak pointer to `this` as a member in `impl`:
|
||||
|
||||
```
|
||||
class impl: public X, public Y
|
||||
{
|
||||
private:
|
||||
|
||||
weak_ptr<impl> weak_this;
|
||||
|
||||
impl(impl const &);
|
||||
impl & operator=(impl const &);
|
||||
|
||||
impl() { ... }
|
||||
|
||||
public:
|
||||
|
||||
static shared_ptr<impl> create()
|
||||
{
|
||||
shared_ptr<impl> pi(new impl);
|
||||
pi->weak_this = pi;
|
||||
return pi;
|
||||
}
|
||||
|
||||
virtual void f() { ... }
|
||||
|
||||
virtual shared_ptr<X> getX()
|
||||
{
|
||||
shared_ptr<X> px(weak_this);
|
||||
return px;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
The library now includes a helper class template `<<enable_shared_from_this,enable_shared_from_this>>` that can be used to encapsulate the solution:
|
||||
|
||||
```
|
||||
class impl: public X, public Y, public enable_shared_from_this<impl>
|
||||
{
|
||||
public:
|
||||
|
||||
impl(impl const &);
|
||||
impl & operator=(impl const &);
|
||||
|
||||
public:
|
||||
|
||||
virtual void f() { ... }
|
||||
|
||||
virtual shared_ptr<X> getX()
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Note that you no longer need to manually initialize the `weak_ptr` member in `enable_shared_from_this`. Constructing a `shared_ptr` to `impl` takes care of that.
|
||||
|
||||
## Using shared_ptr as a smart counted handle
|
||||
|
||||
Some library interfaces use opaque handles, a variation of the <<techniques_incomplete,incomplete class technique>> described above. An example:
|
||||
|
||||
```
|
||||
typedef void * HANDLE;
|
||||
|
||||
HANDLE CreateProcess();
|
||||
void CloseHandle(HANDLE);
|
||||
```
|
||||
|
||||
Instead of a raw pointer, it is possible to use `shared_ptr` as the handle and get reference counting and automatic resource management for free:
|
||||
|
||||
```
|
||||
typedef shared_ptr<void> handle;
|
||||
|
||||
handle createProcess()
|
||||
{
|
||||
shared_ptr<void> pv(CreateProcess(), CloseHandle);
|
||||
return pv;
|
||||
}
|
||||
```
|
||||
|
||||
## Using shared_ptr to execute code on block exit
|
||||
|
||||
`shared_ptr<void>` can automatically execute cleanup code when control leaves a scope.
|
||||
|
||||
* Executing `f(p)`, where `p` is a pointer:
|
||||
+
|
||||
```
|
||||
shared_ptr<void> guard(p, f);
|
||||
```
|
||||
|
||||
* Executing arbitrary code: `f(x, y)`:
|
||||
+
|
||||
```
|
||||
shared_ptr<void> guard(static_cast<void*>(0), bind(f, x, y));
|
||||
```
|
||||
|
||||
## Using shared_ptr<void> to hold an arbitrary object
|
||||
|
||||
`shared_ptr<void>` can act as a generic object pointer similar to `void*`. When a `shared_ptr<void>` instance constructed as:
|
||||
|
||||
shared_ptr<void> pv(new X);
|
||||
|
||||
is destroyed, it will correctly dispose of the `X` object by executing `~X`.
|
||||
|
||||
This propery can be used in much the same manner as a raw `void*` is used to temporarily strip type information from an object pointer.
|
||||
A `shared_ptr<void>` can later be cast back to the correct type by using `<<shared_ptr_static_pointer_cast,static_pointer_cast>>`.
|
||||
|
||||
## Associating arbitrary data with heterogeneous `shared_ptr` instances
|
||||
|
||||
`shared_ptr` and `weak_ptr` support `operator<` comparisons required by standard associative containers such as `std::map`. This can be
|
||||
used to non-intrusively associate arbitrary data with objects managed by `shared_ptr`:
|
||||
|
||||
```
|
||||
typedef int Data;
|
||||
|
||||
std::map<shared_ptr<void>, Data> userData;
|
||||
// or std::map<weak_ptr<void>, Data> userData; to not affect the lifetime
|
||||
|
||||
shared_ptr<X> px(new X);
|
||||
shared_ptr<int> pi(new int(3));
|
||||
|
||||
userData[px] = 42;
|
||||
userData[pi] = 91;
|
||||
```
|
||||
|
||||
## Using `shared_ptr` as a `CopyConstructible` mutex lock
|
||||
|
||||
Sometimes it's necessary to return a mutex lock from a function, and a noncopyable lock cannot be returned by value. It is possible to use `shared_ptr` as a mutex lock:
|
||||
|
||||
```
|
||||
class mutex
|
||||
{
|
||||
public:
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
};
|
||||
|
||||
shared_ptr<mutex> lock(mutex & m)
|
||||
{
|
||||
m.lock();
|
||||
return shared_ptr<mutex>(&m, mem_fn(&mutex::unlock));
|
||||
}
|
||||
```
|
||||
|
||||
Better yet, the `shared_ptr` instance acting as a lock can be encapsulated in a dedicated `shared_lock` class:
|
||||
|
||||
```
|
||||
class shared_lock
|
||||
{
|
||||
private:
|
||||
|
||||
shared_ptr<void> pv;
|
||||
|
||||
public:
|
||||
|
||||
template<class Mutex> explicit shared_lock(Mutex & m): pv((m.lock(), &m), mem_fn(&Mutex::unlock)) {}
|
||||
};
|
||||
```
|
||||
|
||||
`shared_lock` can now be used as:
|
||||
|
||||
shared_lock lock(m);
|
||||
|
||||
Note that `shared_lock` is not templated on the mutex type, thanks to `shared_ptr<void>`’s ability to hide type information.
|
||||
|
||||
## Using shared_ptr to wrap member function calls
|
||||
|
||||
`shared_ptr` implements the ownership semantics required from the `Wrap/CallProxy` scheme described in Bjarne Stroustrup's article
|
||||
"Wrapping C++ Member Function Calls" (available online at http://www.stroustrup.com/wrapper.pdf). An implementation is given below:
|
||||
|
||||
```
|
||||
template<class T> class pointer
|
||||
{
|
||||
private:
|
||||
|
||||
T * p_;
|
||||
|
||||
public:
|
||||
|
||||
explicit pointer(T * p): p_(p)
|
||||
{
|
||||
}
|
||||
|
||||
shared_ptr<T> operator->() const
|
||||
{
|
||||
p_->prefix();
|
||||
return shared_ptr<T>(p_, mem_fn(&T::suffix));
|
||||
}
|
||||
};
|
||||
|
||||
class X
|
||||
{
|
||||
private:
|
||||
|
||||
void prefix();
|
||||
void suffix();
|
||||
friend class pointer<X>;
|
||||
|
||||
public:
|
||||
|
||||
void f();
|
||||
void g();
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
X x;
|
||||
|
||||
pointer<X> px(&x);
|
||||
|
||||
px->f();
|
||||
px->g();
|
||||
}
|
||||
```
|
||||
|
||||
## Delayed deallocation
|
||||
|
||||
In some situations, a single `px.reset()` can trigger an expensive deallocation in a performance-critical region:
|
||||
|
||||
```
|
||||
class X; // ~X is expensive
|
||||
|
||||
class Y
|
||||
{
|
||||
shared_ptr<X> px;
|
||||
|
||||
public:
|
||||
|
||||
void f()
|
||||
{
|
||||
px.reset();
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
The solution is to postpone the potential deallocation by moving `px` to a dedicated free list that can be periodically emptied when performance and response times are not an issue:
|
||||
|
||||
```
|
||||
vector< shared_ptr<void> > free_list;
|
||||
|
||||
class Y
|
||||
{
|
||||
shared_ptr<X> px;
|
||||
|
||||
public:
|
||||
|
||||
void f()
|
||||
{
|
||||
free_list.push_back(px);
|
||||
px.reset();
|
||||
}
|
||||
};
|
||||
|
||||
// periodically invoke free_list.clear() when convenient
|
||||
```
|
||||
|
||||
Another variation is to move the free list logic to the construction point by using a delayed deleter:
|
||||
|
||||
```
|
||||
struct delayed_deleter
|
||||
{
|
||||
template<class T> void operator()(T * p)
|
||||
{
|
||||
try
|
||||
{
|
||||
shared_ptr<void> pv(p);
|
||||
free_list.push_back(pv);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
}
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
[#techniques_weak_without_shared]
|
||||
## Weak pointers to objects not managed by a shared_ptr
|
||||
|
||||
Make the object hold a `shared_ptr` to itself, using a `null_deleter`:
|
||||
|
||||
```
|
||||
class X
|
||||
{
|
||||
private:
|
||||
|
||||
shared_ptr<X> this_;
|
||||
int i_;
|
||||
|
||||
public:
|
||||
|
||||
explicit X(int i): this_(this, null_deleter()), i_(i)
|
||||
{
|
||||
}
|
||||
|
||||
// repeat in all constructors (including the copy constructor!)
|
||||
|
||||
X(X const & rhs): this_(this, null_deleter()), i_(rhs.i_)
|
||||
{
|
||||
}
|
||||
|
||||
// do not forget to not assign this_ in the copy assignment
|
||||
|
||||
X & operator=(X const & rhs)
|
||||
{
|
||||
i_ = rhs.i_;
|
||||
}
|
||||
|
||||
weak_ptr<X> get_weak_ptr() const { return this_; }
|
||||
};
|
||||
```
|
||||
|
||||
When the object's lifetime ends, `X::this_` will be destroyed, and all weak pointers will automatically expire.
|
||||
330
doc/smart_ptr/weak_ptr.adoc
Normal file
330
doc/smart_ptr/weak_ptr.adoc
Normal file
@@ -0,0 +1,330 @@
|
||||
////
|
||||
Copyright 1999 Greg Colvin and Beman Dawes
|
||||
Copyright 2002 Darin Adler
|
||||
Copyright 2002-2005, 2017 Peter Dimov
|
||||
|
||||
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
|
||||
////
|
||||
|
||||
[#weak_ptr]
|
||||
# weak_ptr: Non-owning Observer
|
||||
:toc:
|
||||
:toc-title:
|
||||
:idprefix: weak_ptr_
|
||||
|
||||
## Description
|
||||
|
||||
The `weak_ptr` class template stores a "weak reference" to an object that's already managed by a `shared_ptr`.
|
||||
To access the object, a `weak_ptr` can be converted to a `shared_ptr` using the `shared_ptr` constructor taking
|
||||
`weak_ptr`, or the `weak_ptr` member function `lock`. When the last `shared_ptr` to the object goes away and the
|
||||
object is deleted, the attempt to obtain a `shared_ptr` from the `weak_ptr` instances that refer to the deleted
|
||||
object will fail: the constructor will throw an exception of type `boost::bad_weak_ptr`, and `weak_ptr::lock` will
|
||||
return an empty `shared_ptr`.
|
||||
|
||||
Every `weak_ptr` meets the `CopyConstructible` and `Assignable` requirements of the {cpp} Standard Library, and so
|
||||
can be used in standard library containers. Comparison operators are supplied so that `weak_ptr` works with the standard
|
||||
library's associative containers.
|
||||
|
||||
`weak_ptr` operations never throw exceptions.
|
||||
|
||||
The class template is parameterized on `T`, the type of the object pointed to.
|
||||
|
||||
Compared to `shared_ptr`, `weak_ptr` provides a very limited subset of operations since accessing its stored pointer is
|
||||
often dangerous in multithreaded programs, and sometimes unsafe even within a single thread (that is, it may invoke undefined
|
||||
behavior.) Pretend for a moment that `weak_ptr` had a get member function that returned a raw pointer, and consider this innocent
|
||||
piece of code:
|
||||
|
||||
```
|
||||
shared_ptr<int> p(new int(5));
|
||||
weak_ptr<int> q(p);
|
||||
|
||||
// some time later
|
||||
|
||||
if(int * r = q.get())
|
||||
{
|
||||
// use *r
|
||||
}
|
||||
```
|
||||
|
||||
Imagine that after the `if`, but immediately before `r` is used, another thread executes the statement `p.reset()`. Now `r` is a dangling pointer.
|
||||
|
||||
The solution to this problem is to create a temporary `shared_ptr` from `q`:
|
||||
|
||||
```
|
||||
shared_ptr<int> p(new int(5));
|
||||
weak_ptr<int> q(p);
|
||||
|
||||
// some time later
|
||||
|
||||
if(shared_ptr<int> r = q.lock())
|
||||
{
|
||||
// use *r
|
||||
}
|
||||
```
|
||||
|
||||
Now `r` holds a reference to the object that was pointed by `q`. Even if `p.reset()` is executed in another thread, the object will stay alive until
|
||||
`r` goes out of scope or is reset. By obtaining a `shared_ptr` to the object, we have effectively locked it against destruction.
|
||||
|
||||
## Synopsis
|
||||
|
||||
`weak_ptr` is defined in `<boost/smart_ptr/weak_ptr.hpp>`.
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
|
||||
template<class T> class weak_ptr {
|
||||
public:
|
||||
|
||||
typedef /*see below*/ element_type;
|
||||
|
||||
weak_ptr() noexcept;
|
||||
|
||||
template<class Y> weak_ptr(shared_ptr<Y> const & r) noexcept;
|
||||
weak_ptr(weak_ptr const & r) noexcept;
|
||||
template<class Y> weak_ptr(weak_ptr<Y> const & r) noexcept;
|
||||
|
||||
weak_ptr(weak_ptr && r) noexcept;
|
||||
|
||||
template<class Y> weak_ptr(shared_ptr<Y> const & r, element_type * p) noexcept;
|
||||
template<class Y> weak_ptr(weak_ptr<Y> const & r, element_type * p) noexcept;
|
||||
template<class Y> weak_ptr(weak_ptr<Y> && r, element_type * p) noexcept;
|
||||
|
||||
~weak_ptr() noexcept;
|
||||
|
||||
weak_ptr & operator=(weak_ptr const & r) noexcept;
|
||||
weak_ptr & operator=(weak_ptr && r) noexcept;
|
||||
template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r) noexcept;
|
||||
template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r) noexcept;
|
||||
|
||||
long use_count() const noexcept;
|
||||
bool expired() const noexcept;
|
||||
|
||||
bool empty() const noexcept;
|
||||
|
||||
shared_ptr<T> lock() const noexcept;
|
||||
|
||||
void reset() noexcept;
|
||||
|
||||
void swap(weak_ptr<T> & b) noexcept;
|
||||
|
||||
template<class Y> bool owner_before( weak_ptr<Y> const & r ) const noexcept;
|
||||
template<class Y> bool owner_before( shared_ptr<Y> const & r ) const noexcept;
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b) noexcept;
|
||||
|
||||
template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b) noexcept;
|
||||
}
|
||||
```
|
||||
|
||||
## Members
|
||||
|
||||
### element_type
|
||||
```
|
||||
typedef ... element_type;
|
||||
```
|
||||
`element_type` is `T` when `T` is not an array type, and `U` when `T` is `U[]` or `U[N]`.
|
||||
|
||||
### constructors
|
||||
```
|
||||
weak_ptr() noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Constructs an empty `weak_ptr`.
|
||||
Postconditions:: `use_count() == 0`.
|
||||
|
||||
```
|
||||
template<class Y> weak_ptr(shared_ptr<Y> const & r) noexcept;
|
||||
```
|
||||
```
|
||||
weak_ptr(weak_ptr const & r) noexcept;
|
||||
```
|
||||
```
|
||||
template<class Y> weak_ptr(weak_ptr<Y> const & r) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: If `r` is empty, constructs an empty `weak_ptr`; otherwise, constructs a `weak_ptr` that shares ownership with `r` as if by storing a copy of the pointer stored in `r`.
|
||||
Postconditions:: `use_count() == r.use_count()`.
|
||||
|
||||
```
|
||||
weak_ptr(weak_ptr && r) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Constructs a `weak_ptr` that has the value `r` held.
|
||||
Postconditions:: `r` is empty.
|
||||
|
||||
### aliasing constructors
|
||||
```
|
||||
template<class Y> weak_ptr(shared_ptr<Y> const & r, element_type * p) noexcept;
|
||||
```
|
||||
```
|
||||
template<class Y> weak_ptr(weak_ptr<Y> const & r, element_type * p) noexcept;
|
||||
```
|
||||
```
|
||||
template<class Y> weak_ptr(weak_ptr<Y> && r, element_type * p) noexcept;
|
||||
```
|
||||
Effects:: Constructs a `weak_ptr` from `r` as if by using the corresponding converting/copy/move constructor, but stores `p` instead.
|
||||
Postconditions:: `use_count() == r.use_count()`. When `!expired()`, `shared_ptr<T>(*this).get() == p`.
|
||||
|
||||
NOTE: These constructors are an extension, not present in `std::weak_ptr`.
|
||||
|
||||
### destructor
|
||||
```
|
||||
~weak_ptr() noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Destroys this `weak_ptr` but has no effect on the object its stored pointer points to.
|
||||
|
||||
### assignment
|
||||
```
|
||||
weak_ptr & operator=(weak_ptr const & r) noexcept;
|
||||
```
|
||||
```
|
||||
weak_ptr & operator=(weak_ptr && r) noexcept;
|
||||
```
|
||||
```
|
||||
template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r) noexcept;
|
||||
```
|
||||
```
|
||||
template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Equivalent to `weak_ptr(r).swap(*this)`.
|
||||
|
||||
NOTE: The implementation is free to meet the effects (and the implied guarantees) via different means, without creating a temporary.
|
||||
|
||||
### use_count
|
||||
```
|
||||
long use_count() const noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: 0 if `*this` is empty; otherwise, the number of `shared_ptr` objects that share ownership with `*this`.
|
||||
|
||||
### expired
|
||||
```
|
||||
bool expired() const noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `use_count() == 0`.
|
||||
|
||||
### empty
|
||||
```
|
||||
bool empty() const noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `true` when `*this` is empty, `false` otherwise.
|
||||
|
||||
NOTE: This function is an extension, not present in `std::weak_ptr`.
|
||||
|
||||
### lock
|
||||
```
|
||||
shared_ptr<T> lock() const noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: `expired()? shared_ptr<T>(): shared_ptr<T>(*this)`.
|
||||
|
||||
### reset
|
||||
```
|
||||
void reset() noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Equivalent to `weak_ptr().swap(*this)`.
|
||||
|
||||
### swap
|
||||
```
|
||||
void swap(weak_ptr & b) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Exchanges the contents of the two smart pointers.
|
||||
|
||||
```
|
||||
template<class Y> bool owner_before( weak_ptr<Y> const & r ) const noexcept;
|
||||
```
|
||||
```
|
||||
template<class Y> bool owner_before( shared_ptr<Y> const & r ) const noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: See the description of `operator<`.
|
||||
|
||||
## Free Functions
|
||||
|
||||
### comparison
|
||||
```
|
||||
template<class T, class U>
|
||||
bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns:: An unspecified value such that
|
||||
- `operator<` is a strict weak ordering as described in section [lib.alg.sorting] of the {cpp} standard;
|
||||
- under the equivalence relation defined by `operator<`, `!(a < b) && !(b < a)`, two `weak_ptr` instances
|
||||
are equivalent if and only if they share ownership or are both empty.
|
||||
|
||||
NOTE: Allows `weak_ptr` objects to be used as keys in associative containers.
|
||||
|
||||
### swap
|
||||
```
|
||||
template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects:: Equivalent to `a.swap(b)`.
|
||||
|
||||
## Frequently Asked Questions
|
||||
|
||||
[qanda]
|
||||
Can an object create a weak_ptr to itself in its constructor?::
|
||||
|
||||
No. A `weak_ptr` can only be created from a `shared_ptr`, and at object construction time no
|
||||
`shared_ptr` to the object exists yet. Even if you could create a temporary `shared_ptr` to `this`,
|
||||
it would go out of scope at the end of the constructor, and all `weak_ptr` instances would instantly expire.
|
||||
+
|
||||
The solution is to make the constructor private, and supply a factory function that returns a `shared_ptr`:
|
||||
+
|
||||
```
|
||||
class X
|
||||
{
|
||||
private:
|
||||
|
||||
X();
|
||||
|
||||
public:
|
||||
|
||||
static shared_ptr<X> create()
|
||||
{
|
||||
shared_ptr<X> px(new X);
|
||||
// create weak pointers from px here
|
||||
return px;
|
||||
}
|
||||
};
|
||||
```
|
||||
23
example/scoped_ptr_example.cpp
Normal file
23
example/scoped_ptr_example.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
// Boost scoped_ptr_example implementation file -----------------------------//
|
||||
|
||||
// Copyright Beman Dawes 2001. 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/smart_ptr for documentation.
|
||||
|
||||
#include "scoped_ptr_example.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class example::implementation
|
||||
{
|
||||
public:
|
||||
~implementation() { std::cout << "destroying implementation\n"; }
|
||||
};
|
||||
|
||||
example::example() : _imp( new implementation ) {}
|
||||
|
||||
void example::do_something() { std::cout << "did something\n"; }
|
||||
|
||||
example::~example() {}
|
||||
29
example/scoped_ptr_example.hpp
Normal file
29
example/scoped_ptr_example.hpp
Normal file
@@ -0,0 +1,29 @@
|
||||
// Boost scoped_ptr_example header file ------------------------------------//
|
||||
|
||||
// Copyright Beman Dawes 2001. 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/smart_ptr for documentation.
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
// The point of this example is to prove that even though
|
||||
// example::implementation is an incomplete type in translation units using
|
||||
// this header, scoped_ptr< implementation > is still valid because the type
|
||||
// is complete where it counts - in the inplementation translation unit where
|
||||
// destruction is actually instantiated.
|
||||
|
||||
class example : private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
example();
|
||||
~example();
|
||||
void do_something();
|
||||
private:
|
||||
class implementation;
|
||||
boost::scoped_ptr< implementation > _imp; // hide implementation details
|
||||
};
|
||||
|
||||
17
example/scoped_ptr_example_test.cpp
Normal file
17
example/scoped_ptr_example_test.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
// Boost scoped_ptr_example_test main program -------------------------------//
|
||||
|
||||
// Copyright Beman Dawes 2001. 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/smart_ptr for documentation.
|
||||
|
||||
#include "scoped_ptr_example.hpp"
|
||||
|
||||
int main()
|
||||
{
|
||||
example my_example;
|
||||
my_example.do_something();
|
||||
return 0;
|
||||
}
|
||||
95
example/shared_ptr_example.cpp
Normal file
95
example/shared_ptr_example.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
// Boost shared_ptr_example.cpp --------------------------------------------//
|
||||
|
||||
// Copyright Beman Dawes 2001. 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/smart_ptr for documentation.
|
||||
|
||||
// Revision History
|
||||
// 21 May 01 Initial complete version (Beman Dawes)
|
||||
|
||||
// The original code for this example appeared in the shared_ptr documentation.
|
||||
// Ray Gallimore pointed out that foo_set was missing a Compare template
|
||||
// argument, so would not work as intended. At that point the code was
|
||||
// turned into an actual .cpp file so it could be compiled and tested.
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
// The application will produce a series of
|
||||
// objects of type Foo which later must be
|
||||
// accessed both by occurrence (std::vector)
|
||||
// and by ordering relationship (std::set).
|
||||
|
||||
struct Foo
|
||||
{
|
||||
Foo( int _x ) : x(_x) {}
|
||||
~Foo() { std::cout << "Destructing a Foo with x=" << x << "\n"; }
|
||||
int x;
|
||||
/* ... */
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<Foo> FooPtr;
|
||||
|
||||
struct FooPtrOps
|
||||
{
|
||||
bool operator()( const FooPtr & a, const FooPtr & b )
|
||||
{ return a->x > b->x; }
|
||||
void operator()( const FooPtr & a )
|
||||
{ std::cout << a->x << "\n"; }
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
std::vector<FooPtr> foo_vector;
|
||||
std::set<FooPtr,FooPtrOps> foo_set; // NOT multiset!
|
||||
|
||||
FooPtr foo_ptr( new Foo( 2 ) );
|
||||
foo_vector.push_back( foo_ptr );
|
||||
foo_set.insert( foo_ptr );
|
||||
|
||||
foo_ptr.reset( new Foo( 1 ) );
|
||||
foo_vector.push_back( foo_ptr );
|
||||
foo_set.insert( foo_ptr );
|
||||
|
||||
foo_ptr.reset( new Foo( 3 ) );
|
||||
foo_vector.push_back( foo_ptr );
|
||||
foo_set.insert( foo_ptr );
|
||||
|
||||
foo_ptr.reset ( new Foo( 2 ) );
|
||||
foo_vector.push_back( foo_ptr );
|
||||
foo_set.insert( foo_ptr );
|
||||
|
||||
std::cout << "foo_vector:\n";
|
||||
std::for_each( foo_vector.begin(), foo_vector.end(), FooPtrOps() );
|
||||
|
||||
std::cout << "\nfoo_set:\n";
|
||||
std::for_each( foo_set.begin(), foo_set.end(), FooPtrOps() );
|
||||
std::cout << "\n";
|
||||
|
||||
// Expected output:
|
||||
//
|
||||
// foo_vector:
|
||||
// 2
|
||||
// 1
|
||||
// 3
|
||||
// 2
|
||||
//
|
||||
// foo_set:
|
||||
// 3
|
||||
// 2
|
||||
// 1
|
||||
//
|
||||
// Destructing a Foo with x=2
|
||||
// Destructing a Foo with x=1
|
||||
// Destructing a Foo with x=3
|
||||
// Destructing a Foo with x=2
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
22
example/shared_ptr_example2.cpp
Normal file
22
example/shared_ptr_example2.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
// Boost shared_ptr_example2 implementation file -----------------------------//
|
||||
|
||||
// Copyright Beman Dawes 2001. 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/smart_ptr for documentation.
|
||||
|
||||
#include "shared_ptr_example2.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class example::implementation
|
||||
{
|
||||
public:
|
||||
~implementation() { std::cout << "destroying implementation\n"; }
|
||||
};
|
||||
|
||||
example::example() : _imp( new implementation ) {}
|
||||
|
||||
void example::do_something()
|
||||
{ std::cout << "use_count() is " << _imp.use_count() << "\n"; }
|
||||
31
example/shared_ptr_example2.hpp
Normal file
31
example/shared_ptr_example2.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
// Boost shared_ptr_example2 header file -----------------------------------//
|
||||
|
||||
// Copyright Beman Dawes 2001. 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/smart_ptr for documentation.
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
// This example demonstrates the handle/body idiom (also called pimpl and
|
||||
// several other names). It separates the interface (in this header file)
|
||||
// from the implementation (in shared_ptr_example2.cpp).
|
||||
|
||||
// Note that even though example::implementation is an incomplete type in
|
||||
// some translation units using this header, shared_ptr< implementation >
|
||||
// is still valid because the type is complete where it counts - in the
|
||||
// shared_ptr_example2.cpp translation unit where functions requiring a
|
||||
// complete type are actually instantiated.
|
||||
|
||||
class example
|
||||
{
|
||||
public:
|
||||
example();
|
||||
void do_something();
|
||||
private:
|
||||
class implementation;
|
||||
boost::shared_ptr< implementation > _imp; // hide implementation details
|
||||
};
|
||||
|
||||
22
example/shared_ptr_example2_test.cpp
Normal file
22
example/shared_ptr_example2_test.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
// Boost shared_ptr_example2_test main program ------------------------------//
|
||||
|
||||
// Copyright Beman Dawes 2001. 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/smart_ptr for documentation.
|
||||
|
||||
#include "shared_ptr_example2.hpp"
|
||||
|
||||
int main()
|
||||
{
|
||||
example a;
|
||||
a.do_something();
|
||||
example b(a);
|
||||
b.do_something();
|
||||
example c;
|
||||
c = a;
|
||||
c.do_something();
|
||||
return 0;
|
||||
}
|
||||
270
extras/src/sp_collector.cpp
Normal file
270
extras/src/sp_collector.cpp
Normal file
@@ -0,0 +1,270 @@
|
||||
//
|
||||
// sp_collector.cpp
|
||||
//
|
||||
// Copyright (c) 2002, 2003 Peter Dimov
|
||||
//
|
||||
// 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_SP_ENABLE_DEBUG_HOOKS)
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/detail/lightweight_mutex.hpp>
|
||||
#include <cstdlib>
|
||||
#include <map>
|
||||
#include <deque>
|
||||
#include <iostream>
|
||||
|
||||
typedef std::map< void const *, std::pair<void *, size_t> > map_type;
|
||||
|
||||
static map_type & get_map()
|
||||
{
|
||||
static map_type m;
|
||||
return m;
|
||||
}
|
||||
|
||||
typedef boost::detail::lightweight_mutex mutex_type;
|
||||
|
||||
static mutex_type & get_mutex()
|
||||
{
|
||||
static mutex_type m;
|
||||
return m;
|
||||
}
|
||||
|
||||
static void * init_mutex_before_main = &get_mutex();
|
||||
|
||||
namespace
|
||||
{
|
||||
class X;
|
||||
|
||||
struct count_layout
|
||||
{
|
||||
boost::detail::sp_counted_base * pi;
|
||||
int id;
|
||||
};
|
||||
|
||||
struct shared_ptr_layout
|
||||
{
|
||||
X * px;
|
||||
count_layout pn;
|
||||
};
|
||||
}
|
||||
|
||||
// assume 4 byte alignment for pointers when scanning
|
||||
size_t const pointer_align = 4;
|
||||
|
||||
typedef std::map<void const *, long> map2_type;
|
||||
|
||||
static void scan_and_count(void const * area, size_t size, map_type const & m, map2_type & m2)
|
||||
{
|
||||
unsigned char const * p = static_cast<unsigned char const *>(area);
|
||||
|
||||
for(size_t n = 0; n + sizeof(shared_ptr_layout) <= size; p += pointer_align, n += pointer_align)
|
||||
{
|
||||
shared_ptr_layout const * q = reinterpret_cast<shared_ptr_layout const *>(p);
|
||||
|
||||
if(q->pn.id == boost::detail::shared_count_id && q->pn.pi != 0 && m.count(q->pn.pi) != 0)
|
||||
{
|
||||
++m2[q->pn.pi];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef std::deque<void const *> open_type;
|
||||
|
||||
static void scan_and_mark(void const * area, size_t size, map2_type & m2, open_type & open)
|
||||
{
|
||||
unsigned char const * p = static_cast<unsigned char const *>(area);
|
||||
|
||||
for(size_t n = 0; n + sizeof(shared_ptr_layout) <= size; p += pointer_align, n += pointer_align)
|
||||
{
|
||||
shared_ptr_layout const * q = reinterpret_cast<shared_ptr_layout const *>(p);
|
||||
|
||||
if(q->pn.id == boost::detail::shared_count_id && q->pn.pi != 0 && m2.count(q->pn.pi) != 0)
|
||||
{
|
||||
open.push_back(q->pn.pi);
|
||||
m2.erase(q->pn.pi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void find_unreachable_objects_impl(map_type const & m, map2_type & m2)
|
||||
{
|
||||
// scan objects for shared_ptr members, compute internal counts
|
||||
|
||||
{
|
||||
std::cout << "... " << m.size() << " objects in m.\n";
|
||||
|
||||
for(map_type::const_iterator i = m.begin(); i != m.end(); ++i)
|
||||
{
|
||||
boost::detail::sp_counted_base const * p = static_cast<boost::detail::sp_counted_base const *>(i->first);
|
||||
|
||||
BOOST_ASSERT(p->use_count() != 0); // there should be no inactive counts in the map
|
||||
|
||||
m2[ i->first ];
|
||||
|
||||
scan_and_count(i->second.first, i->second.second, m, m2);
|
||||
}
|
||||
|
||||
std::cout << "... " << m2.size() << " objects in m2.\n";
|
||||
}
|
||||
|
||||
// mark reachable objects
|
||||
|
||||
{
|
||||
open_type open;
|
||||
|
||||
for(map2_type::iterator i = m2.begin(); i != m2.end(); ++i)
|
||||
{
|
||||
boost::detail::sp_counted_base const * p = static_cast<boost::detail::sp_counted_base const *>(i->first);
|
||||
if(p->use_count() != i->second) open.push_back(p);
|
||||
}
|
||||
|
||||
std::cout << "... " << open.size() << " objects in open.\n";
|
||||
|
||||
for(open_type::iterator j = open.begin(); j != open.end(); ++j)
|
||||
{
|
||||
m2.erase(*j);
|
||||
}
|
||||
|
||||
while(!open.empty())
|
||||
{
|
||||
void const * p = open.front();
|
||||
open.pop_front();
|
||||
|
||||
map_type::const_iterator i = m.find(p);
|
||||
BOOST_ASSERT(i != m.end());
|
||||
|
||||
scan_and_mark(i->second.first, i->second.second, m2, open);
|
||||
}
|
||||
}
|
||||
|
||||
// m2 now contains the unreachable objects
|
||||
}
|
||||
|
||||
std::size_t find_unreachable_objects(bool report)
|
||||
{
|
||||
map2_type m2;
|
||||
|
||||
#ifdef BOOST_HAS_THREADS
|
||||
|
||||
// This will work without the #ifdef, but some compilers warn
|
||||
// that lock is not referenced
|
||||
|
||||
mutex_type::scoped_lock lock(get_mutex());
|
||||
|
||||
#endif
|
||||
|
||||
map_type const & m = get_map();
|
||||
|
||||
find_unreachable_objects_impl(m, m2);
|
||||
|
||||
if(report)
|
||||
{
|
||||
for(map2_type::iterator j = m2.begin(); j != m2.end(); ++j)
|
||||
{
|
||||
map_type::const_iterator i = m.find(j->first);
|
||||
BOOST_ASSERT(i != m.end());
|
||||
std::cout << "Unreachable object at " << i->second.first << ", " << i->second.second << " bytes long.\n";
|
||||
}
|
||||
}
|
||||
|
||||
return m2.size();
|
||||
}
|
||||
|
||||
typedef std::deque< boost::shared_ptr<X> > free_list_type;
|
||||
|
||||
static void scan_and_free(void * area, size_t size, map2_type const & m2, free_list_type & free)
|
||||
{
|
||||
unsigned char * p = static_cast<unsigned char *>(area);
|
||||
|
||||
for(size_t n = 0; n + sizeof(shared_ptr_layout) <= size; p += pointer_align, n += pointer_align)
|
||||
{
|
||||
shared_ptr_layout * q = reinterpret_cast<shared_ptr_layout *>(p);
|
||||
|
||||
if(q->pn.id == boost::detail::shared_count_id && q->pn.pi != 0 && m2.count(q->pn.pi) != 0 && q->px != 0)
|
||||
{
|
||||
boost::shared_ptr<X> * ppx = reinterpret_cast< boost::shared_ptr<X> * >(p);
|
||||
free.push_back(*ppx);
|
||||
ppx->reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void free_unreachable_objects()
|
||||
{
|
||||
free_list_type free;
|
||||
|
||||
{
|
||||
map2_type m2;
|
||||
|
||||
#ifdef BOOST_HAS_THREADS
|
||||
|
||||
mutex_type::scoped_lock lock(get_mutex());
|
||||
|
||||
#endif
|
||||
|
||||
map_type const & m = get_map();
|
||||
|
||||
find_unreachable_objects_impl(m, m2);
|
||||
|
||||
for(map2_type::iterator j = m2.begin(); j != m2.end(); ++j)
|
||||
{
|
||||
map_type::const_iterator i = m.find(j->first);
|
||||
BOOST_ASSERT(i != m.end());
|
||||
scan_and_free(i->second.first, i->second.second, m2, free);
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "... about to free " << free.size() << " objects.\n";
|
||||
}
|
||||
|
||||
// debug hooks
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
void sp_scalar_constructor_hook(void *)
|
||||
{
|
||||
}
|
||||
|
||||
void sp_scalar_constructor_hook(void * px, std::size_t size, void * pn)
|
||||
{
|
||||
#ifdef BOOST_HAS_THREADS
|
||||
|
||||
mutex_type::scoped_lock lock(get_mutex());
|
||||
|
||||
#endif
|
||||
|
||||
get_map()[pn] = std::make_pair(px, size);
|
||||
}
|
||||
|
||||
void sp_scalar_destructor_hook(void *)
|
||||
{
|
||||
}
|
||||
|
||||
void sp_scalar_destructor_hook(void *, std::size_t, void * pn)
|
||||
{
|
||||
#ifdef BOOST_HAS_THREADS
|
||||
|
||||
mutex_type::scoped_lock lock(get_mutex());
|
||||
|
||||
#endif
|
||||
|
||||
get_map().erase(pn);
|
||||
}
|
||||
|
||||
void sp_array_constructor_hook(void *)
|
||||
{
|
||||
}
|
||||
|
||||
void sp_array_destructor_hook(void *)
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
243
extras/src/sp_debug_hooks.cpp
Normal file
243
extras/src/sp_debug_hooks.cpp
Normal file
@@ -0,0 +1,243 @@
|
||||
//
|
||||
// sp_debug_hooks.cpp
|
||||
//
|
||||
// Copyright (c) 2002, 2003 Peter Dimov
|
||||
//
|
||||
// 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_SP_ENABLE_DEBUG_HOOKS)
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <new>
|
||||
#include <cstdlib>
|
||||
|
||||
int const m = 2; // m * sizeof(int) must be aligned appropriately
|
||||
|
||||
// magic values to mark heap blocks with
|
||||
|
||||
int const allocated_scalar = 0x1234560C;
|
||||
int const allocated_array = 0x1234560A;
|
||||
int const adopted_scalar = 0x0567890C;
|
||||
int const adopted_array = 0x0567890A;
|
||||
int const deleted = 0x498769DE;
|
||||
|
||||
using namespace std; // for compilers where things aren't in std
|
||||
|
||||
// operator new
|
||||
|
||||
static new_handler get_new_handler()
|
||||
{
|
||||
new_handler p = set_new_handler(0);
|
||||
set_new_handler(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
static void * allocate(size_t n, int mark)
|
||||
{
|
||||
int * pm;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
pm = static_cast<int*>(malloc(n + m * sizeof(int)));
|
||||
|
||||
if(pm != 0) break;
|
||||
|
||||
if(new_handler pnh = get_new_handler())
|
||||
{
|
||||
pnh();
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
*pm = mark;
|
||||
|
||||
return pm + m;
|
||||
}
|
||||
|
||||
void * operator new(size_t n) throw(bad_alloc)
|
||||
{
|
||||
void * p = allocate(n, allocated_scalar);
|
||||
|
||||
#if !defined(BOOST_NO_EXCEPTIONS)
|
||||
|
||||
if(p == 0) throw bad_alloc();
|
||||
|
||||
#endif
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
#if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551)
|
||||
|
||||
void * operator new(size_t n, nothrow_t const &) throw()
|
||||
{
|
||||
return allocate(n, allocated_scalar);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void * operator new[](size_t n) throw(bad_alloc)
|
||||
{
|
||||
void * p = allocate(n, allocated_array);
|
||||
|
||||
#if !defined(BOOST_NO_EXCEPTIONS)
|
||||
|
||||
if(p == 0) throw bad_alloc();
|
||||
|
||||
#endif
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
#if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551)
|
||||
|
||||
void * operator new[](size_t n, nothrow_t const &) throw()
|
||||
{
|
||||
return allocate(n, allocated_array);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// debug hooks
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
void sp_scalar_constructor_hook(void * p)
|
||||
{
|
||||
if(p == 0) return;
|
||||
|
||||
int * pm = static_cast<int*>(p);
|
||||
pm -= m;
|
||||
|
||||
BOOST_ASSERT(*pm != adopted_scalar); // second smart pointer to the same address
|
||||
BOOST_ASSERT(*pm != allocated_array); // allocated with new[]
|
||||
BOOST_ASSERT(*pm == allocated_scalar); // not allocated with new
|
||||
|
||||
*pm = adopted_scalar;
|
||||
}
|
||||
|
||||
void sp_scalar_constructor_hook(void * px, std::size_t, void *)
|
||||
{
|
||||
sp_scalar_constructor_hook(px);
|
||||
}
|
||||
|
||||
void sp_scalar_destructor_hook(void * p)
|
||||
{
|
||||
if(p == 0) return;
|
||||
|
||||
int * pm = static_cast<int*>(p);
|
||||
pm -= m;
|
||||
|
||||
BOOST_ASSERT(*pm == adopted_scalar); // attempt to destroy nonmanaged block
|
||||
|
||||
*pm = allocated_scalar;
|
||||
}
|
||||
|
||||
void sp_scalar_destructor_hook(void * px, std::size_t, void *)
|
||||
{
|
||||
sp_scalar_destructor_hook(px);
|
||||
}
|
||||
|
||||
// It is not possible to handle the array hooks in a portable manner.
|
||||
// The implementation typically reserves a bit of storage for the number
|
||||
// of objects in the array, and the argument of the array hook isn't
|
||||
// equal to the return value of operator new[].
|
||||
|
||||
void sp_array_constructor_hook(void * /* p */)
|
||||
{
|
||||
/*
|
||||
if(p == 0) return;
|
||||
|
||||
// adjust p depending on the implementation
|
||||
|
||||
int * pm = static_cast<int*>(p);
|
||||
pm -= m;
|
||||
|
||||
BOOST_ASSERT(*pm != adopted_array); // second smart array pointer to the same address
|
||||
BOOST_ASSERT(*pm != allocated_scalar); // allocated with new
|
||||
BOOST_ASSERT(*pm == allocated_array); // not allocated with new[]
|
||||
|
||||
*pm = adopted_array;
|
||||
*/
|
||||
}
|
||||
|
||||
void sp_array_destructor_hook(void * /* p */)
|
||||
{
|
||||
/*
|
||||
if(p == 0) return;
|
||||
|
||||
// adjust p depending on the implementation
|
||||
|
||||
int * pm = static_cast<int*>(p);
|
||||
pm -= m;
|
||||
|
||||
BOOST_ASSERT(*pm == adopted_array); // attempt to destroy nonmanaged block
|
||||
|
||||
*pm = allocated_array;
|
||||
*/
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
// operator delete
|
||||
|
||||
void operator delete(void * p) throw()
|
||||
{
|
||||
if(p == 0) return;
|
||||
|
||||
int * pm = static_cast<int*>(p);
|
||||
pm -= m;
|
||||
|
||||
BOOST_ASSERT(*pm != deleted); // double delete
|
||||
BOOST_ASSERT(*pm != adopted_scalar); // delete p.get();
|
||||
BOOST_ASSERT(*pm != allocated_array); // allocated with new[]
|
||||
BOOST_ASSERT(*pm == allocated_scalar); // not allocated with new
|
||||
|
||||
*pm = deleted;
|
||||
|
||||
free(pm);
|
||||
}
|
||||
|
||||
#if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551)
|
||||
|
||||
void operator delete(void * p, nothrow_t const &) throw()
|
||||
{
|
||||
::operator delete(p);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void operator delete[](void * p) throw()
|
||||
{
|
||||
if(p == 0) return;
|
||||
|
||||
int * pm = static_cast<int*>(p);
|
||||
pm -= m;
|
||||
|
||||
BOOST_ASSERT(*pm != deleted); // double delete
|
||||
BOOST_ASSERT(*pm != adopted_scalar); // delete p.get();
|
||||
BOOST_ASSERT(*pm != allocated_scalar); // allocated with new
|
||||
BOOST_ASSERT(*pm == allocated_array); // not allocated with new[]
|
||||
|
||||
*pm = deleted;
|
||||
|
||||
free(pm);
|
||||
}
|
||||
|
||||
#if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551)
|
||||
|
||||
void operator delete[](void * p, nothrow_t const &) throw()
|
||||
{
|
||||
::operator delete[](p);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif // defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
82
extras/test/shared_ptr_mt_test.cpp
Normal file
82
extras/test/shared_ptr_mt_test.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(disable: 4786) // identifier truncated in debug info
|
||||
#pragma warning(disable: 4710) // function not inlined
|
||||
#pragma warning(disable: 4711) // function selected for automatic inline expansion
|
||||
#pragma warning(disable: 4514) // unreferenced inline removed
|
||||
#endif
|
||||
|
||||
// shared_ptr_mt_test.cpp - tests shared_ptr with multiple threads
|
||||
//
|
||||
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
|
||||
// Copyright (c) 2008 Peter Dimov
|
||||
//
|
||||
// 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/shared_ptr.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <cstdio>
|
||||
#include <ctime>
|
||||
|
||||
#include <boost/detail/lightweight_thread.hpp>
|
||||
|
||||
//
|
||||
|
||||
int const n = 1024 * 1024;
|
||||
|
||||
void test( boost::shared_ptr<int> const & pi )
|
||||
{
|
||||
std::vector< boost::shared_ptr<int> > v;
|
||||
|
||||
for( int i = 0; i < n; ++i )
|
||||
{
|
||||
v.push_back( pi );
|
||||
}
|
||||
}
|
||||
|
||||
int const m = 16; // threads
|
||||
|
||||
#if defined( BOOST_HAS_PTHREADS )
|
||||
|
||||
char const * thmodel = "POSIX";
|
||||
|
||||
#else
|
||||
|
||||
char const * thmodel = "Windows";
|
||||
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace std; // printf, clock_t, clock
|
||||
|
||||
printf( "Using %s threads: %d threads, %d iterations: ", thmodel, m, n );
|
||||
|
||||
boost::shared_ptr<int> pi( new int(42) );
|
||||
|
||||
clock_t t = clock();
|
||||
|
||||
boost::detail::lw_thread_t a[ m ];
|
||||
|
||||
for( int i = 0; i < m; ++i )
|
||||
{
|
||||
boost::detail::lw_thread_create( a[ i ], boost::bind( test, pi ) );
|
||||
}
|
||||
|
||||
for( int j = 0; j < m; ++j )
|
||||
{
|
||||
boost::detail::lw_thread_join( a[j] );
|
||||
}
|
||||
|
||||
t = clock() - t;
|
||||
|
||||
printf( "\n\n%.3f seconds.\n", static_cast<double>(t) / CLOCKS_PER_SEC );
|
||||
|
||||
return 0;
|
||||
}
|
||||
46
extras/test/shared_ptr_timing_test.cpp
Normal file
46
extras/test/shared_ptr_timing_test.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(disable: 4786) // identifier truncated in debug info
|
||||
#pragma warning(disable: 4710) // function not inlined
|
||||
#pragma warning(disable: 4711) // function selected for automatic inline expansion
|
||||
#pragma warning(disable: 4514) // unreferenced inline removed
|
||||
#endif
|
||||
|
||||
//
|
||||
// shared_ptr_timing_test.cpp - use to evaluate the impact of thread safety
|
||||
//
|
||||
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// 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/shared_ptr.hpp>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <ctime>
|
||||
|
||||
int const n = 8 * 1024 * 1024;
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
std::vector< boost::shared_ptr<int> > v;
|
||||
boost::shared_ptr<int> pi(new int);
|
||||
|
||||
clock_t t = clock();
|
||||
|
||||
for(int i = 0; i < n; ++i)
|
||||
{
|
||||
v.push_back(pi);
|
||||
}
|
||||
|
||||
t = clock() - t;
|
||||
|
||||
std::cout << static_cast<double>(t) / CLOCKS_PER_SEC << '\n';
|
||||
|
||||
return 0;
|
||||
}
|
||||
247
extras/test/sp_atomic_mt2_test.cpp
Normal file
247
extras/test/sp_atomic_mt2_test.cpp
Normal file
@@ -0,0 +1,247 @@
|
||||
|
||||
// Copyright (c) 2008 Peter Dimov
|
||||
//
|
||||
// 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>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <boost/thread/shared_mutex.hpp>
|
||||
#include <boost/thread/locks.hpp>
|
||||
|
||||
#include <boost/detail/lightweight_mutex.hpp>
|
||||
#include <boost/detail/lightweight_thread.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <numeric>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstddef>
|
||||
#include <ctime>
|
||||
|
||||
//
|
||||
|
||||
static void next_value( unsigned & v )
|
||||
{
|
||||
v = v % 2? 3 * v + 1: v / 2;
|
||||
}
|
||||
|
||||
struct X
|
||||
{
|
||||
std::vector<unsigned> v_;
|
||||
|
||||
explicit X( std::size_t n ): v_( n )
|
||||
{
|
||||
for( std::size_t i = 0; i < n; ++i )
|
||||
{
|
||||
v_[ i ] = i;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned get() const
|
||||
{
|
||||
return std::accumulate( v_.begin(), v_.end(), 0 );
|
||||
}
|
||||
|
||||
void set()
|
||||
{
|
||||
std::for_each( v_.begin(), v_.end(), next_value );
|
||||
}
|
||||
};
|
||||
|
||||
static boost::shared_ptr<X> ps;
|
||||
|
||||
static boost::detail::lightweight_mutex lm;
|
||||
static boost::shared_mutex rw;
|
||||
|
||||
enum prim_type
|
||||
{
|
||||
pt_mutex,
|
||||
pt_rwlock,
|
||||
pt_atomics
|
||||
};
|
||||
|
||||
int read_access( prim_type pt )
|
||||
{
|
||||
switch( pt )
|
||||
{
|
||||
case pt_mutex:
|
||||
{
|
||||
boost::detail::lightweight_mutex::scoped_lock lock( lm );
|
||||
return ps->get();
|
||||
}
|
||||
|
||||
case pt_rwlock:
|
||||
{
|
||||
boost::shared_lock<boost::shared_mutex> lock( rw );
|
||||
return ps->get();
|
||||
}
|
||||
|
||||
case pt_atomics:
|
||||
{
|
||||
boost::shared_ptr<X> p2 = boost::atomic_load( &ps );
|
||||
return p2->get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void write_access( prim_type pt )
|
||||
{
|
||||
switch( pt )
|
||||
{
|
||||
case pt_mutex:
|
||||
{
|
||||
boost::detail::lightweight_mutex::scoped_lock lock( lm );
|
||||
ps->set();
|
||||
}
|
||||
break;
|
||||
|
||||
case pt_rwlock:
|
||||
{
|
||||
boost::unique_lock<boost::shared_mutex> lock( rw );
|
||||
ps->set();
|
||||
}
|
||||
break;
|
||||
|
||||
case pt_atomics:
|
||||
{
|
||||
boost::shared_ptr<X> p1 = boost::atomic_load( &ps );
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
boost::shared_ptr<X> p2( new X( *p1 ) );
|
||||
p2->set();
|
||||
|
||||
if( boost::atomic_compare_exchange( &ps, &p1, p2 ) ) break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void worker( int k, prim_type pt, int n, int r )
|
||||
{
|
||||
++r;
|
||||
|
||||
unsigned s = 0, nr = 0, nw = 0;
|
||||
|
||||
for( int i = 0; i < n; ++i )
|
||||
{
|
||||
if( i % r )
|
||||
{
|
||||
s += read_access( pt );
|
||||
++nr;
|
||||
}
|
||||
else
|
||||
{
|
||||
write_access( pt );
|
||||
++s;
|
||||
++nw;
|
||||
}
|
||||
}
|
||||
|
||||
printf( "Worker %2d: %u:%u, %10u\n", k, nr, nw, s );
|
||||
}
|
||||
|
||||
#if defined( BOOST_HAS_PTHREADS )
|
||||
char const * thmodel = "POSIX";
|
||||
#else
|
||||
char const * thmodel = "Windows";
|
||||
#endif
|
||||
|
||||
char const * pt_to_string( prim_type pt )
|
||||
{
|
||||
switch( pt )
|
||||
{
|
||||
case pt_mutex:
|
||||
|
||||
return "mutex";
|
||||
|
||||
case pt_rwlock:
|
||||
|
||||
return "rwlock";
|
||||
|
||||
case pt_atomics:
|
||||
|
||||
return "atomics";
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_pt_option( std::string const & opt, prim_type & pt, prim_type pt2 )
|
||||
{
|
||||
if( opt == pt_to_string( pt2 ) )
|
||||
{
|
||||
pt = pt2;
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_int_option( std::string const & opt, std::string const & prefix, int & k, int kmin, int kmax )
|
||||
{
|
||||
if( opt.substr( 0, prefix.size() ) == prefix )
|
||||
{
|
||||
int v = atoi( opt.substr( prefix.size() ).c_str() );
|
||||
|
||||
if( v >= kmin && v <= kmax )
|
||||
{
|
||||
k = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main( int ac, char const * av[] )
|
||||
{
|
||||
using namespace std; // printf, clock_t, clock
|
||||
|
||||
int m = 4; // threads
|
||||
int n = 10000; // vector size
|
||||
int k = 1000000; // iterations
|
||||
int r = 100; // read/write ratio, r:1
|
||||
|
||||
prim_type pt = pt_atomics;
|
||||
|
||||
for( int i = 1; i < ac; ++i )
|
||||
{
|
||||
handle_pt_option( av[i], pt, pt_mutex );
|
||||
handle_pt_option( av[i], pt, pt_rwlock );
|
||||
handle_pt_option( av[i], pt, pt_atomics );
|
||||
|
||||
handle_int_option( av[i], "n=", n, 1, INT_MAX );
|
||||
handle_int_option( av[i], "size=", n, 1, INT_MAX );
|
||||
|
||||
handle_int_option( av[i], "k=", k, 1, INT_MAX );
|
||||
handle_int_option( av[i], "iterations=", k, 1, INT_MAX );
|
||||
|
||||
handle_int_option( av[i], "m=", m, 1, INT_MAX );
|
||||
handle_int_option( av[i], "threads=", m, 1, INT_MAX );
|
||||
|
||||
handle_int_option( av[i], "r=", r, 1, INT_MAX );
|
||||
handle_int_option( av[i], "ratio=", r, 1, INT_MAX );
|
||||
}
|
||||
|
||||
printf( "%s: threads=%d size=%d iterations=%d ratio=%d %s\n\n", thmodel, m, n, k, r, pt_to_string( pt ) );
|
||||
|
||||
ps.reset( new X( n ) );
|
||||
|
||||
clock_t t = clock();
|
||||
|
||||
std::vector<boost::detail::lw_thread_t> a( m );
|
||||
|
||||
for( int i = 0; i < m; ++i )
|
||||
{
|
||||
boost::detail::lw_thread_create( a[ i ], boost::bind( worker, i, pt, k, r ) );
|
||||
}
|
||||
|
||||
for( int j = 0; j < m; ++j )
|
||||
{
|
||||
boost::detail::lw_thread_join( a[ j ] );
|
||||
}
|
||||
|
||||
t = clock() - t;
|
||||
|
||||
double ts = static_cast<double>( t ) / CLOCKS_PER_SEC;
|
||||
printf( "%.3f seconds, %.3f accesses per microsecond.\n", ts, m * k / ts / 1e+6 );
|
||||
}
|
||||
191
extras/test/sp_atomic_mt_test.cpp
Normal file
191
extras/test/sp_atomic_mt_test.cpp
Normal file
@@ -0,0 +1,191 @@
|
||||
|
||||
// Copyright (c) 2008 Peter Dimov
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
//#define USE_MUTEX
|
||||
//#define USE_RWLOCK
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#if defined( USE_RWLOCK )
|
||||
#include <boost/thread/shared_mutex.hpp>
|
||||
#include <boost/thread/locks.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/detail/lightweight_mutex.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <boost/detail/lightweight_thread.hpp>
|
||||
|
||||
#include <cstdio>
|
||||
#include <ctime>
|
||||
|
||||
//
|
||||
|
||||
int const n = 1024 * 1024;
|
||||
|
||||
struct X
|
||||
{
|
||||
int v_; // version
|
||||
|
||||
unsigned a_;
|
||||
unsigned b_;
|
||||
|
||||
X(): v_( 0 ), a_( 1 ), b_( 1 )
|
||||
{
|
||||
}
|
||||
|
||||
int get() const
|
||||
{
|
||||
return a_ * 7 + b_ * 11;
|
||||
}
|
||||
|
||||
void set()
|
||||
{
|
||||
int tmp = get();
|
||||
|
||||
b_ = a_;
|
||||
a_ = tmp;
|
||||
|
||||
++v_;
|
||||
}
|
||||
};
|
||||
|
||||
static boost::shared_ptr<X> ps( new X );
|
||||
|
||||
static boost::detail::lightweight_mutex lm;
|
||||
|
||||
#if defined( USE_RWLOCK )
|
||||
static boost::shared_mutex rw;
|
||||
#endif
|
||||
|
||||
static int tr = 0;
|
||||
|
||||
void reader( int r )
|
||||
{
|
||||
int k = 0;
|
||||
unsigned s = 0;
|
||||
|
||||
for( int i = 0; i < n; ++k )
|
||||
{
|
||||
#if defined( USE_MUTEX )
|
||||
|
||||
boost::detail::lightweight_mutex::scoped_lock lock( lm );
|
||||
|
||||
s += ps->get();
|
||||
|
||||
BOOST_TEST( ps->v_ >= i );
|
||||
i = ps->v_;
|
||||
|
||||
#elif defined( USE_RWLOCK )
|
||||
|
||||
boost::shared_lock<boost::shared_mutex> lock( rw );
|
||||
|
||||
s += ps->get();
|
||||
|
||||
BOOST_TEST( ps->v_ >= i );
|
||||
i = ps->v_;
|
||||
|
||||
#else
|
||||
|
||||
boost::shared_ptr<X> p2 = boost::atomic_load( &ps );
|
||||
|
||||
s += p2->get();
|
||||
|
||||
BOOST_TEST( p2->v_ >= i );
|
||||
i = p2->v_;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
printf( "Reader %d: %9d iterations (%6.3fx), %u\n", r, k, (double)k / n, s );
|
||||
|
||||
boost::detail::lightweight_mutex::scoped_lock lock( lm );
|
||||
tr += k;
|
||||
}
|
||||
|
||||
void writer()
|
||||
{
|
||||
for( int i = 0; i < n; ++i )
|
||||
{
|
||||
#if defined( USE_MUTEX )
|
||||
|
||||
boost::detail::lightweight_mutex::scoped_lock lock( lm );
|
||||
|
||||
BOOST_TEST( ps->v_ == i );
|
||||
ps->set();
|
||||
|
||||
#elif defined( USE_RWLOCK )
|
||||
|
||||
boost::unique_lock<boost::shared_mutex> lock( rw );
|
||||
|
||||
BOOST_TEST( ps->v_ == i );
|
||||
ps->set();
|
||||
|
||||
#else
|
||||
|
||||
boost::shared_ptr<X> p2( new X( *ps ) );
|
||||
|
||||
BOOST_TEST( p2->v_ == i );
|
||||
p2->set();
|
||||
|
||||
boost::atomic_store( &ps, p2 );
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if defined( BOOST_HAS_PTHREADS )
|
||||
char const * thmodel = "POSIX";
|
||||
#else
|
||||
char const * thmodel = "Windows";
|
||||
#endif
|
||||
|
||||
int const mr = 8; // reader threads
|
||||
int const mw = 1; // writer thread
|
||||
|
||||
#if defined( USE_MUTEX )
|
||||
char const * prim = "mutex";
|
||||
#elif defined( USE_RWLOCK )
|
||||
char const * prim = "rwlock";
|
||||
#else
|
||||
char const * prim = "atomics";
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace std; // printf, clock_t, clock
|
||||
|
||||
printf( "Using %s threads: %dR + %dW threads, %d iterations, %s\n\n", thmodel, mr, mw, n, prim );
|
||||
|
||||
clock_t t = clock();
|
||||
|
||||
boost::detail::lw_thread_t a[ mr+mw ];
|
||||
|
||||
for( int i = 0; i < mr; ++i )
|
||||
{
|
||||
boost::detail::lw_thread_create( a[ i ], boost::bind( reader, i ) );
|
||||
}
|
||||
|
||||
for( int i = mr; i < mr+mw; ++i )
|
||||
{
|
||||
boost::detail::lw_thread_create( a[ i ], writer );
|
||||
}
|
||||
|
||||
for( int j = 0; j < mr+mw; ++j )
|
||||
{
|
||||
boost::detail::lw_thread_join( a[ j ] );
|
||||
}
|
||||
|
||||
t = clock() - t;
|
||||
|
||||
double ts = static_cast<double>( t ) / CLOCKS_PER_SEC;
|
||||
printf( "%.3f seconds, %.3f reads per microsecond.\n", ts, tr / ts / 1e+6 );
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
122
extras/test/weak_ptr_mt_test.cpp
Normal file
122
extras/test/weak_ptr_mt_test.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(disable: 4786) // identifier truncated in debug info
|
||||
#pragma warning(disable: 4710) // function not inlined
|
||||
#pragma warning(disable: 4711) // function selected for automatic inline expansion
|
||||
#pragma warning(disable: 4514) // unreferenced inline removed
|
||||
#endif
|
||||
|
||||
// weak_ptr_mt_test.cpp
|
||||
//
|
||||
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
|
||||
// Copyright 2005, 2008 Peter Dimov
|
||||
//
|
||||
// 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/shared_ptr.hpp>
|
||||
#include <boost/weak_ptr.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <cstdio>
|
||||
#include <ctime>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <boost/detail/lightweight_thread.hpp>
|
||||
|
||||
//
|
||||
|
||||
int const n = 16384;
|
||||
int const k = 512; // vector size
|
||||
int const m = 16; // threads
|
||||
|
||||
void test( std::vector< boost::shared_ptr<int> > & v )
|
||||
{
|
||||
using namespace std; // printf, rand
|
||||
|
||||
std::vector< boost::weak_ptr<int> > w( v.begin(), v.end() );
|
||||
|
||||
int s = 0, f = 0, r = 0;
|
||||
|
||||
for( int i = 0; i < n; ++i )
|
||||
{
|
||||
// randomly kill a pointer
|
||||
|
||||
v[ rand() % k ].reset();
|
||||
++s;
|
||||
|
||||
for( int j = 0; j < k; ++j )
|
||||
{
|
||||
if( boost::shared_ptr<int> px = w[ j ].lock() )
|
||||
{
|
||||
++s;
|
||||
|
||||
if( rand() & 4 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// rebind anyway with prob. 50% for add_ref_lock() against weak_release() contention
|
||||
++f;
|
||||
}
|
||||
else
|
||||
{
|
||||
++r;
|
||||
}
|
||||
|
||||
w[ j ] = v[ rand() % k ];
|
||||
}
|
||||
}
|
||||
|
||||
printf( "\n%d locks, %d forced rebinds, %d normal rebinds.", s, f, r );
|
||||
}
|
||||
|
||||
#if defined( BOOST_HAS_PTHREADS )
|
||||
|
||||
char const * thmodel = "POSIX";
|
||||
|
||||
#else
|
||||
|
||||
char const * thmodel = "Windows";
|
||||
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace std; // printf, clock_t, clock
|
||||
|
||||
printf("Using %s threads: %d threads, %d * %d iterations: ", thmodel, m, n, k );
|
||||
|
||||
std::vector< boost::shared_ptr<int> > v( k );
|
||||
|
||||
for( int i = 0; i < k; ++i )
|
||||
{
|
||||
v[ i ].reset( new int( 0 ) );
|
||||
}
|
||||
|
||||
clock_t t = clock();
|
||||
|
||||
boost::detail::lw_thread_t a[ m ];
|
||||
|
||||
for( int i = 0; i < m; ++i )
|
||||
{
|
||||
boost::detail::lw_thread_create( a[ i ], boost::bind( test, v ) );
|
||||
}
|
||||
|
||||
v.resize( 0 ); // kill original copies
|
||||
|
||||
for( int j = 0; j < m; ++j )
|
||||
{
|
||||
boost::detail::lw_thread_join( a[j] );
|
||||
}
|
||||
|
||||
t = clock() - t;
|
||||
|
||||
printf("\n\n%.3f seconds.\n", static_cast<double>(t) / CLOCKS_PER_SEC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
85
extras/test/weak_ptr_timing_test.cpp
Normal file
85
extras/test/weak_ptr_timing_test.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(disable: 4786) // identifier truncated in debug info
|
||||
#pragma warning(disable: 4710) // function not inlined
|
||||
#pragma warning(disable: 4711) // function selected for automatic inline expansion
|
||||
#pragma warning(disable: 4514) // unreferenced inline removed
|
||||
#endif
|
||||
|
||||
//
|
||||
// weak_ptr_timing_test.cpp
|
||||
//
|
||||
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
|
||||
// Copyright 2005 Peter Dimov
|
||||
//
|
||||
// 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/shared_ptr.hpp>
|
||||
#include <boost/weak_ptr.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <cstdio>
|
||||
#include <ctime>
|
||||
#include <cstdlib>
|
||||
|
||||
//
|
||||
|
||||
int const n = 29000;
|
||||
int const k = 2048;
|
||||
|
||||
void test( std::vector< boost::shared_ptr<int> > & v )
|
||||
{
|
||||
using namespace std; // printf, rand
|
||||
|
||||
std::vector< boost::weak_ptr<int> > w( v.begin(), v.end() );
|
||||
|
||||
int s = 0, r = 0;
|
||||
|
||||
for( int i = 0; i < n; ++i )
|
||||
{
|
||||
// randomly kill a pointer
|
||||
|
||||
v[ rand() % k ].reset();
|
||||
|
||||
for( int j = 0; j < k; ++j )
|
||||
{
|
||||
if( boost::shared_ptr<int> px = w[ j ].lock() )
|
||||
{
|
||||
++s;
|
||||
}
|
||||
else
|
||||
{
|
||||
++r;
|
||||
w[ j ] = v[ rand() % k ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf( "\n%d locks, %d rebinds.", s, r );
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace std; // printf, clock_t, clock
|
||||
|
||||
std::vector< boost::shared_ptr<int> > v( k );
|
||||
|
||||
for( int i = 0; i < k; ++i )
|
||||
{
|
||||
v[ i ].reset( new int( 0 ) );
|
||||
}
|
||||
|
||||
clock_t t = clock();
|
||||
|
||||
test( v );
|
||||
|
||||
t = clock() - t;
|
||||
|
||||
printf( "\n\n%.3f seconds.\n", static_cast<double>( t ) / CLOCKS_PER_SEC );
|
||||
|
||||
return 0;
|
||||
}
|
||||
21
include/boost/detail/atomic_count.hpp
Normal file
21
include/boost/detail/atomic_count.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED
|
||||
#define BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// boost/detail/atomic_count.hpp - thread/SMP safe reference counter
|
||||
//
|
||||
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// 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/smart_ptr/detail/atomic_count.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED
|
||||
22
include/boost/detail/lightweight_mutex.hpp
Normal file
22
include/boost/detail/lightweight_mutex.hpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED
|
||||
#define BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// boost/detail/lightweight_mutex.hpp - lightweight mutex
|
||||
//
|
||||
// Copyright (c) 2002, 2003 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// 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/smart_ptr/detail/lightweight_mutex.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED
|
||||
188
include/boost/detail/lightweight_thread.hpp
Normal file
188
include/boost/detail/lightweight_thread.hpp
Normal file
@@ -0,0 +1,188 @@
|
||||
#ifndef BOOST_DETAIL_LIGHTWEIGHT_THREAD_HPP_INCLUDED
|
||||
#define BOOST_DETAIL_LIGHTWEIGHT_THREAD_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
// boost/detail/lightweight_thread.hpp
|
||||
//
|
||||
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
|
||||
// Copyright (c) 2008, 2018 Peter Dimov
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//
|
||||
// typedef /*...*/ lw_thread_t; // as pthread_t
|
||||
// template<class F> int lw_thread_create( lw_thread_t & th, F f );
|
||||
// void lw_thread_join( lw_thread_t th );
|
||||
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <memory>
|
||||
#include <cerrno>
|
||||
|
||||
#if defined( BOOST_HAS_PTHREADS )
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
typedef ::pthread_t lw_thread_t;
|
||||
|
||||
inline int lw_thread_create_( lw_thread_t* thread, const pthread_attr_t* attr, void* (*start_routine)( void* ), void* arg )
|
||||
{
|
||||
return ::pthread_create( thread, attr, start_routine, arg );
|
||||
}
|
||||
|
||||
inline void lw_thread_join( lw_thread_t th )
|
||||
{
|
||||
::pthread_join( th, 0 );
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace boost
|
||||
|
||||
#else // defined( BOOST_HAS_PTHREADS )
|
||||
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
typedef HANDLE lw_thread_t;
|
||||
|
||||
inline int lw_thread_create_( lw_thread_t * thread, void const *, unsigned (__stdcall * start_routine) (void*), void* arg )
|
||||
{
|
||||
HANDLE h = (HANDLE)_beginthreadex( 0, 0, start_routine, arg, 0, 0 );
|
||||
|
||||
if( h != 0 )
|
||||
{
|
||||
*thread = h;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return EAGAIN;
|
||||
}
|
||||
}
|
||||
|
||||
inline void lw_thread_join( lw_thread_t thread )
|
||||
{
|
||||
::WaitForSingleObject( thread, INFINITE );
|
||||
::CloseHandle( thread );
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace boost
|
||||
|
||||
#endif // defined( BOOST_HAS_PTHREADS )
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class lw_abstract_thread
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~lw_abstract_thread() {}
|
||||
virtual void run() = 0;
|
||||
};
|
||||
|
||||
#if defined( BOOST_HAS_PTHREADS )
|
||||
|
||||
extern "C" void * lw_thread_routine( void * pv )
|
||||
{
|
||||
#if defined(BOOST_NO_CXX11_SMART_PTR)
|
||||
|
||||
std::auto_ptr<lw_abstract_thread> pt( static_cast<lw_abstract_thread *>( pv ) );
|
||||
|
||||
#else
|
||||
|
||||
std::unique_ptr<lw_abstract_thread> pt( static_cast<lw_abstract_thread *>( pv ) );
|
||||
|
||||
#endif
|
||||
|
||||
pt->run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
unsigned __stdcall lw_thread_routine( void * pv )
|
||||
{
|
||||
#if defined(BOOST_NO_CXX11_SMART_PTR)
|
||||
|
||||
std::auto_ptr<lw_abstract_thread> pt( static_cast<lw_abstract_thread *>( pv ) );
|
||||
|
||||
#else
|
||||
|
||||
std::unique_ptr<lw_abstract_thread> pt( static_cast<lw_abstract_thread *>( pv ) );
|
||||
|
||||
#endif
|
||||
|
||||
pt->run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template<class F> class lw_thread_impl: public lw_abstract_thread
|
||||
{
|
||||
public:
|
||||
|
||||
explicit lw_thread_impl( F f ): f_( f )
|
||||
{
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
f_();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
F f_;
|
||||
};
|
||||
|
||||
template<class F> int lw_thread_create( lw_thread_t & th, F f )
|
||||
{
|
||||
#if defined(BOOST_NO_CXX11_SMART_PTR)
|
||||
|
||||
std::auto_ptr<lw_abstract_thread> p( new lw_thread_impl<F>( f ) );
|
||||
|
||||
#else
|
||||
|
||||
std::unique_ptr<lw_abstract_thread> p( new lw_thread_impl<F>( f ) );
|
||||
|
||||
#endif
|
||||
|
||||
int r = lw_thread_create_( &th, 0, lw_thread_routine, p.get() );
|
||||
|
||||
if( r == 0 )
|
||||
{
|
||||
p.release();
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_DETAIL_LIGHTWEIGHT_THREAD_HPP_INCLUDED
|
||||
23
include/boost/detail/quick_allocator.hpp
Normal file
23
include/boost/detail/quick_allocator.hpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef BOOST_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED
|
||||
#define BOOST_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// detail/quick_allocator.hpp
|
||||
//
|
||||
// Copyright (c) 2003 David Abrahams
|
||||
// Copyright (c) 2003 Peter Dimov
|
||||
//
|
||||
// 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/smart_ptr/detail/quick_allocator.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED
|
||||
18
include/boost/enable_shared_from_this.hpp
Normal file
18
include/boost/enable_shared_from_this.hpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
|
||||
#define BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// enable_shared_from_this.hpp
|
||||
//
|
||||
// Copyright (c) 2002 Peter Dimov
|
||||
//
|
||||
// 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/smart_ptr/ for documentation.
|
||||
//
|
||||
|
||||
#include <boost/smart_ptr/enable_shared_from_this.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
|
||||
18
include/boost/intrusive_ptr.hpp
Normal file
18
include/boost/intrusive_ptr.hpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef BOOST_INTRUSIVE_PTR_HPP_INCLUDED
|
||||
#define BOOST_INTRUSIVE_PTR_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// intrusive_ptr.hpp
|
||||
//
|
||||
// Copyright (c) 2001, 2002 Peter Dimov
|
||||
//
|
||||
// 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/smart_ptr/ for documentation.
|
||||
//
|
||||
|
||||
#include <boost/smart_ptr/intrusive_ptr.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_INTRUSIVE_PTR_HPP_INCLUDED
|
||||
16
include/boost/make_shared.hpp
Normal file
16
include/boost/make_shared.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef BOOST_MAKE_SHARED_HPP_INCLUDED
|
||||
#define BOOST_MAKE_SHARED_HPP_INCLUDED
|
||||
|
||||
// make_shared.hpp
|
||||
//
|
||||
// Copyright (c) 2007, 2008 Peter Dimov
|
||||
//
|
||||
// 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/smart_ptr/ for documentation.
|
||||
|
||||
#include <boost/smart_ptr/make_shared.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_MAKE_SHARED_HPP_INCLUDED
|
||||
13
include/boost/make_unique.hpp
Normal file
13
include/boost/make_unique.hpp
Normal file
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
Copyright 2014 Glen Joseph Fernandes
|
||||
(glenjofe@gmail.com)
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef BOOST_MAKE_UNIQUE_HPP_INCLUDED
|
||||
#define BOOST_MAKE_UNIQUE_HPP_INCLUDED
|
||||
|
||||
#include <boost/smart_ptr/make_unique.hpp>
|
||||
|
||||
#endif
|
||||
122
include/boost/pointer_cast.hpp
Normal file
122
include/boost/pointer_cast.hpp
Normal file
@@ -0,0 +1,122 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005.
|
||||
// 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_POINTER_CAST_HPP
|
||||
#define BOOST_POINTER_CAST_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
//static_pointer_cast overload for raw pointers
|
||||
template<class T, class U>
|
||||
inline T* static_pointer_cast(U *ptr) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return static_cast<T*>(ptr);
|
||||
}
|
||||
|
||||
//dynamic_pointer_cast overload for raw pointers
|
||||
template<class T, class U>
|
||||
inline T* dynamic_pointer_cast(U *ptr) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return dynamic_cast<T*>(ptr);
|
||||
}
|
||||
|
||||
//const_pointer_cast overload for raw pointers
|
||||
template<class T, class U>
|
||||
inline T* const_pointer_cast(U *ptr) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return const_cast<T*>(ptr);
|
||||
}
|
||||
|
||||
//reinterpret_pointer_cast overload for raw pointers
|
||||
template<class T, class U>
|
||||
inline T* reinterpret_pointer_cast(U *ptr) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return reinterpret_cast<T*>(ptr);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_SMART_PTR )
|
||||
|
||||
#include <boost/type_traits/has_virtual_destructor.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <memory>
|
||||
|
||||
namespace boost {
|
||||
|
||||
//static_pointer_cast overload for std::shared_ptr
|
||||
using std::static_pointer_cast;
|
||||
|
||||
//dynamic_pointer_cast overload for std::shared_ptr
|
||||
using std::dynamic_pointer_cast;
|
||||
|
||||
//const_pointer_cast overload for std::shared_ptr
|
||||
using std::const_pointer_cast;
|
||||
|
||||
//reinterpret_pointer_cast overload for std::shared_ptr
|
||||
template<class T, class U> std::shared_ptr<T> reinterpret_pointer_cast(const std::shared_ptr<U> & r ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
(void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
|
||||
|
||||
typedef typename std::shared_ptr<T>::element_type E;
|
||||
|
||||
E * p = reinterpret_cast< E* >( r.get() );
|
||||
return std::shared_ptr<T>( r, p );
|
||||
}
|
||||
|
||||
//static_pointer_cast overload for std::unique_ptr
|
||||
template<class T, class U> std::unique_ptr<T> static_pointer_cast( std::unique_ptr<U> && r ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
(void) static_cast< T* >( static_cast< U* >( 0 ) );
|
||||
|
||||
typedef typename std::unique_ptr<T>::element_type E;
|
||||
|
||||
return std::unique_ptr<T>( static_cast<E*>( r.release() ) );
|
||||
}
|
||||
|
||||
//dynamic_pointer_cast overload for std::unique_ptr
|
||||
template<class T, class U> std::unique_ptr<T> dynamic_pointer_cast( std::unique_ptr<U> && r ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
(void) dynamic_cast< T* >( static_cast< U* >( 0 ) );
|
||||
|
||||
BOOST_STATIC_ASSERT_MSG( boost::has_virtual_destructor<T>::value, "The target of dynamic_pointer_cast must have a virtual destructor." );
|
||||
|
||||
T * p = dynamic_cast<T*>( r.get() );
|
||||
if( p ) r.release();
|
||||
return std::unique_ptr<T>( p );
|
||||
}
|
||||
|
||||
//const_pointer_cast overload for std::unique_ptr
|
||||
template<class T, class U> std::unique_ptr<T> const_pointer_cast( std::unique_ptr<U> && r ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
(void) const_cast< T* >( static_cast< U* >( 0 ) );
|
||||
|
||||
typedef typename std::unique_ptr<T>::element_type E;
|
||||
|
||||
return std::unique_ptr<T>( const_cast<E*>( r.release() ) );
|
||||
}
|
||||
|
||||
//reinterpret_pointer_cast overload for std::unique_ptr
|
||||
template<class T, class U> std::unique_ptr<T> reinterpret_pointer_cast( std::unique_ptr<U> && r ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
(void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
|
||||
|
||||
typedef typename std::unique_ptr<T>::element_type E;
|
||||
|
||||
return std::unique_ptr<T>( reinterpret_cast<E*>( r.release() ) );
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #if !defined( BOOST_NO_CXX11_SMART_PTR )
|
||||
|
||||
#endif //BOOST_POINTER_CAST_HPP
|
||||
55
include/boost/pointer_to_other.hpp
Normal file
55
include/boost/pointer_to_other.hpp
Normal file
@@ -0,0 +1,55 @@
|
||||
#ifndef BOOST_POINTER_TO_OTHER_HPP_INCLUDED
|
||||
#define BOOST_POINTER_TO_OTHER_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// pointer_to_other.hpp
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005.
|
||||
// Copyright (c) 2005 Peter Dimov.
|
||||
//
|
||||
// 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/smart_ptr/ for documentation.
|
||||
//
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
// Defines the same pointer type (raw or smart) to another pointee type
|
||||
|
||||
template<class T, class U>
|
||||
struct pointer_to_other;
|
||||
|
||||
template<class T, class U,
|
||||
template<class> class Sp>
|
||||
struct pointer_to_other< Sp<T>, U >
|
||||
{
|
||||
typedef Sp<U> type;
|
||||
};
|
||||
|
||||
template<class T, class T2, class U,
|
||||
template<class, class> class Sp>
|
||||
struct pointer_to_other< Sp<T, T2>, U >
|
||||
{
|
||||
typedef Sp<U, T2> type;
|
||||
};
|
||||
|
||||
template<class T, class T2, class T3, class U,
|
||||
template<class, class, class> class Sp>
|
||||
struct pointer_to_other< Sp<T, T2, T3>, U >
|
||||
{
|
||||
typedef Sp<U, T2, T3> type;
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
struct pointer_to_other< T*, U >
|
||||
{
|
||||
typedef U* type;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_POINTER_TO_OTHER_HPP_INCLUDED
|
||||
15
include/boost/scoped_array.hpp
Normal file
15
include/boost/scoped_array.hpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED
|
||||
#define BOOST_SCOPED_ARRAY_HPP_INCLUDED
|
||||
|
||||
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
|
||||
// Copyright (c) 2001, 2002 Peter Dimov
|
||||
//
|
||||
// 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/smart_ptr/ for documentation.
|
||||
|
||||
#include <boost/smart_ptr/scoped_array.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED
|
||||
15
include/boost/scoped_ptr.hpp
Normal file
15
include/boost/scoped_ptr.hpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef BOOST_SCOPED_PTR_HPP_INCLUDED
|
||||
#define BOOST_SCOPED_PTR_HPP_INCLUDED
|
||||
|
||||
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
|
||||
// Copyright (c) 2001, 2002 Peter Dimov
|
||||
//
|
||||
// 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/smart_ptr/ for documentation.
|
||||
|
||||
#include <boost/smart_ptr/scoped_ptr.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_SCOPED_PTR_HPP_INCLUDED
|
||||
19
include/boost/shared_array.hpp
Normal file
19
include/boost/shared_array.hpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED
|
||||
#define BOOST_SHARED_ARRAY_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// shared_array.hpp
|
||||
//
|
||||
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
|
||||
// Copyright (c) 2001, 2002 Peter Dimov
|
||||
//
|
||||
// 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/smart_ptr/ for documentation.
|
||||
//
|
||||
|
||||
#include <boost/smart_ptr/shared_array.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED
|
||||
19
include/boost/shared_ptr.hpp
Normal file
19
include/boost/shared_ptr.hpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef BOOST_SHARED_PTR_HPP_INCLUDED
|
||||
#define BOOST_SHARED_PTR_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// shared_ptr.hpp
|
||||
//
|
||||
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
|
||||
// Copyright (c) 2001-2008 Peter Dimov
|
||||
//
|
||||
// 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/smart_ptr/ for documentation.
|
||||
//
|
||||
|
||||
#include <boost/smart_ptr/shared_ptr.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_SHARED_PTR_HPP_INCLUDED
|
||||
26
include/boost/smart_ptr.hpp
Normal file
26
include/boost/smart_ptr.hpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef BOOST_SMART_PTR_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// smart_ptr.hpp
|
||||
//
|
||||
// For convenience, this header includes the rest of the smart
|
||||
// pointer library headers.
|
||||
//
|
||||
// Copyright (c) 2003 Peter Dimov 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/smart_ptr/ for documentation.
|
||||
//
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/scoped_array.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/shared_array.hpp>
|
||||
#include <boost/weak_ptr.hpp>
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_HPP_INCLUDED
|
||||
178
include/boost/smart_ptr/allocate_local_shared_array.hpp
Normal file
178
include/boost/smart_ptr/allocate_local_shared_array.hpp
Normal file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
Copyright 2017-2019 Glen Joseph Fernandes
|
||||
(glenjofe@gmail.com)
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef BOOST_SMART_PTR_ALLOCATE_LOCAL_SHARED_ARRAY_HPP
|
||||
#define BOOST_SMART_PTR_ALLOCATE_LOCAL_SHARED_ARRAY_HPP
|
||||
|
||||
#include <boost/smart_ptr/allocate_shared_array.hpp>
|
||||
#include <boost/smart_ptr/local_shared_ptr.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace detail {
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE lsp_array_base
|
||||
: public local_counted_base {
|
||||
public:
|
||||
void set(sp_counted_base* base) BOOST_SP_NOEXCEPT {
|
||||
count_ = shared_count(base);
|
||||
}
|
||||
|
||||
void local_cb_destroy() BOOST_SP_NOEXCEPT BOOST_OVERRIDE {
|
||||
shared_count().swap(count_);
|
||||
}
|
||||
|
||||
shared_count local_cb_get_shared_count() const
|
||||
BOOST_SP_NOEXCEPT BOOST_OVERRIDE {
|
||||
return count_;
|
||||
}
|
||||
|
||||
private:
|
||||
shared_count count_;
|
||||
};
|
||||
|
||||
template<class A>
|
||||
class lsp_array_state
|
||||
: public sp_array_state<A> {
|
||||
public:
|
||||
template<class U>
|
||||
lsp_array_state(const U& other, std::size_t size) BOOST_SP_NOEXCEPT
|
||||
: sp_array_state<A>(other, size) { }
|
||||
|
||||
lsp_array_base& base() BOOST_SP_NOEXCEPT {
|
||||
return base_;
|
||||
}
|
||||
|
||||
private:
|
||||
lsp_array_base base_;
|
||||
};
|
||||
|
||||
template<class A, std::size_t N>
|
||||
class lsp_size_array_state
|
||||
: public sp_size_array_state<A, N> {
|
||||
public:
|
||||
template<class U>
|
||||
lsp_size_array_state(const U& other, std::size_t size) BOOST_SP_NOEXCEPT
|
||||
: sp_size_array_state<A, N>(other, size) { }
|
||||
|
||||
lsp_array_base& base() BOOST_SP_NOEXCEPT {
|
||||
return base_;
|
||||
}
|
||||
|
||||
private:
|
||||
lsp_array_base base_;
|
||||
};
|
||||
|
||||
} /* detail */
|
||||
|
||||
template<class T, class A>
|
||||
inline typename enable_if_<is_unbounded_array<T>::value,
|
||||
local_shared_ptr<T> >::type
|
||||
allocate_local_shared(const A& allocator, std::size_t count)
|
||||
{
|
||||
typedef typename detail::sp_array_element<T>::type element;
|
||||
typedef typename detail::sp_bind_allocator<A, element>::type other;
|
||||
typedef detail::lsp_array_state<other> state;
|
||||
typedef detail::sp_array_base<state> base;
|
||||
detail::sp_array_result<other, base> result(allocator, count);
|
||||
base* node = result.get();
|
||||
element* start = detail::sp_array_start<element>(node);
|
||||
::new(static_cast<void*>(node)) base(allocator, start, count);
|
||||
detail::lsp_array_base& local = node->state().base();
|
||||
local.set(node);
|
||||
result.release();
|
||||
return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start,
|
||||
&local);
|
||||
}
|
||||
|
||||
template<class T, class A>
|
||||
inline typename enable_if_<is_bounded_array<T>::value,
|
||||
local_shared_ptr<T> >::type
|
||||
allocate_local_shared(const A& allocator)
|
||||
{
|
||||
enum {
|
||||
count = extent<T>::value
|
||||
};
|
||||
typedef typename detail::sp_array_element<T>::type element;
|
||||
typedef typename detail::sp_bind_allocator<A, element>::type other;
|
||||
typedef detail::lsp_size_array_state<other, count> state;
|
||||
typedef detail::sp_array_base<state> base;
|
||||
detail::sp_array_result<other, base> result(allocator, count);
|
||||
base* node = result.get();
|
||||
element* start = detail::sp_array_start<element>(node);
|
||||
::new(static_cast<void*>(node)) base(allocator, start, count);
|
||||
detail::lsp_array_base& local = node->state().base();
|
||||
local.set(node);
|
||||
result.release();
|
||||
return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start,
|
||||
&local);
|
||||
}
|
||||
|
||||
template<class T, class A>
|
||||
inline typename enable_if_<is_unbounded_array<T>::value,
|
||||
local_shared_ptr<T> >::type
|
||||
allocate_local_shared(const A& allocator, std::size_t count,
|
||||
const typename remove_extent<T>::type& value)
|
||||
{
|
||||
typedef typename detail::sp_array_element<T>::type element;
|
||||
typedef typename detail::sp_bind_allocator<A, element>::type other;
|
||||
typedef detail::lsp_array_state<other> state;
|
||||
typedef detail::sp_array_base<state> base;
|
||||
detail::sp_array_result<other, base> result(allocator, count);
|
||||
base* node = result.get();
|
||||
element* start = detail::sp_array_start<element>(node);
|
||||
::new(static_cast<void*>(node)) base(allocator, start, count, value);
|
||||
detail::lsp_array_base& local = node->state().base();
|
||||
local.set(node);
|
||||
result.release();
|
||||
return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start,
|
||||
&local);
|
||||
}
|
||||
|
||||
template<class T, class A>
|
||||
inline typename enable_if_<is_bounded_array<T>::value,
|
||||
local_shared_ptr<T> >::type
|
||||
allocate_local_shared(const A& allocator,
|
||||
const typename remove_extent<T>::type& value)
|
||||
{
|
||||
enum {
|
||||
count = extent<T>::value
|
||||
};
|
||||
typedef typename detail::sp_array_element<T>::type element;
|
||||
typedef typename detail::sp_bind_allocator<A, element>::type other;
|
||||
typedef detail::lsp_size_array_state<other, count> state;
|
||||
typedef detail::sp_array_base<state> base;
|
||||
detail::sp_array_result<other, base> result(allocator, count);
|
||||
base* node = result.get();
|
||||
element* start = detail::sp_array_start<element>(node);
|
||||
::new(static_cast<void*>(node)) base(allocator, start, count, value);
|
||||
detail::lsp_array_base& local = node->state().base();
|
||||
local.set(node);
|
||||
result.release();
|
||||
return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start,
|
||||
&local);
|
||||
}
|
||||
|
||||
template<class T, class A>
|
||||
inline typename enable_if_<is_unbounded_array<T>::value,
|
||||
local_shared_ptr<T> >::type
|
||||
allocate_local_shared_noinit(const A& allocator, std::size_t count)
|
||||
{
|
||||
return boost::allocate_local_shared<T>(boost::noinit_adapt(allocator),
|
||||
count);
|
||||
}
|
||||
|
||||
template<class T, class A>
|
||||
inline typename enable_if_<is_bounded_array<T>::value,
|
||||
local_shared_ptr<T> >::type
|
||||
allocate_local_shared_noinit(const A& allocator)
|
||||
{
|
||||
return boost::allocate_local_shared<T>(boost::noinit_adapt(allocator));
|
||||
}
|
||||
|
||||
} /* boost */
|
||||
|
||||
#endif
|
||||
363
include/boost/smart_ptr/allocate_shared_array.hpp
Normal file
363
include/boost/smart_ptr/allocate_shared_array.hpp
Normal file
@@ -0,0 +1,363 @@
|
||||
/*
|
||||
Copyright 2012-2019 Glen Joseph Fernandes
|
||||
(glenjofe@gmail.com)
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP
|
||||
#define BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP
|
||||
|
||||
#include <boost/core/alloc_construct.hpp>
|
||||
#include <boost/core/first_scalar.hpp>
|
||||
#include <boost/smart_ptr/shared_ptr.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
#include <boost/type_traits/enable_if.hpp>
|
||||
#include <boost/type_traits/extent.hpp>
|
||||
#include <boost/type_traits/is_bounded_array.hpp>
|
||||
#include <boost/type_traits/is_unbounded_array.hpp>
|
||||
#include <boost/type_traits/remove_cv.hpp>
|
||||
#include <boost/type_traits/remove_extent.hpp>
|
||||
#include <boost/type_traits/type_with_alignment.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace detail {
|
||||
|
||||
template<class T>
|
||||
struct sp_array_element {
|
||||
typedef typename boost::remove_cv<typename
|
||||
boost::remove_extent<T>::type>::type type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct sp_array_count {
|
||||
enum {
|
||||
value = 1
|
||||
};
|
||||
};
|
||||
|
||||
template<class T, std::size_t N>
|
||||
struct sp_array_count<T[N]> {
|
||||
enum {
|
||||
value = N * sp_array_count<T>::value
|
||||
};
|
||||
};
|
||||
|
||||
template<std::size_t N, std::size_t M>
|
||||
struct sp_max_size {
|
||||
enum {
|
||||
value = N < M ? M : N
|
||||
};
|
||||
};
|
||||
|
||||
template<std::size_t N, std::size_t M>
|
||||
struct sp_align_up {
|
||||
enum {
|
||||
value = (N + M - 1) & ~(M - 1)
|
||||
};
|
||||
};
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
|
||||
template<class A, class T>
|
||||
struct sp_bind_allocator {
|
||||
typedef typename std::allocator_traits<A>::template rebind_alloc<T> type;
|
||||
};
|
||||
#else
|
||||
template<class A, class T>
|
||||
struct sp_bind_allocator {
|
||||
typedef typename A::template rebind<T>::other type;
|
||||
};
|
||||
#endif
|
||||
|
||||
template<class T>
|
||||
BOOST_CONSTEXPR inline std::size_t
|
||||
sp_objects(std::size_t size) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return (size + sizeof(T) - 1) / sizeof(T);
|
||||
}
|
||||
|
||||
template<class A>
|
||||
class sp_array_state {
|
||||
public:
|
||||
typedef A type;
|
||||
|
||||
template<class U>
|
||||
sp_array_state(const U& _allocator, std::size_t _size) BOOST_SP_NOEXCEPT
|
||||
: allocator_(_allocator),
|
||||
size_(_size) { }
|
||||
|
||||
A& allocator() BOOST_SP_NOEXCEPT {
|
||||
return allocator_;
|
||||
}
|
||||
|
||||
std::size_t size() const BOOST_SP_NOEXCEPT {
|
||||
return size_;
|
||||
}
|
||||
|
||||
private:
|
||||
A allocator_;
|
||||
std::size_t size_;
|
||||
};
|
||||
|
||||
template<class A, std::size_t N>
|
||||
class sp_size_array_state {
|
||||
public:
|
||||
typedef A type;
|
||||
|
||||
template<class U>
|
||||
sp_size_array_state(const U& _allocator, std::size_t) BOOST_SP_NOEXCEPT
|
||||
: allocator_(_allocator) { }
|
||||
|
||||
A& allocator() BOOST_SP_NOEXCEPT {
|
||||
return allocator_;
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR std::size_t size() const BOOST_SP_NOEXCEPT {
|
||||
return N;
|
||||
}
|
||||
|
||||
private:
|
||||
A allocator_;
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
struct sp_array_alignment {
|
||||
enum {
|
||||
value = sp_max_size<boost::alignment_of<T>::value,
|
||||
boost::alignment_of<U>::value>::value
|
||||
};
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
struct sp_array_offset {
|
||||
enum {
|
||||
value = sp_align_up<sizeof(T), sp_array_alignment<T, U>::value>::value
|
||||
};
|
||||
};
|
||||
|
||||
template<class U, class T>
|
||||
inline U*
|
||||
sp_array_start(T* base) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
enum {
|
||||
size = sp_array_offset<T, U>::value
|
||||
};
|
||||
return reinterpret_cast<U*>(reinterpret_cast<char*>(base) + size);
|
||||
}
|
||||
|
||||
template<class A, class T>
|
||||
class sp_array_creator {
|
||||
typedef typename A::value_type element;
|
||||
|
||||
enum {
|
||||
offset = sp_array_offset<T, element>::value
|
||||
};
|
||||
|
||||
typedef typename boost::type_with_alignment<sp_array_alignment<T,
|
||||
element>::value>::type type;
|
||||
|
||||
public:
|
||||
template<class U>
|
||||
sp_array_creator(const U& other, std::size_t size) BOOST_SP_NOEXCEPT
|
||||
: other_(other),
|
||||
size_(sp_objects<type>(offset + sizeof(element) * size)) { }
|
||||
|
||||
T* create() {
|
||||
return reinterpret_cast<T*>(other_.allocate(size_));
|
||||
}
|
||||
|
||||
void destroy(T* base) {
|
||||
other_.deallocate(reinterpret_cast<type*>(base), size_);
|
||||
}
|
||||
|
||||
private:
|
||||
typename sp_bind_allocator<A, type>::type other_;
|
||||
std::size_t size_;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class BOOST_SYMBOL_VISIBLE sp_array_base
|
||||
: public sp_counted_base {
|
||||
typedef typename T::type allocator;
|
||||
|
||||
public:
|
||||
typedef typename allocator::value_type type;
|
||||
|
||||
template<class A>
|
||||
sp_array_base(const A& other, type* start, std::size_t size)
|
||||
: state_(other, size) {
|
||||
boost::alloc_construct_n(state_.allocator(),
|
||||
boost::first_scalar(start),
|
||||
state_.size() * sp_array_count<type>::value);
|
||||
}
|
||||
|
||||
template<class A, class U>
|
||||
sp_array_base(const A& other, type* start, std::size_t size, const U& list)
|
||||
: state_(other, size) {
|
||||
enum {
|
||||
count = sp_array_count<type>::value
|
||||
};
|
||||
boost::alloc_construct_n(state_.allocator(),
|
||||
boost::first_scalar(start), state_.size() * count,
|
||||
boost::first_scalar(&list), count);
|
||||
}
|
||||
|
||||
T& state() BOOST_SP_NOEXCEPT {
|
||||
return state_;
|
||||
}
|
||||
|
||||
void dispose() BOOST_SP_NOEXCEPT BOOST_OVERRIDE {
|
||||
boost::alloc_destroy_n(state_.allocator(),
|
||||
boost::first_scalar(sp_array_start<type>(this)),
|
||||
state_.size() * sp_array_count<type>::value);
|
||||
}
|
||||
|
||||
void destroy() BOOST_SP_NOEXCEPT BOOST_OVERRIDE {
|
||||
sp_array_creator<allocator, sp_array_base> other(state_.allocator(),
|
||||
state_.size());
|
||||
this->~sp_array_base();
|
||||
other.destroy(this);
|
||||
}
|
||||
|
||||
void* get_deleter(const sp_typeinfo_&) BOOST_SP_NOEXCEPT BOOST_OVERRIDE {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* get_local_deleter(const sp_typeinfo_&)
|
||||
BOOST_SP_NOEXCEPT BOOST_OVERRIDE {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* get_untyped_deleter() BOOST_SP_NOEXCEPT BOOST_OVERRIDE {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
T state_;
|
||||
};
|
||||
|
||||
template<class A, class T>
|
||||
struct sp_array_result {
|
||||
public:
|
||||
template<class U>
|
||||
sp_array_result(const U& other, std::size_t size)
|
||||
: creator_(other, size),
|
||||
result_(creator_.create()) { }
|
||||
|
||||
~sp_array_result() {
|
||||
if (result_) {
|
||||
creator_.destroy(result_);
|
||||
}
|
||||
}
|
||||
|
||||
T* get() const BOOST_SP_NOEXCEPT {
|
||||
return result_;
|
||||
}
|
||||
|
||||
void release() BOOST_SP_NOEXCEPT {
|
||||
result_ = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
sp_array_result(const sp_array_result&);
|
||||
sp_array_result& operator=(const sp_array_result&);
|
||||
|
||||
sp_array_creator<A, T> creator_;
|
||||
T* result_;
|
||||
};
|
||||
|
||||
} /* detail */
|
||||
|
||||
template<class T, class A>
|
||||
inline typename enable_if_<is_unbounded_array<T>::value, shared_ptr<T> >::type
|
||||
allocate_shared(const A& allocator, std::size_t count)
|
||||
{
|
||||
typedef typename detail::sp_array_element<T>::type element;
|
||||
typedef typename detail::sp_bind_allocator<A, element>::type other;
|
||||
typedef detail::sp_array_state<other> state;
|
||||
typedef detail::sp_array_base<state> base;
|
||||
detail::sp_array_result<other, base> result(allocator, count);
|
||||
base* node = result.get();
|
||||
element* start = detail::sp_array_start<element>(node);
|
||||
::new(static_cast<void*>(node)) base(allocator, start, count);
|
||||
result.release();
|
||||
return shared_ptr<T>(detail::sp_internal_constructor_tag(), start,
|
||||
detail::shared_count(static_cast<detail::sp_counted_base*>(node)));
|
||||
}
|
||||
|
||||
template<class T, class A>
|
||||
inline typename enable_if_<is_bounded_array<T>::value, shared_ptr<T> >::type
|
||||
allocate_shared(const A& allocator)
|
||||
{
|
||||
enum {
|
||||
count = extent<T>::value
|
||||
};
|
||||
typedef typename detail::sp_array_element<T>::type element;
|
||||
typedef typename detail::sp_bind_allocator<A, element>::type other;
|
||||
typedef detail::sp_size_array_state<other, extent<T>::value> state;
|
||||
typedef detail::sp_array_base<state> base;
|
||||
detail::sp_array_result<other, base> result(allocator, count);
|
||||
base* node = result.get();
|
||||
element* start = detail::sp_array_start<element>(node);
|
||||
::new(static_cast<void*>(node)) base(allocator, start, count);
|
||||
result.release();
|
||||
return shared_ptr<T>(detail::sp_internal_constructor_tag(), start,
|
||||
detail::shared_count(static_cast<detail::sp_counted_base*>(node)));
|
||||
}
|
||||
|
||||
template<class T, class A>
|
||||
inline typename enable_if_<is_unbounded_array<T>::value, shared_ptr<T> >::type
|
||||
allocate_shared(const A& allocator, std::size_t count,
|
||||
const typename remove_extent<T>::type& value)
|
||||
{
|
||||
typedef typename detail::sp_array_element<T>::type element;
|
||||
typedef typename detail::sp_bind_allocator<A, element>::type other;
|
||||
typedef detail::sp_array_state<other> state;
|
||||
typedef detail::sp_array_base<state> base;
|
||||
detail::sp_array_result<other, base> result(allocator, count);
|
||||
base* node = result.get();
|
||||
element* start = detail::sp_array_start<element>(node);
|
||||
::new(static_cast<void*>(node)) base(allocator, start, count, value);
|
||||
result.release();
|
||||
return shared_ptr<T>(detail::sp_internal_constructor_tag(), start,
|
||||
detail::shared_count(static_cast<detail::sp_counted_base*>(node)));
|
||||
}
|
||||
|
||||
template<class T, class A>
|
||||
inline typename enable_if_<is_bounded_array<T>::value, shared_ptr<T> >::type
|
||||
allocate_shared(const A& allocator,
|
||||
const typename remove_extent<T>::type& value)
|
||||
{
|
||||
enum {
|
||||
count = extent<T>::value
|
||||
};
|
||||
typedef typename detail::sp_array_element<T>::type element;
|
||||
typedef typename detail::sp_bind_allocator<A, element>::type other;
|
||||
typedef detail::sp_size_array_state<other, extent<T>::value> state;
|
||||
typedef detail::sp_array_base<state> base;
|
||||
detail::sp_array_result<other, base> result(allocator, count);
|
||||
base* node = result.get();
|
||||
element* start = detail::sp_array_start<element>(node);
|
||||
::new(static_cast<void*>(node)) base(allocator, start, count, value);
|
||||
result.release();
|
||||
return shared_ptr<T>(detail::sp_internal_constructor_tag(), start,
|
||||
detail::shared_count(static_cast<detail::sp_counted_base*>(node)));
|
||||
}
|
||||
|
||||
template<class T, class A>
|
||||
inline typename enable_if_<is_unbounded_array<T>::value, shared_ptr<T> >::type
|
||||
allocate_shared_noinit(const A& allocator, std::size_t count)
|
||||
{
|
||||
return boost::allocate_shared<T>(boost::noinit_adapt(allocator), count);
|
||||
}
|
||||
|
||||
template<class T, class A>
|
||||
inline typename enable_if_<is_bounded_array<T>::value, shared_ptr<T> >::type
|
||||
allocate_shared_noinit(const A& allocator)
|
||||
{
|
||||
return boost::allocate_shared<T>(boost::noinit_adapt(allocator));
|
||||
}
|
||||
|
||||
} /* boost */
|
||||
|
||||
#endif
|
||||
505
include/boost/smart_ptr/allocate_unique.hpp
Normal file
505
include/boost/smart_ptr/allocate_unique.hpp
Normal file
@@ -0,0 +1,505 @@
|
||||
/*
|
||||
Copyright 2019 Glen Joseph Fernandes
|
||||
(glenjofe@gmail.com)
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef BOOST_SMART_PTR_ALLOCATE_UNIQUE_HPP
|
||||
#define BOOST_SMART_PTR_ALLOCATE_UNIQUE_HPP
|
||||
|
||||
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
|
||||
#include <boost/smart_ptr/detail/sp_nullptr_t.hpp>
|
||||
#include <boost/core/alloc_construct.hpp>
|
||||
#include <boost/core/empty_value.hpp>
|
||||
#include <boost/core/first_scalar.hpp>
|
||||
#include <boost/core/noinit_adaptor.hpp>
|
||||
#include <boost/core/pointer_traits.hpp>
|
||||
#include <boost/type_traits/enable_if.hpp>
|
||||
#include <boost/type_traits/extent.hpp>
|
||||
#include <boost/type_traits/is_array.hpp>
|
||||
#include <boost/type_traits/is_bounded_array.hpp>
|
||||
#include <boost/type_traits/is_unbounded_array.hpp>
|
||||
#include <boost/type_traits/remove_cv.hpp>
|
||||
#include <boost/type_traits/remove_extent.hpp>
|
||||
#include <boost/type_traits/type_identity.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace detail {
|
||||
|
||||
template<class T>
|
||||
struct sp_alloc_size {
|
||||
BOOST_STATIC_CONSTEXPR std::size_t value = 1;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct sp_alloc_size<T[]> {
|
||||
BOOST_STATIC_CONSTEXPR std::size_t value = sp_alloc_size<T>::value;
|
||||
};
|
||||
|
||||
template<class T, std::size_t N>
|
||||
struct sp_alloc_size<T[N]> {
|
||||
BOOST_STATIC_CONSTEXPR std::size_t value = N * sp_alloc_size<T>::value;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct sp_alloc_result {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<class T, std::size_t N>
|
||||
struct sp_alloc_result<T[N]> {
|
||||
typedef T type[];
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct sp_alloc_value {
|
||||
typedef typename boost::remove_cv<typename
|
||||
boost::remove_extent<T>::type>::type type;
|
||||
};
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
|
||||
template<class A, class T>
|
||||
struct sp_alloc_to {
|
||||
typedef typename std::allocator_traits<A>::template rebind_alloc<T> type;
|
||||
};
|
||||
#else
|
||||
template<class A, class T>
|
||||
struct sp_alloc_to {
|
||||
typedef typename A::template rebind<T>::other type;
|
||||
};
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
|
||||
template<class A>
|
||||
struct sp_alloc_type {
|
||||
typedef typename std::allocator_traits<A>::pointer type;
|
||||
};
|
||||
#else
|
||||
template<class A>
|
||||
struct sp_alloc_type {
|
||||
typedef typename A::pointer type;
|
||||
};
|
||||
#endif
|
||||
|
||||
template<class T, class P>
|
||||
class sp_alloc_ptr {
|
||||
public:
|
||||
typedef T element_type;
|
||||
|
||||
sp_alloc_ptr() BOOST_SP_NOEXCEPT
|
||||
: p_() { }
|
||||
|
||||
#if defined(BOOST_MSVC) && BOOST_MSVC == 1600
|
||||
sp_alloc_ptr(T* p) BOOST_SP_NOEXCEPT
|
||||
: p_(const_cast<typename boost::remove_cv<T>::type*>(p)) { }
|
||||
#endif
|
||||
|
||||
sp_alloc_ptr(std::size_t, P p) BOOST_SP_NOEXCEPT
|
||||
: p_(p) { }
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_NULLPTR)
|
||||
sp_alloc_ptr(detail::sp_nullptr_t) BOOST_SP_NOEXCEPT
|
||||
: p_() { }
|
||||
#endif
|
||||
|
||||
T& operator*() const {
|
||||
return *p_;
|
||||
}
|
||||
|
||||
T* operator->() const BOOST_SP_NOEXCEPT {
|
||||
return boost::to_address(p_);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
|
||||
explicit operator bool() const BOOST_SP_NOEXCEPT {
|
||||
return !!p_;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool operator!() const BOOST_SP_NOEXCEPT {
|
||||
return !p_;
|
||||
}
|
||||
|
||||
P ptr() const BOOST_SP_NOEXCEPT {
|
||||
return p_;
|
||||
}
|
||||
|
||||
BOOST_STATIC_CONSTEXPR std::size_t size() BOOST_SP_NOEXCEPT {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if defined(BOOST_MSVC) && BOOST_MSVC < 1910
|
||||
static sp_alloc_ptr pointer_to(T& v) {
|
||||
return sp_alloc_ptr(1,
|
||||
std::pointer_traits<P>::pointer_to(const_cast<typename
|
||||
boost::remove_cv<T>::type&>(v)));
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
P p_;
|
||||
};
|
||||
|
||||
template<class T, class P>
|
||||
class sp_alloc_ptr<T[], P> {
|
||||
public:
|
||||
typedef T element_type;
|
||||
|
||||
sp_alloc_ptr() BOOST_SP_NOEXCEPT
|
||||
: p_() { }
|
||||
|
||||
sp_alloc_ptr(std::size_t n, P p) BOOST_SP_NOEXCEPT
|
||||
: p_(p)
|
||||
, n_(n) { }
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_NULLPTR)
|
||||
sp_alloc_ptr(detail::sp_nullptr_t) BOOST_SP_NOEXCEPT
|
||||
: p_() { }
|
||||
#endif
|
||||
|
||||
T& operator[](std::size_t i) const {
|
||||
return p_[i];
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
|
||||
explicit operator bool() const BOOST_SP_NOEXCEPT {
|
||||
return !!p_;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool operator!() const BOOST_SP_NOEXCEPT {
|
||||
return !p_;
|
||||
}
|
||||
|
||||
P ptr() const BOOST_SP_NOEXCEPT {
|
||||
return p_;
|
||||
}
|
||||
|
||||
std::size_t size() const BOOST_SP_NOEXCEPT {
|
||||
return n_;
|
||||
}
|
||||
|
||||
#if defined(BOOST_MSVC) && BOOST_MSVC < 1910
|
||||
static sp_alloc_ptr pointer_to(T& v) {
|
||||
return sp_alloc_ptr(n_,
|
||||
std::pointer_traits<P>::pointer_to(const_cast<typename
|
||||
boost::remove_cv<T>::type&>(v)));
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
P p_;
|
||||
std::size_t n_;
|
||||
};
|
||||
|
||||
template<class T, std::size_t N, class P>
|
||||
class sp_alloc_ptr<T[N], P> {
|
||||
public:
|
||||
typedef T element_type;
|
||||
|
||||
sp_alloc_ptr() BOOST_SP_NOEXCEPT
|
||||
: p_() { }
|
||||
|
||||
sp_alloc_ptr(std::size_t, P p) BOOST_SP_NOEXCEPT
|
||||
: p_(p) { }
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_NULLPTR)
|
||||
sp_alloc_ptr(detail::sp_nullptr_t) BOOST_SP_NOEXCEPT
|
||||
: p_() { }
|
||||
#endif
|
||||
|
||||
T& operator[](std::size_t i) const {
|
||||
return p_[i];
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
|
||||
explicit operator bool() const BOOST_SP_NOEXCEPT {
|
||||
return !!p_;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool operator!() const BOOST_SP_NOEXCEPT {
|
||||
return !p_;
|
||||
}
|
||||
|
||||
P ptr() const BOOST_SP_NOEXCEPT {
|
||||
return p_;
|
||||
}
|
||||
|
||||
BOOST_STATIC_CONSTEXPR std::size_t size() BOOST_SP_NOEXCEPT {
|
||||
return N;
|
||||
}
|
||||
|
||||
#if defined(BOOST_MSVC) && BOOST_MSVC < 1910
|
||||
static sp_alloc_ptr pointer_to(T& v) {
|
||||
return sp_alloc_ptr(N,
|
||||
std::pointer_traits<P>::pointer_to(const_cast<typename
|
||||
boost::remove_cv<T>::type&>(v)));
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
P p_;
|
||||
};
|
||||
|
||||
template<class T, class P>
|
||||
inline bool
|
||||
operator==(const sp_alloc_ptr<T, P>& lhs, const sp_alloc_ptr<T, P>& rhs)
|
||||
{
|
||||
return lhs.ptr() == rhs.ptr();
|
||||
}
|
||||
|
||||
template<class T, class P>
|
||||
inline bool
|
||||
operator!=(const sp_alloc_ptr<T, P>& lhs, const sp_alloc_ptr<T, P>& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_NULLPTR)
|
||||
template<class T, class P>
|
||||
inline bool
|
||||
operator==(const sp_alloc_ptr<T, P>& lhs,
|
||||
detail::sp_nullptr_t) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return !lhs.ptr();
|
||||
}
|
||||
|
||||
template<class T, class P>
|
||||
inline bool
|
||||
operator==(detail::sp_nullptr_t,
|
||||
const sp_alloc_ptr<T, P>& rhs) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return !rhs.ptr();
|
||||
}
|
||||
|
||||
template<class T, class P>
|
||||
inline bool
|
||||
operator!=(const sp_alloc_ptr<T, P>& lhs,
|
||||
detail::sp_nullptr_t) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return !!lhs.ptr();
|
||||
}
|
||||
|
||||
template<class T, class P>
|
||||
inline bool
|
||||
operator!=(detail::sp_nullptr_t,
|
||||
const sp_alloc_ptr<T, P>& rhs) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return !!rhs.ptr();
|
||||
}
|
||||
#endif
|
||||
|
||||
template<class A>
|
||||
inline void
|
||||
sp_alloc_clear(A& a, typename sp_alloc_type<A>::type p, std::size_t,
|
||||
boost::false_type)
|
||||
{
|
||||
boost::alloc_destroy(a, boost::to_address(p));
|
||||
}
|
||||
|
||||
template<class A>
|
||||
inline void
|
||||
sp_alloc_clear(A& a, typename sp_alloc_type<A>::type p, std::size_t n,
|
||||
boost::true_type)
|
||||
{
|
||||
#if defined(BOOST_MSVC) && BOOST_MSVC < 1800
|
||||
if (!p) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
boost::alloc_destroy_n(a, boost::first_scalar(boost::to_address(p)),
|
||||
n * sp_alloc_size<typename A::value_type>::value);
|
||||
}
|
||||
|
||||
} /* detail */
|
||||
|
||||
template<class T, class A>
|
||||
class alloc_deleter
|
||||
: empty_value<typename detail::sp_alloc_to<A,
|
||||
typename detail::sp_alloc_value<T>::type>::type> {
|
||||
typedef typename detail::sp_alloc_to<A,
|
||||
typename detail::sp_alloc_value<T>::type>::type allocator;
|
||||
typedef empty_value<allocator> base;
|
||||
|
||||
public:
|
||||
typedef detail::sp_alloc_ptr<T,
|
||||
typename detail::sp_alloc_type<allocator>::type> pointer;
|
||||
|
||||
explicit alloc_deleter(const allocator& a) BOOST_SP_NOEXCEPT
|
||||
: base(empty_init_t(), a) { }
|
||||
|
||||
void operator()(pointer p) {
|
||||
detail::sp_alloc_clear(base::get(), p.ptr(), p.size(), is_array<T>());
|
||||
base::get().deallocate(p.ptr(), p.size());
|
||||
}
|
||||
};
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
|
||||
template<class T, class A>
|
||||
using alloc_noinit_deleter = alloc_deleter<T, noinit_adaptor<A> >;
|
||||
#endif
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class T, class A>
|
||||
class sp_alloc_make {
|
||||
public:
|
||||
typedef typename sp_alloc_to<A,
|
||||
typename sp_alloc_value<T>::type>::type allocator;
|
||||
|
||||
private:
|
||||
typedef boost::alloc_deleter<T, A> deleter;
|
||||
|
||||
public:
|
||||
typedef std::unique_ptr<typename sp_alloc_result<T>::type, deleter> type;
|
||||
|
||||
sp_alloc_make(const A& a, std::size_t n)
|
||||
: a_(a)
|
||||
, n_(n)
|
||||
, p_(a_.allocate(n)) { }
|
||||
|
||||
~sp_alloc_make() {
|
||||
if (p_) {
|
||||
a_.deallocate(p_, n_);
|
||||
}
|
||||
}
|
||||
|
||||
typename allocator::value_type* get() const BOOST_SP_NOEXCEPT {
|
||||
return boost::to_address(p_);
|
||||
}
|
||||
|
||||
allocator& state() BOOST_SP_NOEXCEPT {
|
||||
return a_;
|
||||
}
|
||||
|
||||
type release() BOOST_SP_NOEXCEPT {
|
||||
pointer p = p_;
|
||||
p_ = pointer();
|
||||
return type(typename deleter::pointer(n_, p), deleter(a_));
|
||||
}
|
||||
|
||||
private:
|
||||
typedef typename sp_alloc_type<allocator>::type pointer;
|
||||
|
||||
allocator a_;
|
||||
std::size_t n_;
|
||||
pointer p_;
|
||||
};
|
||||
|
||||
} /* detail */
|
||||
|
||||
template<class T, class A>
|
||||
inline typename enable_if_<!is_array<T>::value,
|
||||
std::unique_ptr<T, alloc_deleter<T, A> > >::type
|
||||
allocate_unique(const A& alloc)
|
||||
{
|
||||
detail::sp_alloc_make<T, A> c(alloc, 1);
|
||||
boost::alloc_construct(c.state(), c.get());
|
||||
return c.release();
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template<class T, class A, class... Args>
|
||||
inline typename enable_if_<!is_array<T>::value,
|
||||
std::unique_ptr<T, alloc_deleter<T, A> > >::type
|
||||
allocate_unique(const A& alloc, Args&&... args)
|
||||
{
|
||||
detail::sp_alloc_make<T, A> c(alloc, 1);
|
||||
boost::alloc_construct(c.state(), c.get(), std::forward<Args>(args)...);
|
||||
return c.release();
|
||||
}
|
||||
#endif
|
||||
|
||||
template<class T, class A>
|
||||
inline typename enable_if_<!is_array<T>::value,
|
||||
std::unique_ptr<T, alloc_deleter<T, A> > >::type
|
||||
allocate_unique(const A& alloc, typename type_identity<T>::type&& value)
|
||||
{
|
||||
detail::sp_alloc_make<T, A> c(alloc, 1);
|
||||
boost::alloc_construct(c.state(), c.get(), std::move(value));
|
||||
return c.release();
|
||||
}
|
||||
|
||||
template<class T, class A>
|
||||
inline typename enable_if_<!is_array<T>::value,
|
||||
std::unique_ptr<T, alloc_deleter<T, noinit_adaptor<A> > > >::type
|
||||
allocate_unique_noinit(const A& alloc)
|
||||
{
|
||||
return boost::allocate_unique<T, noinit_adaptor<A> >(alloc);
|
||||
}
|
||||
|
||||
template<class T, class A>
|
||||
inline typename enable_if_<is_unbounded_array<T>::value,
|
||||
std::unique_ptr<T, alloc_deleter<T, A> > >::type
|
||||
allocate_unique(const A& alloc, std::size_t size)
|
||||
{
|
||||
detail::sp_alloc_make<T, A> c(alloc, size);
|
||||
boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()),
|
||||
size * detail::sp_alloc_size<T>::value);
|
||||
return c.release();
|
||||
}
|
||||
|
||||
template<class T, class A>
|
||||
inline typename enable_if_<is_bounded_array<T>::value,
|
||||
std::unique_ptr<typename detail::sp_alloc_result<T>::type,
|
||||
alloc_deleter<T, A> > >::type
|
||||
allocate_unique(const A& alloc)
|
||||
{
|
||||
detail::sp_alloc_make<T, A> c(alloc, extent<T>::value);
|
||||
boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()),
|
||||
detail::sp_alloc_size<T>::value);
|
||||
return c.release();
|
||||
}
|
||||
|
||||
template<class T, class A>
|
||||
inline typename enable_if_<is_unbounded_array<T>::value,
|
||||
std::unique_ptr<T, alloc_deleter<T, noinit_adaptor<A> > > >::type
|
||||
allocate_unique_noinit(const A& alloc, std::size_t size)
|
||||
{
|
||||
return boost::allocate_unique<T, noinit_adaptor<A> >(alloc, size);
|
||||
}
|
||||
|
||||
template<class T, class A>
|
||||
inline typename enable_if_<is_bounded_array<T>::value,
|
||||
std::unique_ptr<typename detail::sp_alloc_result<T>::type,
|
||||
alloc_deleter<T, noinit_adaptor<A> > > >::type
|
||||
allocate_unique_noinit(const A& alloc)
|
||||
{
|
||||
return boost::allocate_unique<T, noinit_adaptor<A> >(alloc);
|
||||
}
|
||||
|
||||
template<class T, class A>
|
||||
inline typename enable_if_<is_unbounded_array<T>::value,
|
||||
std::unique_ptr<T, alloc_deleter<T, A> > >::type
|
||||
allocate_unique(const A& alloc, std::size_t size,
|
||||
const typename remove_extent<T>::type& value)
|
||||
{
|
||||
detail::sp_alloc_make<T, A> c(alloc, size);
|
||||
boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()),
|
||||
size * detail::sp_alloc_size<T>::value, boost::first_scalar(&value),
|
||||
detail::sp_alloc_size<typename remove_extent<T>::type>::value);
|
||||
return c.release();
|
||||
}
|
||||
|
||||
template<class T, class A>
|
||||
inline typename enable_if_<is_bounded_array<T>::value,
|
||||
std::unique_ptr<typename detail::sp_alloc_result<T>::type,
|
||||
alloc_deleter<T, A> > >::type
|
||||
allocate_unique(const A& alloc,
|
||||
const typename remove_extent<T>::type& value)
|
||||
{
|
||||
detail::sp_alloc_make<T, A> c(alloc, extent<T>::value);
|
||||
boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()),
|
||||
detail::sp_alloc_size<T>::value, boost::first_scalar(&value),
|
||||
detail::sp_alloc_size<typename remove_extent<T>::type>::value);
|
||||
return c.release();
|
||||
}
|
||||
|
||||
} /* boost */
|
||||
|
||||
#endif
|
||||
238
include/boost/smart_ptr/atomic_shared_ptr.hpp
Normal file
238
include/boost/smart_ptr/atomic_shared_ptr.hpp
Normal file
@@ -0,0 +1,238 @@
|
||||
#ifndef BOOST_SMART_PTR_ATOMIC_SHARED_PTR_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_ATOMIC_SHARED_PTR_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// atomic_shared_ptr.hpp
|
||||
//
|
||||
// Copyright 2017 Peter Dimov
|
||||
//
|
||||
// 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/smart_ptr/ for documentation.
|
||||
//
|
||||
|
||||
#include <boost/smart_ptr/shared_ptr.hpp>
|
||||
#include <boost/smart_ptr/detail/spinlock.hpp>
|
||||
#include <cstring>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
template<class T> class atomic_shared_ptr
|
||||
{
|
||||
private:
|
||||
|
||||
boost::shared_ptr<T> p_;
|
||||
|
||||
mutable boost::detail::spinlock l_;
|
||||
|
||||
atomic_shared_ptr(const atomic_shared_ptr&);
|
||||
atomic_shared_ptr& operator=(const atomic_shared_ptr&);
|
||||
|
||||
private:
|
||||
|
||||
bool compare_exchange( shared_ptr<T>& v, shared_ptr<T> w ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
l_.lock();
|
||||
|
||||
if( p_._internal_equiv( v ) )
|
||||
{
|
||||
p_.swap( w );
|
||||
|
||||
l_.unlock();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
shared_ptr<T> tmp( p_ );
|
||||
|
||||
l_.unlock();
|
||||
|
||||
tmp.swap( v );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX ) && !defined( BOOST_NO_CXX11_CONSTEXPR )
|
||||
|
||||
constexpr atomic_shared_ptr() BOOST_SP_NOEXCEPT: l_ BOOST_DETAIL_SPINLOCK_INIT
|
||||
{
|
||||
}
|
||||
|
||||
atomic_shared_ptr( shared_ptr<T> p ) BOOST_SP_NOEXCEPT
|
||||
: p_( std::move( p ) ), l_ BOOST_DETAIL_SPINLOCK_INIT
|
||||
{
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
atomic_shared_ptr() BOOST_SP_NOEXCEPT
|
||||
{
|
||||
boost::detail::spinlock init = BOOST_DETAIL_SPINLOCK_INIT;
|
||||
std::memcpy( &l_, &init, sizeof( init ) );
|
||||
}
|
||||
|
||||
atomic_shared_ptr( shared_ptr<T> p ) BOOST_SP_NOEXCEPT
|
||||
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
|
||||
: p_( std::move( p ) )
|
||||
#else
|
||||
: p_( p )
|
||||
#endif
|
||||
{
|
||||
boost::detail::spinlock init = BOOST_DETAIL_SPINLOCK_INIT;
|
||||
std::memcpy( &l_, &init, sizeof( init ) );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
atomic_shared_ptr& operator=( shared_ptr<T> r ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
boost::detail::spinlock::scoped_lock lock( l_ );
|
||||
p_.swap( r );
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR bool is_lock_free() const BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
shared_ptr<T> load() const BOOST_SP_NOEXCEPT
|
||||
{
|
||||
boost::detail::spinlock::scoped_lock lock( l_ );
|
||||
return p_;
|
||||
}
|
||||
|
||||
template<class M> shared_ptr<T> load( M ) const BOOST_SP_NOEXCEPT
|
||||
{
|
||||
boost::detail::spinlock::scoped_lock lock( l_ );
|
||||
return p_;
|
||||
}
|
||||
|
||||
operator shared_ptr<T>() const BOOST_SP_NOEXCEPT
|
||||
{
|
||||
boost::detail::spinlock::scoped_lock lock( l_ );
|
||||
return p_;
|
||||
}
|
||||
|
||||
void store( shared_ptr<T> r ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
boost::detail::spinlock::scoped_lock lock( l_ );
|
||||
p_.swap( r );
|
||||
}
|
||||
|
||||
template<class M> void store( shared_ptr<T> r, M ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
boost::detail::spinlock::scoped_lock lock( l_ );
|
||||
p_.swap( r );
|
||||
}
|
||||
|
||||
shared_ptr<T> exchange( shared_ptr<T> r ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
{
|
||||
boost::detail::spinlock::scoped_lock lock( l_ );
|
||||
p_.swap( r );
|
||||
}
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
|
||||
|
||||
return std::move( r );
|
||||
|
||||
#else
|
||||
|
||||
return r;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class M> shared_ptr<T> exchange( shared_ptr<T> r, M ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
{
|
||||
boost::detail::spinlock::scoped_lock lock( l_ );
|
||||
p_.swap( r );
|
||||
}
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
|
||||
|
||||
return std::move( r );
|
||||
|
||||
#else
|
||||
|
||||
return r;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class M> bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, M, M ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return compare_exchange( v, w );
|
||||
}
|
||||
|
||||
template<class M> bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, M ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return compare_exchange( v, w );
|
||||
}
|
||||
|
||||
bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return compare_exchange( v, w );
|
||||
}
|
||||
|
||||
template<class M> bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, M, M ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return compare_exchange( v, w );
|
||||
}
|
||||
|
||||
template<class M> bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, M ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return compare_exchange( v, w );
|
||||
}
|
||||
|
||||
bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return compare_exchange( v, w );
|
||||
}
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
|
||||
|
||||
template<class M> bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, M, M ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return compare_exchange( v, std::move( w ) );
|
||||
}
|
||||
|
||||
template<class M> bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, M ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return compare_exchange( v, std::move( w ) );
|
||||
}
|
||||
|
||||
bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return compare_exchange( v, std::move( w ) );
|
||||
}
|
||||
|
||||
template<class M> bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, M, M ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return compare_exchange( v, std::move( w ) );
|
||||
}
|
||||
|
||||
template<class M> bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, M ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return compare_exchange( v, std::move( w ) );
|
||||
}
|
||||
|
||||
bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return compare_exchange( v, std::move( w ) );
|
||||
}
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_ATOMIC_SHARED_PTR_HPP_INCLUDED
|
||||
70
include/boost/smart_ptr/bad_weak_ptr.hpp
Normal file
70
include/boost/smart_ptr/bad_weak_ptr.hpp
Normal file
@@ -0,0 +1,70 @@
|
||||
#ifndef BOOST_SMART_PTR_BAD_WEAK_PTR_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_BAD_WEAK_PTR_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// boost/smart_ptr/bad_weak_ptr.hpp
|
||||
//
|
||||
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// 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>
|
||||
#include <exception>
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
# pragma warn -8026 // Functions with excep. spec. are not expanded inline
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
// The standard library that comes with Borland C++ 5.5.1, 5.6.4
|
||||
// defines std::exception and its members as having C calling
|
||||
// convention (-pc). When the definition of bad_weak_ptr
|
||||
// is compiled with -ps, the compiler issues an error.
|
||||
// Hence, the temporary #pragma option -pc below.
|
||||
|
||||
#if defined(__BORLANDC__) && __BORLANDC__ <= 0x564
|
||||
# pragma option push -pc
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_CLANG)
|
||||
// Intel C++ on Mac defines __clang__ but doesn't support the pragma
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wweak-vtables"
|
||||
#endif
|
||||
|
||||
class bad_weak_ptr: public std::exception
|
||||
{
|
||||
public:
|
||||
|
||||
virtual char const * what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE
|
||||
{
|
||||
return "tr1::bad_weak_ptr";
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(BOOST_CLANG)
|
||||
# pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#if defined(__BORLANDC__) && __BORLANDC__ <= 0x564
|
||||
# pragma option pop
|
||||
#endif
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
# pragma warn .8026 // Functions with excep. spec. are not expanded inline
|
||||
#endif
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_BAD_WEAK_PTR_HPP_INCLUDED
|
||||
99
include/boost/smart_ptr/detail/atomic_count.hpp
Normal file
99
include/boost/smart_ptr/detail/atomic_count.hpp
Normal file
@@ -0,0 +1,99 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// boost/detail/atomic_count.hpp - thread/SMP safe reference counter
|
||||
//
|
||||
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
|
||||
// Copyright (c) 2013 Peter Dimov
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// typedef <implementation-defined> boost::detail::atomic_count;
|
||||
//
|
||||
// atomic_count a(n);
|
||||
//
|
||||
// (n is convertible to long)
|
||||
//
|
||||
// Effects: Constructs an atomic_count with an initial value of n
|
||||
//
|
||||
// a;
|
||||
//
|
||||
// Returns: (long) the current value of a
|
||||
// Memory Ordering: acquire
|
||||
//
|
||||
// ++a;
|
||||
//
|
||||
// Effects: Atomically increments the value of a
|
||||
// Returns: (long) the new value of a
|
||||
// Memory Ordering: acquire/release
|
||||
//
|
||||
// --a;
|
||||
//
|
||||
// Effects: Atomically decrements the value of a
|
||||
// Returns: (long) the new value of a
|
||||
// Memory Ordering: acquire/release
|
||||
//
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/smart_ptr/detail/sp_has_sync.hpp>
|
||||
|
||||
#if defined( BOOST_AC_DISABLE_THREADS )
|
||||
# include <boost/smart_ptr/detail/atomic_count_nt.hpp>
|
||||
|
||||
#elif defined( BOOST_AC_USE_STD_ATOMIC )
|
||||
# include <boost/smart_ptr/detail/atomic_count_std_atomic.hpp>
|
||||
|
||||
#elif defined( BOOST_AC_USE_SPINLOCK )
|
||||
# include <boost/smart_ptr/detail/atomic_count_spin.hpp>
|
||||
|
||||
#elif defined( BOOST_AC_USE_PTHREADS )
|
||||
# include <boost/smart_ptr/detail/atomic_count_pt.hpp>
|
||||
|
||||
#elif defined( BOOST_SP_DISABLE_THREADS )
|
||||
# include <boost/smart_ptr/detail/atomic_count_nt.hpp>
|
||||
|
||||
#elif defined( BOOST_SP_USE_STD_ATOMIC )
|
||||
# include <boost/smart_ptr/detail/atomic_count_std_atomic.hpp>
|
||||
|
||||
#elif defined( BOOST_SP_USE_SPINLOCK )
|
||||
# include <boost/smart_ptr/detail/atomic_count_spin.hpp>
|
||||
|
||||
#elif defined( BOOST_SP_USE_PTHREADS )
|
||||
# include <boost/smart_ptr/detail/atomic_count_pt.hpp>
|
||||
|
||||
#elif defined( BOOST_DISABLE_THREADS ) && !defined( BOOST_SP_ENABLE_THREADS ) && !defined( BOOST_DISABLE_WIN32 )
|
||||
# include <boost/smart_ptr/detail/atomic_count_nt.hpp>
|
||||
|
||||
#elif !defined( BOOST_NO_CXX11_HDR_ATOMIC )
|
||||
# include <boost/smart_ptr/detail/atomic_count_std_atomic.hpp>
|
||||
|
||||
#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) && !defined( __PATHSCALE__ )
|
||||
# include <boost/smart_ptr/detail/atomic_count_gcc_x86.hpp>
|
||||
|
||||
#elif defined( BOOST_SP_HAS_SYNC )
|
||||
# include <boost/smart_ptr/detail/atomic_count_sync.hpp>
|
||||
|
||||
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
|
||||
# include <boost/smart_ptr/detail/atomic_count_win32.hpp>
|
||||
|
||||
#elif defined(__GLIBCPP__) || defined(__GLIBCXX__)
|
||||
# include <boost/smart_ptr/detail/atomic_count_gcc.hpp>
|
||||
|
||||
#elif !defined( BOOST_HAS_THREADS )
|
||||
# include <boost/smart_ptr/detail/atomic_count_nt.hpp>
|
||||
|
||||
#else
|
||||
# include <boost/smart_ptr/detail/atomic_count_spin.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_HPP_INCLUDED
|
||||
72
include/boost/smart_ptr/detail/atomic_count_gcc.hpp
Normal file
72
include/boost/smart_ptr/detail/atomic_count_gcc.hpp
Normal file
@@ -0,0 +1,72 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// boost/detail/atomic_count_gcc.hpp
|
||||
//
|
||||
// atomic_count for GNU libstdc++ v3
|
||||
//
|
||||
// http://gcc.gnu.org/onlinedocs/porting/Thread-safety.html
|
||||
//
|
||||
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
|
||||
// Copyright (c) 2002 Lars Gullik Bjønnes <larsbj@lyx.org>
|
||||
// Copyright 2003-2005 Peter Dimov
|
||||
//
|
||||
// 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 __GNUC__ * 100 + __GNUC_MINOR__ >= 402
|
||||
# include <ext/atomicity.h>
|
||||
#else
|
||||
# include <bits/atomicity.h>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
#if defined(__GLIBCXX__) // g++ 3.4+
|
||||
|
||||
using __gnu_cxx::__atomic_add;
|
||||
using __gnu_cxx::__exchange_and_add;
|
||||
|
||||
#endif
|
||||
|
||||
class atomic_count
|
||||
{
|
||||
public:
|
||||
|
||||
explicit atomic_count( long v ) : value_( v ) {}
|
||||
|
||||
long operator++()
|
||||
{
|
||||
return __exchange_and_add( &value_, +1 ) + 1;
|
||||
}
|
||||
|
||||
long operator--()
|
||||
{
|
||||
return __exchange_and_add( &value_, -1 ) - 1;
|
||||
}
|
||||
|
||||
operator long() const
|
||||
{
|
||||
return __exchange_and_add( &value_, 0 );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
atomic_count(atomic_count const &);
|
||||
atomic_count & operator=(atomic_count const &);
|
||||
|
||||
mutable _Atomic_word value_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED
|
||||
77
include/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp
Normal file
77
include/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp
Normal file
@@ -0,0 +1,77 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// boost/detail/atomic_count_gcc_x86.hpp
|
||||
//
|
||||
// atomic_count for g++ on 486+/AMD64
|
||||
//
|
||||
// Copyright 2007 Peter Dimov
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class atomic_count
|
||||
{
|
||||
public:
|
||||
|
||||
explicit atomic_count( long v ) : value_( static_cast< int >( v ) ) {}
|
||||
|
||||
long operator++()
|
||||
{
|
||||
return atomic_exchange_and_add( &value_, +1 ) + 1;
|
||||
}
|
||||
|
||||
long operator--()
|
||||
{
|
||||
return atomic_exchange_and_add( &value_, -1 ) - 1;
|
||||
}
|
||||
|
||||
operator long() const
|
||||
{
|
||||
return atomic_exchange_and_add( &value_, 0 );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
atomic_count(atomic_count const &);
|
||||
atomic_count & operator=(atomic_count const &);
|
||||
|
||||
mutable int value_;
|
||||
|
||||
private:
|
||||
|
||||
static int atomic_exchange_and_add( int * pw, int dv )
|
||||
{
|
||||
// int r = *pw;
|
||||
// *pw += dv;
|
||||
// return r;
|
||||
|
||||
int r;
|
||||
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"lock\n\t"
|
||||
"xadd %1, %0":
|
||||
"+m"( *pw ), "=r"( r ): // outputs (%0, %1)
|
||||
"1"( dv ): // inputs (%2 == %1)
|
||||
"memory", "cc" // clobbers
|
||||
);
|
||||
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED
|
||||
59
include/boost/smart_ptr/detail/atomic_count_nt.hpp
Normal file
59
include/boost/smart_ptr/detail/atomic_count_nt.hpp
Normal file
@@ -0,0 +1,59 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_NT_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_NT_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// boost/detail/atomic_count_nt.hpp
|
||||
//
|
||||
// Trivial atomic_count for the single-threaded case
|
||||
//
|
||||
// http://gcc.gnu.org/onlinedocs/porting/Thread-safety.html
|
||||
//
|
||||
// Copyright 2013 Peter Dimov
|
||||
//
|
||||
// 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
|
||||
//
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class atomic_count
|
||||
{
|
||||
public:
|
||||
|
||||
explicit atomic_count( long v ): value_( v )
|
||||
{
|
||||
}
|
||||
|
||||
long operator++()
|
||||
{
|
||||
return ++value_;
|
||||
}
|
||||
|
||||
long operator--()
|
||||
{
|
||||
return --value_;
|
||||
}
|
||||
|
||||
operator long() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
atomic_count(atomic_count const &);
|
||||
atomic_count & operator=(atomic_count const &);
|
||||
|
||||
long value_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_NT_HPP_INCLUDED
|
||||
97
include/boost/smart_ptr/detail/atomic_count_pt.hpp
Normal file
97
include/boost/smart_ptr/detail/atomic_count_pt.hpp
Normal file
@@ -0,0 +1,97 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// boost/detail/atomic_count_pthreads.hpp
|
||||
//
|
||||
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// 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/assert.hpp>
|
||||
#include <pthread.h>
|
||||
|
||||
//
|
||||
// The generic pthread_mutex-based implementation sometimes leads to
|
||||
// inefficiencies. Example: a class with two atomic_count members
|
||||
// can get away with a single mutex.
|
||||
//
|
||||
// Users can detect this situation by checking BOOST_AC_USE_PTHREADS.
|
||||
//
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class atomic_count
|
||||
{
|
||||
private:
|
||||
|
||||
class scoped_lock
|
||||
{
|
||||
public:
|
||||
|
||||
scoped_lock(pthread_mutex_t & m): m_(m)
|
||||
{
|
||||
BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );
|
||||
}
|
||||
|
||||
~scoped_lock()
|
||||
{
|
||||
BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
pthread_mutex_t & m_;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
explicit atomic_count(long v): value_(v)
|
||||
{
|
||||
BOOST_VERIFY( pthread_mutex_init( &mutex_, 0 ) == 0 );
|
||||
}
|
||||
|
||||
~atomic_count()
|
||||
{
|
||||
BOOST_VERIFY( pthread_mutex_destroy( &mutex_ ) == 0 );
|
||||
}
|
||||
|
||||
long operator++()
|
||||
{
|
||||
scoped_lock lock(mutex_);
|
||||
return ++value_;
|
||||
}
|
||||
|
||||
long operator--()
|
||||
{
|
||||
scoped_lock lock(mutex_);
|
||||
return --value_;
|
||||
}
|
||||
|
||||
operator long() const
|
||||
{
|
||||
scoped_lock lock(mutex_);
|
||||
return value_;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
atomic_count(atomic_count const &);
|
||||
atomic_count & operator=(atomic_count const &);
|
||||
|
||||
mutable pthread_mutex_t mutex_;
|
||||
long value_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED
|
||||
59
include/boost/smart_ptr/detail/atomic_count_solaris.hpp
Normal file
59
include/boost/smart_ptr/detail/atomic_count_solaris.hpp
Normal file
@@ -0,0 +1,59 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// boost/detail/atomic_count_solaris.hpp
|
||||
// based on: boost/detail/atomic_count_win32.hpp
|
||||
//
|
||||
// Copyright (c) 2001-2005 Peter Dimov
|
||||
// Copyright (c) 2006 Michael van der Westhuizen
|
||||
//
|
||||
// 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 <atomic.h>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class atomic_count
|
||||
{
|
||||
public:
|
||||
|
||||
explicit atomic_count( uint32_t v ): value_( v )
|
||||
{
|
||||
}
|
||||
|
||||
long operator++()
|
||||
{
|
||||
return atomic_inc_32_nv( &value_ );
|
||||
}
|
||||
|
||||
long operator--()
|
||||
{
|
||||
return atomic_dec_32_nv( &value_ );
|
||||
}
|
||||
|
||||
operator uint32_t() const
|
||||
{
|
||||
return static_cast<uint32_t const volatile &>( value_ );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
atomic_count( atomic_count const & );
|
||||
atomic_count & operator=( atomic_count const & );
|
||||
|
||||
uint32_t value_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED
|
||||
62
include/boost/smart_ptr/detail/atomic_count_spin.hpp
Normal file
62
include/boost/smart_ptr/detail/atomic_count_spin.hpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SPIN_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SPIN_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// boost/detail/atomic_count_spin.hpp
|
||||
//
|
||||
// Copyright (c) 2013 Peter Dimov
|
||||
//
|
||||
// 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/smart_ptr/detail/spinlock_pool.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class atomic_count
|
||||
{
|
||||
private:
|
||||
|
||||
public:
|
||||
|
||||
explicit atomic_count( long v ): value_( v )
|
||||
{
|
||||
}
|
||||
|
||||
long operator++()
|
||||
{
|
||||
spinlock_pool<0>::scoped_lock lock( &value_ );
|
||||
return ++value_;
|
||||
}
|
||||
|
||||
long operator--()
|
||||
{
|
||||
spinlock_pool<0>::scoped_lock lock( &value_ );
|
||||
return --value_;
|
||||
}
|
||||
|
||||
operator long() const
|
||||
{
|
||||
spinlock_pool<0>::scoped_lock lock( &value_ );
|
||||
return value_;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
atomic_count(atomic_count const &);
|
||||
atomic_count & operator=(atomic_count const &);
|
||||
|
||||
long value_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SPIN_HPP_INCLUDED
|
||||
60
include/boost/smart_ptr/detail/atomic_count_std_atomic.hpp
Normal file
60
include/boost/smart_ptr/detail/atomic_count_std_atomic.hpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_STD_ATOMIC_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_STD_ATOMIC_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// boost/detail/atomic_count_std_atomic.hpp
|
||||
//
|
||||
// atomic_count for std::atomic
|
||||
//
|
||||
// Copyright 2013 Peter Dimov
|
||||
//
|
||||
// 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 <atomic>
|
||||
#include <cstdint>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class atomic_count
|
||||
{
|
||||
public:
|
||||
|
||||
explicit atomic_count( long v ): value_( static_cast< std::int_least32_t >( v ) )
|
||||
{
|
||||
}
|
||||
|
||||
long operator++()
|
||||
{
|
||||
return value_.fetch_add( 1, std::memory_order_acq_rel ) + 1;
|
||||
}
|
||||
|
||||
long operator--()
|
||||
{
|
||||
return value_.fetch_sub( 1, std::memory_order_acq_rel ) - 1;
|
||||
}
|
||||
|
||||
operator long() const
|
||||
{
|
||||
return value_.load( std::memory_order_acquire );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
atomic_count(atomic_count const &);
|
||||
atomic_count & operator=(atomic_count const &);
|
||||
|
||||
std::atomic_int_least32_t value_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_STD_ATOMIC_HPP_INCLUDED
|
||||
61
include/boost/smart_ptr/detail/atomic_count_sync.hpp
Normal file
61
include/boost/smart_ptr/detail/atomic_count_sync.hpp
Normal file
@@ -0,0 +1,61 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// boost/detail/atomic_count_sync.hpp
|
||||
//
|
||||
// atomic_count for g++ 4.1+
|
||||
//
|
||||
// http://gcc.gnu.org/onlinedocs/gcc-4.1.1/gcc/Atomic-Builtins.html
|
||||
//
|
||||
// Copyright 2007 Peter Dimov
|
||||
//
|
||||
// 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( __ia64__ ) && defined( __INTEL_COMPILER )
|
||||
# include <ia64intrin.h>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class atomic_count
|
||||
{
|
||||
public:
|
||||
|
||||
explicit atomic_count( long v ) : value_( v ) {}
|
||||
|
||||
long operator++()
|
||||
{
|
||||
return __sync_add_and_fetch( &value_, 1 );
|
||||
}
|
||||
|
||||
long operator--()
|
||||
{
|
||||
return __sync_add_and_fetch( &value_, -1 );
|
||||
}
|
||||
|
||||
operator long() const
|
||||
{
|
||||
return __sync_fetch_and_add( &value_, 0 );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
atomic_count(atomic_count const &);
|
||||
atomic_count & operator=(atomic_count const &);
|
||||
|
||||
mutable long value_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED
|
||||
63
include/boost/smart_ptr/detail/atomic_count_win32.hpp
Normal file
63
include/boost/smart_ptr/detail/atomic_count_win32.hpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// boost/detail/atomic_count_win32.hpp
|
||||
//
|
||||
// Copyright (c) 2001-2005 Peter Dimov
|
||||
//
|
||||
// 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/smart_ptr/detail/sp_interlocked.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class atomic_count
|
||||
{
|
||||
public:
|
||||
|
||||
explicit atomic_count( long v ): value_( v )
|
||||
{
|
||||
}
|
||||
|
||||
long operator++()
|
||||
{
|
||||
return BOOST_SP_INTERLOCKED_INCREMENT( &value_ );
|
||||
}
|
||||
|
||||
long operator--()
|
||||
{
|
||||
return BOOST_SP_INTERLOCKED_DECREMENT( &value_ );
|
||||
}
|
||||
|
||||
operator long() const
|
||||
{
|
||||
return static_cast<long const volatile &>( value_ );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
atomic_count( atomic_count const & );
|
||||
atomic_count & operator=( atomic_count const & );
|
||||
|
||||
long value_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED
|
||||
39
include/boost/smart_ptr/detail/lightweight_mutex.hpp
Normal file
39
include/boost/smart_ptr/detail/lightweight_mutex.hpp
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// boost/detail/lightweight_mutex.hpp - lightweight mutex
|
||||
//
|
||||
// Copyright (c) 2002, 2003 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
// typedef <unspecified> boost::detail::lightweight_mutex;
|
||||
//
|
||||
// boost::detail::lightweight_mutex is a header-only implementation of
|
||||
// a subset of the Mutex concept requirements:
|
||||
//
|
||||
// http://www.boost.org/doc/html/threads/concepts.html#threads.concepts.Mutex
|
||||
//
|
||||
// It maps to a CRITICAL_SECTION on Windows or a pthread_mutex on POSIX.
|
||||
//
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_MUTEX )
|
||||
# include <boost/smart_ptr/detail/lwm_std_mutex.hpp>
|
||||
#elif defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
|
||||
# include <boost/smart_ptr/detail/lwm_win32_cs.hpp>
|
||||
#else
|
||||
# include <boost/smart_ptr/detail/lwm_pthreads.hpp>
|
||||
#endif
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED
|
||||
148
include/boost/smart_ptr/detail/local_counted_base.hpp
Normal file
148
include/boost/smart_ptr/detail/local_counted_base.hpp
Normal file
@@ -0,0 +1,148 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_LOCAL_COUNTED_BASE_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_LOCAL_COUNTED_BASE_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
// detail/local_counted_base.hpp
|
||||
//
|
||||
// Copyright 2017 Peter Dimov
|
||||
//
|
||||
// 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/smart_ptr/ for documentation.
|
||||
|
||||
#include <boost/smart_ptr/detail/shared_count.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <utility>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE local_counted_base
|
||||
{
|
||||
private:
|
||||
|
||||
local_counted_base & operator= ( local_counted_base const & );
|
||||
|
||||
private:
|
||||
|
||||
// not 'int' or 'unsigned' to avoid aliasing and enable optimizations
|
||||
enum count_type { min_ = 0, initial_ = 1, max_ = 2147483647 };
|
||||
|
||||
count_type local_use_count_;
|
||||
|
||||
public:
|
||||
|
||||
BOOST_CONSTEXPR local_counted_base() BOOST_SP_NOEXCEPT: local_use_count_( initial_ )
|
||||
{
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR local_counted_base( local_counted_base const & ) BOOST_SP_NOEXCEPT: local_use_count_( initial_ )
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~local_counted_base() /*BOOST_SP_NOEXCEPT*/
|
||||
{
|
||||
}
|
||||
|
||||
virtual void local_cb_destroy() BOOST_SP_NOEXCEPT = 0;
|
||||
|
||||
virtual boost::detail::shared_count local_cb_get_shared_count() const BOOST_SP_NOEXCEPT = 0;
|
||||
|
||||
void add_ref() BOOST_SP_NOEXCEPT
|
||||
{
|
||||
#if !defined(__NVCC__)
|
||||
#if defined( __has_builtin )
|
||||
# if __has_builtin( __builtin_assume )
|
||||
|
||||
__builtin_assume( local_use_count_ >= 1 );
|
||||
|
||||
# endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
local_use_count_ = static_cast<count_type>( local_use_count_ + 1 );
|
||||
}
|
||||
|
||||
void release() BOOST_SP_NOEXCEPT
|
||||
{
|
||||
local_use_count_ = static_cast<count_type>( local_use_count_ - 1 );
|
||||
|
||||
if( local_use_count_ == 0 )
|
||||
{
|
||||
local_cb_destroy();
|
||||
}
|
||||
}
|
||||
|
||||
long local_use_count() const BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return local_use_count_;
|
||||
}
|
||||
};
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE local_counted_impl: public local_counted_base
|
||||
{
|
||||
private:
|
||||
|
||||
local_counted_impl( local_counted_impl const & );
|
||||
|
||||
private:
|
||||
|
||||
shared_count pn_;
|
||||
|
||||
public:
|
||||
|
||||
explicit local_counted_impl( shared_count const& pn ) BOOST_SP_NOEXCEPT: pn_( pn )
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
|
||||
|
||||
explicit local_counted_impl( shared_count && pn ) BOOST_SP_NOEXCEPT: pn_( std::move(pn) )
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
virtual void local_cb_destroy() BOOST_SP_NOEXCEPT BOOST_OVERRIDE
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
virtual boost::detail::shared_count local_cb_get_shared_count() const BOOST_SP_NOEXCEPT BOOST_OVERRIDE
|
||||
{
|
||||
return pn_;
|
||||
}
|
||||
};
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE local_counted_impl_em: public local_counted_base
|
||||
{
|
||||
public:
|
||||
|
||||
shared_count pn_;
|
||||
|
||||
virtual void local_cb_destroy() BOOST_SP_NOEXCEPT BOOST_OVERRIDE
|
||||
{
|
||||
shared_count().swap( pn_ );
|
||||
}
|
||||
|
||||
virtual boost::detail::shared_count local_cb_get_shared_count() const BOOST_SP_NOEXCEPT BOOST_OVERRIDE
|
||||
{
|
||||
return pn_;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_LOCAL_COUNTED_BASE_HPP_INCLUDED
|
||||
91
include/boost/smart_ptr/detail/local_sp_deleter.hpp
Normal file
91
include/boost/smart_ptr/detail/local_sp_deleter.hpp
Normal file
@@ -0,0 +1,91 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_LOCAL_SP_DELETER_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_LOCAL_SP_DELETER_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
// detail/local_sp_deleter.hpp
|
||||
//
|
||||
// Copyright 2017 Peter Dimov
|
||||
//
|
||||
// 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/smart_ptr/ for documentation.
|
||||
|
||||
#include <boost/smart_ptr/detail/local_counted_base.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<class D> class local_sp_deleter: public local_counted_impl_em
|
||||
{
|
||||
private:
|
||||
|
||||
D d_;
|
||||
|
||||
public:
|
||||
|
||||
local_sp_deleter(): d_()
|
||||
{
|
||||
}
|
||||
|
||||
explicit local_sp_deleter( D const& d ) BOOST_SP_NOEXCEPT: d_( d )
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
|
||||
|
||||
explicit local_sp_deleter( D&& d ) BOOST_SP_NOEXCEPT: d_( std::move(d) )
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
D& deleter() BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return d_;
|
||||
}
|
||||
|
||||
template<class Y> void operator()( Y* p ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
d_( p );
|
||||
}
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_NULLPTR )
|
||||
|
||||
void operator()( boost::detail::sp_nullptr_t p ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
d_( p );
|
||||
}
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
template<> class local_sp_deleter<void>
|
||||
{
|
||||
};
|
||||
|
||||
template<class D> D * get_local_deleter( local_sp_deleter<D> * p ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return &p->deleter();
|
||||
}
|
||||
|
||||
inline void * get_local_deleter( local_sp_deleter<void> * /*p*/ ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_LOCAL_SP_DELETER_HPP_INCLUDED
|
||||
87
include/boost/smart_ptr/detail/lwm_pthreads.hpp
Normal file
87
include/boost/smart_ptr/detail/lwm_pthreads.hpp
Normal file
@@ -0,0 +1,87 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_LWM_PTHREADS_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_LWM_PTHREADS_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// boost/detail/lwm_pthreads.hpp
|
||||
//
|
||||
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// 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/assert.hpp>
|
||||
#include <pthread.h>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class lightweight_mutex
|
||||
{
|
||||
private:
|
||||
|
||||
pthread_mutex_t m_;
|
||||
|
||||
lightweight_mutex(lightweight_mutex const &);
|
||||
lightweight_mutex & operator=(lightweight_mutex const &);
|
||||
|
||||
public:
|
||||
|
||||
lightweight_mutex()
|
||||
{
|
||||
|
||||
// HPUX 10.20 / DCE has a nonstandard pthread_mutex_init
|
||||
|
||||
#if defined(__hpux) && defined(_DECTHREADS_)
|
||||
BOOST_VERIFY( pthread_mutex_init( &m_, pthread_mutexattr_default ) == 0 );
|
||||
#else
|
||||
BOOST_VERIFY( pthread_mutex_init( &m_, 0 ) == 0 );
|
||||
#endif
|
||||
}
|
||||
|
||||
~lightweight_mutex()
|
||||
{
|
||||
BOOST_VERIFY( pthread_mutex_destroy( &m_ ) == 0 );
|
||||
}
|
||||
|
||||
class scoped_lock;
|
||||
friend class scoped_lock;
|
||||
|
||||
class scoped_lock
|
||||
{
|
||||
private:
|
||||
|
||||
pthread_mutex_t & m_;
|
||||
|
||||
scoped_lock(scoped_lock const &);
|
||||
scoped_lock & operator=(scoped_lock const &);
|
||||
|
||||
public:
|
||||
|
||||
scoped_lock(lightweight_mutex & m): m_(m.m_)
|
||||
{
|
||||
BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );
|
||||
}
|
||||
|
||||
~scoped_lock()
|
||||
{
|
||||
BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_LWM_PTHREADS_HPP_INCLUDED
|
||||
62
include/boost/smart_ptr/detail/lwm_std_mutex.hpp
Normal file
62
include/boost/smart_ptr/detail/lwm_std_mutex.hpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_LWM_STD_MUTEX_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_LWM_STD_MUTEX_HPP_INCLUDED
|
||||
|
||||
// Copyright 2020 Peter Dimov
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <mutex>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class lightweight_mutex
|
||||
{
|
||||
private:
|
||||
|
||||
std::mutex m_;
|
||||
|
||||
lightweight_mutex(lightweight_mutex const &);
|
||||
lightweight_mutex & operator=(lightweight_mutex const &);
|
||||
|
||||
public:
|
||||
|
||||
lightweight_mutex()
|
||||
{
|
||||
}
|
||||
|
||||
class scoped_lock;
|
||||
friend class scoped_lock;
|
||||
|
||||
class scoped_lock
|
||||
{
|
||||
private:
|
||||
|
||||
std::mutex & m_;
|
||||
|
||||
scoped_lock(scoped_lock const &);
|
||||
scoped_lock & operator=(scoped_lock const &);
|
||||
|
||||
public:
|
||||
|
||||
scoped_lock( lightweight_mutex & m ): m_( m.m_ )
|
||||
{
|
||||
m_.lock();
|
||||
}
|
||||
|
||||
~scoped_lock()
|
||||
{
|
||||
m_.unlock();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_LWM_STD_MUTEX_HPP_INCLUDED
|
||||
123
include/boost/smart_ptr/detail/lwm_win32_cs.hpp
Normal file
123
include/boost/smart_ptr/detail/lwm_win32_cs.hpp
Normal file
@@ -0,0 +1,123 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_LWM_WIN32_CS_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_LWM_WIN32_CS_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// boost/detail/lwm_win32_cs.hpp
|
||||
//
|
||||
// Copyright (c) 2002, 2003 Peter Dimov
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
#ifdef BOOST_USE_WINDOWS_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#else
|
||||
|
||||
struct _RTL_CRITICAL_SECTION;
|
||||
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
#ifndef BOOST_USE_WINDOWS_H
|
||||
|
||||
struct critical_section
|
||||
{
|
||||
struct critical_section_debug * DebugInfo;
|
||||
long LockCount;
|
||||
long RecursionCount;
|
||||
void * OwningThread;
|
||||
void * LockSemaphore;
|
||||
#if defined(_WIN64)
|
||||
unsigned __int64 SpinCount;
|
||||
#else
|
||||
unsigned long SpinCount;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(::_RTL_CRITICAL_SECTION *);
|
||||
extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(::_RTL_CRITICAL_SECTION *);
|
||||
extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(::_RTL_CRITICAL_SECTION *);
|
||||
extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(::_RTL_CRITICAL_SECTION *);
|
||||
|
||||
typedef ::_RTL_CRITICAL_SECTION rtl_critical_section;
|
||||
|
||||
#else // #ifndef BOOST_USE_WINDOWS_H
|
||||
|
||||
typedef ::CRITICAL_SECTION critical_section;
|
||||
|
||||
using ::InitializeCriticalSection;
|
||||
using ::EnterCriticalSection;
|
||||
using ::LeaveCriticalSection;
|
||||
using ::DeleteCriticalSection;
|
||||
|
||||
typedef ::CRITICAL_SECTION rtl_critical_section;
|
||||
|
||||
#endif // #ifndef BOOST_USE_WINDOWS_H
|
||||
|
||||
class lightweight_mutex
|
||||
{
|
||||
private:
|
||||
|
||||
critical_section cs_;
|
||||
|
||||
lightweight_mutex(lightweight_mutex const &);
|
||||
lightweight_mutex & operator=(lightweight_mutex const &);
|
||||
|
||||
public:
|
||||
|
||||
lightweight_mutex()
|
||||
{
|
||||
boost::detail::InitializeCriticalSection(reinterpret_cast< rtl_critical_section* >(&cs_));
|
||||
}
|
||||
|
||||
~lightweight_mutex()
|
||||
{
|
||||
boost::detail::DeleteCriticalSection(reinterpret_cast< rtl_critical_section* >(&cs_));
|
||||
}
|
||||
|
||||
class scoped_lock;
|
||||
friend class scoped_lock;
|
||||
|
||||
class scoped_lock
|
||||
{
|
||||
private:
|
||||
|
||||
lightweight_mutex & m_;
|
||||
|
||||
scoped_lock(scoped_lock const &);
|
||||
scoped_lock & operator=(scoped_lock const &);
|
||||
|
||||
public:
|
||||
|
||||
explicit scoped_lock(lightweight_mutex & m): m_(m)
|
||||
{
|
||||
boost::detail::EnterCriticalSection(reinterpret_cast< rtl_critical_section* >(&m_.cs_));
|
||||
}
|
||||
|
||||
~scoped_lock()
|
||||
{
|
||||
boost::detail::LeaveCriticalSection(reinterpret_cast< rtl_critical_section* >(&m_.cs_));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_LWM_WIN32_CS_HPP_INCLUDED
|
||||
64
include/boost/smart_ptr/detail/operator_bool.hpp
Normal file
64
include/boost/smart_ptr/detail/operator_bool.hpp
Normal file
@@ -0,0 +1,64 @@
|
||||
// This header intentionally has no include guards.
|
||||
//
|
||||
// Copyright (c) 2001-2009, 2012 Peter Dimov
|
||||
//
|
||||
// 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_EXPLICIT_CONVERSION_OPERATORS ) && !defined( BOOST_NO_CXX11_NULLPTR )\
|
||||
&& !(defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5130))
|
||||
|
||||
explicit operator bool () const BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return px != 0;
|
||||
}
|
||||
|
||||
#elif ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, < 0x570) ) || defined(__CINT__)
|
||||
|
||||
operator bool () const BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return px != 0;
|
||||
}
|
||||
|
||||
#elif defined( _MANAGED )
|
||||
|
||||
static void unspecified_bool( this_type*** )
|
||||
{
|
||||
}
|
||||
|
||||
typedef void (*unspecified_bool_type)( this_type*** );
|
||||
|
||||
operator unspecified_bool_type() const BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return px == 0? 0: unspecified_bool;
|
||||
}
|
||||
|
||||
#elif \
|
||||
( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \
|
||||
( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) || \
|
||||
( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590) )
|
||||
|
||||
typedef element_type * (this_type::*unspecified_bool_type)() const;
|
||||
|
||||
operator unspecified_bool_type() const BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return px == 0? 0: &this_type::get;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
typedef element_type * this_type::*unspecified_bool_type;
|
||||
|
||||
operator unspecified_bool_type() const BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return px == 0? 0: &this_type::px;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// operator! is redundant, but some compilers need it
|
||||
bool operator! () const BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return px == 0;
|
||||
}
|
||||
199
include/boost/smart_ptr/detail/quick_allocator.hpp
Normal file
199
include/boost/smart_ptr/detail/quick_allocator.hpp
Normal file
@@ -0,0 +1,199 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// detail/quick_allocator.hpp
|
||||
//
|
||||
// Copyright (c) 2003 David Abrahams
|
||||
// Copyright (c) 2003 Peter Dimov
|
||||
//
|
||||
// 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>
|
||||
|
||||
#include <boost/smart_ptr/detail/lightweight_mutex.hpp>
|
||||
#include <boost/type_traits/type_with_alignment.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
|
||||
#include <new> // ::operator new, ::operator delete
|
||||
#include <cstddef> // std::size_t
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<unsigned size, unsigned align_> union freeblock
|
||||
{
|
||||
typedef typename boost::type_with_alignment<align_>::type aligner_type;
|
||||
aligner_type aligner;
|
||||
char bytes[size];
|
||||
freeblock * next;
|
||||
};
|
||||
|
||||
template<unsigned size, unsigned align_> struct allocator_impl
|
||||
{
|
||||
typedef freeblock<size, align_> block;
|
||||
|
||||
// It may seem odd to use such small pages.
|
||||
//
|
||||
// However, on a typical Windows implementation that uses
|
||||
// the OS allocator, "normal size" pages interact with the
|
||||
// "ordinary" operator new, slowing it down dramatically.
|
||||
//
|
||||
// 512 byte pages are handled by the small object allocator,
|
||||
// and don't interfere with ::new.
|
||||
//
|
||||
// The other alternative is to use much bigger pages (1M.)
|
||||
//
|
||||
// It is surprisingly easy to hit pathological behavior by
|
||||
// varying the page size. g++ 2.96 on Red Hat Linux 7.2,
|
||||
// for example, passionately dislikes 496. 512 seems OK.
|
||||
|
||||
#if defined(BOOST_QA_PAGE_SIZE)
|
||||
|
||||
enum { items_per_page = BOOST_QA_PAGE_SIZE / size };
|
||||
|
||||
#else
|
||||
|
||||
enum { items_per_page = 512 / size }; // 1048560 / size
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_HAS_THREADS
|
||||
|
||||
static lightweight_mutex & mutex()
|
||||
{
|
||||
static freeblock< sizeof( lightweight_mutex ), boost::alignment_of< lightweight_mutex >::value > fbm;
|
||||
static lightweight_mutex * pm = new( &fbm ) lightweight_mutex;
|
||||
return *pm;
|
||||
}
|
||||
|
||||
static lightweight_mutex * mutex_init;
|
||||
|
||||
#endif
|
||||
|
||||
static block * free;
|
||||
static block * page;
|
||||
static unsigned last;
|
||||
|
||||
static inline void * alloc()
|
||||
{
|
||||
#ifdef BOOST_HAS_THREADS
|
||||
lightweight_mutex::scoped_lock lock( mutex() );
|
||||
#endif
|
||||
if(block * x = free)
|
||||
{
|
||||
free = x->next;
|
||||
return x;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(last == items_per_page)
|
||||
{
|
||||
// "Listen to me carefully: there is no memory leak"
|
||||
// -- Scott Meyers, Eff C++ 2nd Ed Item 10
|
||||
page = ::new block[items_per_page];
|
||||
last = 0;
|
||||
}
|
||||
|
||||
return &page[last++];
|
||||
}
|
||||
}
|
||||
|
||||
static inline void * alloc(std::size_t n)
|
||||
{
|
||||
if(n != size) // class-specific new called for a derived object
|
||||
{
|
||||
return ::operator new(n);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef BOOST_HAS_THREADS
|
||||
lightweight_mutex::scoped_lock lock( mutex() );
|
||||
#endif
|
||||
if(block * x = free)
|
||||
{
|
||||
free = x->next;
|
||||
return x;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(last == items_per_page)
|
||||
{
|
||||
page = ::new block[items_per_page];
|
||||
last = 0;
|
||||
}
|
||||
|
||||
return &page[last++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void dealloc(void * pv)
|
||||
{
|
||||
if(pv != 0) // 18.4.1.1/13
|
||||
{
|
||||
#ifdef BOOST_HAS_THREADS
|
||||
lightweight_mutex::scoped_lock lock( mutex() );
|
||||
#endif
|
||||
block * pb = static_cast<block *>(pv);
|
||||
pb->next = free;
|
||||
free = pb;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void dealloc(void * pv, std::size_t n)
|
||||
{
|
||||
if(n != size) // class-specific delete called for a derived object
|
||||
{
|
||||
::operator delete(pv);
|
||||
}
|
||||
else if(pv != 0) // 18.4.1.1/13
|
||||
{
|
||||
#ifdef BOOST_HAS_THREADS
|
||||
lightweight_mutex::scoped_lock lock( mutex() );
|
||||
#endif
|
||||
block * pb = static_cast<block *>(pv);
|
||||
pb->next = free;
|
||||
free = pb;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef BOOST_HAS_THREADS
|
||||
|
||||
template<unsigned size, unsigned align_>
|
||||
lightweight_mutex * allocator_impl<size, align_>::mutex_init = &allocator_impl<size, align_>::mutex();
|
||||
|
||||
#endif
|
||||
|
||||
template<unsigned size, unsigned align_>
|
||||
freeblock<size, align_> * allocator_impl<size, align_>::free = 0;
|
||||
|
||||
template<unsigned size, unsigned align_>
|
||||
freeblock<size, align_> * allocator_impl<size, align_>::page = 0;
|
||||
|
||||
template<unsigned size, unsigned align_>
|
||||
unsigned allocator_impl<size, align_>::last = allocator_impl<size, align_>::items_per_page;
|
||||
|
||||
template<class T>
|
||||
struct quick_allocator: public allocator_impl< sizeof(T), boost::alignment_of<T>::value >
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED
|
||||
668
include/boost/smart_ptr/detail/shared_count.hpp
Normal file
668
include/boost/smart_ptr/detail/shared_count.hpp
Normal file
@@ -0,0 +1,668 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// detail/shared_count.hpp
|
||||
//
|
||||
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
|
||||
// Copyright 2004-2005 Peter Dimov
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
# pragma warn -8027 // Functions containing try are not expanded inline
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/checked_delete.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/smart_ptr/bad_weak_ptr.hpp>
|
||||
#include <boost/smart_ptr/detail/sp_counted_base.hpp>
|
||||
#include <boost/smart_ptr/detail/sp_counted_impl.hpp>
|
||||
#include <boost/smart_ptr/detail/sp_disable_deprecated.hpp>
|
||||
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
|
||||
#include <boost/config/workaround.hpp>
|
||||
// In order to avoid circular dependencies with Boost.TR1
|
||||
// we make sure that our include of <memory> doesn't try to
|
||||
// pull in the TR1 headers: that's why we use this header
|
||||
// rather than including <memory> directly:
|
||||
#include <boost/config/no_tr1/memory.hpp> // std::auto_ptr
|
||||
#include <functional> // std::less
|
||||
|
||||
#ifdef BOOST_NO_EXCEPTIONS
|
||||
# include <new> // std::bad_alloc
|
||||
#endif
|
||||
|
||||
#include <boost/core/addressof.hpp>
|
||||
|
||||
#if defined( BOOST_SP_DISABLE_DEPRECATED )
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace movelib
|
||||
{
|
||||
|
||||
template< class T, class D > class unique_ptr;
|
||||
|
||||
} // namespace movelib
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
|
||||
int const shared_count_id = 0x2C35F101;
|
||||
int const weak_count_id = 0x298C38A4;
|
||||
|
||||
#endif
|
||||
|
||||
struct sp_nothrow_tag {};
|
||||
|
||||
template< class D > struct sp_inplace_tag
|
||||
{
|
||||
};
|
||||
|
||||
template< class T > class sp_reference_wrapper
|
||||
{
|
||||
public:
|
||||
|
||||
explicit sp_reference_wrapper( T & t): t_( boost::addressof( t ) )
|
||||
{
|
||||
}
|
||||
|
||||
template< class Y > void operator()( Y * p ) const
|
||||
{
|
||||
(*t_)( p );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
T * t_;
|
||||
};
|
||||
|
||||
template< class D > struct sp_convert_reference
|
||||
{
|
||||
typedef D type;
|
||||
};
|
||||
|
||||
template< class D > struct sp_convert_reference< D& >
|
||||
{
|
||||
typedef sp_reference_wrapper< D > type;
|
||||
};
|
||||
|
||||
class weak_count;
|
||||
|
||||
class shared_count
|
||||
{
|
||||
private:
|
||||
|
||||
sp_counted_base * pi_;
|
||||
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
int id_;
|
||||
#endif
|
||||
|
||||
friend class weak_count;
|
||||
|
||||
public:
|
||||
|
||||
BOOST_CONSTEXPR shared_count() BOOST_SP_NOEXCEPT: pi_(0)
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
, id_(shared_count_id)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR explicit shared_count( sp_counted_base * pi ) BOOST_SP_NOEXCEPT: pi_( pi )
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
, id_(shared_count_id)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
template<class Y> explicit shared_count( Y * p ): pi_( 0 )
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
, id_(shared_count_id)
|
||||
#endif
|
||||
{
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
|
||||
try
|
||||
{
|
||||
pi_ = new sp_counted_impl_p<Y>( p );
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
boost::checked_delete( p );
|
||||
throw;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
pi_ = new sp_counted_impl_p<Y>( p );
|
||||
|
||||
if( pi_ == 0 )
|
||||
{
|
||||
boost::checked_delete( p );
|
||||
boost::throw_exception( std::bad_alloc() );
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1200 )
|
||||
template<class Y, class D> shared_count( Y * p, D d ): pi_(0)
|
||||
#else
|
||||
template<class P, class D> shared_count( P p, D d ): pi_(0)
|
||||
#endif
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
, id_(shared_count_id)
|
||||
#endif
|
||||
{
|
||||
#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1200 )
|
||||
typedef Y* P;
|
||||
#endif
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
|
||||
try
|
||||
{
|
||||
pi_ = new sp_counted_impl_pd<P, D>(p, d);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
d(p); // delete p
|
||||
throw;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
pi_ = new sp_counted_impl_pd<P, D>(p, d);
|
||||
|
||||
if(pi_ == 0)
|
||||
{
|
||||
d(p); // delete p
|
||||
boost::throw_exception(std::bad_alloc());
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
|
||||
|
||||
template< class P, class D > shared_count( P p, sp_inplace_tag<D> ): pi_( 0 )
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
, id_(shared_count_id)
|
||||
#endif
|
||||
{
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
|
||||
try
|
||||
{
|
||||
pi_ = new sp_counted_impl_pd< P, D >( p );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
D::operator_fn( p ); // delete p
|
||||
throw;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
pi_ = new sp_counted_impl_pd< P, D >( p );
|
||||
|
||||
if( pi_ == 0 )
|
||||
{
|
||||
D::operator_fn( p ); // delete p
|
||||
boost::throw_exception( std::bad_alloc() );
|
||||
}
|
||||
|
||||
#endif // #ifndef BOOST_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
#endif // !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
|
||||
|
||||
template<class P, class D, class A> shared_count( P p, D d, A a ): pi_( 0 )
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
, id_(shared_count_id)
|
||||
#endif
|
||||
{
|
||||
typedef sp_counted_impl_pda<P, D, A> impl_type;
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
|
||||
|
||||
typedef typename std::allocator_traits<A>::template rebind_alloc< impl_type > A2;
|
||||
|
||||
#else
|
||||
|
||||
typedef typename A::template rebind< impl_type >::other A2;
|
||||
|
||||
#endif
|
||||
|
||||
A2 a2( a );
|
||||
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
|
||||
try
|
||||
{
|
||||
pi_ = a2.allocate( 1 );
|
||||
::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
d( p );
|
||||
|
||||
if( pi_ != 0 )
|
||||
{
|
||||
a2.deallocate( static_cast< impl_type* >( pi_ ), 1 );
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
pi_ = a2.allocate( 1 );
|
||||
|
||||
if( pi_ != 0 )
|
||||
{
|
||||
::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
|
||||
}
|
||||
else
|
||||
{
|
||||
d( p );
|
||||
boost::throw_exception( std::bad_alloc() );
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
|
||||
|
||||
template< class P, class D, class A > shared_count( P p, sp_inplace_tag< D >, A a ): pi_( 0 )
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
, id_(shared_count_id)
|
||||
#endif
|
||||
{
|
||||
typedef sp_counted_impl_pda< P, D, A > impl_type;
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
|
||||
|
||||
typedef typename std::allocator_traits<A>::template rebind_alloc< impl_type > A2;
|
||||
|
||||
#else
|
||||
|
||||
typedef typename A::template rebind< impl_type >::other A2;
|
||||
|
||||
#endif
|
||||
|
||||
A2 a2( a );
|
||||
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
|
||||
try
|
||||
{
|
||||
pi_ = a2.allocate( 1 );
|
||||
::new( static_cast< void* >( pi_ ) ) impl_type( p, a );
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
D::operator_fn( p );
|
||||
|
||||
if( pi_ != 0 )
|
||||
{
|
||||
a2.deallocate( static_cast< impl_type* >( pi_ ), 1 );
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
pi_ = a2.allocate( 1 );
|
||||
|
||||
if( pi_ != 0 )
|
||||
{
|
||||
::new( static_cast< void* >( pi_ ) ) impl_type( p, a );
|
||||
}
|
||||
else
|
||||
{
|
||||
D::operator_fn( p );
|
||||
boost::throw_exception( std::bad_alloc() );
|
||||
}
|
||||
|
||||
#endif // #ifndef BOOST_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
#endif // !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
|
||||
|
||||
#ifndef BOOST_NO_AUTO_PTR
|
||||
|
||||
// auto_ptr<Y> is special cased to provide the strong guarantee
|
||||
|
||||
template<class Y>
|
||||
explicit shared_count( std::auto_ptr<Y> & r ): pi_( new sp_counted_impl_p<Y>( r.get() ) )
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
, id_(shared_count_id)
|
||||
#endif
|
||||
{
|
||||
#ifdef BOOST_NO_EXCEPTIONS
|
||||
|
||||
if( pi_ == 0 )
|
||||
{
|
||||
boost::throw_exception(std::bad_alloc());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
r.release();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_SMART_PTR )
|
||||
|
||||
template<class Y, class D>
|
||||
explicit shared_count( std::unique_ptr<Y, D> & r ): pi_( 0 )
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
, id_(shared_count_id)
|
||||
#endif
|
||||
{
|
||||
typedef typename sp_convert_reference<D>::type D2;
|
||||
|
||||
D2 d2( r.get_deleter() );
|
||||
pi_ = new sp_counted_impl_pd< typename std::unique_ptr<Y, D>::pointer, D2 >( r.get(), d2 );
|
||||
|
||||
#ifdef BOOST_NO_EXCEPTIONS
|
||||
|
||||
if( pi_ == 0 )
|
||||
{
|
||||
boost::throw_exception( std::bad_alloc() );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
r.release();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template<class Y, class D>
|
||||
explicit shared_count( boost::movelib::unique_ptr<Y, D> & r ): pi_( 0 )
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
, id_(shared_count_id)
|
||||
#endif
|
||||
{
|
||||
typedef typename sp_convert_reference<D>::type D2;
|
||||
|
||||
D2 d2( r.get_deleter() );
|
||||
pi_ = new sp_counted_impl_pd< typename boost::movelib::unique_ptr<Y, D>::pointer, D2 >( r.get(), d2 );
|
||||
|
||||
#ifdef BOOST_NO_EXCEPTIONS
|
||||
|
||||
if( pi_ == 0 )
|
||||
{
|
||||
boost::throw_exception( std::bad_alloc() );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
r.release();
|
||||
}
|
||||
|
||||
~shared_count() /*BOOST_SP_NOEXCEPT*/
|
||||
{
|
||||
if( pi_ != 0 ) pi_->release();
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
id_ = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
shared_count(shared_count const & r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
, id_(shared_count_id)
|
||||
#endif
|
||||
{
|
||||
if( pi_ != 0 ) pi_->add_ref_copy();
|
||||
}
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
|
||||
|
||||
shared_count(shared_count && r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
, id_(shared_count_id)
|
||||
#endif
|
||||
{
|
||||
r.pi_ = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0
|
||||
shared_count( weak_count const & r, sp_nothrow_tag ) BOOST_SP_NOEXCEPT; // constructs an empty *this when r.use_count() == 0
|
||||
|
||||
shared_count & operator= (shared_count const & r) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
sp_counted_base * tmp = r.pi_;
|
||||
|
||||
if( tmp != pi_ )
|
||||
{
|
||||
if( tmp != 0 ) tmp->add_ref_copy();
|
||||
if( pi_ != 0 ) pi_->release();
|
||||
pi_ = tmp;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(shared_count & r) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
sp_counted_base * tmp = r.pi_;
|
||||
r.pi_ = pi_;
|
||||
pi_ = tmp;
|
||||
}
|
||||
|
||||
long use_count() const BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return pi_ != 0? pi_->use_count(): 0;
|
||||
}
|
||||
|
||||
bool unique() const BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return use_count() == 1;
|
||||
}
|
||||
|
||||
bool empty() const BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return pi_ == 0;
|
||||
}
|
||||
|
||||
friend inline bool operator==(shared_count const & a, shared_count const & b) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return a.pi_ == b.pi_;
|
||||
}
|
||||
|
||||
friend inline bool operator<(shared_count const & a, shared_count const & b) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return std::less<sp_counted_base *>()( a.pi_, b.pi_ );
|
||||
}
|
||||
|
||||
void * get_deleter( sp_typeinfo_ const & ti ) const BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return pi_? pi_->get_deleter( ti ): 0;
|
||||
}
|
||||
|
||||
void * get_local_deleter( sp_typeinfo_ const & ti ) const BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return pi_? pi_->get_local_deleter( ti ): 0;
|
||||
}
|
||||
|
||||
void * get_untyped_deleter() const BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return pi_? pi_->get_untyped_deleter(): 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class weak_count
|
||||
{
|
||||
private:
|
||||
|
||||
sp_counted_base * pi_;
|
||||
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
int id_;
|
||||
#endif
|
||||
|
||||
friend class shared_count;
|
||||
|
||||
public:
|
||||
|
||||
BOOST_CONSTEXPR weak_count() BOOST_SP_NOEXCEPT: pi_(0)
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
, id_(weak_count_id)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
weak_count(shared_count const & r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
, id_(weak_count_id)
|
||||
#endif
|
||||
{
|
||||
if(pi_ != 0) pi_->weak_add_ref();
|
||||
}
|
||||
|
||||
weak_count(weak_count const & r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
, id_(weak_count_id)
|
||||
#endif
|
||||
{
|
||||
if(pi_ != 0) pi_->weak_add_ref();
|
||||
}
|
||||
|
||||
// Move support
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
|
||||
|
||||
weak_count(weak_count && r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
, id_(weak_count_id)
|
||||
#endif
|
||||
{
|
||||
r.pi_ = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
~weak_count() /*BOOST_SP_NOEXCEPT*/
|
||||
{
|
||||
if(pi_ != 0) pi_->weak_release();
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
id_ = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
weak_count & operator= (shared_count const & r) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
sp_counted_base * tmp = r.pi_;
|
||||
|
||||
if( tmp != pi_ )
|
||||
{
|
||||
if(tmp != 0) tmp->weak_add_ref();
|
||||
if(pi_ != 0) pi_->weak_release();
|
||||
pi_ = tmp;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
weak_count & operator= (weak_count const & r) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
sp_counted_base * tmp = r.pi_;
|
||||
|
||||
if( tmp != pi_ )
|
||||
{
|
||||
if(tmp != 0) tmp->weak_add_ref();
|
||||
if(pi_ != 0) pi_->weak_release();
|
||||
pi_ = tmp;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(weak_count & r) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
sp_counted_base * tmp = r.pi_;
|
||||
r.pi_ = pi_;
|
||||
pi_ = tmp;
|
||||
}
|
||||
|
||||
long use_count() const BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return pi_ != 0? pi_->use_count(): 0;
|
||||
}
|
||||
|
||||
bool empty() const BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return pi_ == 0;
|
||||
}
|
||||
|
||||
friend inline bool operator==(weak_count const & a, weak_count const & b) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return a.pi_ == b.pi_;
|
||||
}
|
||||
|
||||
friend inline bool operator<(weak_count const & a, weak_count const & b) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return std::less<sp_counted_base *>()(a.pi_, b.pi_);
|
||||
}
|
||||
};
|
||||
|
||||
inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ )
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
, id_(shared_count_id)
|
||||
#endif
|
||||
{
|
||||
if( pi_ == 0 || !pi_->add_ref_lock() )
|
||||
{
|
||||
boost::throw_exception( boost::bad_weak_ptr() );
|
||||
}
|
||||
}
|
||||
|
||||
inline shared_count::shared_count( weak_count const & r, sp_nothrow_tag ) BOOST_SP_NOEXCEPT: pi_( r.pi_ )
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
, id_(shared_count_id)
|
||||
#endif
|
||||
{
|
||||
if( pi_ != 0 && !pi_->add_ref_lock() )
|
||||
{
|
||||
pi_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#if defined( BOOST_SP_DISABLE_DEPRECATED )
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
# pragma warn .8027 // Functions containing try are not expanded inline
|
||||
#endif
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED
|
||||
92
include/boost/smart_ptr/detail/sp_convertible.hpp
Normal file
92
include/boost/smart_ptr/detail/sp_convertible.hpp
Normal file
@@ -0,0 +1,92 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
// detail/sp_convertible.hpp
|
||||
//
|
||||
// Copyright 2008 Peter Dimov
|
||||
//
|
||||
// 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>
|
||||
#include <cstddef>
|
||||
|
||||
#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( BOOST_NO_SFINAE )
|
||||
# define BOOST_SP_NO_SP_CONVERTIBLE
|
||||
#endif
|
||||
|
||||
#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ < 303 )
|
||||
# define BOOST_SP_NO_SP_CONVERTIBLE
|
||||
#endif
|
||||
|
||||
#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x630 )
|
||||
# define BOOST_SP_NO_SP_CONVERTIBLE
|
||||
#endif
|
||||
|
||||
#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template< class Y, class T > struct sp_convertible
|
||||
{
|
||||
typedef char (&yes) [1];
|
||||
typedef char (&no) [2];
|
||||
|
||||
static yes f( T* );
|
||||
static no f( ... );
|
||||
|
||||
enum _vt { value = sizeof( (f)( static_cast<Y*>(0) ) ) == sizeof(yes) };
|
||||
};
|
||||
|
||||
template< class Y, class T > struct sp_convertible< Y, T[] >
|
||||
{
|
||||
enum _vt { value = false };
|
||||
};
|
||||
|
||||
template< class Y, class T > struct sp_convertible< Y[], T[] >
|
||||
{
|
||||
enum _vt { value = sp_convertible< Y[1], T[1] >::value };
|
||||
};
|
||||
|
||||
template< class Y, std::size_t N, class T > struct sp_convertible< Y[N], T[] >
|
||||
{
|
||||
enum _vt { value = sp_convertible< Y[1], T[1] >::value };
|
||||
};
|
||||
|
||||
struct sp_empty
|
||||
{
|
||||
};
|
||||
|
||||
template< bool > struct sp_enable_if_convertible_impl;
|
||||
|
||||
template<> struct sp_enable_if_convertible_impl<true>
|
||||
{
|
||||
typedef sp_empty type;
|
||||
};
|
||||
|
||||
template<> struct sp_enable_if_convertible_impl<false>
|
||||
{
|
||||
};
|
||||
|
||||
template< class Y, class T > struct sp_enable_if_convertible: public sp_enable_if_convertible_impl< sp_convertible< Y, T >::value >
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // !defined( BOOST_SP_NO_SP_CONVERTIBLE )
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED
|
||||
96
include/boost/smart_ptr/detail/sp_counted_base.hpp
Normal file
96
include/boost/smart_ptr/detail/sp_counted_base.hpp
Normal file
@@ -0,0 +1,96 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// detail/sp_counted_base.hpp
|
||||
//
|
||||
// Copyright 2005-2013 Peter Dimov
|
||||
//
|
||||
// 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>
|
||||
#include <boost/smart_ptr/detail/sp_has_sync.hpp>
|
||||
|
||||
#if !defined( __c2__ ) && defined( __clang__ ) && defined( __has_extension )
|
||||
# if __has_extension( __c_atomic__ )
|
||||
# define BOOST_SP_HAS_CLANG_C11_ATOMICS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined( BOOST_SP_DISABLE_THREADS )
|
||||
# include <boost/smart_ptr/detail/sp_counted_base_nt.hpp>
|
||||
|
||||
#elif defined( BOOST_SP_USE_STD_ATOMIC )
|
||||
# include <boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp>
|
||||
|
||||
#elif defined( BOOST_SP_USE_SPINLOCK )
|
||||
# include <boost/smart_ptr/detail/sp_counted_base_spin.hpp>
|
||||
|
||||
#elif defined( BOOST_SP_USE_PTHREADS )
|
||||
# include <boost/smart_ptr/detail/sp_counted_base_pt.hpp>
|
||||
|
||||
#elif defined( BOOST_DISABLE_THREADS ) && !defined( BOOST_SP_ENABLE_THREADS ) && !defined( BOOST_DISABLE_WIN32 )
|
||||
# include <boost/smart_ptr/detail/sp_counted_base_nt.hpp>
|
||||
|
||||
#elif defined( BOOST_SP_HAS_CLANG_C11_ATOMICS )
|
||||
# include <boost/smart_ptr/detail/sp_counted_base_clang.hpp>
|
||||
|
||||
#elif !defined( BOOST_NO_CXX11_HDR_ATOMIC )
|
||||
# include <boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp>
|
||||
|
||||
#elif defined( __SNC__ )
|
||||
# include <boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp>
|
||||
|
||||
#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) && !defined(__PATHSCALE__)
|
||||
# include <boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp>
|
||||
|
||||
#elif defined(__HP_aCC) && defined(__ia64)
|
||||
# include <boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp>
|
||||
|
||||
#elif defined( __GNUC__ ) && defined( __ia64__ ) && !defined( __INTEL_COMPILER ) && !defined(__PATHSCALE__)
|
||||
# include <boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp>
|
||||
|
||||
#elif defined( __IBMCPP__ ) && defined( __powerpc )
|
||||
# include <boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp>
|
||||
|
||||
#elif defined( __MWERKS__ ) && defined( __POWERPC__ )
|
||||
# include <boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp>
|
||||
|
||||
#elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc ) ) && !defined(__PATHSCALE__) && !defined( _AIX )
|
||||
# include <boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp>
|
||||
|
||||
#elif defined( __GNUC__ ) && ( defined( __mips__ ) || defined( _mips ) ) && !defined(__PATHSCALE__) && !defined( __mips16 )
|
||||
# include <boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp>
|
||||
|
||||
#elif defined( BOOST_SP_HAS_SYNC )
|
||||
# include <boost/smart_ptr/detail/sp_counted_base_sync.hpp>
|
||||
|
||||
#elif defined(__GNUC__) && ( defined( __sparcv9 ) || ( defined( __sparcv8 ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 402 ) ) )
|
||||
# include <boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp>
|
||||
|
||||
#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined(__CYGWIN__)
|
||||
# include <boost/smart_ptr/detail/sp_counted_base_w32.hpp>
|
||||
|
||||
#elif defined( _AIX )
|
||||
# include <boost/smart_ptr/detail/sp_counted_base_aix.hpp>
|
||||
|
||||
#elif !defined( BOOST_HAS_THREADS )
|
||||
# include <boost/smart_ptr/detail/sp_counted_base_nt.hpp>
|
||||
|
||||
#else
|
||||
# include <boost/smart_ptr/detail/sp_counted_base_spin.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
#undef BOOST_SP_HAS_CLANG_C11_ATOMICS
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED
|
||||
153
include/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp
Normal file
153
include/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp
Normal file
@@ -0,0 +1,153 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// detail/sp_counted_base_acc_ia64.hpp - aC++ on HP-UX IA64
|
||||
//
|
||||
// Copyright 2007 Baruch Zilber
|
||||
// Copyright 2007 Boris Gubenko
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
//
|
||||
// Lock-free algorithm by Alexander Terekhov
|
||||
//
|
||||
|
||||
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <machine/sys/inline.h>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
inline void atomic_increment( int * pw )
|
||||
{
|
||||
// ++*pw;
|
||||
|
||||
_Asm_fetchadd(_FASZ_W, _SEM_REL, pw, +1, _LDHINT_NONE);
|
||||
}
|
||||
|
||||
inline int atomic_decrement( int * pw )
|
||||
{
|
||||
// return --*pw;
|
||||
|
||||
int r = static_cast<int>(_Asm_fetchadd(_FASZ_W, _SEM_REL, pw, -1, _LDHINT_NONE));
|
||||
if (1 == r)
|
||||
{
|
||||
_Asm_mf();
|
||||
}
|
||||
|
||||
return r - 1;
|
||||
}
|
||||
|
||||
inline int atomic_conditional_increment( int * pw )
|
||||
{
|
||||
// if( *pw != 0 ) ++*pw;
|
||||
// return *pw;
|
||||
|
||||
int v = *pw;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (0 == v)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
_Asm_mov_to_ar(_AREG_CCV,
|
||||
v,
|
||||
(_UP_CALL_FENCE | _UP_SYS_FENCE | _DOWN_CALL_FENCE | _DOWN_SYS_FENCE));
|
||||
int r = static_cast<int>(_Asm_cmpxchg(_SZ_W, _SEM_ACQ, pw, v + 1, _LDHINT_NONE));
|
||||
if (r == v)
|
||||
{
|
||||
return r + 1;
|
||||
}
|
||||
|
||||
v = r;
|
||||
}
|
||||
}
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE sp_counted_base
|
||||
{
|
||||
private:
|
||||
|
||||
sp_counted_base( sp_counted_base const & );
|
||||
sp_counted_base & operator= ( sp_counted_base const & );
|
||||
|
||||
int use_count_; // #shared
|
||||
int weak_count_; // #weak + (#shared != 0)
|
||||
|
||||
public:
|
||||
|
||||
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~sp_counted_base() // nothrow
|
||||
{
|
||||
}
|
||||
|
||||
// dispose() is called when use_count_ drops to zero, to release
|
||||
// the resources managed by *this.
|
||||
|
||||
virtual void dispose() = 0; // nothrow
|
||||
|
||||
// destroy() is called when weak_count_ drops to zero.
|
||||
|
||||
virtual void destroy() // nothrow
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
|
||||
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
|
||||
virtual void * get_untyped_deleter() = 0;
|
||||
|
||||
void add_ref_copy()
|
||||
{
|
||||
atomic_increment( &use_count_ );
|
||||
}
|
||||
|
||||
bool add_ref_lock() // true on success
|
||||
{
|
||||
return atomic_conditional_increment( &use_count_ ) != 0;
|
||||
}
|
||||
|
||||
void release() // nothrow
|
||||
{
|
||||
if( atomic_decrement( &use_count_ ) == 0 )
|
||||
{
|
||||
dispose();
|
||||
weak_release();
|
||||
}
|
||||
}
|
||||
|
||||
void weak_add_ref() // nothrow
|
||||
{
|
||||
atomic_increment( &weak_count_ );
|
||||
}
|
||||
|
||||
void weak_release() // nothrow
|
||||
{
|
||||
if( atomic_decrement( &weak_count_ ) == 0 )
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
|
||||
long use_count() const // nothrow
|
||||
{
|
||||
return static_cast<int const volatile &>( use_count_ ); // TODO use ld.acq here
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED
|
||||
145
include/boost/smart_ptr/detail/sp_counted_base_aix.hpp
Normal file
145
include/boost/smart_ptr/detail/sp_counted_base_aix.hpp
Normal file
@@ -0,0 +1,145 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_AIX_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_AIX_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// detail/sp_counted_base_aix.hpp
|
||||
// based on: detail/sp_counted_base_w32.hpp
|
||||
//
|
||||
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
|
||||
// Copyright 2004-2005 Peter Dimov
|
||||
// Copyright 2006 Michael van der Westhuizen
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
//
|
||||
// Lock-free algorithm by Alexander Terekhov
|
||||
//
|
||||
// Thanks to Ben Hitchings for the #weak + (#shared != 0)
|
||||
// formulation
|
||||
//
|
||||
|
||||
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <builtins.h>
|
||||
#include <sys/atomic_op.h>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
inline void atomic_increment( int32_t* pw )
|
||||
{
|
||||
// ++*pw;
|
||||
|
||||
fetch_and_add( pw, 1 );
|
||||
}
|
||||
|
||||
inline int32_t atomic_decrement( int32_t * pw )
|
||||
{
|
||||
// return --*pw;
|
||||
|
||||
int32_t originalValue;
|
||||
|
||||
__lwsync();
|
||||
originalValue = fetch_and_add( pw, -1 );
|
||||
__isync();
|
||||
|
||||
return (originalValue - 1);
|
||||
}
|
||||
|
||||
inline int32_t atomic_conditional_increment( int32_t * pw )
|
||||
{
|
||||
// if( *pw != 0 ) ++*pw;
|
||||
// return *pw;
|
||||
|
||||
int32_t tmp = fetch_and_add( pw, 0 );
|
||||
for( ;; )
|
||||
{
|
||||
if( tmp == 0 ) return 0;
|
||||
if( compare_and_swap( pw, &tmp, tmp + 1 ) ) return (tmp + 1);
|
||||
}
|
||||
}
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE sp_counted_base
|
||||
{
|
||||
private:
|
||||
|
||||
sp_counted_base( sp_counted_base const & );
|
||||
sp_counted_base & operator= ( sp_counted_base const & );
|
||||
|
||||
int32_t use_count_; // #shared
|
||||
int32_t weak_count_; // #weak + (#shared != 0)
|
||||
|
||||
public:
|
||||
|
||||
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~sp_counted_base() // nothrow
|
||||
{
|
||||
}
|
||||
|
||||
// dispose() is called when use_count_ drops to zero, to release
|
||||
// the resources managed by *this.
|
||||
|
||||
virtual void dispose() = 0; // nothrow
|
||||
|
||||
// destroy() is called when weak_count_ drops to zero.
|
||||
|
||||
virtual void destroy() // nothrow
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
|
||||
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
|
||||
virtual void * get_untyped_deleter() = 0;
|
||||
|
||||
void add_ref_copy()
|
||||
{
|
||||
atomic_increment( &use_count_ );
|
||||
}
|
||||
|
||||
bool add_ref_lock() // true on success
|
||||
{
|
||||
return atomic_conditional_increment( &use_count_ ) != 0;
|
||||
}
|
||||
|
||||
void release() // nothrow
|
||||
{
|
||||
if( atomic_decrement( &use_count_ ) == 0 )
|
||||
{
|
||||
dispose();
|
||||
weak_release();
|
||||
}
|
||||
}
|
||||
|
||||
void weak_add_ref() // nothrow
|
||||
{
|
||||
atomic_increment( &weak_count_ );
|
||||
}
|
||||
|
||||
void weak_release() // nothrow
|
||||
{
|
||||
if( atomic_decrement( &weak_count_ ) == 0 )
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
|
||||
long use_count() const // nothrow
|
||||
{
|
||||
return fetch_and_add( const_cast<int32_t*>(&use_count_), 0 );
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_AIX_HPP_INCLUDED
|
||||
161
include/boost/smart_ptr/detail/sp_counted_base_clang.hpp
Normal file
161
include/boost/smart_ptr/detail/sp_counted_base_clang.hpp
Normal file
@@ -0,0 +1,161 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CLANG_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CLANG_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
// detail/sp_counted_base_clang.hpp - __c11 clang intrinsics
|
||||
//
|
||||
// Copyright (c) 2007, 2013, 2015 Peter Dimov
|
||||
//
|
||||
// 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/smart_ptr/detail/sp_typeinfo_.hpp>
|
||||
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic push
|
||||
#endif
|
||||
|
||||
#if defined(__clang__) && defined(__has_warning)
|
||||
# if __has_warning( "-Wc11-extensions" )
|
||||
# pragma clang diagnostic ignored "-Wc11-extensions"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
typedef _Atomic( boost::int_least32_t ) atomic_int_least32_t;
|
||||
|
||||
inline void atomic_increment( atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
__c11_atomic_fetch_add( pw, 1, __ATOMIC_RELAXED );
|
||||
}
|
||||
|
||||
inline boost::int_least32_t atomic_decrement( atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return __c11_atomic_fetch_sub( pw, 1, __ATOMIC_ACQ_REL );
|
||||
}
|
||||
|
||||
inline boost::int_least32_t atomic_conditional_increment( atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
// long r = *pw;
|
||||
// if( r != 0 ) ++*pw;
|
||||
// return r;
|
||||
|
||||
boost::int_least32_t r = __c11_atomic_load( pw, __ATOMIC_RELAXED );
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
if( r == 0 )
|
||||
{
|
||||
return r;
|
||||
}
|
||||
|
||||
if( __c11_atomic_compare_exchange_weak( pw, &r, r + 1, __ATOMIC_RELAXED, __ATOMIC_RELAXED ) )
|
||||
{
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic ignored "-Wweak-vtables"
|
||||
#endif
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE sp_counted_base
|
||||
{
|
||||
private:
|
||||
|
||||
sp_counted_base( sp_counted_base const & );
|
||||
sp_counted_base & operator= ( sp_counted_base const & );
|
||||
|
||||
atomic_int_least32_t use_count_; // #shared
|
||||
atomic_int_least32_t weak_count_; // #weak + (#shared != 0)
|
||||
|
||||
public:
|
||||
|
||||
sp_counted_base() BOOST_SP_NOEXCEPT
|
||||
{
|
||||
__c11_atomic_init( &use_count_, 1 );
|
||||
__c11_atomic_init( &weak_count_, 1 );
|
||||
}
|
||||
|
||||
virtual ~sp_counted_base() /*BOOST_SP_NOEXCEPT*/
|
||||
{
|
||||
}
|
||||
|
||||
// dispose() is called when use_count_ drops to zero, to release
|
||||
// the resources managed by *this.
|
||||
|
||||
virtual void dispose() BOOST_SP_NOEXCEPT = 0; // nothrow
|
||||
|
||||
// destroy() is called when weak_count_ drops to zero.
|
||||
|
||||
virtual void destroy() BOOST_SP_NOEXCEPT // nothrow
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
virtual void * get_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT = 0;
|
||||
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT = 0;
|
||||
virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT = 0;
|
||||
|
||||
void add_ref_copy() BOOST_SP_NOEXCEPT
|
||||
{
|
||||
atomic_increment( &use_count_ );
|
||||
}
|
||||
|
||||
bool add_ref_lock() BOOST_SP_NOEXCEPT // true on success
|
||||
{
|
||||
return atomic_conditional_increment( &use_count_ ) != 0;
|
||||
}
|
||||
|
||||
void release() BOOST_SP_NOEXCEPT
|
||||
{
|
||||
if( atomic_decrement( &use_count_ ) == 1 )
|
||||
{
|
||||
dispose();
|
||||
weak_release();
|
||||
}
|
||||
}
|
||||
|
||||
void weak_add_ref() BOOST_SP_NOEXCEPT
|
||||
{
|
||||
atomic_increment( &weak_count_ );
|
||||
}
|
||||
|
||||
void weak_release() BOOST_SP_NOEXCEPT
|
||||
{
|
||||
if( atomic_decrement( &weak_count_ ) == 1 )
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
|
||||
long use_count() const BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return __c11_atomic_load( const_cast< atomic_int_least32_t* >( &use_count_ ), __ATOMIC_ACQUIRE );
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CLANG_HPP_INCLUDED
|
||||
173
include/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp
Normal file
173
include/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp
Normal file
@@ -0,0 +1,173 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// detail/sp_counted_base_cw_ppc.hpp - CodeWarrior on PowerPC
|
||||
//
|
||||
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
|
||||
// Copyright 2004-2005 Peter Dimov
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
//
|
||||
// Lock-free algorithm by Alexander Terekhov
|
||||
//
|
||||
// Thanks to Ben Hitchings for the #weak + (#shared != 0)
|
||||
// formulation
|
||||
//
|
||||
|
||||
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
inline void atomic_increment( register long * pw )
|
||||
{
|
||||
register int a;
|
||||
|
||||
asm
|
||||
{
|
||||
loop:
|
||||
|
||||
lwarx a, 0, pw
|
||||
addi a, a, 1
|
||||
stwcx. a, 0, pw
|
||||
bne- loop
|
||||
}
|
||||
}
|
||||
|
||||
inline long atomic_decrement( register long * pw )
|
||||
{
|
||||
register int a;
|
||||
|
||||
asm
|
||||
{
|
||||
sync
|
||||
|
||||
loop:
|
||||
|
||||
lwarx a, 0, pw
|
||||
addi a, a, -1
|
||||
stwcx. a, 0, pw
|
||||
bne- loop
|
||||
|
||||
isync
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
inline long atomic_conditional_increment( register long * pw )
|
||||
{
|
||||
register int a;
|
||||
|
||||
asm
|
||||
{
|
||||
loop:
|
||||
|
||||
lwarx a, 0, pw
|
||||
cmpwi a, 0
|
||||
beq store
|
||||
|
||||
addi a, a, 1
|
||||
|
||||
store:
|
||||
|
||||
stwcx. a, 0, pw
|
||||
bne- loop
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE sp_counted_base
|
||||
{
|
||||
private:
|
||||
|
||||
sp_counted_base( sp_counted_base const & );
|
||||
sp_counted_base & operator= ( sp_counted_base const & );
|
||||
|
||||
long use_count_; // #shared
|
||||
long weak_count_; // #weak + (#shared != 0)
|
||||
|
||||
public:
|
||||
|
||||
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~sp_counted_base() // nothrow
|
||||
{
|
||||
}
|
||||
|
||||
// dispose() is called when use_count_ drops to zero, to release
|
||||
// the resources managed by *this.
|
||||
|
||||
virtual void dispose() = 0; // nothrow
|
||||
|
||||
// destroy() is called when weak_count_ drops to zero.
|
||||
|
||||
virtual void destroy() // nothrow
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
|
||||
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
|
||||
virtual void * get_untyped_deleter() = 0;
|
||||
|
||||
void add_ref_copy()
|
||||
{
|
||||
atomic_increment( &use_count_ );
|
||||
}
|
||||
|
||||
bool add_ref_lock() // true on success
|
||||
{
|
||||
return atomic_conditional_increment( &use_count_ ) != 0;
|
||||
}
|
||||
|
||||
void release() // nothrow
|
||||
{
|
||||
if( atomic_decrement( &use_count_ ) == 0 )
|
||||
{
|
||||
dispose();
|
||||
weak_release();
|
||||
}
|
||||
}
|
||||
|
||||
void weak_add_ref() // nothrow
|
||||
{
|
||||
atomic_increment( &weak_count_ );
|
||||
}
|
||||
|
||||
void weak_release() // nothrow
|
||||
{
|
||||
if( atomic_decrement( &weak_count_ ) == 0 )
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
|
||||
long use_count() const // nothrow
|
||||
{
|
||||
return static_cast<long const volatile &>( use_count_ );
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED
|
||||
161
include/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp
Normal file
161
include/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp
Normal file
@@ -0,0 +1,161 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// detail/sp_counted_base_cw_x86.hpp - CodeWarrion on 486+
|
||||
//
|
||||
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
|
||||
// Copyright 2004-2005 Peter Dimov
|
||||
// Copyright 2005 Rene Rivera
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
//
|
||||
// Lock-free algorithm by Alexander Terekhov
|
||||
//
|
||||
// Thanks to Ben Hitchings for the #weak + (#shared != 0)
|
||||
// formulation
|
||||
//
|
||||
|
||||
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
inline int atomic_exchange_and_add( int * pw, int dv )
|
||||
{
|
||||
// int r = *pw;
|
||||
// *pw += dv;
|
||||
// return r;
|
||||
|
||||
asm
|
||||
{
|
||||
mov esi, [pw]
|
||||
mov eax, dv
|
||||
lock xadd dword ptr [esi], eax
|
||||
}
|
||||
}
|
||||
|
||||
inline void atomic_increment( int * pw )
|
||||
{
|
||||
//atomic_exchange_and_add( pw, 1 );
|
||||
|
||||
asm
|
||||
{
|
||||
mov esi, [pw]
|
||||
lock inc dword ptr [esi]
|
||||
}
|
||||
}
|
||||
|
||||
inline int atomic_conditional_increment( int * pw )
|
||||
{
|
||||
// int rv = *pw;
|
||||
// if( rv != 0 ) ++*pw;
|
||||
// return rv;
|
||||
|
||||
asm
|
||||
{
|
||||
mov esi, [pw]
|
||||
mov eax, dword ptr [esi]
|
||||
L0:
|
||||
test eax, eax
|
||||
je L1
|
||||
mov ebx, eax
|
||||
inc ebx
|
||||
lock cmpxchg dword ptr [esi], ebx
|
||||
jne L0
|
||||
L1:
|
||||
}
|
||||
}
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE sp_counted_base
|
||||
{
|
||||
private:
|
||||
|
||||
sp_counted_base( sp_counted_base const & );
|
||||
sp_counted_base & operator= ( sp_counted_base const & );
|
||||
|
||||
int use_count_; // #shared
|
||||
int weak_count_; // #weak + (#shared != 0)
|
||||
|
||||
public:
|
||||
|
||||
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~sp_counted_base() // nothrow
|
||||
{
|
||||
}
|
||||
|
||||
// dispose() is called when use_count_ drops to zero, to release
|
||||
// the resources managed by *this.
|
||||
|
||||
virtual void dispose() = 0; // nothrow
|
||||
|
||||
// destroy() is called when weak_count_ drops to zero.
|
||||
|
||||
virtual void destroy() // nothrow
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
|
||||
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
|
||||
virtual void * get_untyped_deleter() = 0;
|
||||
|
||||
void add_ref_copy()
|
||||
{
|
||||
atomic_increment( &use_count_ );
|
||||
}
|
||||
|
||||
bool add_ref_lock() // true on success
|
||||
{
|
||||
return atomic_conditional_increment( &use_count_ ) != 0;
|
||||
}
|
||||
|
||||
void release() // nothrow
|
||||
{
|
||||
if( atomic_exchange_and_add( &use_count_, -1 ) == 1 )
|
||||
{
|
||||
dispose();
|
||||
weak_release();
|
||||
}
|
||||
}
|
||||
|
||||
void weak_add_ref() // nothrow
|
||||
{
|
||||
atomic_increment( &weak_count_ );
|
||||
}
|
||||
|
||||
void weak_release() // nothrow
|
||||
{
|
||||
if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 )
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
|
||||
long use_count() const // nothrow
|
||||
{
|
||||
return static_cast<int const volatile &>( use_count_ );
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED
|
||||
160
include/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp
Normal file
160
include/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp
Normal file
@@ -0,0 +1,160 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// detail/sp_counted_base_gcc_ia64.hpp - g++ on IA64
|
||||
//
|
||||
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
|
||||
// Copyright 2004-2006 Peter Dimov
|
||||
// Copyright 2005 Ben Hutchings
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
//
|
||||
// Lock-free algorithm by Alexander Terekhov
|
||||
//
|
||||
|
||||
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
inline void atomic_increment( int * pw )
|
||||
{
|
||||
// ++*pw;
|
||||
|
||||
int tmp;
|
||||
|
||||
// No barrier is required here but fetchadd always has an acquire or
|
||||
// release barrier associated with it. We choose release as it should be
|
||||
// cheaper.
|
||||
__asm__ ("fetchadd4.rel %0=%1,1" :
|
||||
"=r"(tmp), "=m"(*pw) :
|
||||
"m"( *pw ));
|
||||
}
|
||||
|
||||
inline int atomic_decrement( int * pw )
|
||||
{
|
||||
// return --*pw;
|
||||
|
||||
int rv;
|
||||
|
||||
__asm__ (" fetchadd4.rel %0=%1,-1 ;; \n"
|
||||
" cmp.eq p7,p0=1,%0 ;; \n"
|
||||
"(p7) ld4.acq %0=%1 " :
|
||||
"=&r"(rv), "=m"(*pw) :
|
||||
"m"( *pw ) :
|
||||
"p7");
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
inline int atomic_conditional_increment( int * pw )
|
||||
{
|
||||
// if( *pw != 0 ) ++*pw;
|
||||
// return *pw;
|
||||
|
||||
int rv, tmp, tmp2;
|
||||
|
||||
__asm__ ("0: ld4 %0=%3 ;; \n"
|
||||
" cmp.eq p7,p0=0,%0 ;; \n"
|
||||
"(p7) br.cond.spnt 1f \n"
|
||||
" mov ar.ccv=%0 \n"
|
||||
" add %1=1,%0 ;; \n"
|
||||
" cmpxchg4.acq %2=%3,%1,ar.ccv ;; \n"
|
||||
" cmp.ne p7,p0=%0,%2 ;; \n"
|
||||
"(p7) br.cond.spnt 0b \n"
|
||||
" mov %0=%1 ;; \n"
|
||||
"1:" :
|
||||
"=&r"(rv), "=&r"(tmp), "=&r"(tmp2), "=m"(*pw) :
|
||||
"m"( *pw ) :
|
||||
"ar.ccv", "p7");
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE sp_counted_base
|
||||
{
|
||||
private:
|
||||
|
||||
sp_counted_base( sp_counted_base const & );
|
||||
sp_counted_base & operator= ( sp_counted_base const & );
|
||||
|
||||
int use_count_; // #shared
|
||||
int weak_count_; // #weak + (#shared != 0)
|
||||
|
||||
public:
|
||||
|
||||
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~sp_counted_base() // nothrow
|
||||
{
|
||||
}
|
||||
|
||||
// dispose() is called when use_count_ drops to zero, to release
|
||||
// the resources managed by *this.
|
||||
|
||||
virtual void dispose() = 0; // nothrow
|
||||
|
||||
// destroy() is called when weak_count_ drops to zero.
|
||||
|
||||
virtual void destroy() // nothrow
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
|
||||
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
|
||||
virtual void * get_untyped_deleter() = 0;
|
||||
|
||||
void add_ref_copy()
|
||||
{
|
||||
atomic_increment( &use_count_ );
|
||||
}
|
||||
|
||||
bool add_ref_lock() // true on success
|
||||
{
|
||||
return atomic_conditional_increment( &use_count_ ) != 0;
|
||||
}
|
||||
|
||||
void release() // nothrow
|
||||
{
|
||||
if( atomic_decrement( &use_count_ ) == 0 )
|
||||
{
|
||||
dispose();
|
||||
weak_release();
|
||||
}
|
||||
}
|
||||
|
||||
void weak_add_ref() // nothrow
|
||||
{
|
||||
atomic_increment( &weak_count_ );
|
||||
}
|
||||
|
||||
void weak_release() // nothrow
|
||||
{
|
||||
if( atomic_decrement( &weak_count_ ) == 0 )
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
|
||||
long use_count() const // nothrow
|
||||
{
|
||||
return static_cast<int const volatile &>( use_count_ ); // TODO use ld.acq here
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED
|
||||
190
include/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp
Normal file
190
include/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp
Normal file
@@ -0,0 +1,190 @@
|
||||
#ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_MIPS_HPP_INCLUDED
|
||||
#define BOOST_DETAIL_SP_COUNTED_BASE_GCC_MIPS_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// detail/sp_counted_base_gcc_mips.hpp - g++ on MIPS
|
||||
//
|
||||
// Copyright (c) 2009, Spirent Communications, Inc.
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
//
|
||||
// Lock-free algorithm by Alexander Terekhov
|
||||
//
|
||||
|
||||
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
inline void atomic_increment( int * pw )
|
||||
{
|
||||
// ++*pw;
|
||||
|
||||
int tmp;
|
||||
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"0:\n\t"
|
||||
".set push\n\t"
|
||||
#if !defined(__mips_isa_rev) || (__mips_isa_rev < 6)
|
||||
".set mips2\n\t"
|
||||
#endif
|
||||
"ll %0, %1\n\t"
|
||||
"addiu %0, 1\n\t"
|
||||
"sc %0, %1\n\t"
|
||||
".set pop\n\t"
|
||||
"beqz %0, 0b":
|
||||
"=&r"( tmp ), "=m"( *pw ):
|
||||
"m"( *pw )
|
||||
);
|
||||
}
|
||||
|
||||
inline int atomic_decrement( int * pw )
|
||||
{
|
||||
// return --*pw;
|
||||
|
||||
int rv, tmp;
|
||||
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"0:\n\t"
|
||||
".set push\n\t"
|
||||
#if !defined(__mips_isa_rev) || (__mips_isa_rev < 6)
|
||||
".set mips2\n\t"
|
||||
#endif
|
||||
"ll %1, %2\n\t"
|
||||
"addiu %0, %1, -1\n\t"
|
||||
"sc %0, %2\n\t"
|
||||
".set pop\n\t"
|
||||
"beqz %0, 0b\n\t"
|
||||
"addiu %0, %1, -1":
|
||||
"=&r"( rv ), "=&r"( tmp ), "=m"( *pw ):
|
||||
"m"( *pw ):
|
||||
"memory"
|
||||
);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
inline int atomic_conditional_increment( int * pw )
|
||||
{
|
||||
// if( *pw != 0 ) ++*pw;
|
||||
// return *pw;
|
||||
|
||||
int rv, tmp;
|
||||
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"0:\n\t"
|
||||
".set push\n\t"
|
||||
#if !defined(__mips_isa_rev) || (__mips_isa_rev < 6)
|
||||
".set mips2\n\t"
|
||||
#endif
|
||||
"ll %0, %2\n\t"
|
||||
"beqz %0, 1f\n\t"
|
||||
"addiu %1, %0, 1\n\t"
|
||||
"sc %1, %2\n\t"
|
||||
".set pop\n\t"
|
||||
"beqz %1, 0b\n\t"
|
||||
"addiu %0, %0, 1\n\t"
|
||||
"1:":
|
||||
"=&r"( rv ), "=&r"( tmp ), "=m"( *pw ):
|
||||
"m"( *pw ):
|
||||
"memory"
|
||||
);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE sp_counted_base
|
||||
{
|
||||
private:
|
||||
|
||||
sp_counted_base( sp_counted_base const & );
|
||||
sp_counted_base & operator= ( sp_counted_base const & );
|
||||
|
||||
int use_count_; // #shared
|
||||
int weak_count_; // #weak + (#shared != 0)
|
||||
|
||||
public:
|
||||
|
||||
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~sp_counted_base() // nothrow
|
||||
{
|
||||
}
|
||||
|
||||
// dispose() is called when use_count_ drops to zero, to release
|
||||
// the resources managed by *this.
|
||||
|
||||
virtual void dispose() = 0; // nothrow
|
||||
|
||||
// destroy() is called when weak_count_ drops to zero.
|
||||
|
||||
virtual void destroy() // nothrow
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
|
||||
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
|
||||
virtual void * get_untyped_deleter() = 0;
|
||||
|
||||
void add_ref_copy()
|
||||
{
|
||||
atomic_increment( &use_count_ );
|
||||
}
|
||||
|
||||
bool add_ref_lock() // true on success
|
||||
{
|
||||
return atomic_conditional_increment( &use_count_ ) != 0;
|
||||
}
|
||||
|
||||
void release() // nothrow
|
||||
{
|
||||
if( atomic_decrement( &use_count_ ) == 0 )
|
||||
{
|
||||
dispose();
|
||||
weak_release();
|
||||
}
|
||||
}
|
||||
|
||||
void weak_add_ref() // nothrow
|
||||
{
|
||||
atomic_increment( &weak_count_ );
|
||||
}
|
||||
|
||||
void weak_release() // nothrow
|
||||
{
|
||||
if( atomic_decrement( &weak_count_ ) == 0 )
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
|
||||
long use_count() const // nothrow
|
||||
{
|
||||
return static_cast<int const volatile &>( use_count_ );
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_MIPS_HPP_INCLUDED
|
||||
184
include/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp
Normal file
184
include/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp
Normal file
@@ -0,0 +1,184 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// detail/sp_counted_base_gcc_ppc.hpp - g++ on PowerPC
|
||||
//
|
||||
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
|
||||
// Copyright 2004-2005 Peter Dimov
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
//
|
||||
// Lock-free algorithm by Alexander Terekhov
|
||||
//
|
||||
// Thanks to Ben Hitchings for the #weak + (#shared != 0)
|
||||
// formulation
|
||||
//
|
||||
|
||||
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
inline void atomic_increment( int * pw )
|
||||
{
|
||||
// ++*pw;
|
||||
|
||||
int tmp;
|
||||
|
||||
__asm__
|
||||
(
|
||||
"0:\n\t"
|
||||
"lwarx %1, 0, %2\n\t"
|
||||
"addi %1, %1, 1\n\t"
|
||||
"stwcx. %1, 0, %2\n\t"
|
||||
"bne- 0b":
|
||||
|
||||
"=m"( *pw ), "=&b"( tmp ):
|
||||
"r"( pw ), "m"( *pw ):
|
||||
"cc"
|
||||
);
|
||||
}
|
||||
|
||||
inline int atomic_decrement( int * pw )
|
||||
{
|
||||
// return --*pw;
|
||||
|
||||
int rv;
|
||||
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"sync\n\t"
|
||||
"0:\n\t"
|
||||
"lwarx %1, 0, %2\n\t"
|
||||
"addi %1, %1, -1\n\t"
|
||||
"stwcx. %1, 0, %2\n\t"
|
||||
"bne- 0b\n\t"
|
||||
"isync":
|
||||
|
||||
"=m"( *pw ), "=&b"( rv ):
|
||||
"r"( pw ), "m"( *pw ):
|
||||
"memory", "cc"
|
||||
);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
inline int atomic_conditional_increment( int * pw )
|
||||
{
|
||||
// if( *pw != 0 ) ++*pw;
|
||||
// return *pw;
|
||||
|
||||
int rv;
|
||||
|
||||
__asm__
|
||||
(
|
||||
"0:\n\t"
|
||||
"lwarx %1, 0, %2\n\t"
|
||||
"cmpwi %1, 0\n\t"
|
||||
"beq 1f\n\t"
|
||||
"addi %1, %1, 1\n\t"
|
||||
"1:\n\t"
|
||||
"stwcx. %1, 0, %2\n\t"
|
||||
"bne- 0b":
|
||||
|
||||
"=m"( *pw ), "=&b"( rv ):
|
||||
"r"( pw ), "m"( *pw ):
|
||||
"cc"
|
||||
);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE sp_counted_base
|
||||
{
|
||||
private:
|
||||
|
||||
sp_counted_base( sp_counted_base const & );
|
||||
sp_counted_base & operator= ( sp_counted_base const & );
|
||||
|
||||
int use_count_; // #shared
|
||||
int weak_count_; // #weak + (#shared != 0)
|
||||
|
||||
public:
|
||||
|
||||
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~sp_counted_base() // nothrow
|
||||
{
|
||||
}
|
||||
|
||||
// dispose() is called when use_count_ drops to zero, to release
|
||||
// the resources managed by *this.
|
||||
|
||||
virtual void dispose() = 0; // nothrow
|
||||
|
||||
// destroy() is called when weak_count_ drops to zero.
|
||||
|
||||
virtual void destroy() // nothrow
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
|
||||
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
|
||||
virtual void * get_untyped_deleter() = 0;
|
||||
|
||||
void add_ref_copy()
|
||||
{
|
||||
atomic_increment( &use_count_ );
|
||||
}
|
||||
|
||||
bool add_ref_lock() // true on success
|
||||
{
|
||||
return atomic_conditional_increment( &use_count_ ) != 0;
|
||||
}
|
||||
|
||||
void release() // nothrow
|
||||
{
|
||||
if( atomic_decrement( &use_count_ ) == 0 )
|
||||
{
|
||||
dispose();
|
||||
weak_release();
|
||||
}
|
||||
}
|
||||
|
||||
void weak_add_ref() // nothrow
|
||||
{
|
||||
atomic_increment( &weak_count_ );
|
||||
}
|
||||
|
||||
void weak_release() // nothrow
|
||||
{
|
||||
if( atomic_decrement( &weak_count_ ) == 0 )
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
|
||||
long use_count() const // nothrow
|
||||
{
|
||||
return static_cast<int const volatile &>( use_count_ );
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED
|
||||
169
include/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp
Normal file
169
include/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp
Normal file
@@ -0,0 +1,169 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
// detail/sp_counted_base_gcc_sparc.hpp - g++ on Sparc V8+
|
||||
//
|
||||
// Copyright (c) 2006 Piotr Wyderski
|
||||
// Copyright (c) 2006 Tomas Puverle
|
||||
// Copyright (c) 2006 Peter Dimov
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Thanks to Michael van der Westhuizen
|
||||
|
||||
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <inttypes.h> // int32_t
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
inline int32_t compare_and_swap( int32_t * dest_, int32_t compare_, int32_t swap_ )
|
||||
{
|
||||
__asm__ __volatile__( "cas [%1], %2, %0"
|
||||
: "+r" (swap_)
|
||||
: "r" (dest_), "r" (compare_)
|
||||
: "memory" );
|
||||
|
||||
return swap_;
|
||||
}
|
||||
|
||||
inline int32_t atomic_fetch_and_add( int32_t * pw, int32_t dv )
|
||||
{
|
||||
// long r = *pw;
|
||||
// *pw += dv;
|
||||
// return r;
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
int32_t r = *pw;
|
||||
|
||||
if( __builtin_expect((compare_and_swap(pw, r, r + dv) == r), 1) )
|
||||
{
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void atomic_increment( int32_t * pw )
|
||||
{
|
||||
atomic_fetch_and_add( pw, 1 );
|
||||
}
|
||||
|
||||
inline int32_t atomic_decrement( int32_t * pw )
|
||||
{
|
||||
return atomic_fetch_and_add( pw, -1 );
|
||||
}
|
||||
|
||||
inline int32_t atomic_conditional_increment( int32_t * pw )
|
||||
{
|
||||
// long r = *pw;
|
||||
// if( r != 0 ) ++*pw;
|
||||
// return r;
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
int32_t r = *pw;
|
||||
|
||||
if( r == 0 )
|
||||
{
|
||||
return r;
|
||||
}
|
||||
|
||||
if( __builtin_expect( ( compare_and_swap( pw, r, r + 1 ) == r ), 1 ) )
|
||||
{
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE sp_counted_base
|
||||
{
|
||||
private:
|
||||
|
||||
sp_counted_base( sp_counted_base const & );
|
||||
sp_counted_base & operator= ( sp_counted_base const & );
|
||||
|
||||
int32_t use_count_; // #shared
|
||||
int32_t weak_count_; // #weak + (#shared != 0)
|
||||
|
||||
public:
|
||||
|
||||
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~sp_counted_base() // nothrow
|
||||
{
|
||||
}
|
||||
|
||||
// dispose() is called when use_count_ drops to zero, to release
|
||||
// the resources managed by *this.
|
||||
|
||||
virtual void dispose() = 0; // nothrow
|
||||
|
||||
// destroy() is called when weak_count_ drops to zero.
|
||||
|
||||
virtual void destroy() // nothrow
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
|
||||
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
|
||||
virtual void * get_untyped_deleter() = 0;
|
||||
|
||||
void add_ref_copy()
|
||||
{
|
||||
atomic_increment( &use_count_ );
|
||||
}
|
||||
|
||||
bool add_ref_lock() // true on success
|
||||
{
|
||||
return atomic_conditional_increment( &use_count_ ) != 0;
|
||||
}
|
||||
|
||||
void release() // nothrow
|
||||
{
|
||||
if( atomic_decrement( &use_count_ ) == 1 )
|
||||
{
|
||||
dispose();
|
||||
weak_release();
|
||||
}
|
||||
}
|
||||
|
||||
void weak_add_ref() // nothrow
|
||||
{
|
||||
atomic_increment( &weak_count_ );
|
||||
}
|
||||
|
||||
void weak_release() // nothrow
|
||||
{
|
||||
if( atomic_decrement( &weak_count_ ) == 1 )
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
|
||||
long use_count() const // nothrow
|
||||
{
|
||||
return const_cast< int32_t const volatile & >( use_count_ );
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED
|
||||
176
include/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp
Normal file
176
include/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp
Normal file
@@ -0,0 +1,176 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// detail/sp_counted_base_gcc_x86.hpp - g++ on 486+ or AMD64
|
||||
//
|
||||
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
|
||||
// Copyright 2004-2005 Peter Dimov
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
//
|
||||
// Lock-free algorithm by Alexander Terekhov
|
||||
//
|
||||
// Thanks to Ben Hitchings for the #weak + (#shared != 0)
|
||||
// formulation
|
||||
//
|
||||
|
||||
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
inline int atomic_exchange_and_add( int * pw, int dv )
|
||||
{
|
||||
// int r = *pw;
|
||||
// *pw += dv;
|
||||
// return r;
|
||||
|
||||
int r;
|
||||
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"lock\n\t"
|
||||
"xadd %1, %0":
|
||||
"=m"( *pw ), "=r"( r ): // outputs (%0, %1)
|
||||
"m"( *pw ), "1"( dv ): // inputs (%2, %3 == %1)
|
||||
"memory", "cc" // clobbers
|
||||
);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
inline void atomic_increment( int * pw )
|
||||
{
|
||||
//atomic_exchange_and_add( pw, 1 );
|
||||
|
||||
__asm__
|
||||
(
|
||||
"lock\n\t"
|
||||
"incl %0":
|
||||
"=m"( *pw ): // output (%0)
|
||||
"m"( *pw ): // input (%1)
|
||||
"cc" // clobbers
|
||||
);
|
||||
}
|
||||
|
||||
inline int atomic_conditional_increment( int * pw )
|
||||
{
|
||||
// int rv = *pw;
|
||||
// if( rv != 0 ) ++*pw;
|
||||
// return rv;
|
||||
|
||||
int rv, tmp;
|
||||
|
||||
__asm__
|
||||
(
|
||||
"movl %0, %%eax\n\t"
|
||||
"0:\n\t"
|
||||
"test %%eax, %%eax\n\t"
|
||||
"je 1f\n\t"
|
||||
"movl %%eax, %2\n\t"
|
||||
"incl %2\n\t"
|
||||
"lock\n\t"
|
||||
"cmpxchgl %2, %0\n\t"
|
||||
"jne 0b\n\t"
|
||||
"1:":
|
||||
"=m"( *pw ), "=&a"( rv ), "=&r"( tmp ): // outputs (%0, %1, %2)
|
||||
"m"( *pw ): // input (%3)
|
||||
"cc" // clobbers
|
||||
);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE sp_counted_base
|
||||
{
|
||||
private:
|
||||
|
||||
sp_counted_base( sp_counted_base const & );
|
||||
sp_counted_base & operator= ( sp_counted_base const & );
|
||||
|
||||
int use_count_; // #shared
|
||||
int weak_count_; // #weak + (#shared != 0)
|
||||
|
||||
public:
|
||||
|
||||
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~sp_counted_base() // nothrow
|
||||
{
|
||||
}
|
||||
|
||||
// dispose() is called when use_count_ drops to zero, to release
|
||||
// the resources managed by *this.
|
||||
|
||||
virtual void dispose() = 0; // nothrow
|
||||
|
||||
// destroy() is called when weak_count_ drops to zero.
|
||||
|
||||
virtual void destroy() // nothrow
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
|
||||
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
|
||||
virtual void * get_untyped_deleter() = 0;
|
||||
|
||||
void add_ref_copy()
|
||||
{
|
||||
atomic_increment( &use_count_ );
|
||||
}
|
||||
|
||||
bool add_ref_lock() // true on success
|
||||
{
|
||||
return atomic_conditional_increment( &use_count_ ) != 0;
|
||||
}
|
||||
|
||||
void release() // nothrow
|
||||
{
|
||||
if( atomic_exchange_and_add( &use_count_, -1 ) == 1 )
|
||||
{
|
||||
dispose();
|
||||
weak_release();
|
||||
}
|
||||
}
|
||||
|
||||
void weak_add_ref() // nothrow
|
||||
{
|
||||
atomic_increment( &weak_count_ );
|
||||
}
|
||||
|
||||
void weak_release() // nothrow
|
||||
{
|
||||
if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 )
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
|
||||
long use_count() const // nothrow
|
||||
{
|
||||
return static_cast<int const volatile &>( use_count_ );
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED
|
||||
112
include/boost/smart_ptr/detail/sp_counted_base_nt.hpp
Normal file
112
include/boost/smart_ptr/detail/sp_counted_base_nt.hpp
Normal file
@@ -0,0 +1,112 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// detail/sp_counted_base_nt.hpp
|
||||
//
|
||||
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
|
||||
// Copyright 2004-2005 Peter Dimov
|
||||
//
|
||||
// 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/smart_ptr/detail/sp_typeinfo_.hpp>
|
||||
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE sp_counted_base
|
||||
{
|
||||
private:
|
||||
|
||||
sp_counted_base( sp_counted_base const & );
|
||||
sp_counted_base & operator= ( sp_counted_base const & );
|
||||
|
||||
boost::int_least32_t use_count_; // #shared
|
||||
boost::int_least32_t weak_count_; // #weak + (#shared != 0)
|
||||
|
||||
public:
|
||||
|
||||
sp_counted_base() BOOST_SP_NOEXCEPT: use_count_( 1 ), weak_count_( 1 )
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~sp_counted_base() /*BOOST_SP_NOEXCEPT*/
|
||||
{
|
||||
}
|
||||
|
||||
// dispose() is called when use_count_ drops to zero, to release
|
||||
// the resources managed by *this.
|
||||
|
||||
virtual void dispose() BOOST_SP_NOEXCEPT = 0; // nothrow
|
||||
|
||||
// destroy() is called when weak_count_ drops to zero.
|
||||
|
||||
virtual void destroy() BOOST_SP_NOEXCEPT // nothrow
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
virtual void * get_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT = 0;
|
||||
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT = 0;
|
||||
virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT = 0;
|
||||
|
||||
void add_ref_copy() BOOST_SP_NOEXCEPT
|
||||
{
|
||||
++use_count_;
|
||||
}
|
||||
|
||||
bool add_ref_lock() BOOST_SP_NOEXCEPT // true on success
|
||||
{
|
||||
if( use_count_ == 0 ) return false;
|
||||
++use_count_;
|
||||
return true;
|
||||
}
|
||||
|
||||
void release() BOOST_SP_NOEXCEPT
|
||||
{
|
||||
if( --use_count_ == 0 )
|
||||
{
|
||||
dispose();
|
||||
weak_release();
|
||||
}
|
||||
}
|
||||
|
||||
void weak_add_ref() BOOST_SP_NOEXCEPT
|
||||
{
|
||||
++weak_count_;
|
||||
}
|
||||
|
||||
void weak_release() BOOST_SP_NOEXCEPT
|
||||
{
|
||||
if( --weak_count_ == 0 )
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
|
||||
long use_count() const BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return use_count_;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED
|
||||
140
include/boost/smart_ptr/detail/sp_counted_base_pt.hpp
Normal file
140
include/boost/smart_ptr/detail/sp_counted_base_pt.hpp
Normal file
@@ -0,0 +1,140 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// detail/sp_counted_base_pt.hpp
|
||||
//
|
||||
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
|
||||
// Copyright 2004-2005 Peter Dimov
|
||||
//
|
||||
// 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/smart_ptr/detail/sp_typeinfo_.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <pthread.h>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE sp_counted_base
|
||||
{
|
||||
private:
|
||||
|
||||
sp_counted_base( sp_counted_base const & );
|
||||
sp_counted_base & operator= ( sp_counted_base const & );
|
||||
|
||||
boost::int_least32_t use_count_; // #shared
|
||||
boost::int_least32_t weak_count_; // #weak + (#shared != 0)
|
||||
|
||||
mutable pthread_mutex_t m_;
|
||||
|
||||
public:
|
||||
|
||||
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
|
||||
{
|
||||
// HPUX 10.20 / DCE has a nonstandard pthread_mutex_init
|
||||
|
||||
#if defined(__hpux) && defined(_DECTHREADS_)
|
||||
BOOST_VERIFY( pthread_mutex_init( &m_, pthread_mutexattr_default ) == 0 );
|
||||
#else
|
||||
BOOST_VERIFY( pthread_mutex_init( &m_, 0 ) == 0 );
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual ~sp_counted_base() // nothrow
|
||||
{
|
||||
BOOST_VERIFY( pthread_mutex_destroy( &m_ ) == 0 );
|
||||
}
|
||||
|
||||
// dispose() is called when use_count_ drops to zero, to release
|
||||
// the resources managed by *this.
|
||||
|
||||
virtual void dispose() = 0; // nothrow
|
||||
|
||||
// destroy() is called when weak_count_ drops to zero.
|
||||
|
||||
virtual void destroy() // nothrow
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
|
||||
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
|
||||
virtual void * get_untyped_deleter() = 0;
|
||||
|
||||
void add_ref_copy()
|
||||
{
|
||||
BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );
|
||||
++use_count_;
|
||||
BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );
|
||||
}
|
||||
|
||||
bool add_ref_lock() // true on success
|
||||
{
|
||||
BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );
|
||||
bool r = use_count_ == 0? false: ( ++use_count_, true );
|
||||
BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );
|
||||
return r;
|
||||
}
|
||||
|
||||
void release() // nothrow
|
||||
{
|
||||
BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );
|
||||
boost::int_least32_t new_use_count = --use_count_;
|
||||
BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );
|
||||
|
||||
if( new_use_count == 0 )
|
||||
{
|
||||
dispose();
|
||||
weak_release();
|
||||
}
|
||||
}
|
||||
|
||||
void weak_add_ref() // nothrow
|
||||
{
|
||||
BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );
|
||||
++weak_count_;
|
||||
BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );
|
||||
}
|
||||
|
||||
void weak_release() // nothrow
|
||||
{
|
||||
BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );
|
||||
boost::int_least32_t new_weak_count = --weak_count_;
|
||||
BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );
|
||||
|
||||
if( new_weak_count == 0 )
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
|
||||
long use_count() const // nothrow
|
||||
{
|
||||
BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );
|
||||
boost::int_least32_t r = use_count_;
|
||||
BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );
|
||||
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED
|
||||
164
include/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp
Normal file
164
include/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp
Normal file
@@ -0,0 +1,164 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SNC_PS3_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SNC_PS3_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
// detail/sp_counted_base_gcc_sparc.hpp - g++ on Sparc V8+
|
||||
//
|
||||
// Copyright (c) 2006 Piotr Wyderski
|
||||
// Copyright (c) 2006 Tomas Puverle
|
||||
// Copyright (c) 2006 Peter Dimov
|
||||
// Copyright (c) 2011 Emil Dotchevski
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Thanks to Michael van der Westhuizen
|
||||
|
||||
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <inttypes.h> // uint32_t
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
inline uint32_t compare_and_swap( uint32_t * dest_, uint32_t compare_, uint32_t swap_ )
|
||||
{
|
||||
return __builtin_cellAtomicCompareAndSwap32(dest_,compare_,swap_);
|
||||
}
|
||||
|
||||
inline uint32_t atomic_fetch_and_add( uint32_t * pw, uint32_t dv )
|
||||
{
|
||||
// long r = *pw;
|
||||
// *pw += dv;
|
||||
// return r;
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
uint32_t r = *pw;
|
||||
|
||||
if( __builtin_expect((compare_and_swap(pw, r, r + dv) == r), 1) )
|
||||
{
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void atomic_increment( uint32_t * pw )
|
||||
{
|
||||
(void) __builtin_cellAtomicIncr32( pw );
|
||||
}
|
||||
|
||||
inline uint32_t atomic_decrement( uint32_t * pw )
|
||||
{
|
||||
return __builtin_cellAtomicDecr32( pw );
|
||||
}
|
||||
|
||||
inline uint32_t atomic_conditional_increment( uint32_t * pw )
|
||||
{
|
||||
// long r = *pw;
|
||||
// if( r != 0 ) ++*pw;
|
||||
// return r;
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
uint32_t r = *pw;
|
||||
|
||||
if( r == 0 )
|
||||
{
|
||||
return r;
|
||||
}
|
||||
|
||||
if( __builtin_expect( ( compare_and_swap( pw, r, r + 1 ) == r ), 1 ) )
|
||||
{
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE sp_counted_base
|
||||
{
|
||||
private:
|
||||
|
||||
sp_counted_base( sp_counted_base const & );
|
||||
sp_counted_base & operator= ( sp_counted_base const & );
|
||||
|
||||
uint32_t use_count_; // #shared
|
||||
uint32_t weak_count_; // #weak + (#shared != 0)
|
||||
|
||||
public:
|
||||
|
||||
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~sp_counted_base() // nothrow
|
||||
{
|
||||
}
|
||||
|
||||
// dispose() is called when use_count_ drops to zero, to release
|
||||
// the resources managed by *this.
|
||||
|
||||
virtual void dispose() = 0; // nothrow
|
||||
|
||||
// destroy() is called when weak_count_ drops to zero.
|
||||
|
||||
virtual void destroy() // nothrow
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
|
||||
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
|
||||
virtual void * get_untyped_deleter() = 0;
|
||||
|
||||
void add_ref_copy()
|
||||
{
|
||||
atomic_increment( &use_count_ );
|
||||
}
|
||||
|
||||
bool add_ref_lock() // true on success
|
||||
{
|
||||
return atomic_conditional_increment( &use_count_ ) != 0;
|
||||
}
|
||||
|
||||
void release() // nothrow
|
||||
{
|
||||
if( atomic_decrement( &use_count_ ) == 1 )
|
||||
{
|
||||
dispose();
|
||||
weak_release();
|
||||
}
|
||||
}
|
||||
|
||||
void weak_add_ref() // nothrow
|
||||
{
|
||||
atomic_increment( &weak_count_ );
|
||||
}
|
||||
|
||||
void weak_release() // nothrow
|
||||
{
|
||||
if( atomic_decrement( &weak_count_ ) == 1 )
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
|
||||
long use_count() const // nothrow
|
||||
{
|
||||
return const_cast< uint32_t const volatile & >( use_count_ );
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SNC_PS3_HPP_INCLUDED
|
||||
116
include/boost/smart_ptr/detail/sp_counted_base_solaris.hpp
Normal file
116
include/boost/smart_ptr/detail/sp_counted_base_solaris.hpp
Normal file
@@ -0,0 +1,116 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// detail/sp_counted_base_solaris.hpp
|
||||
// based on: detail/sp_counted_base_w32.hpp
|
||||
//
|
||||
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
|
||||
// Copyright 2004-2005 Peter Dimov
|
||||
// Copyright 2006 Michael van der Westhuizen
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
//
|
||||
// Lock-free algorithm by Alexander Terekhov
|
||||
//
|
||||
// Thanks to Ben Hitchings for the #weak + (#shared != 0)
|
||||
// formulation
|
||||
//
|
||||
|
||||
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <atomic.h>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE sp_counted_base
|
||||
{
|
||||
private:
|
||||
|
||||
sp_counted_base( sp_counted_base const & );
|
||||
sp_counted_base & operator= ( sp_counted_base const & );
|
||||
|
||||
uint32_t use_count_; // #shared
|
||||
uint32_t weak_count_; // #weak + (#shared != 0)
|
||||
|
||||
public:
|
||||
|
||||
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~sp_counted_base() // nothrow
|
||||
{
|
||||
}
|
||||
|
||||
// dispose() is called when use_count_ drops to zero, to release
|
||||
// the resources managed by *this.
|
||||
|
||||
virtual void dispose() = 0; // nothrow
|
||||
|
||||
// destroy() is called when weak_count_ drops to zero.
|
||||
|
||||
virtual void destroy() // nothrow
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
|
||||
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
|
||||
virtual void * get_untyped_deleter() = 0;
|
||||
|
||||
void add_ref_copy()
|
||||
{
|
||||
atomic_inc_32( &use_count_ );
|
||||
}
|
||||
|
||||
bool add_ref_lock() // true on success
|
||||
{
|
||||
for( ;; )
|
||||
{
|
||||
uint32_t tmp = static_cast< uint32_t const volatile& >( use_count_ );
|
||||
if( tmp == 0 ) return false;
|
||||
if( atomic_cas_32( &use_count_, tmp, tmp + 1 ) == tmp ) return true;
|
||||
}
|
||||
}
|
||||
|
||||
void release() // nothrow
|
||||
{
|
||||
if( atomic_dec_32_nv( &use_count_ ) == 0 )
|
||||
{
|
||||
dispose();
|
||||
weak_release();
|
||||
}
|
||||
}
|
||||
|
||||
void weak_add_ref() // nothrow
|
||||
{
|
||||
atomic_inc_32( &weak_count_ );
|
||||
}
|
||||
|
||||
void weak_release() // nothrow
|
||||
{
|
||||
if( atomic_dec_32_nv( &weak_count_ ) == 0 )
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
|
||||
long use_count() const // nothrow
|
||||
{
|
||||
return static_cast<long const volatile &>( use_count_ );
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED
|
||||
134
include/boost/smart_ptr/detail/sp_counted_base_spin.hpp
Normal file
134
include/boost/smart_ptr/detail/sp_counted_base_spin.hpp
Normal file
@@ -0,0 +1,134 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// detail/sp_counted_base_spin.hpp - spinlock pool atomic emulation
|
||||
//
|
||||
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
|
||||
// Copyright 2004-2008 Peter Dimov
|
||||
//
|
||||
// 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/smart_ptr/detail/sp_typeinfo_.hpp>
|
||||
#include <boost/smart_ptr/detail/spinlock_pool.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
inline int atomic_exchange_and_add( int * pw, int dv )
|
||||
{
|
||||
spinlock_pool<1>::scoped_lock lock( pw );
|
||||
|
||||
int r = *pw;
|
||||
*pw += dv;
|
||||
return r;
|
||||
}
|
||||
|
||||
inline void atomic_increment( int * pw )
|
||||
{
|
||||
spinlock_pool<1>::scoped_lock lock( pw );
|
||||
++*pw;
|
||||
}
|
||||
|
||||
inline int atomic_conditional_increment( int * pw )
|
||||
{
|
||||
spinlock_pool<1>::scoped_lock lock( pw );
|
||||
|
||||
int rv = *pw;
|
||||
if( rv != 0 ) ++*pw;
|
||||
return rv;
|
||||
}
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE sp_counted_base
|
||||
{
|
||||
private:
|
||||
|
||||
sp_counted_base( sp_counted_base const & );
|
||||
sp_counted_base & operator= ( sp_counted_base const & );
|
||||
|
||||
int use_count_; // #shared
|
||||
int weak_count_; // #weak + (#shared != 0)
|
||||
|
||||
public:
|
||||
|
||||
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~sp_counted_base() // nothrow
|
||||
{
|
||||
}
|
||||
|
||||
// dispose() is called when use_count_ drops to zero, to release
|
||||
// the resources managed by *this.
|
||||
|
||||
virtual void dispose() = 0; // nothrow
|
||||
|
||||
// destroy() is called when weak_count_ drops to zero.
|
||||
|
||||
virtual void destroy() // nothrow
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
|
||||
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
|
||||
virtual void * get_untyped_deleter() = 0;
|
||||
|
||||
void add_ref_copy()
|
||||
{
|
||||
atomic_increment( &use_count_ );
|
||||
}
|
||||
|
||||
bool add_ref_lock() // true on success
|
||||
{
|
||||
return atomic_conditional_increment( &use_count_ ) != 0;
|
||||
}
|
||||
|
||||
void release() // nothrow
|
||||
{
|
||||
if( atomic_exchange_and_add( &use_count_, -1 ) == 1 )
|
||||
{
|
||||
dispose();
|
||||
weak_release();
|
||||
}
|
||||
}
|
||||
|
||||
void weak_add_ref() // nothrow
|
||||
{
|
||||
atomic_increment( &weak_count_ );
|
||||
}
|
||||
|
||||
void weak_release() // nothrow
|
||||
{
|
||||
if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 )
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
|
||||
long use_count() const // nothrow
|
||||
{
|
||||
spinlock_pool<1>::scoped_lock lock( &use_count_ );
|
||||
return use_count_;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user