mirror of
https://github.com/boostorg/smart_ptr.git
synced 2025-10-23 21:01:51 +02:00
Compare commits
524 Commits
boost-1.18
...
boost-1.43
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6848b09e73 | ||
|
|
697f338510 | ||
|
|
f4386409d9 | ||
|
|
ba349679f3 | ||
|
|
a3b84f8586 | ||
|
|
b0fd8a6b08 | ||
|
|
4f5062004a | ||
|
|
f040bed751 | ||
|
|
2f8945a885 | ||
|
|
2bd0778778 | ||
|
|
eec640bfd7 | ||
|
|
754fd941ee | ||
|
|
e94f64039d | ||
|
|
63b17c24ea | ||
|
|
8a421c2098 | ||
|
|
5fa1cbf6e1 | ||
|
|
9f30442d1e | ||
|
|
a4293f9dfa | ||
|
|
28de0cb1e3 | ||
|
|
a1b4fc8d95 | ||
|
|
77971c6ff5 | ||
|
|
1742c37942 | ||
|
|
31e06b4a1d | ||
|
|
22f1b092c9 | ||
|
|
5a2771e585 | ||
|
|
dad59f3325 | ||
|
|
bad394b1e9 | ||
|
|
f93110620a | ||
|
|
6be1e3fceb | ||
|
|
cf91287732 | ||
|
|
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 |
88
compatibility.htm
Normal file
88
compatibility.htm
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Smart Pointer Changes</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="#ffffff" text="#000000">
|
||||||
|
<h1><A href="../../index.htm"><img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" width="277" height="86"
|
||||||
|
border="0"></A>Smart Pointer Changes</h1>
|
||||||
|
<p>The February 2002 change to the Boost smart pointers introduced a number of
|
||||||
|
changes. Since the previous version of the smart pointers was in use for a long
|
||||||
|
time, it's useful to have a detailed list of what changed from a library user's
|
||||||
|
point of view.</p>
|
||||||
|
<p>Note that for compilers that don't support member templates well enough, a
|
||||||
|
separate implementation is used that lacks many of the new features and is more
|
||||||
|
like the old version.</p>
|
||||||
|
<h2>Features Requiring Code Changes to Take Advantage</h2>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
The smart pointer class templates now each have their own header file. For
|
||||||
|
compatibility, the <a href="../../boost/smart_ptr.hpp"><boost/smart_ptr.hpp></a>
|
||||||
|
header now includes the headers for the four classic smart pointer class
|
||||||
|
templates.
|
||||||
|
<li>
|
||||||
|
The <b>weak_ptr</b>
|
||||||
|
template was added.
|
||||||
|
<li>
|
||||||
|
The new <b>shared_ptr</b> and <b>shared_array</b> relax the requirement that
|
||||||
|
the pointed-to object's destructor must be visible when instantiating the <b>shared_ptr</b>
|
||||||
|
destructor. This makes it easier to have shared_ptr members in classes without
|
||||||
|
explicit destructors.
|
||||||
|
<li>
|
||||||
|
A custom deallocator can be passed in when creating a <b>shared_ptr</b> or <b>shared_array</b>.
|
||||||
|
<li>
|
||||||
|
<b>shared_static_cast</b> and <b>shared_dynamic_cast</b> function templates are
|
||||||
|
provided which work for <b>shared_ptr</b> and <b>weak_ptr</b> as <b>static_cast</b>
|
||||||
|
and <b>dynamic_cast</b>
|
||||||
|
do for pointers.
|
||||||
|
<li>
|
||||||
|
The self-assignment misfeature has been removed from <b>shared_ptr::reset</b>,
|
||||||
|
although it is still present in <b>scoped_ptr</b>, and in <b>std::auto_ptr</b>.
|
||||||
|
Calling <b>reset</b> with a pointer to the object that's already owned by the <b>shared_ptr</b>
|
||||||
|
results in undefined behavior (an assertion, or eventually a double-delete if
|
||||||
|
assertions are off).
|
||||||
|
<li>
|
||||||
|
The <b>BOOST_SMART_PTR_CONVERSION</b>
|
||||||
|
feature has been removed.
|
||||||
|
<li>
|
||||||
|
<b>shared_ptr<void></b> is now allowed.</li>
|
||||||
|
</ul>
|
||||||
|
<h2>Features That Improve Robustness</h2>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
The manipulation of use counts is now <a name="threadsafe">thread safe</a> on
|
||||||
|
Windows, Linux, and platforms that support pthreads. See the <a href="../../boost/detail/atomic_count.hpp">
|
||||||
|
<boost/detail/atomic_count.hpp></a>
|
||||||
|
file for details
|
||||||
|
<li>
|
||||||
|
The new shared_ptr will always delete the object using the pointer it was
|
||||||
|
originally constructed with. This prevents subtle problems that could happen if
|
||||||
|
the last <b>shared_ptr</b> was a pointer to a sub-object of a class that did
|
||||||
|
not have a virtual destructor.</li>
|
||||||
|
</ul>
|
||||||
|
<h2>Implementation Details</h2>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
Some bugs in the assignment operator implementations and in <b>reset</b>
|
||||||
|
have been fixed by using the "copy and swap" idiom.
|
||||||
|
<li>
|
||||||
|
Assertions have been added to check preconditions of various functions;
|
||||||
|
however, since these use the new <a href="../../boost/assert.hpp"><boost/assert.hpp></a>
|
||||||
|
header, the assertions are disabled by default.
|
||||||
|
<li>
|
||||||
|
The partial specialization of <b>std::less</b> has been replaced by <b>operator<</b>
|
||||||
|
overloads which accomplish the same thing without relying on undefined
|
||||||
|
behavior.
|
||||||
|
<li>
|
||||||
|
The incorrect overload of <b>std::swap</b> has been replaced by <b>boost::swap</b>,
|
||||||
|
which has many of the same advantages for generic programming but does not
|
||||||
|
violate the C++ standard.</li>
|
||||||
|
</ul>
|
||||||
|
<hr>
|
||||||
|
<p>Revised 1 February 2002</p>
|
||||||
|
<p><small>Copyright 2002 Darin Adler. Distributed under the Boost Software License, Version
|
||||||
|
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
|
||||||
|
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
95
enable_shared_from_this.html
Normal file
95
enable_shared_from_this.html
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Boost: enable_shared_from_this.hpp documentation</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white" style="MARGIN-LEFT: 5%; MARGIN-RIGHT: 5%">
|
||||||
|
<table border="0" width="100%">
|
||||||
|
<tr>
|
||||||
|
<td width="277"><A href="../../index.htm"> <img src="../../boost.png" alt="boost.png (6897 bytes)" width="277" height="86" border="0"></A>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<h1>enable_shared_from_this.hpp</h1>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2" height="64"> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<h3><a name="Purpose">Purpose</a></h3>
|
||||||
|
<p>
|
||||||
|
The header <STRONG><boost/enable_shared_from_this.hpp></STRONG> defines
|
||||||
|
the class template <STRONG>enable_shared_from_this</STRONG>. It is used as a
|
||||||
|
base class that allows a <A href="shared_ptr.htm">shared_ptr</A> to the current
|
||||||
|
object to be obtained from within a member function.
|
||||||
|
</p>
|
||||||
|
<P><STRONG>enable_shared_from_this<T></STRONG> defines two member functions
|
||||||
|
called <STRONG>shared_from_this</STRONG> that return a <STRONG>shared_ptr<T></STRONG>
|
||||||
|
and <STRONG>shared_ptr<T const></STRONG>, depending on constness, to <STRONG>this</STRONG>.</P>
|
||||||
|
<h3><a name="Example">Example</a></h3>
|
||||||
|
<pre>
|
||||||
|
#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
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
<h3><a name="Synopsis">Synopsis</a></h3>
|
||||||
|
<pre>
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
template<class T> class enable_shared_from_this
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
shared_ptr<T> shared_from_this();
|
||||||
|
shared_ptr<T const> shared_from_this() const;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
<h4>template<class T> shared_ptr<T>
|
||||||
|
enable_shared_from_this<T>::shared_from_this();</h4>
|
||||||
|
<h4>template<class T> shared_ptr<T const>
|
||||||
|
enable_shared_from_this<T>::shared_from_this() const;</h4>
|
||||||
|
<blockquote>
|
||||||
|
<p>
|
||||||
|
<b>Requires:</b> <STRONG>enable_shared_from_this<T></STRONG> must be an
|
||||||
|
accessible base class of <b>T</b>. <STRONG>*this</STRONG> must be a subobject
|
||||||
|
of an instance <STRONG>t</STRONG> of type <STRONG>T</STRONG> . There must exist
|
||||||
|
at least one <STRONG>shared_ptr</STRONG> instance <STRONG>p</STRONG> that <EM>owns</EM>
|
||||||
|
<STRONG>t</STRONG>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<b>Returns:</b> A <b>shared_ptr<T></b> instance <b>r</b> that shares
|
||||||
|
ownership with <b>p</b>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<b>Postconditions:</b> <tt>r.get() == this</tt>.
|
||||||
|
</p>
|
||||||
|
</blockquote>
|
||||||
|
<p>
|
||||||
|
<br>
|
||||||
|
<small>Copyright <20> 2002, 2003 by Peter Dimov. Distributed under the Boost Software License, Version
|
||||||
|
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
|
||||||
|
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
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;
|
||||||
|
}
|
||||||
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
|
||||||
129
include/boost/detail/sp_typeinfo.hpp
Normal file
129
include/boost/detail/sp_typeinfo.hpp
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
#ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED
|
||||||
|
#define BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED
|
||||||
|
|
||||||
|
// MS compatible compilers support #pragma once
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||||
|
# pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// detail/sp_typeinfo.hpp
|
||||||
|
//
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
|
||||||
|
#if defined( BOOST_NO_TYPEID )
|
||||||
|
|
||||||
|
#include <boost/current_function.hpp>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
class sp_typeinfo
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
sp_typeinfo( sp_typeinfo const& );
|
||||||
|
sp_typeinfo& operator=( sp_typeinfo const& );
|
||||||
|
|
||||||
|
char const * name_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit sp_typeinfo( char const * name ): name_( name )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==( sp_typeinfo const& rhs ) const
|
||||||
|
{
|
||||||
|
return this == &rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=( sp_typeinfo const& rhs ) const
|
||||||
|
{
|
||||||
|
return this != &rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool before( sp_typeinfo const& rhs ) const
|
||||||
|
{
|
||||||
|
return std::less< sp_typeinfo const* >()( this, &rhs );
|
||||||
|
}
|
||||||
|
|
||||||
|
char const* name() const
|
||||||
|
{
|
||||||
|
return name_;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T> struct sp_typeid_
|
||||||
|
{
|
||||||
|
static sp_typeinfo ti_;
|
||||||
|
|
||||||
|
static char const * name()
|
||||||
|
{
|
||||||
|
return BOOST_CURRENT_FUNCTION;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T> sp_typeinfo sp_typeid_< T >::ti_( sp_typeid_< T >::name() );
|
||||||
|
|
||||||
|
template<class T> struct sp_typeid_< T & >: sp_typeid_< T >
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T> struct sp_typeid_< T const >: sp_typeid_< T >
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T> struct sp_typeid_< T volatile >: sp_typeid_< T >
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T> struct sp_typeid_< T const volatile >: sp_typeid_< T >
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#define BOOST_SP_TYPEID(T) (boost::detail::sp_typeid_<T>::ti_)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <typeinfo>
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
#if defined( BOOST_NO_STD_TYPEINFO )
|
||||||
|
|
||||||
|
typedef ::type_info sp_typeinfo;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
typedef std::type_info sp_typeinfo;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#define BOOST_SP_TYPEID(T) typeid(T)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_DETAIL_SP_TYPEINFO_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
|
||||||
|
//
|
||||||
|
// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <boost/smart_ptr/enable_shared_from_this.hpp>
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
|
||||||
33
include/boost/get_pointer.hpp
Normal file
33
include/boost/get_pointer.hpp
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
// Copyright Peter Dimov and David Abrahams 2002.
|
||||||
|
// 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 GET_POINTER_DWA20021219_HPP
|
||||||
|
# define GET_POINTER_DWA20021219_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
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
|
||||||
|
// get_pointer(p) extracts a ->* capable pointer from p
|
||||||
|
|
||||||
|
template<class T> T * get_pointer(T * p)
|
||||||
|
{
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get_pointer(shared_ptr<T> const & p) has been moved to shared_ptr.hpp
|
||||||
|
|
||||||
|
template<class T> T * get_pointer(std::auto_ptr<T> const& p)
|
||||||
|
{
|
||||||
|
return p.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // GET_POINTER_DWA20021219_HPP
|
||||||
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/intrusive_ptr.html for documentation.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <boost/smart_ptr/intrusive_ptr.hpp>
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_INTRUSIVE_PTR_HPP_INCLUDED
|
||||||
17
include/boost/make_shared.hpp
Normal file
17
include/boost/make_shared.hpp
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#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/make_shared.html
|
||||||
|
// for documentation.
|
||||||
|
|
||||||
|
#include <boost/smart_ptr/make_shared.hpp>
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_MAKE_SHARED_HPP_INCLUDED
|
||||||
53
include/boost/memory_order.hpp
Normal file
53
include/boost/memory_order.hpp
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#ifndef BOOST_MEMORY_ORDER_HPP_INCLUDED
|
||||||
|
#define BOOST_MEMORY_ORDER_HPP_INCLUDED
|
||||||
|
|
||||||
|
// MS compatible compilers support #pragma once
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||||
|
# pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// boost/memory_order.hpp
|
||||||
|
//
|
||||||
|
// Defines enum boost::memory_order per the C++0x working draft
|
||||||
|
//
|
||||||
|
// Copyright (c) 2008, 2009 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
|
||||||
|
{
|
||||||
|
|
||||||
|
//
|
||||||
|
// Enum values are chosen so that code that needs to insert
|
||||||
|
// a trailing fence for acquire semantics can use a single
|
||||||
|
// test such as:
|
||||||
|
//
|
||||||
|
// if( mo & memory_order_acquire ) { ...fence... }
|
||||||
|
//
|
||||||
|
// For leading fences one can use:
|
||||||
|
//
|
||||||
|
// if( mo & memory_order_release ) { ...fence... }
|
||||||
|
//
|
||||||
|
// Architectures such as Alpha that need a fence on consume
|
||||||
|
// can use:
|
||||||
|
//
|
||||||
|
// if( mo & ( memory_order_acquire | memory_order_consume ) ) { ...fence... }
|
||||||
|
//
|
||||||
|
|
||||||
|
enum memory_order
|
||||||
|
{
|
||||||
|
memory_order_relaxed = 0,
|
||||||
|
memory_order_acquire = 1,
|
||||||
|
memory_order_release = 2,
|
||||||
|
memory_order_acq_rel = 3, // acquire | release
|
||||||
|
memory_order_seq_cst = 7, // acq_rel | 4
|
||||||
|
memory_order_consume = 8
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_MEMORY_ORDER_HPP_INCLUDED
|
||||||
45
include/boost/pointer_cast.hpp
Normal file
45
include/boost/pointer_cast.hpp
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// (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
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
|
||||||
|
//static_pointer_cast overload for raw pointers
|
||||||
|
template<class T, class U>
|
||||||
|
inline T* static_pointer_cast(U *ptr)
|
||||||
|
{
|
||||||
|
return static_cast<T*>(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
//dynamic_pointer_cast overload for raw pointers
|
||||||
|
template<class T, class U>
|
||||||
|
inline T* dynamic_pointer_cast(U *ptr)
|
||||||
|
{
|
||||||
|
return dynamic_cast<T*>(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
//const_pointer_cast overload for raw pointers
|
||||||
|
template<class T, class U>
|
||||||
|
inline T* const_pointer_cast(U *ptr)
|
||||||
|
{
|
||||||
|
return const_cast<T*>(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
//reinterpret_pointer_cast overload for raw pointers
|
||||||
|
template<class T, class U>
|
||||||
|
inline T* reinterpret_pointer_cast(U *ptr)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<T*>(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#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/pointer_to_other.html
|
||||||
|
//
|
||||||
|
|
||||||
|
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
|
||||||
16
include/boost/scoped_array.hpp
Normal file
16
include/boost/scoped_array.hpp
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#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)
|
||||||
|
//
|
||||||
|
// http://www.boost.org/libs/smart_ptr/scoped_array.htm
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <boost/smart_ptr/scoped_array.hpp>
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED
|
||||||
16
include/boost/scoped_ptr.hpp
Normal file
16
include/boost/scoped_ptr.hpp
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#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)
|
||||||
|
//
|
||||||
|
// http://www.boost.org/libs/smart_ptr/scoped_ptr.htm
|
||||||
|
//
|
||||||
|
|
||||||
|
#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/shared_array.htm 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/shared_ptr.htm for documentation.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <boost/smart_ptr/shared_ptr.hpp>
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_SHARED_PTR_HPP_INCLUDED
|
||||||
@@ -1,372 +1,25 @@
|
|||||||
// Boost smart_ptr.hpp header file -----------------------------------------//
|
//
|
||||||
|
// 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)
|
||||||
|
//
|
||||||
|
// http://www.boost.org/libs/smart_ptr/smart_ptr.htm
|
||||||
|
//
|
||||||
|
|
||||||
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. Permission to copy,
|
#include <boost/config.hpp>
|
||||||
// use, modify, sell and distribute this software is granted provided this
|
|
||||||
// copyright notice appears in all copies. This software is provided "as is"
|
|
||||||
// without express or implied warranty, and with no claim as to its
|
|
||||||
// suitability for any purpose.
|
|
||||||
|
|
||||||
// See http://www.boost.org for most recent version including documentation.
|
#include <boost/scoped_ptr.hpp>
|
||||||
|
#include <boost/scoped_array.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <boost/shared_array.hpp>
|
||||||
|
|
||||||
// Revision History
|
#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES)
|
||||||
// 24 Jul 00 Change throw() to // never throws. See lib guidelines
|
# include <boost/weak_ptr.hpp>
|
||||||
// Exception-specification rationale. (Beman Dawes)
|
# include <boost/intrusive_ptr.hpp>
|
||||||
// 22 Jun 00 Remove #if continuations to fix GCC 2.95.2 problem (Beman Dawes)
|
# include <boost/enable_shared_from_this.hpp>
|
||||||
// 1 Feb 00 Additional shared_ptr BOOST_NO_MEMBER_TEMPLATES workarounds
|
|
||||||
// (Dave Abrahams)
|
|
||||||
// 31 Dec 99 Condition tightened for no member template friend workaround
|
|
||||||
// (Dave Abrahams)
|
|
||||||
// 30 Dec 99 Moved BOOST_NMEMBER_TEMPLATES compatibility code to config.hpp
|
|
||||||
// (Dave Abrahams)
|
|
||||||
// 30 Nov 99 added operator ==, operator !=, and std::swap and std::less
|
|
||||||
// specializations for shared types (Darin Adler)
|
|
||||||
// 11 Oct 99 replaced op[](int) with op[](std::size_t) (Ed Brey, Valentin
|
|
||||||
// Bonnard), added shared_ptr workaround for no member template
|
|
||||||
// friends (Matthew Langston)
|
|
||||||
// 25 Sep 99 added shared_ptr::swap and shared_array::swap (Luis Coelho).
|
|
||||||
// 20 Jul 99 changed name to smart_ptr.hpp, #include <boost/config.hpp>,
|
|
||||||
// #include <boost/utility.hpp> and use boost::noncopyable
|
|
||||||
// 17 May 99 remove scoped_array and shared_array operator*() as
|
|
||||||
// unnecessary (Beman Dawes)
|
|
||||||
// 14 May 99 reorder code so no effects when bad_alloc thrown (Abrahams/Dawes)
|
|
||||||
// 13 May 99 remove certain throw() specifiers to avoid generated try/catch
|
|
||||||
// code cost (Beman Dawes)
|
|
||||||
// 11 May 99 get() added, conversion to T* placed in macro guard (Valentin
|
|
||||||
// Bonnard, Dave Abrahams, and others argued for elimination
|
|
||||||
// of the automatic conversion)
|
|
||||||
// 28 Apr 99 #include <memory> fix (Valentin Bonnard)
|
|
||||||
// 28 Apr 99 rename transfer() to share() for clarity (Dave Abrahams)
|
|
||||||
// 28 Apr 99 remove unsafe shared_array template conversions(Valentin Bonnard)
|
|
||||||
// 28 Apr 99 p(r) changed to p(r.px) for clarity (Dave Abrahams)
|
|
||||||
// 21 Apr 99 reset() self assignment fix (Valentin Bonnard)
|
|
||||||
// 21 Apr 99 dispose() provided to improve clarity (Valentin Bonnard)
|
|
||||||
// 27 Apr 99 leak when new throws fixes (Dave Abrahams)
|
|
||||||
// 21 Oct 98 initial Version (Greg Colvin/Beman Dawes)
|
|
||||||
|
|
||||||
#ifndef BOOST_SMART_PTR_HPP
|
|
||||||
#define BOOST_SMART_PTR_HPP
|
|
||||||
|
|
||||||
#include <boost/config.hpp> // for broken compiler workarounds
|
|
||||||
#include <cstddef> // for std::size_t
|
|
||||||
#include <memory> // for std::auto_ptr
|
|
||||||
#include <algorithm> // for std::swap
|
|
||||||
#include <boost/utility.hpp> // for boost::noncopyable
|
|
||||||
#include <functional> // for std::less
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
|
|
||||||
// scoped_ptr --------------------------------------------------------------//
|
|
||||||
|
|
||||||
// scoped_ptr mimics a built-in pointer except that it guarantees deletion
|
|
||||||
// of the object pointed to, either on destruction of the scoped_ptr or via
|
|
||||||
// an explicit reset(). scoped_ptr is a simple solution for simple needs;
|
|
||||||
// see shared_ptr (below) or std::auto_ptr if your needs are more complex.
|
|
||||||
|
|
||||||
template<typename T> class scoped_ptr : noncopyable {
|
|
||||||
|
|
||||||
T* ptr;
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef T element_type;
|
|
||||||
|
|
||||||
explicit scoped_ptr( T* p=0 ) : ptr(p) {} // never throws
|
|
||||||
~scoped_ptr() { delete ptr; }
|
|
||||||
|
|
||||||
void reset( T* p=0 ) { if ( ptr != p ) { delete ptr; ptr = p; } }
|
|
||||||
T& operator*() const { return *ptr; } // never throws
|
|
||||||
T* operator->() const { return ptr; } // never throws
|
|
||||||
T* get() const { return ptr; } // never throws
|
|
||||||
#ifdef BOOST_SMART_PTR_CONVERSION
|
|
||||||
// get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk!
|
|
||||||
operator T*() const { return ptr; } // never throws
|
|
||||||
#endif
|
#endif
|
||||||
}; // scoped_ptr
|
|
||||||
|
|
||||||
// scoped_array ------------------------------------------------------------//
|
|
||||||
|
|
||||||
// scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to
|
|
||||||
// is guaranteed, either on destruction of the scoped_array or via an explicit
|
|
||||||
// reset(). See shared_array or std::vector if your needs are more complex.
|
|
||||||
|
|
||||||
template<typename T> class scoped_array : noncopyable {
|
|
||||||
|
|
||||||
T* ptr;
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef T element_type;
|
|
||||||
|
|
||||||
explicit scoped_array( T* p=0 ) : ptr(p) {} // never throws
|
|
||||||
~scoped_array() { delete [] ptr; }
|
|
||||||
|
|
||||||
void reset( T* p=0 ) { if ( ptr != p ) {delete [] ptr; ptr=p;} }
|
|
||||||
|
|
||||||
T* get() const { return ptr; } // never throws
|
|
||||||
#ifdef BOOST_SMART_PTR_CONVERSION
|
|
||||||
// get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk!
|
|
||||||
operator T*() const { return ptr; } // never throws
|
|
||||||
#else
|
|
||||||
T& operator[](std::size_t i) const { return ptr[i]; } // never throws
|
|
||||||
#endif
|
|
||||||
}; // scoped_array
|
|
||||||
|
|
||||||
// shared_ptr --------------------------------------------------------------//
|
|
||||||
|
|
||||||
// An enhanced relative of scoped_ptr with reference counted copy semantics.
|
|
||||||
// The object pointed to is deleted when the last shared_ptr pointing to it
|
|
||||||
// is destroyed or reset.
|
|
||||||
|
|
||||||
template<typename T> class shared_ptr {
|
|
||||||
public:
|
|
||||||
typedef T element_type;
|
|
||||||
|
|
||||||
explicit shared_ptr(T* p =0) : px(p) {
|
|
||||||
try { pn = new long(1); } // fix: prevent leak if new throws
|
|
||||||
catch (...) { delete p; throw; }
|
|
||||||
}
|
|
||||||
|
|
||||||
shared_ptr(const shared_ptr& r) : px(r.px) { ++*(pn = r.pn); } // never throws
|
|
||||||
|
|
||||||
~shared_ptr() { dispose(); }
|
|
||||||
|
|
||||||
shared_ptr& operator=(const shared_ptr& r) {
|
|
||||||
share(r.px,r.pn);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined( BOOST_NO_MEMBER_TEMPLATES )
|
|
||||||
template<typename Y>
|
|
||||||
shared_ptr(const shared_ptr<Y>& r) : px(r.px) { // never throws
|
|
||||||
++*(pn = r.pn);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Y>
|
|
||||||
shared_ptr(std::auto_ptr<Y>& r) {
|
|
||||||
pn = new long(1); // may throw
|
|
||||||
px = r.release(); // fix: moved here to stop leak if new throws
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Y>
|
|
||||||
shared_ptr& operator=(const shared_ptr<Y>& r) {
|
|
||||||
share(r.px,r.pn);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Y>
|
|
||||||
shared_ptr& operator=(std::auto_ptr<Y>& r) {
|
|
||||||
// code choice driven by guarantee of "no effect if new throws"
|
|
||||||
if (*pn == 1) { delete px; }
|
|
||||||
else { // allocate new reference counter
|
|
||||||
long * tmp = new long(1); // may throw
|
|
||||||
--*pn; // only decrement once danger of new throwing is past
|
|
||||||
pn = tmp;
|
|
||||||
} // allocate new reference counter
|
|
||||||
px = r.release(); // fix: moved here so doesn't leak if new throws
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
shared_ptr(std::auto_ptr<T>& r) {
|
|
||||||
pn = new long(1); // may throw
|
|
||||||
px = r.release(); // fix: moved here to stop leak if new throws
|
|
||||||
}
|
|
||||||
|
|
||||||
shared_ptr& operator=(std::auto_ptr<T>& r) {
|
|
||||||
// code choice driven by guarantee of "no effect if new throws"
|
|
||||||
if (*pn == 1) { delete px; }
|
|
||||||
else { // allocate new reference counter
|
|
||||||
long * tmp = new long(1); // may throw
|
|
||||||
--*pn; // only decrement once danger of new throwing is past
|
|
||||||
pn = tmp;
|
|
||||||
} // allocate new reference counter
|
|
||||||
px = r.release(); // fix: moved here so doesn't leak if new throws
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void reset(T* p=0) {
|
|
||||||
if ( px == p ) return; // fix: self-assignment safe
|
|
||||||
if (--*pn == 0) { delete px; }
|
|
||||||
else { // allocate new reference counter
|
|
||||||
try { pn = new long; } // fix: prevent leak if new throws
|
|
||||||
catch (...) {
|
|
||||||
++*pn; // undo effect of --*pn above to meet effects guarantee
|
|
||||||
delete p;
|
|
||||||
throw;
|
|
||||||
} // catch
|
|
||||||
} // allocate new reference counter
|
|
||||||
*pn = 1;
|
|
||||||
px = p;
|
|
||||||
} // reset
|
|
||||||
|
|
||||||
T& operator*() const { return *px; } // never throws
|
|
||||||
T* operator->() const { return px; } // never throws
|
|
||||||
T* get() const { return px; } // never throws
|
|
||||||
#ifdef BOOST_SMART_PTR_CONVERSION
|
|
||||||
// get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk!
|
|
||||||
operator T*() const { return px; } // never throws
|
|
||||||
#endif
|
|
||||||
|
|
||||||
long use_count() const { return *pn; } // never throws
|
|
||||||
bool unique() const { return *pn == 1; } // never throws
|
|
||||||
|
|
||||||
void swap(shared_ptr<T>& other) // never throws
|
|
||||||
{ std::swap(px,other.px); std::swap(pn,other.pn); }
|
|
||||||
|
|
||||||
// Tasteless as this may seem, making all members public allows member templates
|
|
||||||
// to work in the absence of member template friends. (Matthew Langston)
|
|
||||||
// Don't split this line into two; that causes problems for some GCC 2.95.2 builds
|
|
||||||
#if defined(BOOST_NO_MEMBER_TEMPLATES) || !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS )
|
|
||||||
private:
|
|
||||||
#endif
|
|
||||||
|
|
||||||
T* px; // contained pointer
|
|
||||||
long* pn; // ptr to reference counter
|
|
||||||
|
|
||||||
// Don't split this line into two; that causes problems for some GCC 2.95.2 builds
|
|
||||||
#if !defined( BOOST_NO_MEMBER_TEMPLATES ) && !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS )
|
|
||||||
template<typename Y> friend class shared_ptr;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void dispose() { if (--*pn == 0) { delete px; delete pn; } }
|
|
||||||
|
|
||||||
void share(T* rpx, long* rpn) {
|
|
||||||
if (pn != rpn) {
|
|
||||||
dispose();
|
|
||||||
px = rpx;
|
|
||||||
++*(pn = rpn);
|
|
||||||
}
|
|
||||||
} // share
|
|
||||||
}; // shared_ptr
|
|
||||||
|
|
||||||
template<typename T, typename U>
|
|
||||||
inline bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b)
|
|
||||||
{ return a.get() == b.get(); }
|
|
||||||
|
|
||||||
template<typename T, typename U>
|
|
||||||
inline bool operator!=(const shared_ptr<T>& a, const shared_ptr<U>& b)
|
|
||||||
{ return a.get() != b.get(); }
|
|
||||||
|
|
||||||
// shared_array ------------------------------------------------------------//
|
|
||||||
|
|
||||||
// shared_array extends shared_ptr to arrays.
|
|
||||||
// The array pointed to is deleted when the last shared_array pointing to it
|
|
||||||
// is destroyed or reset.
|
|
||||||
|
|
||||||
template<typename T> class shared_array {
|
|
||||||
public:
|
|
||||||
typedef T element_type;
|
|
||||||
|
|
||||||
explicit shared_array(T* p =0) : px(p) {
|
|
||||||
try { pn = new long(1); } // fix: prevent leak if new throws
|
|
||||||
catch (...) { delete [] p; throw; }
|
|
||||||
}
|
|
||||||
|
|
||||||
shared_array(const shared_array& r) : px(r.px) // never throws
|
|
||||||
{ ++*(pn = r.pn); }
|
|
||||||
|
|
||||||
~shared_array() { dispose(); }
|
|
||||||
|
|
||||||
shared_array& operator=(const shared_array& r) {
|
|
||||||
if (pn != r.pn) {
|
|
||||||
dispose();
|
|
||||||
px = r.px;
|
|
||||||
++*(pn = r.pn);
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
} // operator=
|
|
||||||
|
|
||||||
void reset(T* p=0) {
|
|
||||||
if ( px == p ) return; // fix: self-assignment safe
|
|
||||||
if (--*pn == 0) { delete [] px; }
|
|
||||||
else { // allocate new reference counter
|
|
||||||
try { pn = new long; } // fix: prevent leak if new throws
|
|
||||||
catch (...) {
|
|
||||||
++*pn; // undo effect of --*pn above to meet effects guarantee
|
|
||||||
delete [] p;
|
|
||||||
throw;
|
|
||||||
} // catch
|
|
||||||
} // allocate new reference counter
|
|
||||||
*pn = 1;
|
|
||||||
px = p;
|
|
||||||
} // reset
|
|
||||||
|
|
||||||
T* get() const { return px; } // never throws
|
|
||||||
#ifdef BOOST_SMART_PTR_CONVERSION
|
|
||||||
// get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk!
|
|
||||||
operator T*() const { return px; } // never throws
|
|
||||||
#else
|
|
||||||
T& operator[](std::size_t i) const { return px[i]; } // never throws
|
|
||||||
#endif
|
|
||||||
|
|
||||||
long use_count() const { return *pn; } // never throws
|
|
||||||
bool unique() const { return *pn == 1; } // never throws
|
|
||||||
|
|
||||||
void swap(shared_array<T>& other) // never throws
|
|
||||||
{ std::swap(px,other.px); std::swap(pn,other.pn); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
T* px; // contained pointer
|
|
||||||
long* pn; // ptr to reference counter
|
|
||||||
|
|
||||||
void dispose() { if (--*pn == 0) { delete [] px; delete pn; } }
|
|
||||||
|
|
||||||
}; // shared_array
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline bool operator==(const shared_array<T>& a, const shared_array<T>& b)
|
|
||||||
{ return a.get() == b.get(); }
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline bool operator!=(const shared_array<T>& a, const shared_array<T>& b)
|
|
||||||
{ return a.get() != b.get(); }
|
|
||||||
|
|
||||||
} // namespace boost
|
|
||||||
|
|
||||||
// specializations for things in namespace std -----------------------------//
|
|
||||||
|
|
||||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
|
|
||||||
// Specialize std::swap to use the fast, non-throwing swap that's provided
|
|
||||||
// as a member function instead of using the default algorithm which creates
|
|
||||||
// a temporary and uses assignment.
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline void swap(boost::shared_ptr<T>& a, boost::shared_ptr<T>& b)
|
|
||||||
{ a.swap(b); }
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline void swap(boost::shared_array<T>& a, boost::shared_array<T>& b)
|
|
||||||
{ a.swap(b); }
|
|
||||||
|
|
||||||
// Specialize std::less so we can use shared pointers and arrays as keys in
|
|
||||||
// associative collections.
|
|
||||||
|
|
||||||
// It's still a controversial question whether this is better than supplying
|
|
||||||
// a full range of comparison operators (<, >, <=, >=).
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct less< boost::shared_ptr<T> >
|
|
||||||
: binary_function<boost::shared_ptr<T>, boost::shared_ptr<T>, bool>
|
|
||||||
{
|
|
||||||
bool operator()(const boost::shared_ptr<T>& a,
|
|
||||||
const boost::shared_ptr<T>& b) const
|
|
||||||
{ return less<T*>()(a.get(),b.get()); }
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct less< boost::shared_array<T> >
|
|
||||||
: binary_function<boost::shared_array<T>, boost::shared_array<T>, bool>
|
|
||||||
{
|
|
||||||
bool operator()(const boost::shared_array<T>& a,
|
|
||||||
const boost::shared_array<T>& b) const
|
|
||||||
{ return less<T*>()(a.get(),b.get()); }
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace std
|
|
||||||
|
|
||||||
#endif // ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
||||||
|
|
||||||
#endif // BOOST_SMART_PTR_HPP
|
|
||||||
|
|
||||||
|
|||||||
59
include/boost/smart_ptr/bad_weak_ptr.hpp
Normal file
59
include/boost/smart_ptr/bad_weak_ptr.hpp
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
#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 <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
|
||||||
|
|
||||||
|
class bad_weak_ptr: public std::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual char const * what() const throw()
|
||||||
|
{
|
||||||
|
return "tr1::bad_weak_ptr";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#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
|
||||||
119
include/boost/smart_ptr/detail/atomic_count.hpp
Normal file
119
include/boost/smart_ptr/detail/atomic_count.hpp
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
#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.
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
// ++a;
|
||||||
|
//
|
||||||
|
// Effects: Atomically increments the value of a
|
||||||
|
// Returns: (long) the new value of a
|
||||||
|
//
|
||||||
|
// --a;
|
||||||
|
//
|
||||||
|
// Effects: Atomically decrements the value of a
|
||||||
|
// Returns: (long) the new value of a
|
||||||
|
//
|
||||||
|
// Important note: when --a returns zero, it must act as a
|
||||||
|
// read memory barrier (RMB); i.e. the calling thread must
|
||||||
|
// have a synchronized view of the memory
|
||||||
|
//
|
||||||
|
// On Intel IA-32 (x86) memory is always synchronized, so this
|
||||||
|
// is not a problem.
|
||||||
|
//
|
||||||
|
// On many architectures the atomic instructions already act as
|
||||||
|
// a memory barrier.
|
||||||
|
//
|
||||||
|
// This property is necessary for proper reference counting, since
|
||||||
|
// a thread can update the contents of a shared object, then
|
||||||
|
// release its reference, and another thread may immediately
|
||||||
|
// release the last reference causing object destruction.
|
||||||
|
//
|
||||||
|
// The destructor needs to have a synchronized view of the
|
||||||
|
// object to perform proper cleanup.
|
||||||
|
//
|
||||||
|
// Original example by Alexander Terekhov:
|
||||||
|
//
|
||||||
|
// Given:
|
||||||
|
//
|
||||||
|
// - a mutable shared object OBJ;
|
||||||
|
// - two threads THREAD1 and THREAD2 each holding
|
||||||
|
// a private smart_ptr object pointing to that OBJ.
|
||||||
|
//
|
||||||
|
// t1: THREAD1 updates OBJ (thread-safe via some synchronization)
|
||||||
|
// and a few cycles later (after "unlock") destroys smart_ptr;
|
||||||
|
//
|
||||||
|
// t2: THREAD2 destroys smart_ptr WITHOUT doing any synchronization
|
||||||
|
// with respect to shared mutable object OBJ; OBJ destructors
|
||||||
|
// are called driven by smart_ptr interface...
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#include <boost/smart_ptr/detail/sp_has_sync.hpp>
|
||||||
|
|
||||||
|
#ifndef BOOST_HAS_THREADS
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
typedef long atomic_count;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(BOOST_AC_USE_PTHREADS)
|
||||||
|
# include <boost/smart_ptr/detail/atomic_count_pthreads.hpp>
|
||||||
|
|
||||||
|
#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) )
|
||||||
|
# include <boost/smart_ptr/detail/atomic_count_gcc_x86.hpp>
|
||||||
|
|
||||||
|
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
|
||||||
|
# include <boost/smart_ptr/detail/atomic_count_win32.hpp>
|
||||||
|
|
||||||
|
#elif defined( BOOST_SP_HAS_SYNC )
|
||||||
|
# include <boost/smart_ptr/detail/atomic_count_sync.hpp>
|
||||||
|
|
||||||
|
#elif defined(__GLIBCPP__) || defined(__GLIBCXX__)
|
||||||
|
# include <boost/smart_ptr/detail/atomic_count_gcc.hpp>
|
||||||
|
|
||||||
|
#elif defined(BOOST_HAS_PTHREADS)
|
||||||
|
|
||||||
|
# define BOOST_AC_USE_PTHREADS
|
||||||
|
# include <boost/smart_ptr/detail/atomic_count_pthreads.hpp>
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// Use #define BOOST_DISABLE_THREADS to avoid the error
|
||||||
|
#error Unrecognized threading platform
|
||||||
|
|
||||||
|
#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<42>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
|
||||||
96
include/boost/smart_ptr/detail/atomic_count_pthreads.hpp
Normal file
96
include/boost/smart_ptr/detail/atomic_count_pthreads.hpp
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
#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 <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)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&m_);
|
||||||
|
}
|
||||||
|
|
||||||
|
~scoped_lock()
|
||||||
|
{
|
||||||
|
pthread_mutex_unlock(&m_);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
pthread_mutex_t & m_;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit atomic_count(long v): value_(v)
|
||||||
|
{
|
||||||
|
pthread_mutex_init(&mutex_, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
~atomic_count()
|
||||||
|
{
|
||||||
|
pthread_mutex_destroy(&mutex_);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
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/detail/interlocked.hpp>
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
class atomic_count
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit atomic_count( long v ): value_( v )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
long operator++()
|
||||||
|
{
|
||||||
|
return BOOST_INTERLOCKED_INCREMENT( &value_ );
|
||||||
|
}
|
||||||
|
|
||||||
|
long operator--()
|
||||||
|
{
|
||||||
|
return BOOST_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
|
||||||
42
include/boost/smart_ptr/detail/lightweight_mutex.hpp
Normal file
42
include/boost/smart_ptr/detail/lightweight_mutex.hpp
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
#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_HAS_THREADS)
|
||||||
|
# include <boost/smart_ptr/detail/lwm_nop.hpp>
|
||||||
|
#elif defined(BOOST_HAS_PTHREADS)
|
||||||
|
# include <boost/smart_ptr/detail/lwm_pthreads.hpp>
|
||||||
|
#elif defined(BOOST_HAS_WINTHREADS) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
|
||||||
|
# include <boost/smart_ptr/detail/lwm_win32_cs.hpp>
|
||||||
|
#else
|
||||||
|
// Use #define BOOST_DISABLE_THREADS to avoid the error
|
||||||
|
# error Unrecognized threading platform
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_SMART_PTR_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED
|
||||||
37
include/boost/smart_ptr/detail/lwm_nop.hpp
Normal file
37
include/boost/smart_ptr/detail/lwm_nop.hpp
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#ifndef BOOST_SMART_PTR_DETAIL_LWM_NOP_HPP_INCLUDED
|
||||||
|
#define BOOST_SMART_PTR_DETAIL_LWM_NOP_HPP_INCLUDED
|
||||||
|
|
||||||
|
// MS compatible compilers support #pragma once
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||||
|
# pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// boost/detail/lwm_nop.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)
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
class lightweight_mutex
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef lightweight_mutex scoped_lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_SMART_PTR_DETAIL_LWM_NOP_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
|
||||||
108
include/boost/smart_ptr/detail/lwm_win32_cs.hpp
Normal file
108
include/boost/smart_ptr/detail/lwm_win32_cs.hpp
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
#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>
|
||||||
|
#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(critical_section *);
|
||||||
|
extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(critical_section *);
|
||||||
|
extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(critical_section *);
|
||||||
|
extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(critical_section *);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
typedef ::CRITICAL_SECTION 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()
|
||||||
|
{
|
||||||
|
InitializeCriticalSection(&cs_);
|
||||||
|
}
|
||||||
|
|
||||||
|
~lightweight_mutex()
|
||||||
|
{
|
||||||
|
DeleteCriticalSection(&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)
|
||||||
|
{
|
||||||
|
EnterCriticalSection(&m_.cs_);
|
||||||
|
}
|
||||||
|
|
||||||
|
~scoped_lock()
|
||||||
|
{
|
||||||
|
LeaveCriticalSection(&m_.cs_);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_SMART_PTR_DETAIL_LWM_WIN32_CS_HPP_INCLUDED
|
||||||
56
include/boost/smart_ptr/detail/operator_bool.hpp
Normal file
56
include/boost/smart_ptr/detail/operator_bool.hpp
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
// This header intentionally has no include guards.
|
||||||
|
//
|
||||||
|
// Copyright (c) 2001-2009 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(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, < 0x570) ) || defined(__CINT__)
|
||||||
|
|
||||||
|
operator bool () const
|
||||||
|
{
|
||||||
|
return px != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined( _MANAGED )
|
||||||
|
|
||||||
|
static void unspecified_bool( this_type*** )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef void (*unspecified_bool_type)( this_type*** );
|
||||||
|
|
||||||
|
operator unspecified_bool_type() const // never throws
|
||||||
|
{
|
||||||
|
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 T * (this_type::*unspecified_bool_type)() const;
|
||||||
|
|
||||||
|
operator unspecified_bool_type() const // never throws
|
||||||
|
{
|
||||||
|
return px == 0? 0: &this_type::get;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
typedef T * this_type::*unspecified_bool_type;
|
||||||
|
|
||||||
|
operator unspecified_bool_type() const // never throws
|
||||||
|
{
|
||||||
|
return px == 0? 0: &this_type::px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// operator! is redundant, but some compilers need it
|
||||||
|
bool operator! () const // never throws
|
||||||
|
{
|
||||||
|
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
|
||||||
151
include/boost/smart_ptr/detail/shared_array_nmt.hpp
Normal file
151
include/boost/smart_ptr/detail/shared_array_nmt.hpp
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
#ifndef BOOST_SMART_PTR_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED
|
||||||
|
#define BOOST_SMART_PTR_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED
|
||||||
|
|
||||||
|
//
|
||||||
|
// detail/shared_array_nmt.hpp - shared_array.hpp without member templates
|
||||||
|
//
|
||||||
|
// (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/shared_array.htm for documentation.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/checked_delete.hpp>
|
||||||
|
#include <boost/throw_exception.hpp>
|
||||||
|
#include <boost/smart_ptr/detail/atomic_count.hpp>
|
||||||
|
|
||||||
|
#include <cstddef> // for std::ptrdiff_t
|
||||||
|
#include <algorithm> // for std::swap
|
||||||
|
#include <functional> // for std::less
|
||||||
|
#include <new> // for std::bad_alloc
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
template<class T> class shared_array
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
typedef detail::atomic_count count_type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef T element_type;
|
||||||
|
|
||||||
|
explicit shared_array(T * p = 0): px(p)
|
||||||
|
{
|
||||||
|
#ifndef BOOST_NO_EXCEPTIONS
|
||||||
|
|
||||||
|
try // prevent leak if new throws
|
||||||
|
{
|
||||||
|
pn = new count_type(1);
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
boost::checked_array_delete(p);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
pn = new count_type(1);
|
||||||
|
|
||||||
|
if(pn == 0)
|
||||||
|
{
|
||||||
|
boost::checked_array_delete(p);
|
||||||
|
boost::throw_exception(std::bad_alloc());
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
~shared_array()
|
||||||
|
{
|
||||||
|
if(--*pn == 0)
|
||||||
|
{
|
||||||
|
boost::checked_array_delete(px);
|
||||||
|
delete pn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_array(shared_array const & r) : px(r.px) // never throws
|
||||||
|
{
|
||||||
|
pn = r.pn;
|
||||||
|
++*pn;
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_array & operator=(shared_array const & r)
|
||||||
|
{
|
||||||
|
shared_array(r).swap(*this);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset(T * p = 0)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(p == 0 || p != px);
|
||||||
|
shared_array(p).swap(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
T * get() const // never throws
|
||||||
|
{
|
||||||
|
return px;
|
||||||
|
}
|
||||||
|
|
||||||
|
T & operator[](std::ptrdiff_t i) const // never throws
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(px != 0);
|
||||||
|
BOOST_ASSERT(i >= 0);
|
||||||
|
return px[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
long use_count() const // never throws
|
||||||
|
{
|
||||||
|
return *pn;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool unique() const // never throws
|
||||||
|
{
|
||||||
|
return *pn == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void swap(shared_array<T> & other) // never throws
|
||||||
|
{
|
||||||
|
std::swap(px, other.px);
|
||||||
|
std::swap(pn, other.pn);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
T * px; // contained pointer
|
||||||
|
count_type * pn; // ptr to reference counter
|
||||||
|
|
||||||
|
}; // shared_array
|
||||||
|
|
||||||
|
template<class T, class U> inline bool operator==(shared_array<T> const & a, shared_array<U> const & b)
|
||||||
|
{
|
||||||
|
return a.get() == b.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class U> inline bool operator!=(shared_array<T> const & a, shared_array<U> const & b)
|
||||||
|
{
|
||||||
|
return a.get() != b.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T> inline bool operator<(shared_array<T> const & a, shared_array<T> const & b)
|
||||||
|
{
|
||||||
|
return std::less<T*>()(a.get(), b.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T> void swap(shared_array<T> & a, shared_array<T> & b)
|
||||||
|
{
|
||||||
|
a.swap(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED
|
||||||
444
include/boost/smart_ptr/detail/shared_count.hpp
Normal file
444
include/boost/smart_ptr/detail/shared_count.hpp
Normal file
@@ -0,0 +1,444 @@
|
|||||||
|
#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/detail/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
|
||||||
|
#include <new> // std::bad_alloc
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
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 {};
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
shared_count(): pi_(0) // nothrow
|
||||||
|
#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
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
typedef typename A::template rebind< impl_type >::other A2;
|
||||||
|
|
||||||
|
A2 a2( a );
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_EXCEPTIONS
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );
|
||||||
|
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, static_cast< impl_type* >( 0 ) );
|
||||||
|
|
||||||
|
if( pi_ != 0 )
|
||||||
|
{
|
||||||
|
new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
d( p );
|
||||||
|
boost::throw_exception( std::bad_alloc() );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
~shared_count() // nothrow
|
||||||
|
{
|
||||||
|
if( pi_ != 0 ) pi_->release();
|
||||||
|
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||||
|
id_ = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_count(shared_count const & r): pi_(r.pi_) // nothrow
|
||||||
|
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||||
|
, id_(shared_count_id)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if( pi_ != 0 ) pi_->add_ref_copy();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined( BOOST_HAS_RVALUE_REFS )
|
||||||
|
|
||||||
|
shared_count(shared_count && r): pi_(r.pi_) // nothrow
|
||||||
|
#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 ); // constructs an empty *this when r.use_count() == 0
|
||||||
|
|
||||||
|
shared_count & operator= (shared_count const & r) // nothrow
|
||||||
|
{
|
||||||
|
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) // nothrow
|
||||||
|
{
|
||||||
|
sp_counted_base * tmp = r.pi_;
|
||||||
|
r.pi_ = pi_;
|
||||||
|
pi_ = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
long use_count() const // nothrow
|
||||||
|
{
|
||||||
|
return pi_ != 0? pi_->use_count(): 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool unique() const // nothrow
|
||||||
|
{
|
||||||
|
return use_count() == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty() const // nothrow
|
||||||
|
{
|
||||||
|
return pi_ == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend inline bool operator==(shared_count const & a, shared_count const & b)
|
||||||
|
{
|
||||||
|
return a.pi_ == b.pi_;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend inline bool operator<(shared_count const & a, shared_count const & b)
|
||||||
|
{
|
||||||
|
return std::less<sp_counted_base *>()( a.pi_, b.pi_ );
|
||||||
|
}
|
||||||
|
|
||||||
|
void * get_deleter( sp_typeinfo const & ti ) const
|
||||||
|
{
|
||||||
|
return pi_? pi_->get_deleter( ti ): 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class weak_count
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
sp_counted_base * pi_;
|
||||||
|
|
||||||
|
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||||
|
int id_;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
friend class shared_count;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
weak_count(): pi_(0) // nothrow
|
||||||
|
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||||
|
, id_(weak_count_id)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
weak_count(shared_count const & r): pi_(r.pi_) // nothrow
|
||||||
|
#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): pi_(r.pi_) // nothrow
|
||||||
|
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||||
|
, id_(weak_count_id)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if(pi_ != 0) pi_->weak_add_ref();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move support
|
||||||
|
|
||||||
|
#if defined( BOOST_HAS_RVALUE_REFS )
|
||||||
|
|
||||||
|
weak_count(weak_count && r): pi_(r.pi_) // nothrow
|
||||||
|
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||||
|
, id_(weak_count_id)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
r.pi_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
~weak_count() // nothrow
|
||||||
|
{
|
||||||
|
if(pi_ != 0) pi_->weak_release();
|
||||||
|
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||||
|
id_ = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
weak_count & operator= (shared_count const & r) // nothrow
|
||||||
|
{
|
||||||
|
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) // nothrow
|
||||||
|
{
|
||||||
|
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) // nothrow
|
||||||
|
{
|
||||||
|
sp_counted_base * tmp = r.pi_;
|
||||||
|
r.pi_ = pi_;
|
||||||
|
pi_ = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
long use_count() const // nothrow
|
||||||
|
{
|
||||||
|
return pi_ != 0? pi_->use_count(): 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty() const // nothrow
|
||||||
|
{
|
||||||
|
return pi_ == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend inline bool operator==(weak_count const & a, weak_count const & b)
|
||||||
|
{
|
||||||
|
return a.pi_ == b.pi_;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend inline bool operator<(weak_count const & a, weak_count const & b)
|
||||||
|
{
|
||||||
|
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 ): 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
|
||||||
|
|
||||||
|
#ifdef __BORLANDC__
|
||||||
|
# pragma warn .8027 // Functions containing try are not expanded inline
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED
|
||||||
182
include/boost/smart_ptr/detail/shared_ptr_nmt.hpp
Normal file
182
include/boost/smart_ptr/detail/shared_ptr_nmt.hpp
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
#ifndef BOOST_SMART_PTR_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED
|
||||||
|
#define BOOST_SMART_PTR_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED
|
||||||
|
|
||||||
|
//
|
||||||
|
// detail/shared_ptr_nmt.hpp - shared_ptr.hpp without member templates
|
||||||
|
//
|
||||||
|
// (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/shared_ptr.htm for documentation.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/checked_delete.hpp>
|
||||||
|
#include <boost/throw_exception.hpp>
|
||||||
|
#include <boost/smart_ptr/detail/atomic_count.hpp>
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_AUTO_PTR
|
||||||
|
# include <memory> // for std::auto_ptr
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <algorithm> // for std::swap
|
||||||
|
#include <functional> // for std::less
|
||||||
|
#include <new> // for std::bad_alloc
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
template<class T> class shared_ptr
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
typedef detail::atomic_count count_type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef T element_type;
|
||||||
|
typedef T value_type;
|
||||||
|
|
||||||
|
explicit shared_ptr(T * p = 0): px(p)
|
||||||
|
{
|
||||||
|
#ifndef BOOST_NO_EXCEPTIONS
|
||||||
|
|
||||||
|
try // prevent leak if new throws
|
||||||
|
{
|
||||||
|
pn = new count_type(1);
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
boost::checked_delete(p);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
pn = new count_type(1);
|
||||||
|
|
||||||
|
if(pn == 0)
|
||||||
|
{
|
||||||
|
boost::checked_delete(p);
|
||||||
|
boost::throw_exception(std::bad_alloc());
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
~shared_ptr()
|
||||||
|
{
|
||||||
|
if(--*pn == 0)
|
||||||
|
{
|
||||||
|
boost::checked_delete(px);
|
||||||
|
delete pn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_ptr(shared_ptr const & r): px(r.px) // never throws
|
||||||
|
{
|
||||||
|
pn = r.pn;
|
||||||
|
++*pn;
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_ptr & operator=(shared_ptr const & r)
|
||||||
|
{
|
||||||
|
shared_ptr(r).swap(*this);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_AUTO_PTR
|
||||||
|
|
||||||
|
explicit shared_ptr(std::auto_ptr<T> & r)
|
||||||
|
{
|
||||||
|
pn = new count_type(1); // may throw
|
||||||
|
px = r.release(); // fix: moved here to stop leak if new throws
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_ptr & operator=(std::auto_ptr<T> & r)
|
||||||
|
{
|
||||||
|
shared_ptr(r).swap(*this);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void reset(T * p = 0)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(p == 0 || p != px);
|
||||||
|
shared_ptr(p).swap(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
T & operator*() const // never throws
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(px != 0);
|
||||||
|
return *px;
|
||||||
|
}
|
||||||
|
|
||||||
|
T * operator->() const // never throws
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(px != 0);
|
||||||
|
return px;
|
||||||
|
}
|
||||||
|
|
||||||
|
T * get() const // never throws
|
||||||
|
{
|
||||||
|
return px;
|
||||||
|
}
|
||||||
|
|
||||||
|
long use_count() const // never throws
|
||||||
|
{
|
||||||
|
return *pn;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool unique() const // never throws
|
||||||
|
{
|
||||||
|
return *pn == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void swap(shared_ptr<T> & other) // never throws
|
||||||
|
{
|
||||||
|
std::swap(px, other.px);
|
||||||
|
std::swap(pn, other.pn);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
T * px; // contained pointer
|
||||||
|
count_type * pn; // ptr to reference counter
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b)
|
||||||
|
{
|
||||||
|
return a.get() == b.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b)
|
||||||
|
{
|
||||||
|
return a.get() != b.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T> inline bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b)
|
||||||
|
{
|
||||||
|
return std::less<T*>()(a.get(), b.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T> void swap(shared_ptr<T> & a, shared_ptr<T> & b)
|
||||||
|
{
|
||||||
|
a.swap(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get_pointer() enables boost::mem_fn to recognize shared_ptr
|
||||||
|
|
||||||
|
template<class T> inline T * get_pointer(shared_ptr<T> const & p)
|
||||||
|
{
|
||||||
|
return p.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED
|
||||||
76
include/boost/smart_ptr/detail/sp_convertible.hpp
Normal file
76
include/boost/smart_ptr/detail/sp_convertible.hpp
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
#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>
|
||||||
|
|
||||||
|
#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) };
|
||||||
|
};
|
||||||
|
|
||||||
|
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
|
||||||
70
include/boost/smart_ptr/detail/sp_counted_base.hpp
Normal file
70
include/boost/smart_ptr/detail/sp_counted_base.hpp
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
#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, 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)
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#include <boost/smart_ptr/detail/sp_has_sync.hpp>
|
||||||
|
|
||||||
|
#if defined( BOOST_SP_DISABLE_THREADS )
|
||||||
|
# include <boost/smart_ptr/detail/sp_counted_base_nt.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( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) )
|
||||||
|
# include <boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp>
|
||||||
|
|
||||||
|
#elif defined( __GNUC__ ) && defined( __ia64__ ) && !defined( __INTEL_COMPILER )
|
||||||
|
# include <boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp>
|
||||||
|
|
||||||
|
#elif defined(__HP_aCC) && defined(__ia64)
|
||||||
|
# include <boost/smart_ptr/detail/sp_counted_base_acc_ia64.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 ) )
|
||||||
|
# include <boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp>
|
||||||
|
|
||||||
|
#elif defined( __GNUC__ ) && ( defined( __mips__ ) || defined( _mips ) )
|
||||||
|
# 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( 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
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED
|
||||||
150
include/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp
Normal file
150
include/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
#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/detail/sp_typeinfo.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 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;
|
||||||
|
|
||||||
|
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
|
||||||
170
include/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp
Normal file
170
include/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
#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/detail/sp_typeinfo.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 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;
|
||||||
|
|
||||||
|
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
|
||||||
158
include/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp
Normal file
158
include/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
#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/detail/sp_typeinfo.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 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;
|
||||||
|
|
||||||
|
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
|
||||||
157
include/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp
Normal file
157
include/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
#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/detail/sp_typeinfo.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 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;
|
||||||
|
|
||||||
|
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
|
||||||
172
include/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp
Normal file
172
include/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
#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/detail/sp_typeinfo.hpp>
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
inline void atomic_increment( int * pw )
|
||||||
|
{
|
||||||
|
// ++*pw;
|
||||||
|
|
||||||
|
int tmp;
|
||||||
|
|
||||||
|
__asm__ __volatile__
|
||||||
|
(
|
||||||
|
"0:\n\t"
|
||||||
|
"ll %0, %1\n\t"
|
||||||
|
"addiu %0, 1\n\t"
|
||||||
|
"sc %0, %1\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"
|
||||||
|
"ll %1, %2\n\t"
|
||||||
|
"addiu %0, %1, -1\n\t"
|
||||||
|
"sc %0, %2\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"
|
||||||
|
"ll %0, %2\n\t"
|
||||||
|
"beqz %0, 1f\n\t"
|
||||||
|
"addiu %1, %0, 1\n\t"
|
||||||
|
"sc %1, %2\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 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;
|
||||||
|
|
||||||
|
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
|
||||||
181
include/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp
Normal file
181
include/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
#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/detail/sp_typeinfo.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 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;
|
||||||
|
|
||||||
|
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
|
||||||
166
include/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp
Normal file
166
include/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
#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/detail/sp_typeinfo.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 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;
|
||||||
|
|
||||||
|
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
|
||||||
173
include/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp
Normal file
173
include/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
#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/detail/sp_typeinfo.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 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;
|
||||||
|
|
||||||
|
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
|
||||||
107
include/boost/smart_ptr/detail/sp_counted_base_nt.hpp
Normal file
107
include/boost/smart_ptr/detail/sp_counted_base_nt.hpp
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
#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/detail/sp_typeinfo.hpp>
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
class 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;
|
||||||
|
|
||||||
|
void add_ref_copy()
|
||||||
|
{
|
||||||
|
++use_count_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool add_ref_lock() // true on success
|
||||||
|
{
|
||||||
|
if( use_count_ == 0 ) return false;
|
||||||
|
++use_count_;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void release() // nothrow
|
||||||
|
{
|
||||||
|
if( --use_count_ == 0 )
|
||||||
|
{
|
||||||
|
dispose();
|
||||||
|
weak_release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void weak_add_ref() // nothrow
|
||||||
|
{
|
||||||
|
++weak_count_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void weak_release() // nothrow
|
||||||
|
{
|
||||||
|
if( --weak_count_ == 0 )
|
||||||
|
{
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
long use_count() const // nothrow
|
||||||
|
{
|
||||||
|
return use_count_;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED
|
||||||
135
include/boost/smart_ptr/detail/sp_counted_base_pt.hpp
Normal file
135
include/boost/smart_ptr/detail/sp_counted_base_pt.hpp
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
#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/detail/sp_typeinfo.hpp>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
class 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)
|
||||||
|
|
||||||
|
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_)
|
||||||
|
pthread_mutex_init( &m_, pthread_mutexattr_default );
|
||||||
|
#else
|
||||||
|
pthread_mutex_init( &m_, 0 );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~sp_counted_base() // nothrow
|
||||||
|
{
|
||||||
|
pthread_mutex_destroy( &m_ );
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
void add_ref_copy()
|
||||||
|
{
|
||||||
|
pthread_mutex_lock( &m_ );
|
||||||
|
++use_count_;
|
||||||
|
pthread_mutex_unlock( &m_ );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool add_ref_lock() // true on success
|
||||||
|
{
|
||||||
|
pthread_mutex_lock( &m_ );
|
||||||
|
bool r = use_count_ == 0? false: ( ++use_count_, true );
|
||||||
|
pthread_mutex_unlock( &m_ );
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void release() // nothrow
|
||||||
|
{
|
||||||
|
pthread_mutex_lock( &m_ );
|
||||||
|
long new_use_count = --use_count_;
|
||||||
|
pthread_mutex_unlock( &m_ );
|
||||||
|
|
||||||
|
if( new_use_count == 0 )
|
||||||
|
{
|
||||||
|
dispose();
|
||||||
|
weak_release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void weak_add_ref() // nothrow
|
||||||
|
{
|
||||||
|
pthread_mutex_lock( &m_ );
|
||||||
|
++weak_count_;
|
||||||
|
pthread_mutex_unlock( &m_ );
|
||||||
|
}
|
||||||
|
|
||||||
|
void weak_release() // nothrow
|
||||||
|
{
|
||||||
|
pthread_mutex_lock( &m_ );
|
||||||
|
long new_weak_count = --weak_count_;
|
||||||
|
pthread_mutex_unlock( &m_ );
|
||||||
|
|
||||||
|
if( new_weak_count == 0 )
|
||||||
|
{
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
long use_count() const // nothrow
|
||||||
|
{
|
||||||
|
pthread_mutex_lock( &m_ );
|
||||||
|
long r = use_count_;
|
||||||
|
pthread_mutex_unlock( &m_ );
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED
|
||||||
113
include/boost/smart_ptr/detail/sp_counted_base_solaris.hpp
Normal file
113
include/boost/smart_ptr/detail/sp_counted_base_solaris.hpp
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
#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/detail/sp_typeinfo.hpp>
|
||||||
|
#include <atomic.h>
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
class 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;
|
||||||
|
|
||||||
|
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
|
||||||
131
include/boost/smart_ptr/detail/sp_counted_base_spin.hpp
Normal file
131
include/boost/smart_ptr/detail/sp_counted_base_spin.hpp
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
#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/detail/sp_typeinfo.hpp>
|
||||||
|
#include <boost/smart_ptr/detail/spinlock_pool.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 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;
|
||||||
|
|
||||||
|
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
|
||||||
155
include/boost/smart_ptr/detail/sp_counted_base_sync.hpp
Normal file
155
include/boost/smart_ptr/detail/sp_counted_base_sync.hpp
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED
|
||||||
|
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED
|
||||||
|
|
||||||
|
// MS compatible compilers support #pragma once
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||||
|
# pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// detail/sp_counted_base_sync.hpp - g++ 4.1+ __sync intrinsics
|
||||||
|
//
|
||||||
|
// Copyright (c) 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
|
||||||
|
|
||||||
|
#include <boost/detail/sp_typeinfo.hpp>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#if defined( __ia64__ ) && defined( __INTEL_COMPILER )
|
||||||
|
# include <ia64intrin.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
#if INT_MAX >= 2147483647
|
||||||
|
|
||||||
|
typedef int sp_int32_t;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
typedef long sp_int32_t;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline void atomic_increment( sp_int32_t * pw )
|
||||||
|
{
|
||||||
|
__sync_fetch_and_add( pw, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
inline sp_int32_t atomic_decrement( sp_int32_t * pw )
|
||||||
|
{
|
||||||
|
return __sync_fetch_and_add( pw, -1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
inline sp_int32_t atomic_conditional_increment( sp_int32_t * pw )
|
||||||
|
{
|
||||||
|
// long r = *pw;
|
||||||
|
// if( r != 0 ) ++*pw;
|
||||||
|
// return r;
|
||||||
|
|
||||||
|
sp_int32_t r = *pw;
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
if( r == 0 )
|
||||||
|
{
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
sp_int32_t r2 = __sync_val_compare_and_swap( pw, r, r + 1 );
|
||||||
|
|
||||||
|
if( r2 == r )
|
||||||
|
{
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
r = r2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class sp_counted_base
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
sp_counted_base( sp_counted_base const & );
|
||||||
|
sp_counted_base & operator= ( sp_counted_base const & );
|
||||||
|
|
||||||
|
sp_int32_t use_count_; // #shared
|
||||||
|
sp_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;
|
||||||
|
|
||||||
|
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< sp_int32_t const volatile & >( use_count_ );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED
|
||||||
130
include/boost/smart_ptr/detail/sp_counted_base_w32.hpp
Normal file
130
include/boost/smart_ptr/detail/sp_counted_base_w32.hpp
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED
|
||||||
|
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED
|
||||||
|
|
||||||
|
// MS compatible compilers support #pragma once
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||||
|
# pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// detail/sp_counted_base_w32.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)
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Lock-free algorithm by Alexander Terekhov
|
||||||
|
//
|
||||||
|
// Thanks to Ben Hitchings for the #weak + (#shared != 0)
|
||||||
|
// formulation
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <boost/detail/interlocked.hpp>
|
||||||
|
#include <boost/detail/workaround.hpp>
|
||||||
|
#include <boost/detail/sp_typeinfo.hpp>
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
class 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;
|
||||||
|
|
||||||
|
void add_ref_copy()
|
||||||
|
{
|
||||||
|
BOOST_INTERLOCKED_INCREMENT( &use_count_ );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool add_ref_lock() // true on success
|
||||||
|
{
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
long tmp = static_cast< long const volatile& >( use_count_ );
|
||||||
|
if( tmp == 0 ) return false;
|
||||||
|
|
||||||
|
#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, == 1200 )
|
||||||
|
|
||||||
|
// work around a code generation bug
|
||||||
|
|
||||||
|
long tmp2 = tmp + 1;
|
||||||
|
if( BOOST_INTERLOCKED_COMPARE_EXCHANGE( &use_count_, tmp2, tmp ) == tmp2 - 1 ) return true;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
if( BOOST_INTERLOCKED_COMPARE_EXCHANGE( &use_count_, tmp + 1, tmp ) == tmp ) return true;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void release() // nothrow
|
||||||
|
{
|
||||||
|
if( BOOST_INTERLOCKED_DECREMENT( &use_count_ ) == 0 )
|
||||||
|
{
|
||||||
|
dispose();
|
||||||
|
weak_release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void weak_add_ref() // nothrow
|
||||||
|
{
|
||||||
|
BOOST_INTERLOCKED_INCREMENT( &weak_count_ );
|
||||||
|
}
|
||||||
|
|
||||||
|
void weak_release() // nothrow
|
||||||
|
{
|
||||||
|
if( BOOST_INTERLOCKED_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_W32_HPP_INCLUDED
|
||||||
231
include/boost/smart_ptr/detail/sp_counted_impl.hpp
Normal file
231
include/boost/smart_ptr/detail/sp_counted_impl.hpp
Normal file
@@ -0,0 +1,231 @@
|
|||||||
|
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED
|
||||||
|
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED
|
||||||
|
|
||||||
|
// MS compatible compilers support #pragma once
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||||
|
# pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// detail/sp_counted_impl.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/config.hpp>
|
||||||
|
|
||||||
|
#if defined(BOOST_SP_USE_STD_ALLOCATOR) && defined(BOOST_SP_USE_QUICK_ALLOCATOR)
|
||||||
|
# error BOOST_SP_USE_STD_ALLOCATOR and BOOST_SP_USE_QUICK_ALLOCATOR are incompatible.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/checked_delete.hpp>
|
||||||
|
#include <boost/smart_ptr/detail/sp_counted_base.hpp>
|
||||||
|
|
||||||
|
#if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
|
||||||
|
#include <boost/smart_ptr/detail/quick_allocator.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(BOOST_SP_USE_STD_ALLOCATOR)
|
||||||
|
#include <memory> // std::allocator
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <cstddef> // std::size_t
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||||
|
|
||||||
|
void sp_scalar_constructor_hook( void * px, std::size_t size, void * pn );
|
||||||
|
void sp_scalar_destructor_hook( void * px, std::size_t size, void * pn );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
template<class X> class sp_counted_impl_p: public sp_counted_base
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
X * px_;
|
||||||
|
|
||||||
|
sp_counted_impl_p( sp_counted_impl_p const & );
|
||||||
|
sp_counted_impl_p & operator= ( sp_counted_impl_p const & );
|
||||||
|
|
||||||
|
typedef sp_counted_impl_p<X> this_type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit sp_counted_impl_p( X * px ): px_( px )
|
||||||
|
{
|
||||||
|
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||||
|
boost::sp_scalar_constructor_hook( px, sizeof(X), this );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void dispose() // nothrow
|
||||||
|
{
|
||||||
|
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||||
|
boost::sp_scalar_destructor_hook( px_, sizeof(X), this );
|
||||||
|
#endif
|
||||||
|
boost::checked_delete( px_ );
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void * get_deleter( detail::sp_typeinfo const & )
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(BOOST_SP_USE_STD_ALLOCATOR)
|
||||||
|
|
||||||
|
void * operator new( std::size_t )
|
||||||
|
{
|
||||||
|
return std::allocator<this_type>().allocate( 1, static_cast<this_type *>(0) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete( void * p )
|
||||||
|
{
|
||||||
|
std::allocator<this_type>().deallocate( static_cast<this_type *>(p), 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
|
||||||
|
|
||||||
|
void * operator new( std::size_t )
|
||||||
|
{
|
||||||
|
return quick_allocator<this_type>::alloc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete( void * p )
|
||||||
|
{
|
||||||
|
quick_allocator<this_type>::dealloc( p );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Borland's Codeguard trips up over the -Vx- option here:
|
||||||
|
//
|
||||||
|
#ifdef __CODEGUARD__
|
||||||
|
# pragma option push -Vx-
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<class P, class D> class sp_counted_impl_pd: public sp_counted_base
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
P ptr; // copy constructor must not throw
|
||||||
|
D del; // copy constructor must not throw
|
||||||
|
|
||||||
|
sp_counted_impl_pd( sp_counted_impl_pd const & );
|
||||||
|
sp_counted_impl_pd & operator= ( sp_counted_impl_pd const & );
|
||||||
|
|
||||||
|
typedef sp_counted_impl_pd<P, D> this_type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// pre: d(p) must not throw
|
||||||
|
|
||||||
|
sp_counted_impl_pd( P p, D d ): ptr(p), del(d)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void dispose() // nothrow
|
||||||
|
{
|
||||||
|
del( ptr );
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void * get_deleter( detail::sp_typeinfo const & ti )
|
||||||
|
{
|
||||||
|
return ti == BOOST_SP_TYPEID(D)? &reinterpret_cast<char&>( del ): 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(BOOST_SP_USE_STD_ALLOCATOR)
|
||||||
|
|
||||||
|
void * operator new( std::size_t )
|
||||||
|
{
|
||||||
|
return std::allocator<this_type>().allocate( 1, static_cast<this_type *>(0) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete( void * p )
|
||||||
|
{
|
||||||
|
std::allocator<this_type>().deallocate( static_cast<this_type *>(p), 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
|
||||||
|
|
||||||
|
void * operator new( std::size_t )
|
||||||
|
{
|
||||||
|
return quick_allocator<this_type>::alloc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete( void * p )
|
||||||
|
{
|
||||||
|
quick_allocator<this_type>::dealloc( p );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class P, class D, class A> class sp_counted_impl_pda: public sp_counted_base
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
P p_; // copy constructor must not throw
|
||||||
|
D d_; // copy constructor must not throw
|
||||||
|
A a_; // copy constructor must not throw
|
||||||
|
|
||||||
|
sp_counted_impl_pda( sp_counted_impl_pda const & );
|
||||||
|
sp_counted_impl_pda & operator= ( sp_counted_impl_pda const & );
|
||||||
|
|
||||||
|
typedef sp_counted_impl_pda<P, D, A> this_type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// pre: d( p ) must not throw
|
||||||
|
|
||||||
|
sp_counted_impl_pda( P p, D d, A a ): p_( p ), d_( d ), a_( a )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void dispose() // nothrow
|
||||||
|
{
|
||||||
|
d_( p_ );
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void destroy() // nothrow
|
||||||
|
{
|
||||||
|
typedef typename A::template rebind< this_type >::other A2;
|
||||||
|
|
||||||
|
A2 a2( a_ );
|
||||||
|
|
||||||
|
this->~this_type();
|
||||||
|
a2.deallocate( this, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void * get_deleter( detail::sp_typeinfo const & ti )
|
||||||
|
{
|
||||||
|
return ti == BOOST_SP_TYPEID( D )? &reinterpret_cast<char&>( d_ ): 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __CODEGUARD__
|
||||||
|
# pragma option pop
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED
|
||||||
49
include/boost/smart_ptr/detail/sp_has_sync.hpp
Normal file
49
include/boost/smart_ptr/detail/sp_has_sync.hpp
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#ifndef BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_HPP_INCLUDED
|
||||||
|
#define BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_HPP_INCLUDED
|
||||||
|
|
||||||
|
// MS compatible compilers support #pragma once
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||||
|
# pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// boost/smart_ptr/detail/sp_has_sync.hpp
|
||||||
|
//
|
||||||
|
// Copyright (c) 2008, 2009 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)
|
||||||
|
//
|
||||||
|
// Defines the BOOST_SP_HAS_SYNC macro if the __sync_* intrinsics
|
||||||
|
// are available.
|
||||||
|
//
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 )
|
||||||
|
|
||||||
|
#define BOOST_SP_HAS_SYNC
|
||||||
|
|
||||||
|
#if defined( __arm__ ) || defined( __armel__ )
|
||||||
|
#undef BOOST_SP_HAS_SYNC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( __hppa ) || defined( __hppa__ )
|
||||||
|
#undef BOOST_SP_HAS_SYNC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( __m68k__ )
|
||||||
|
#undef BOOST_SP_HAS_SYNC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( __sparc__ )
|
||||||
|
#undef BOOST_SP_HAS_SYNC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( __INTEL_COMPILER ) && !defined( __ia64__ ) && ( __INTEL_COMPILER < 1100 )
|
||||||
|
#undef BOOST_SP_HAS_SYNC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // __GNUC__ * 100 + __GNUC_MINOR__ >= 401
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_HPP_INCLUDED
|
||||||
53
include/boost/smart_ptr/detail/spinlock.hpp
Normal file
53
include/boost/smart_ptr/detail/spinlock.hpp
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_HPP_INCLUDED
|
||||||
|
#define BOOST_SMART_PTR_DETAIL_SPINLOCK_HPP_INCLUDED
|
||||||
|
|
||||||
|
// MS compatible compilers support #pragma once
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||||
|
# pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// boost/detail/spinlock.hpp
|
||||||
|
//
|
||||||
|
// 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)
|
||||||
|
//
|
||||||
|
// struct spinlock
|
||||||
|
// {
|
||||||
|
// void lock();
|
||||||
|
// bool try_lock();
|
||||||
|
// void unlock();
|
||||||
|
//
|
||||||
|
// class scoped_lock;
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// #define BOOST_DETAIL_SPINLOCK_INIT <unspecified>
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#include <boost/smart_ptr/detail/sp_has_sync.hpp>
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && defined( __arm__ ) && !defined( __thumb__ )
|
||||||
|
# include <boost/smart_ptr/detail/spinlock_gcc_arm.hpp>
|
||||||
|
|
||||||
|
#elif defined( BOOST_SP_HAS_SYNC )
|
||||||
|
# include <boost/smart_ptr/detail/spinlock_sync.hpp>
|
||||||
|
|
||||||
|
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
|
||||||
|
# include <boost/smart_ptr/detail/spinlock_w32.hpp>
|
||||||
|
|
||||||
|
#elif defined(BOOST_HAS_PTHREADS)
|
||||||
|
# include <boost/smart_ptr/detail/spinlock_pt.hpp>
|
||||||
|
|
||||||
|
#elif !defined(BOOST_HAS_THREADS)
|
||||||
|
# include <boost/smart_ptr/detail/spinlock_nt.hpp>
|
||||||
|
|
||||||
|
#else
|
||||||
|
# error Unrecognized threading platform
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_HPP_INCLUDED
|
||||||
85
include/boost/smart_ptr/detail/spinlock_gcc_arm.hpp
Normal file
85
include/boost/smart_ptr/detail/spinlock_gcc_arm.hpp
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED
|
||||||
|
#define BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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/smart_ptr/detail/yield_k.hpp>
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
class spinlock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
int v_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
bool try_lock()
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"swp %0, %1, [%2]":
|
||||||
|
"=&r"( r ): // outputs
|
||||||
|
"r"( 1 ), "r"( &v_ ): // inputs
|
||||||
|
"memory", "cc" );
|
||||||
|
|
||||||
|
return r == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lock()
|
||||||
|
{
|
||||||
|
for( unsigned k = 0; !try_lock(); ++k )
|
||||||
|
{
|
||||||
|
boost::detail::yield( k );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void unlock()
|
||||||
|
{
|
||||||
|
__asm__ __volatile__( "" ::: "memory" );
|
||||||
|
*const_cast< int volatile* >( &v_ ) = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
class scoped_lock
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
spinlock & sp_;
|
||||||
|
|
||||||
|
scoped_lock( scoped_lock const & );
|
||||||
|
scoped_lock & operator=( scoped_lock const & );
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit scoped_lock( spinlock & sp ): sp_( sp )
|
||||||
|
{
|
||||||
|
sp.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
~scoped_lock()
|
||||||
|
{
|
||||||
|
sp_.unlock();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#define BOOST_DETAIL_SPINLOCK_INIT {0}
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED
|
||||||
89
include/boost/smart_ptr/detail/spinlock_nt.hpp
Normal file
89
include/boost/smart_ptr/detail/spinlock_nt.hpp
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_NT_HPP_INCLUDED
|
||||||
|
#define BOOST_SMART_PTR_DETAIL_SPINLOCK_NT_HPP_INCLUDED
|
||||||
|
|
||||||
|
// MS compatible compilers support #pragma once
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||||
|
# pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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/assert.hpp>
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
class spinlock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
bool locked_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
inline bool try_lock()
|
||||||
|
{
|
||||||
|
if( locked_ )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
locked_ = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void lock()
|
||||||
|
{
|
||||||
|
BOOST_ASSERT( !locked_ );
|
||||||
|
locked_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void unlock()
|
||||||
|
{
|
||||||
|
BOOST_ASSERT( locked_ );
|
||||||
|
locked_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
class scoped_lock
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
spinlock & sp_;
|
||||||
|
|
||||||
|
scoped_lock( scoped_lock const & );
|
||||||
|
scoped_lock & operator=( scoped_lock const & );
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit scoped_lock( spinlock & sp ): sp_( sp )
|
||||||
|
{
|
||||||
|
sp.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
~scoped_lock()
|
||||||
|
{
|
||||||
|
sp_.unlock();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#define BOOST_DETAIL_SPINLOCK_INIT { false }
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_NT_HPP_INCLUDED
|
||||||
87
include/boost/smart_ptr/detail/spinlock_pool.hpp
Normal file
87
include/boost/smart_ptr/detail/spinlock_pool.hpp
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_POOL_HPP_INCLUDED
|
||||||
|
#define BOOST_SMART_PTR_DETAIL_SPINLOCK_POOL_HPP_INCLUDED
|
||||||
|
|
||||||
|
// MS compatible compilers support #pragma once
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||||
|
# pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// boost/detail/spinlock_pool.hpp
|
||||||
|
//
|
||||||
|
// 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)
|
||||||
|
//
|
||||||
|
// spinlock_pool<0> is reserved for atomic<>, when/if it arrives
|
||||||
|
// spinlock_pool<1> is reserved for shared_ptr reference counts
|
||||||
|
// spinlock_pool<2> is reserved for shared_ptr atomic access
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#include <boost/smart_ptr/detail/spinlock.hpp>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
template< int I > class spinlock_pool
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
static spinlock pool_[ 41 ];
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
static spinlock & spinlock_for( void const * pv )
|
||||||
|
{
|
||||||
|
std::size_t i = reinterpret_cast< std::size_t >( pv ) % 41;
|
||||||
|
return pool_[ i ];
|
||||||
|
}
|
||||||
|
|
||||||
|
class scoped_lock
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
spinlock & sp_;
|
||||||
|
|
||||||
|
scoped_lock( scoped_lock const & );
|
||||||
|
scoped_lock & operator=( scoped_lock const & );
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit scoped_lock( void const * pv ): sp_( spinlock_for( pv ) )
|
||||||
|
{
|
||||||
|
sp_.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
~scoped_lock()
|
||||||
|
{
|
||||||
|
sp_.unlock();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template< int I > spinlock spinlock_pool< I >::pool_[ 41 ] =
|
||||||
|
{
|
||||||
|
BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
|
||||||
|
BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
|
||||||
|
BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
|
||||||
|
BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
|
||||||
|
BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
|
||||||
|
BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
|
||||||
|
BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
|
||||||
|
BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
|
||||||
|
BOOST_DETAIL_SPINLOCK_INIT
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_POOL_HPP_INCLUDED
|
||||||
79
include/boost/smart_ptr/detail/spinlock_pt.hpp
Normal file
79
include/boost/smart_ptr/detail/spinlock_pt.hpp
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_PT_HPP_INCLUDED
|
||||||
|
#define BOOST_SMART_PTR_DETAIL_SPINLOCK_PT_HPP_INCLUDED
|
||||||
|
|
||||||
|
// MS compatible compilers support #pragma once
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||||
|
# pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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 <pthread.h>
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
class spinlock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
pthread_mutex_t v_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
bool try_lock()
|
||||||
|
{
|
||||||
|
return pthread_mutex_trylock( &v_ ) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lock()
|
||||||
|
{
|
||||||
|
pthread_mutex_lock( &v_ );
|
||||||
|
}
|
||||||
|
|
||||||
|
void unlock()
|
||||||
|
{
|
||||||
|
pthread_mutex_unlock( &v_ );
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
class scoped_lock
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
spinlock & sp_;
|
||||||
|
|
||||||
|
scoped_lock( scoped_lock const & );
|
||||||
|
scoped_lock & operator=( scoped_lock const & );
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit scoped_lock( spinlock & sp ): sp_( sp )
|
||||||
|
{
|
||||||
|
sp.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
~scoped_lock()
|
||||||
|
{
|
||||||
|
sp_.unlock();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#define BOOST_DETAIL_SPINLOCK_INIT { PTHREAD_MUTEX_INITIALIZER }
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_PT_HPP_INCLUDED
|
||||||
87
include/boost/smart_ptr/detail/spinlock_sync.hpp
Normal file
87
include/boost/smart_ptr/detail/spinlock_sync.hpp
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED
|
||||||
|
#define BOOST_SMART_PTR_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED
|
||||||
|
|
||||||
|
// MS compatible compilers support #pragma once
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||||
|
# pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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/smart_ptr/detail/yield_k.hpp>
|
||||||
|
|
||||||
|
#if defined( __ia64__ ) && defined( __INTEL_COMPILER )
|
||||||
|
# include <ia64intrin.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
class spinlock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
int v_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
bool try_lock()
|
||||||
|
{
|
||||||
|
int r = __sync_lock_test_and_set( &v_, 1 );
|
||||||
|
return r == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lock()
|
||||||
|
{
|
||||||
|
for( unsigned k = 0; !try_lock(); ++k )
|
||||||
|
{
|
||||||
|
boost::detail::yield( k );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void unlock()
|
||||||
|
{
|
||||||
|
__sync_lock_release( &v_ );
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
class scoped_lock
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
spinlock & sp_;
|
||||||
|
|
||||||
|
scoped_lock( scoped_lock const & );
|
||||||
|
scoped_lock & operator=( scoped_lock const & );
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit scoped_lock( spinlock & sp ): sp_( sp )
|
||||||
|
{
|
||||||
|
sp.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
~scoped_lock()
|
||||||
|
{
|
||||||
|
sp_.unlock();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#define BOOST_DETAIL_SPINLOCK_INIT {0}
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED
|
||||||
113
include/boost/smart_ptr/detail/spinlock_w32.hpp
Normal file
113
include/boost/smart_ptr/detail/spinlock_w32.hpp
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_W32_HPP_INCLUDED
|
||||||
|
#define BOOST_SMART_PTR_DETAIL_SPINLOCK_W32_HPP_INCLUDED
|
||||||
|
|
||||||
|
// MS compatible compilers support #pragma once
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||||
|
# pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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/detail/interlocked.hpp>
|
||||||
|
#include <boost/smart_ptr/detail/yield_k.hpp>
|
||||||
|
|
||||||
|
// BOOST_COMPILER_FENCE
|
||||||
|
|
||||||
|
#if defined(__INTEL_COMPILER)
|
||||||
|
|
||||||
|
#define BOOST_COMPILER_FENCE __memory_barrier();
|
||||||
|
|
||||||
|
#elif defined( _MSC_VER ) && _MSC_VER >= 1310
|
||||||
|
|
||||||
|
extern "C" void _ReadWriteBarrier();
|
||||||
|
#pragma intrinsic( _ReadWriteBarrier )
|
||||||
|
|
||||||
|
#define BOOST_COMPILER_FENCE _ReadWriteBarrier();
|
||||||
|
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
|
||||||
|
#define BOOST_COMPILER_FENCE __asm__ __volatile__( "" : : : "memory" );
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define BOOST_COMPILER_FENCE
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
class spinlock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
long v_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
bool try_lock()
|
||||||
|
{
|
||||||
|
long r = BOOST_INTERLOCKED_EXCHANGE( &v_, 1 );
|
||||||
|
|
||||||
|
BOOST_COMPILER_FENCE
|
||||||
|
|
||||||
|
return r == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lock()
|
||||||
|
{
|
||||||
|
for( unsigned k = 0; !try_lock(); ++k )
|
||||||
|
{
|
||||||
|
boost::detail::yield( k );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void unlock()
|
||||||
|
{
|
||||||
|
BOOST_COMPILER_FENCE
|
||||||
|
*const_cast< long volatile* >( &v_ ) = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
class scoped_lock
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
spinlock & sp_;
|
||||||
|
|
||||||
|
scoped_lock( scoped_lock const & );
|
||||||
|
scoped_lock & operator=( scoped_lock const & );
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit scoped_lock( spinlock & sp ): sp_( sp )
|
||||||
|
{
|
||||||
|
sp.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
~scoped_lock()
|
||||||
|
{
|
||||||
|
sp_.unlock();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#define BOOST_DETAIL_SPINLOCK_INIT {0}
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_W32_HPP_INCLUDED
|
||||||
149
include/boost/smart_ptr/detail/yield_k.hpp
Normal file
149
include/boost/smart_ptr/detail/yield_k.hpp
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
#ifndef BOOST_SMART_PTR_DETAIL_YIELD_K_HPP_INCLUDED
|
||||||
|
#define BOOST_SMART_PTR_DETAIL_YIELD_K_HPP_INCLUDED
|
||||||
|
|
||||||
|
// MS compatible compilers support #pragma once
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||||
|
# pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// yield_k.hpp
|
||||||
|
//
|
||||||
|
// Copyright (c) 2008 Peter Dimov
|
||||||
|
//
|
||||||
|
// void yield( unsigned k );
|
||||||
|
//
|
||||||
|
// Typical use:
|
||||||
|
//
|
||||||
|
// for( unsigned k = 0; !try_lock(); ++k ) yield( k );
|
||||||
|
//
|
||||||
|
// 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>
|
||||||
|
|
||||||
|
// BOOST_SMT_PAUSE
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER >= 1310 && ( defined(_M_IX86) || defined(_M_X64) )
|
||||||
|
|
||||||
|
extern "C" void _mm_pause();
|
||||||
|
#pragma intrinsic( _mm_pause )
|
||||||
|
|
||||||
|
#define BOOST_SMT_PAUSE _mm_pause();
|
||||||
|
|
||||||
|
#elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
|
||||||
|
|
||||||
|
#define BOOST_SMT_PAUSE __asm__ __volatile__( "rep; nop" : : : "memory" );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined( __CYGWIN__ )
|
||||||
|
|
||||||
|
#if defined( BOOST_USE_WINDOWS_H )
|
||||||
|
# include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
#if !defined( BOOST_USE_WINDOWS_H )
|
||||||
|
extern "C" void __stdcall Sleep( unsigned ms );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline void yield( unsigned k )
|
||||||
|
{
|
||||||
|
if( k < 4 )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#if defined( BOOST_SMT_PAUSE )
|
||||||
|
else if( k < 16 )
|
||||||
|
{
|
||||||
|
BOOST_SMT_PAUSE
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else if( k < 32 )
|
||||||
|
{
|
||||||
|
Sleep( 0 );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Sleep( 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#elif defined( BOOST_HAS_PTHREADS )
|
||||||
|
|
||||||
|
#include <sched.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
inline void yield( unsigned k )
|
||||||
|
{
|
||||||
|
if( k < 4 )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#if defined( BOOST_SMT_PAUSE )
|
||||||
|
else if( k < 16 )
|
||||||
|
{
|
||||||
|
BOOST_SMT_PAUSE
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else if( k < 32 || k & 1 )
|
||||||
|
{
|
||||||
|
sched_yield();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// g++ -Wextra warns on {} or {0}
|
||||||
|
struct timespec rqtp = { 0, 0 };
|
||||||
|
|
||||||
|
// POSIX says that timespec has tv_sec and tv_nsec
|
||||||
|
// But it doesn't guarantee order or placement
|
||||||
|
|
||||||
|
rqtp.tv_sec = 0;
|
||||||
|
rqtp.tv_nsec = 1000;
|
||||||
|
|
||||||
|
nanosleep( &rqtp, 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
inline void yield( unsigned )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_SMART_PTR_DETAIL_YIELD_K_HPP_INCLUDED
|
||||||
79
include/boost/smart_ptr/enable_shared_from_this.hpp
Normal file
79
include/boost/smart_ptr/enable_shared_from_this.hpp
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
#ifndef BOOST_SMART_PTR_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
|
||||||
|
#define BOOST_SMART_PTR_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
|
||||||
|
|
||||||
|
//
|
||||||
|
// enable_shared_from_this.hpp
|
||||||
|
//
|
||||||
|
// Copyright 2002, 2009 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
|
||||||
|
//
|
||||||
|
// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <boost/smart_ptr/weak_ptr.hpp>
|
||||||
|
#include <boost/smart_ptr/shared_ptr.hpp>
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
template<class T> class enable_shared_from_this
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
enable_shared_from_this()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
enable_shared_from_this(enable_shared_from_this const &)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
enable_shared_from_this & operator=(enable_shared_from_this const &)
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
~enable_shared_from_this()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
shared_ptr<T> shared_from_this()
|
||||||
|
{
|
||||||
|
shared_ptr<T> p( weak_this_ );
|
||||||
|
BOOST_ASSERT( p.get() == this );
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_ptr<T const> shared_from_this() const
|
||||||
|
{
|
||||||
|
shared_ptr<T const> p( weak_this_ );
|
||||||
|
BOOST_ASSERT( p.get() == this );
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
public: // actually private, but avoids compiler template friendship issues
|
||||||
|
|
||||||
|
// Note: invoked automatically by shared_ptr; do not call
|
||||||
|
template<class X, class Y> void _internal_accept_owner( shared_ptr<X> const * ppx, Y * py ) const
|
||||||
|
{
|
||||||
|
if( weak_this_.expired() )
|
||||||
|
{
|
||||||
|
weak_this_ = shared_ptr<T>( *ppx, py );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
mutable weak_ptr<T> weak_this_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_SMART_PTR_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
|
||||||
132
include/boost/smart_ptr/enable_shared_from_this2.hpp
Normal file
132
include/boost/smart_ptr/enable_shared_from_this2.hpp
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
#ifndef BOOST_ENABLE_SHARED_FROM_THIS2_HPP_INCLUDED
|
||||||
|
#define BOOST_ENABLE_SHARED_FROM_THIS2_HPP_INCLUDED
|
||||||
|
|
||||||
|
//
|
||||||
|
// enable_shared_from_this2.hpp
|
||||||
|
//
|
||||||
|
// Copyright 2002, 2009 Peter Dimov
|
||||||
|
// Copyright 2008 Frank Mori Hess
|
||||||
|
//
|
||||||
|
// 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/assert.hpp>
|
||||||
|
#include <boost/detail/workaround.hpp>
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
class esft2_deleter_wrapper
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
shared_ptr<void> deleter_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
esft2_deleter_wrapper()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T > void set_deleter( shared_ptr<T> const & deleter )
|
||||||
|
{
|
||||||
|
deleter_ = deleter;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T> void operator()( T* )
|
||||||
|
{
|
||||||
|
BOOST_ASSERT( deleter_.use_count() <= 1 );
|
||||||
|
deleter_.reset();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template< class T > class enable_shared_from_this2
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
enable_shared_from_this2()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
enable_shared_from_this2( enable_shared_from_this2 const & )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
enable_shared_from_this2 & operator=( enable_shared_from_this2 const & )
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
~enable_shared_from_this2()
|
||||||
|
{
|
||||||
|
BOOST_ASSERT( shared_this_.use_count() <= 1 ); // make sure no dangling shared_ptr objects exist
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
mutable weak_ptr<T> weak_this_;
|
||||||
|
mutable shared_ptr<T> shared_this_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
shared_ptr<T> shared_from_this()
|
||||||
|
{
|
||||||
|
init_weak_once();
|
||||||
|
return shared_ptr<T>( weak_this_ );
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_ptr<T const> shared_from_this() const
|
||||||
|
{
|
||||||
|
init_weak_once();
|
||||||
|
return shared_ptr<T>( weak_this_ );
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void init_weak_once() const
|
||||||
|
{
|
||||||
|
if( weak_this_._empty() )
|
||||||
|
{
|
||||||
|
shared_this_.reset( static_cast< T* >( 0 ), detail::esft2_deleter_wrapper() );
|
||||||
|
weak_this_ = shared_this_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public: // actually private, but avoids compiler template friendship issues
|
||||||
|
|
||||||
|
// Note: invoked automatically by shared_ptr; do not call
|
||||||
|
template<class X, class Y> void _internal_accept_owner( shared_ptr<X> * ppx, Y * py ) const
|
||||||
|
{
|
||||||
|
BOOST_ASSERT( ppx != 0 );
|
||||||
|
|
||||||
|
if( weak_this_.use_count() == 0 )
|
||||||
|
{
|
||||||
|
weak_this_ = shared_ptr<T>( *ppx, py );
|
||||||
|
}
|
||||||
|
else if( shared_this_.use_count() != 0 )
|
||||||
|
{
|
||||||
|
BOOST_ASSERT( ppx->unique() ); // no weak_ptrs should exist either, but there's no way to check that
|
||||||
|
|
||||||
|
detail::esft2_deleter_wrapper * pd = boost::get_deleter<detail::esft2_deleter_wrapper>( shared_this_ );
|
||||||
|
BOOST_ASSERT( pd != 0 );
|
||||||
|
|
||||||
|
pd->set_deleter( *ppx );
|
||||||
|
|
||||||
|
ppx->reset( shared_this_, ppx->get() );
|
||||||
|
shared_this_.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_ENABLE_SHARED_FROM_THIS2_HPP_INCLUDED
|
||||||
299
include/boost/smart_ptr/intrusive_ptr.hpp
Normal file
299
include/boost/smart_ptr/intrusive_ptr.hpp
Normal file
@@ -0,0 +1,299 @@
|
|||||||
|
#ifndef BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED
|
||||||
|
#define BOOST_SMART_PTR_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/intrusive_ptr.html for documentation.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
|
||||||
|
#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash
|
||||||
|
# pragma warning(push)
|
||||||
|
# pragma warning(disable:4284) // odd return type for operator->
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/detail/workaround.hpp>
|
||||||
|
#include <boost/smart_ptr/detail/sp_convertible.hpp>
|
||||||
|
|
||||||
|
#include <boost/config/no_tr1/functional.hpp> // for std::less
|
||||||
|
|
||||||
|
#if !defined(BOOST_NO_IOSTREAM)
|
||||||
|
#if !defined(BOOST_NO_IOSFWD)
|
||||||
|
#include <iosfwd> // for std::basic_ostream
|
||||||
|
#else
|
||||||
|
#include <ostream>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
//
|
||||||
|
// intrusive_ptr
|
||||||
|
//
|
||||||
|
// A smart pointer that uses intrusive reference counting.
|
||||||
|
//
|
||||||
|
// Relies on unqualified calls to
|
||||||
|
//
|
||||||
|
// void intrusive_ptr_add_ref(T * p);
|
||||||
|
// void intrusive_ptr_release(T * p);
|
||||||
|
//
|
||||||
|
// (p != 0)
|
||||||
|
//
|
||||||
|
// The object is responsible for destroying itself.
|
||||||
|
//
|
||||||
|
|
||||||
|
template<class T> class intrusive_ptr
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
typedef intrusive_ptr this_type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef T element_type;
|
||||||
|
|
||||||
|
intrusive_ptr(): px( 0 )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
intrusive_ptr( T * p, bool add_ref = true ): px( p )
|
||||||
|
{
|
||||||
|
if( px != 0 && add_ref ) intrusive_ptr_add_ref( px );
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES)
|
||||||
|
|
||||||
|
template<class U>
|
||||||
|
#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
|
||||||
|
|
||||||
|
intrusive_ptr( intrusive_ptr<U> const & rhs, typename boost::detail::sp_enable_if_convertible<U,T>::type = boost::detail::sp_empty() )
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
intrusive_ptr( intrusive_ptr<U> const & rhs )
|
||||||
|
|
||||||
|
#endif
|
||||||
|
: px( rhs.get() )
|
||||||
|
{
|
||||||
|
if( px != 0 ) intrusive_ptr_add_ref( px );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
intrusive_ptr(intrusive_ptr const & rhs): px( rhs.px )
|
||||||
|
{
|
||||||
|
if( px != 0 ) intrusive_ptr_add_ref( px );
|
||||||
|
}
|
||||||
|
|
||||||
|
~intrusive_ptr()
|
||||||
|
{
|
||||||
|
if( px != 0 ) intrusive_ptr_release( px );
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES)
|
||||||
|
|
||||||
|
template<class U> intrusive_ptr & operator=(intrusive_ptr<U> const & rhs)
|
||||||
|
{
|
||||||
|
this_type(rhs).swap(*this);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Move support
|
||||||
|
|
||||||
|
#if defined( BOOST_HAS_RVALUE_REFS )
|
||||||
|
|
||||||
|
intrusive_ptr(intrusive_ptr && rhs): px( rhs.px )
|
||||||
|
{
|
||||||
|
rhs.px = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
intrusive_ptr & operator=(intrusive_ptr && rhs)
|
||||||
|
{
|
||||||
|
this_type( static_cast< intrusive_ptr && >( rhs ) ).swap(*this);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
intrusive_ptr & operator=(intrusive_ptr const & rhs)
|
||||||
|
{
|
||||||
|
this_type(rhs).swap(*this);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
intrusive_ptr & operator=(T * rhs)
|
||||||
|
{
|
||||||
|
this_type(rhs).swap(*this);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset()
|
||||||
|
{
|
||||||
|
this_type().swap( *this );
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset( T * rhs )
|
||||||
|
{
|
||||||
|
this_type( rhs ).swap( *this );
|
||||||
|
}
|
||||||
|
|
||||||
|
T * get() const
|
||||||
|
{
|
||||||
|
return px;
|
||||||
|
}
|
||||||
|
|
||||||
|
T & operator*() const
|
||||||
|
{
|
||||||
|
BOOST_ASSERT( px != 0 );
|
||||||
|
return *px;
|
||||||
|
}
|
||||||
|
|
||||||
|
T * operator->() const
|
||||||
|
{
|
||||||
|
BOOST_ASSERT( px != 0 );
|
||||||
|
return px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// implicit conversion to "bool"
|
||||||
|
#include <boost/smart_ptr/detail/operator_bool.hpp>
|
||||||
|
|
||||||
|
void swap(intrusive_ptr & rhs)
|
||||||
|
{
|
||||||
|
T * tmp = px;
|
||||||
|
px = rhs.px;
|
||||||
|
rhs.px = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
T * px;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b)
|
||||||
|
{
|
||||||
|
return a.get() == b.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b)
|
||||||
|
{
|
||||||
|
return a.get() != b.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, U * b)
|
||||||
|
{
|
||||||
|
return a.get() == b;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, U * b)
|
||||||
|
{
|
||||||
|
return a.get() != b;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class U> inline bool operator==(T * a, intrusive_ptr<U> const & b)
|
||||||
|
{
|
||||||
|
return a == b.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class U> inline bool operator!=(T * a, intrusive_ptr<U> const & b)
|
||||||
|
{
|
||||||
|
return a != b.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
|
||||||
|
|
||||||
|
// Resolve the ambiguity between our op!= and the one in rel_ops
|
||||||
|
|
||||||
|
template<class T> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b)
|
||||||
|
{
|
||||||
|
return a.get() != b.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<class T> inline bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b)
|
||||||
|
{
|
||||||
|
return std::less<T *>()(a.get(), b.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T> void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs)
|
||||||
|
{
|
||||||
|
lhs.swap(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// mem_fn support
|
||||||
|
|
||||||
|
template<class T> T * get_pointer(intrusive_ptr<T> const & p)
|
||||||
|
{
|
||||||
|
return p.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class U> intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & p)
|
||||||
|
{
|
||||||
|
return static_cast<T *>(p.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class U> intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & p)
|
||||||
|
{
|
||||||
|
return const_cast<T *>(p.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class U> intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & p)
|
||||||
|
{
|
||||||
|
return dynamic_cast<T *>(p.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
// operator<<
|
||||||
|
|
||||||
|
#if !defined(BOOST_NO_IOSTREAM)
|
||||||
|
|
||||||
|
#if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) )
|
||||||
|
|
||||||
|
template<class Y> std::ostream & operator<< (std::ostream & os, intrusive_ptr<Y> const & p)
|
||||||
|
{
|
||||||
|
os << p.get();
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// in STLport's no-iostreams mode no iostream symbols can be used
|
||||||
|
#ifndef _STLP_NO_IOSTREAMS
|
||||||
|
|
||||||
|
# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT)
|
||||||
|
// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
|
||||||
|
using std::basic_ostream;
|
||||||
|
template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, intrusive_ptr<Y> const & p)
|
||||||
|
# else
|
||||||
|
template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, intrusive_ptr<Y> const & p)
|
||||||
|
# endif
|
||||||
|
{
|
||||||
|
os << p.get();
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // _STLP_NO_IOSTREAMS
|
||||||
|
|
||||||
|
#endif // __GNUC__ < 3
|
||||||
|
|
||||||
|
#endif // !defined(BOOST_NO_IOSTREAM)
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#ifdef BOOST_MSVC
|
||||||
|
# pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED
|
||||||
506
include/boost/smart_ptr/make_shared.hpp
Normal file
506
include/boost/smart_ptr/make_shared.hpp
Normal file
@@ -0,0 +1,506 @@
|
|||||||
|
#ifndef BOOST_SMART_PTR_MAKE_SHARED_HPP_INCLUDED
|
||||||
|
#define BOOST_SMART_PTR_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/make_shared.html
|
||||||
|
// for documentation.
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#include <boost/smart_ptr/shared_ptr.hpp>
|
||||||
|
#include <boost/type_traits/type_with_alignment.hpp>
|
||||||
|
#include <boost/type_traits/alignment_of.hpp>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
template< std::size_t N, std::size_t A > struct sp_aligned_storage
|
||||||
|
{
|
||||||
|
union type
|
||||||
|
{
|
||||||
|
char data_[ N ];
|
||||||
|
typename boost::type_with_alignment< A >::type align_;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template< class T > class sp_ms_deleter
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
typedef typename sp_aligned_storage< sizeof( T ), ::boost::alignment_of< T >::value >::type storage_type;
|
||||||
|
|
||||||
|
bool initialized_;
|
||||||
|
storage_type storage_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void destroy()
|
||||||
|
{
|
||||||
|
if( initialized_ )
|
||||||
|
{
|
||||||
|
reinterpret_cast< T* >( storage_.data_ )->~T();
|
||||||
|
initialized_ = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
sp_ms_deleter(): initialized_( false )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// optimization: do not copy storage_
|
||||||
|
sp_ms_deleter( sp_ms_deleter const & ): initialized_( false )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~sp_ms_deleter()
|
||||||
|
{
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()( T * )
|
||||||
|
{
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void * address()
|
||||||
|
{
|
||||||
|
return storage_.data_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_initialized()
|
||||||
|
{
|
||||||
|
initialized_ = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined( BOOST_HAS_RVALUE_REFS )
|
||||||
|
template< class T > T&& forward( T &&t )
|
||||||
|
{
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
// Zero-argument versions
|
||||||
|
//
|
||||||
|
// Used even when variadic templates are available because of the new T() vs new T issue
|
||||||
|
|
||||||
|
template< class T > boost::shared_ptr< T > make_shared()
|
||||||
|
{
|
||||||
|
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
|
||||||
|
|
||||||
|
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
||||||
|
|
||||||
|
void * pv = pd->address();
|
||||||
|
|
||||||
|
::new( pv ) T();
|
||||||
|
pd->set_initialized();
|
||||||
|
|
||||||
|
T * pt2 = static_cast< T* >( pv );
|
||||||
|
|
||||||
|
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
|
||||||
|
return boost::shared_ptr< T >( pt, pt2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class A > boost::shared_ptr< T > allocate_shared( A const & a )
|
||||||
|
{
|
||||||
|
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a );
|
||||||
|
|
||||||
|
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
||||||
|
|
||||||
|
void * pv = pd->address();
|
||||||
|
|
||||||
|
::new( pv ) T();
|
||||||
|
pd->set_initialized();
|
||||||
|
|
||||||
|
T * pt2 = static_cast< T* >( pv );
|
||||||
|
|
||||||
|
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
|
||||||
|
return boost::shared_ptr< T >( pt, pt2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined( BOOST_HAS_VARIADIC_TMPL ) && defined( BOOST_HAS_RVALUE_REFS )
|
||||||
|
|
||||||
|
// Variadic templates, rvalue reference
|
||||||
|
|
||||||
|
template< class T, class... Args > boost::shared_ptr< T > make_shared( Args && ... args )
|
||||||
|
{
|
||||||
|
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
|
||||||
|
|
||||||
|
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
||||||
|
|
||||||
|
void * pv = pd->address();
|
||||||
|
|
||||||
|
::new( pv ) T( detail::forward<Args>( args )... );
|
||||||
|
pd->set_initialized();
|
||||||
|
|
||||||
|
T * pt2 = static_cast< T* >( pv );
|
||||||
|
|
||||||
|
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
|
||||||
|
return boost::shared_ptr< T >( pt, pt2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class A, class... Args > boost::shared_ptr< T > allocate_shared( A const & a, Args && ... args )
|
||||||
|
{
|
||||||
|
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a );
|
||||||
|
|
||||||
|
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
||||||
|
|
||||||
|
void * pv = pd->address();
|
||||||
|
|
||||||
|
::new( pv ) T( detail::forward<Args>( args )... );
|
||||||
|
pd->set_initialized();
|
||||||
|
|
||||||
|
T * pt2 = static_cast< T* >( pv );
|
||||||
|
|
||||||
|
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
|
||||||
|
return boost::shared_ptr< T >( pt, pt2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// C++03 version
|
||||||
|
|
||||||
|
template< class T, class A1 >
|
||||||
|
boost::shared_ptr< T > make_shared( A1 const & a1 )
|
||||||
|
{
|
||||||
|
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
|
||||||
|
|
||||||
|
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
||||||
|
|
||||||
|
void * pv = pd->address();
|
||||||
|
|
||||||
|
::new( pv ) T( a1 );
|
||||||
|
pd->set_initialized();
|
||||||
|
|
||||||
|
T * pt2 = static_cast< T* >( pv );
|
||||||
|
|
||||||
|
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
|
||||||
|
return boost::shared_ptr< T >( pt, pt2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class A, class A1 >
|
||||||
|
boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1 )
|
||||||
|
{
|
||||||
|
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a );
|
||||||
|
|
||||||
|
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
||||||
|
|
||||||
|
void * pv = pd->address();
|
||||||
|
|
||||||
|
::new( pv ) T( a1 );
|
||||||
|
pd->set_initialized();
|
||||||
|
|
||||||
|
T * pt2 = static_cast< T* >( pv );
|
||||||
|
|
||||||
|
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
|
||||||
|
return boost::shared_ptr< T >( pt, pt2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class A1, class A2 >
|
||||||
|
boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2 )
|
||||||
|
{
|
||||||
|
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
|
||||||
|
|
||||||
|
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
||||||
|
|
||||||
|
void * pv = pd->address();
|
||||||
|
|
||||||
|
::new( pv ) T( a1, a2 );
|
||||||
|
pd->set_initialized();
|
||||||
|
|
||||||
|
T * pt2 = static_cast< T* >( pv );
|
||||||
|
|
||||||
|
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
|
||||||
|
return boost::shared_ptr< T >( pt, pt2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class A, class A1, class A2 >
|
||||||
|
boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2 )
|
||||||
|
{
|
||||||
|
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a );
|
||||||
|
|
||||||
|
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
||||||
|
|
||||||
|
void * pv = pd->address();
|
||||||
|
|
||||||
|
::new( pv ) T( a1, a2 );
|
||||||
|
pd->set_initialized();
|
||||||
|
|
||||||
|
T * pt2 = static_cast< T* >( pv );
|
||||||
|
|
||||||
|
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
|
||||||
|
return boost::shared_ptr< T >( pt, pt2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class A1, class A2, class A3 >
|
||||||
|
boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3 )
|
||||||
|
{
|
||||||
|
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
|
||||||
|
|
||||||
|
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
||||||
|
|
||||||
|
void * pv = pd->address();
|
||||||
|
|
||||||
|
::new( pv ) T( a1, a2, a3 );
|
||||||
|
pd->set_initialized();
|
||||||
|
|
||||||
|
T * pt2 = static_cast< T* >( pv );
|
||||||
|
|
||||||
|
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
|
||||||
|
return boost::shared_ptr< T >( pt, pt2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class A, class A1, class A2, class A3 >
|
||||||
|
boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3 )
|
||||||
|
{
|
||||||
|
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a );
|
||||||
|
|
||||||
|
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
||||||
|
|
||||||
|
void * pv = pd->address();
|
||||||
|
|
||||||
|
::new( pv ) T( a1, a2, a3 );
|
||||||
|
pd->set_initialized();
|
||||||
|
|
||||||
|
T * pt2 = static_cast< T* >( pv );
|
||||||
|
|
||||||
|
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
|
||||||
|
return boost::shared_ptr< T >( pt, pt2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class A1, class A2, class A3, class A4 >
|
||||||
|
boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4 )
|
||||||
|
{
|
||||||
|
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
|
||||||
|
|
||||||
|
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
||||||
|
|
||||||
|
void * pv = pd->address();
|
||||||
|
|
||||||
|
::new( pv ) T( a1, a2, a3, a4 );
|
||||||
|
pd->set_initialized();
|
||||||
|
|
||||||
|
T * pt2 = static_cast< T* >( pv );
|
||||||
|
|
||||||
|
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
|
||||||
|
return boost::shared_ptr< T >( pt, pt2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class A, class A1, class A2, class A3, class A4 >
|
||||||
|
boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4 )
|
||||||
|
{
|
||||||
|
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a );
|
||||||
|
|
||||||
|
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
||||||
|
|
||||||
|
void * pv = pd->address();
|
||||||
|
|
||||||
|
::new( pv ) T( a1, a2, a3, a4 );
|
||||||
|
pd->set_initialized();
|
||||||
|
|
||||||
|
T * pt2 = static_cast< T* >( pv );
|
||||||
|
|
||||||
|
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
|
||||||
|
return boost::shared_ptr< T >( pt, pt2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class A1, class A2, class A3, class A4, class A5 >
|
||||||
|
boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5 )
|
||||||
|
{
|
||||||
|
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
|
||||||
|
|
||||||
|
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
||||||
|
|
||||||
|
void * pv = pd->address();
|
||||||
|
|
||||||
|
::new( pv ) T( a1, a2, a3, a4, a5 );
|
||||||
|
pd->set_initialized();
|
||||||
|
|
||||||
|
T * pt2 = static_cast< T* >( pv );
|
||||||
|
|
||||||
|
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
|
||||||
|
return boost::shared_ptr< T >( pt, pt2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class A, class A1, class A2, class A3, class A4, class A5 >
|
||||||
|
boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5 )
|
||||||
|
{
|
||||||
|
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a );
|
||||||
|
|
||||||
|
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
||||||
|
|
||||||
|
void * pv = pd->address();
|
||||||
|
|
||||||
|
::new( pv ) T( a1, a2, a3, a4, a5 );
|
||||||
|
pd->set_initialized();
|
||||||
|
|
||||||
|
T * pt2 = static_cast< T* >( pv );
|
||||||
|
|
||||||
|
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
|
||||||
|
return boost::shared_ptr< T >( pt, pt2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class A1, class A2, class A3, class A4, class A5, class A6 >
|
||||||
|
boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6 )
|
||||||
|
{
|
||||||
|
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
|
||||||
|
|
||||||
|
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
||||||
|
|
||||||
|
void * pv = pd->address();
|
||||||
|
|
||||||
|
::new( pv ) T( a1, a2, a3, a4, a5, a6 );
|
||||||
|
pd->set_initialized();
|
||||||
|
|
||||||
|
T * pt2 = static_cast< T* >( pv );
|
||||||
|
|
||||||
|
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
|
||||||
|
return boost::shared_ptr< T >( pt, pt2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6 >
|
||||||
|
boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6 )
|
||||||
|
{
|
||||||
|
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a );
|
||||||
|
|
||||||
|
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
||||||
|
|
||||||
|
void * pv = pd->address();
|
||||||
|
|
||||||
|
::new( pv ) T( a1, a2, a3, a4, a5, a6 );
|
||||||
|
pd->set_initialized();
|
||||||
|
|
||||||
|
T * pt2 = static_cast< T* >( pv );
|
||||||
|
|
||||||
|
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
|
||||||
|
return boost::shared_ptr< T >( pt, pt2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 >
|
||||||
|
boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7 )
|
||||||
|
{
|
||||||
|
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
|
||||||
|
|
||||||
|
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
||||||
|
|
||||||
|
void * pv = pd->address();
|
||||||
|
|
||||||
|
::new( pv ) T( a1, a2, a3, a4, a5, a6, a7 );
|
||||||
|
pd->set_initialized();
|
||||||
|
|
||||||
|
T * pt2 = static_cast< T* >( pv );
|
||||||
|
|
||||||
|
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
|
||||||
|
return boost::shared_ptr< T >( pt, pt2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7 >
|
||||||
|
boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7 )
|
||||||
|
{
|
||||||
|
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a );
|
||||||
|
|
||||||
|
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
||||||
|
|
||||||
|
void * pv = pd->address();
|
||||||
|
|
||||||
|
::new( pv ) T( a1, a2, a3, a4, a5, a6, a7 );
|
||||||
|
pd->set_initialized();
|
||||||
|
|
||||||
|
T * pt2 = static_cast< T* >( pv );
|
||||||
|
|
||||||
|
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
|
||||||
|
return boost::shared_ptr< T >( pt, pt2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 >
|
||||||
|
boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8 )
|
||||||
|
{
|
||||||
|
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
|
||||||
|
|
||||||
|
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
||||||
|
|
||||||
|
void * pv = pd->address();
|
||||||
|
|
||||||
|
::new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 );
|
||||||
|
pd->set_initialized();
|
||||||
|
|
||||||
|
T * pt2 = static_cast< T* >( pv );
|
||||||
|
|
||||||
|
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
|
||||||
|
return boost::shared_ptr< T >( pt, pt2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 >
|
||||||
|
boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8 )
|
||||||
|
{
|
||||||
|
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a );
|
||||||
|
|
||||||
|
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
||||||
|
|
||||||
|
void * pv = pd->address();
|
||||||
|
|
||||||
|
::new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 );
|
||||||
|
pd->set_initialized();
|
||||||
|
|
||||||
|
T * pt2 = static_cast< T* >( pv );
|
||||||
|
|
||||||
|
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
|
||||||
|
return boost::shared_ptr< T >( pt, pt2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 >
|
||||||
|
boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8, A9 const & a9 )
|
||||||
|
{
|
||||||
|
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
|
||||||
|
|
||||||
|
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
||||||
|
|
||||||
|
void * pv = pd->address();
|
||||||
|
|
||||||
|
::new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 );
|
||||||
|
pd->set_initialized();
|
||||||
|
|
||||||
|
T * pt2 = static_cast< T* >( pv );
|
||||||
|
|
||||||
|
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
|
||||||
|
return boost::shared_ptr< T >( pt, pt2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 >
|
||||||
|
boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8, A9 const & a9 )
|
||||||
|
{
|
||||||
|
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a );
|
||||||
|
|
||||||
|
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
||||||
|
|
||||||
|
void * pv = pd->address();
|
||||||
|
|
||||||
|
::new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 );
|
||||||
|
pd->set_initialized();
|
||||||
|
|
||||||
|
T * pt2 = static_cast< T* >( pv );
|
||||||
|
|
||||||
|
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
|
||||||
|
return boost::shared_ptr< T >( pt, pt2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_SMART_PTR_MAKE_SHARED_HPP_INCLUDED
|
||||||
107
include/boost/smart_ptr/scoped_array.hpp
Normal file
107
include/boost/smart_ptr/scoped_array.hpp
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
#ifndef BOOST_SMART_PTR_SCOPED_ARRAY_HPP_INCLUDED
|
||||||
|
#define BOOST_SMART_PTR_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)
|
||||||
|
//
|
||||||
|
// http://www.boost.org/libs/smart_ptr/scoped_array.htm
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/checked_delete.hpp>
|
||||||
|
#include <boost/config.hpp> // in case ptrdiff_t not in std
|
||||||
|
|
||||||
|
#include <boost/detail/workaround.hpp>
|
||||||
|
|
||||||
|
#include <cstddef> // for std::ptrdiff_t
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
// Debug hooks
|
||||||
|
|
||||||
|
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||||
|
|
||||||
|
void sp_array_constructor_hook(void * p);
|
||||||
|
void sp_array_destructor_hook(void * p);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to
|
||||||
|
// is guaranteed, either on destruction of the scoped_array or via an explicit
|
||||||
|
// reset(). Use shared_array or std::vector if your needs are more complex.
|
||||||
|
|
||||||
|
template<class T> class scoped_array // noncopyable
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
T * px;
|
||||||
|
|
||||||
|
scoped_array(scoped_array const &);
|
||||||
|
scoped_array & operator=(scoped_array const &);
|
||||||
|
|
||||||
|
typedef scoped_array<T> this_type;
|
||||||
|
|
||||||
|
void operator==( scoped_array const& ) const;
|
||||||
|
void operator!=( scoped_array const& ) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef T element_type;
|
||||||
|
|
||||||
|
explicit scoped_array( T * p = 0 ) : px( p ) // never throws
|
||||||
|
{
|
||||||
|
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||||
|
boost::sp_array_constructor_hook( px );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
~scoped_array() // never throws
|
||||||
|
{
|
||||||
|
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||||
|
boost::sp_array_destructor_hook( px );
|
||||||
|
#endif
|
||||||
|
boost::checked_array_delete( px );
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset(T * p = 0) // never throws
|
||||||
|
{
|
||||||
|
BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors
|
||||||
|
this_type(p).swap(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
T & operator[](std::ptrdiff_t i) const // never throws
|
||||||
|
{
|
||||||
|
BOOST_ASSERT( px != 0 );
|
||||||
|
BOOST_ASSERT( i >= 0 );
|
||||||
|
return px[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
T * get() const // never throws
|
||||||
|
{
|
||||||
|
return px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// implicit conversion to "bool"
|
||||||
|
#include <boost/smart_ptr/detail/operator_bool.hpp>
|
||||||
|
|
||||||
|
void swap(scoped_array & b) // never throws
|
||||||
|
{
|
||||||
|
T * tmp = b.px;
|
||||||
|
b.px = px;
|
||||||
|
px = tmp;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T> inline void swap(scoped_array<T> & a, scoped_array<T> & b) // never throws
|
||||||
|
{
|
||||||
|
a.swap(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_SMART_PTR_SCOPED_ARRAY_HPP_INCLUDED
|
||||||
131
include/boost/smart_ptr/scoped_ptr.hpp
Normal file
131
include/boost/smart_ptr/scoped_ptr.hpp
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
#ifndef BOOST_SMART_PTR_SCOPED_PTR_HPP_INCLUDED
|
||||||
|
#define BOOST_SMART_PTR_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)
|
||||||
|
//
|
||||||
|
// http://www.boost.org/libs/smart_ptr/scoped_ptr.htm
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/checked_delete.hpp>
|
||||||
|
#include <boost/detail/workaround.hpp>
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_AUTO_PTR
|
||||||
|
# include <memory> // for std::auto_ptr
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
// Debug hooks
|
||||||
|
|
||||||
|
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||||
|
|
||||||
|
void sp_scalar_constructor_hook(void * p);
|
||||||
|
void sp_scalar_destructor_hook(void * p);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// scoped_ptr mimics a built-in pointer except that it guarantees deletion
|
||||||
|
// of the object pointed to, either on destruction of the scoped_ptr or via
|
||||||
|
// an explicit reset(). scoped_ptr is a simple solution for simple needs;
|
||||||
|
// use shared_ptr or std::auto_ptr if your needs are more complex.
|
||||||
|
|
||||||
|
template<class T> class scoped_ptr // noncopyable
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
T * px;
|
||||||
|
|
||||||
|
scoped_ptr(scoped_ptr const &);
|
||||||
|
scoped_ptr & operator=(scoped_ptr const &);
|
||||||
|
|
||||||
|
typedef scoped_ptr<T> this_type;
|
||||||
|
|
||||||
|
void operator==( scoped_ptr const& ) const;
|
||||||
|
void operator!=( scoped_ptr const& ) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef T element_type;
|
||||||
|
|
||||||
|
explicit scoped_ptr( T * p = 0 ): px( p ) // never throws
|
||||||
|
{
|
||||||
|
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||||
|
boost::sp_scalar_constructor_hook( px );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_AUTO_PTR
|
||||||
|
|
||||||
|
explicit scoped_ptr( std::auto_ptr<T> p ): px( p.release() ) // never throws
|
||||||
|
{
|
||||||
|
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||||
|
boost::sp_scalar_constructor_hook( px );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
~scoped_ptr() // never throws
|
||||||
|
{
|
||||||
|
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||||
|
boost::sp_scalar_destructor_hook( px );
|
||||||
|
#endif
|
||||||
|
boost::checked_delete( px );
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset(T * p = 0) // never throws
|
||||||
|
{
|
||||||
|
BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors
|
||||||
|
this_type(p).swap(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
T & operator*() const // never throws
|
||||||
|
{
|
||||||
|
BOOST_ASSERT( px != 0 );
|
||||||
|
return *px;
|
||||||
|
}
|
||||||
|
|
||||||
|
T * operator->() const // never throws
|
||||||
|
{
|
||||||
|
BOOST_ASSERT( px != 0 );
|
||||||
|
return px;
|
||||||
|
}
|
||||||
|
|
||||||
|
T * get() const // never throws
|
||||||
|
{
|
||||||
|
return px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// implicit conversion to "bool"
|
||||||
|
#include <boost/smart_ptr/detail/operator_bool.hpp>
|
||||||
|
|
||||||
|
void swap(scoped_ptr & b) // never throws
|
||||||
|
{
|
||||||
|
T * tmp = b.px;
|
||||||
|
b.px = px;
|
||||||
|
px = tmp;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T> inline void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) // never throws
|
||||||
|
{
|
||||||
|
a.swap(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get_pointer(p) is a generic way to say p.get()
|
||||||
|
|
||||||
|
template<class T> inline T * get_pointer(scoped_ptr<T> const & p)
|
||||||
|
{
|
||||||
|
return p.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_SMART_PTR_SCOPED_PTR_HPP_INCLUDED
|
||||||
147
include/boost/smart_ptr/shared_array.hpp
Normal file
147
include/boost/smart_ptr/shared_array.hpp
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
#ifndef BOOST_SMART_PTR_SHARED_ARRAY_HPP_INCLUDED
|
||||||
|
#define BOOST_SMART_PTR_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/shared_array.htm for documentation.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <boost/config.hpp> // for broken compiler workarounds
|
||||||
|
|
||||||
|
#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
|
||||||
|
#include <boost/smart_ptr/detail/shared_array_nmt.hpp>
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <memory> // TR1 cyclic inclusion fix
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/checked_delete.hpp>
|
||||||
|
|
||||||
|
#include <boost/smart_ptr/detail/shared_count.hpp>
|
||||||
|
#include <boost/detail/workaround.hpp>
|
||||||
|
|
||||||
|
#include <cstddef> // for std::ptrdiff_t
|
||||||
|
#include <algorithm> // for std::swap
|
||||||
|
#include <functional> // for std::less
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
//
|
||||||
|
// shared_array
|
||||||
|
//
|
||||||
|
// shared_array extends shared_ptr to arrays.
|
||||||
|
// The array pointed to is deleted when the last shared_array pointing to it
|
||||||
|
// is destroyed or reset.
|
||||||
|
//
|
||||||
|
|
||||||
|
template<class T> class shared_array
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Borland 5.5.1 specific workarounds
|
||||||
|
typedef checked_array_deleter<T> deleter;
|
||||||
|
typedef shared_array<T> this_type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef T element_type;
|
||||||
|
|
||||||
|
explicit shared_array(T * p = 0): px(p), pn(p, deleter())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Requirements: D's copy constructor must not throw
|
||||||
|
//
|
||||||
|
// shared_array will release p by calling d(p)
|
||||||
|
//
|
||||||
|
|
||||||
|
template<class D> shared_array(T * p, D d): px(p), pn(p, d)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// generated copy constructor, assignment, destructor are fine
|
||||||
|
|
||||||
|
void reset(T * p = 0)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(p == 0 || p != px);
|
||||||
|
this_type(p).swap(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class D> void reset(T * p, D d)
|
||||||
|
{
|
||||||
|
this_type(p, d).swap(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
T & operator[] (std::ptrdiff_t i) const // never throws
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(px != 0);
|
||||||
|
BOOST_ASSERT(i >= 0);
|
||||||
|
return px[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
T * get() const // never throws
|
||||||
|
{
|
||||||
|
return px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// implicit conversion to "bool"
|
||||||
|
#include <boost/smart_ptr/detail/operator_bool.hpp>
|
||||||
|
|
||||||
|
bool unique() const // never throws
|
||||||
|
{
|
||||||
|
return pn.unique();
|
||||||
|
}
|
||||||
|
|
||||||
|
long use_count() const // never throws
|
||||||
|
{
|
||||||
|
return pn.use_count();
|
||||||
|
}
|
||||||
|
|
||||||
|
void swap(shared_array<T> & other) // never throws
|
||||||
|
{
|
||||||
|
std::swap(px, other.px);
|
||||||
|
pn.swap(other.pn);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
T * px; // contained pointer
|
||||||
|
detail::shared_count pn; // reference counter
|
||||||
|
|
||||||
|
}; // shared_array
|
||||||
|
|
||||||
|
template<class T> inline bool operator==(shared_array<T> const & a, shared_array<T> const & b) // never throws
|
||||||
|
{
|
||||||
|
return a.get() == b.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T> inline bool operator!=(shared_array<T> const & a, shared_array<T> const & b) // never throws
|
||||||
|
{
|
||||||
|
return a.get() != b.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T> inline bool operator<(shared_array<T> const & a, shared_array<T> const & b) // never throws
|
||||||
|
{
|
||||||
|
return std::less<T*>()(a.get(), b.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T> void swap(shared_array<T> & a, shared_array<T> & b) // never throws
|
||||||
|
{
|
||||||
|
a.swap(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_SMART_PTR_SHARED_ARRAY_HPP_INCLUDED
|
||||||
701
include/boost/smart_ptr/shared_ptr.hpp
Normal file
701
include/boost/smart_ptr/shared_ptr.hpp
Normal file
@@ -0,0 +1,701 @@
|
|||||||
|
#ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED
|
||||||
|
#define BOOST_SMART_PTR_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/shared_ptr.htm for documentation.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <boost/config.hpp> // for broken compiler workarounds
|
||||||
|
|
||||||
|
#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
|
||||||
|
#include <boost/smart_ptr/detail/shared_ptr_nmt.hpp>
|
||||||
|
#else
|
||||||
|
|
||||||
|
// 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 <boost/assert.hpp>
|
||||||
|
#include <boost/checked_delete.hpp>
|
||||||
|
#include <boost/throw_exception.hpp>
|
||||||
|
#include <boost/smart_ptr/detail/shared_count.hpp>
|
||||||
|
#include <boost/detail/workaround.hpp>
|
||||||
|
#include <boost/smart_ptr/detail/sp_convertible.hpp>
|
||||||
|
|
||||||
|
#if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
|
||||||
|
#include <boost/smart_ptr/detail/spinlock_pool.hpp>
|
||||||
|
#include <boost/memory_order.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <algorithm> // for std::swap
|
||||||
|
#include <functional> // for std::less
|
||||||
|
#include <typeinfo> // for std::bad_cast
|
||||||
|
|
||||||
|
#if !defined(BOOST_NO_IOSTREAM)
|
||||||
|
#if !defined(BOOST_NO_IOSFWD)
|
||||||
|
#include <iosfwd> // for std::basic_ostream
|
||||||
|
#else
|
||||||
|
#include <ostream>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash
|
||||||
|
# pragma warning(push)
|
||||||
|
# pragma warning(disable:4284) // odd return type for operator->
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
template<class T> class shared_ptr;
|
||||||
|
template<class T> class weak_ptr;
|
||||||
|
template<class T> class enable_shared_from_this;
|
||||||
|
template<class T> class enable_shared_from_this2;
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
struct static_cast_tag {};
|
||||||
|
struct const_cast_tag {};
|
||||||
|
struct dynamic_cast_tag {};
|
||||||
|
struct polymorphic_cast_tag {};
|
||||||
|
|
||||||
|
template<class T> struct shared_ptr_traits
|
||||||
|
{
|
||||||
|
typedef T & reference;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<> struct shared_ptr_traits<void>
|
||||||
|
{
|
||||||
|
typedef void reference;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
|
||||||
|
|
||||||
|
template<> struct shared_ptr_traits<void const>
|
||||||
|
{
|
||||||
|
typedef void reference;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<> struct shared_ptr_traits<void volatile>
|
||||||
|
{
|
||||||
|
typedef void reference;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<> struct shared_ptr_traits<void const volatile>
|
||||||
|
{
|
||||||
|
typedef void reference;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// enable_shared_from_this support
|
||||||
|
|
||||||
|
template< class X, class Y, class T > inline void sp_enable_shared_from_this( boost::shared_ptr<X> const * ppx, Y const * py, boost::enable_shared_from_this< T > const * pe )
|
||||||
|
{
|
||||||
|
if( pe != 0 )
|
||||||
|
{
|
||||||
|
pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class X, class Y, class T > inline void sp_enable_shared_from_this( boost::shared_ptr<X> * ppx, Y const * py, boost::enable_shared_from_this2< T > const * pe )
|
||||||
|
{
|
||||||
|
if( pe != 0 )
|
||||||
|
{
|
||||||
|
pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _MANAGED
|
||||||
|
|
||||||
|
// Avoid C4793, ... causes native code generation
|
||||||
|
|
||||||
|
struct sp_any_pointer
|
||||||
|
{
|
||||||
|
template<class T> sp_any_pointer( T* ) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void sp_enable_shared_from_this( sp_any_pointer, sp_any_pointer, sp_any_pointer )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // _MANAGED
|
||||||
|
|
||||||
|
inline void sp_enable_shared_from_this( ... )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // _MANAGED
|
||||||
|
|
||||||
|
#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR )
|
||||||
|
|
||||||
|
// rvalue auto_ptr support based on a technique by Dave Abrahams
|
||||||
|
|
||||||
|
template< class T, class R > struct sp_enable_if_auto_ptr
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R >
|
||||||
|
{
|
||||||
|
typedef R type;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// shared_ptr
|
||||||
|
//
|
||||||
|
// An enhanced relative of scoped_ptr with reference counted copy semantics.
|
||||||
|
// The object pointed to is deleted when the last shared_ptr pointing to it
|
||||||
|
// is destroyed or reset.
|
||||||
|
//
|
||||||
|
|
||||||
|
template<class T> class shared_ptr
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Borland 5.5.1 specific workaround
|
||||||
|
typedef shared_ptr<T> this_type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef T element_type;
|
||||||
|
typedef T value_type;
|
||||||
|
typedef T * pointer;
|
||||||
|
typedef typename boost::detail::shared_ptr_traits<T>::reference reference;
|
||||||
|
|
||||||
|
shared_ptr(): px(0), pn() // never throws in 1.30+
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Y>
|
||||||
|
explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete
|
||||||
|
{
|
||||||
|
boost::detail::sp_enable_shared_from_this( this, p, p );
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Requirements: D's copy constructor must not throw
|
||||||
|
//
|
||||||
|
// shared_ptr will release p by calling d(p)
|
||||||
|
//
|
||||||
|
|
||||||
|
template<class Y, class D> shared_ptr(Y * p, D d): px(p), pn(p, d)
|
||||||
|
{
|
||||||
|
boost::detail::sp_enable_shared_from_this( this, p, p );
|
||||||
|
}
|
||||||
|
|
||||||
|
// As above, but with allocator. A's copy constructor shall not throw.
|
||||||
|
|
||||||
|
template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a )
|
||||||
|
{
|
||||||
|
boost::detail::sp_enable_shared_from_this( this, p, p );
|
||||||
|
}
|
||||||
|
|
||||||
|
// generated copy constructor, destructor are fine
|
||||||
|
|
||||||
|
template<class Y>
|
||||||
|
explicit shared_ptr(weak_ptr<Y> const & r): pn(r.pn) // may throw
|
||||||
|
{
|
||||||
|
// it is now safe to copy r.px, as pn(r.pn) did not throw
|
||||||
|
px = r.px;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Y>
|
||||||
|
shared_ptr( weak_ptr<Y> const & r, boost::detail::sp_nothrow_tag ): px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() ) // never throws
|
||||||
|
{
|
||||||
|
if( !pn.empty() )
|
||||||
|
{
|
||||||
|
px = r.px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Y>
|
||||||
|
#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
|
||||||
|
|
||||||
|
shared_ptr( shared_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
shared_ptr( shared_ptr<Y> const & r )
|
||||||
|
|
||||||
|
#endif
|
||||||
|
: px( r.px ), pn( r.pn ) // never throws
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// aliasing
|
||||||
|
template< class Y >
|
||||||
|
shared_ptr( shared_ptr<Y> const & r, T * p ): px( p ), pn( r.pn ) // never throws
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Y>
|
||||||
|
shared_ptr(shared_ptr<Y> const & r, boost::detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Y>
|
||||||
|
shared_ptr(shared_ptr<Y> const & r, boost::detail::const_cast_tag): px(const_cast<element_type *>(r.px)), pn(r.pn)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Y>
|
||||||
|
shared_ptr(shared_ptr<Y> const & r, boost::detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
|
||||||
|
{
|
||||||
|
if(px == 0) // need to allocate new counter -- the cast failed
|
||||||
|
{
|
||||||
|
pn = boost::detail::shared_count();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Y>
|
||||||
|
shared_ptr(shared_ptr<Y> const & r, boost::detail::polymorphic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
|
||||||
|
{
|
||||||
|
if(px == 0)
|
||||||
|
{
|
||||||
|
boost::throw_exception(std::bad_cast());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_AUTO_PTR
|
||||||
|
|
||||||
|
template<class Y>
|
||||||
|
explicit shared_ptr(std::auto_ptr<Y> & r): px(r.get()), pn()
|
||||||
|
{
|
||||||
|
Y * tmp = r.get();
|
||||||
|
pn = boost::detail::shared_count(r);
|
||||||
|
boost::detail::sp_enable_shared_from_this( this, tmp, tmp );
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
|
||||||
|
|
||||||
|
template<class Ap>
|
||||||
|
explicit shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr<Ap, int>::type = 0 ): px( r.get() ), pn()
|
||||||
|
{
|
||||||
|
typename Ap::element_type * tmp = r.get();
|
||||||
|
pn = boost::detail::shared_count( r );
|
||||||
|
boost::detail::sp_enable_shared_from_this( this, tmp, tmp );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
|
|
||||||
|
#endif // BOOST_NO_AUTO_PTR
|
||||||
|
|
||||||
|
// assignment
|
||||||
|
|
||||||
|
shared_ptr & operator=( shared_ptr const & r ) // never throws
|
||||||
|
{
|
||||||
|
this_type(r).swap(*this);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1400)
|
||||||
|
|
||||||
|
template<class Y>
|
||||||
|
shared_ptr & operator=(shared_ptr<Y> const & r) // never throws
|
||||||
|
{
|
||||||
|
this_type(r).swap(*this);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_AUTO_PTR
|
||||||
|
|
||||||
|
template<class Y>
|
||||||
|
shared_ptr & operator=( std::auto_ptr<Y> & r )
|
||||||
|
{
|
||||||
|
this_type(r).swap(*this);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
|
||||||
|
|
||||||
|
template<class Ap>
|
||||||
|
typename boost::detail::sp_enable_if_auto_ptr< Ap, shared_ptr & >::type operator=( Ap r )
|
||||||
|
{
|
||||||
|
this_type( r ).swap( *this );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
|
|
||||||
|
#endif // BOOST_NO_AUTO_PTR
|
||||||
|
|
||||||
|
// Move support
|
||||||
|
|
||||||
|
#if defined( BOOST_HAS_RVALUE_REFS )
|
||||||
|
|
||||||
|
shared_ptr( shared_ptr && r ): px( r.px ), pn() // never throws
|
||||||
|
{
|
||||||
|
pn.swap( r.pn );
|
||||||
|
r.px = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Y>
|
||||||
|
#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
|
||||||
|
|
||||||
|
shared_ptr( shared_ptr<Y> && r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
shared_ptr( shared_ptr<Y> && r )
|
||||||
|
|
||||||
|
#endif
|
||||||
|
: px( r.px ), pn() // never throws
|
||||||
|
{
|
||||||
|
pn.swap( r.pn );
|
||||||
|
r.px = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_ptr & operator=( shared_ptr && r ) // never throws
|
||||||
|
{
|
||||||
|
this_type( static_cast< shared_ptr && >( r ) ).swap( *this );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Y>
|
||||||
|
shared_ptr & operator=( shared_ptr<Y> && r ) // never throws
|
||||||
|
{
|
||||||
|
this_type( static_cast< shared_ptr<Y> && >( r ) ).swap( *this );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void reset() // never throws in 1.30+
|
||||||
|
{
|
||||||
|
this_type().swap(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Y> void reset(Y * p) // Y must be complete
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors
|
||||||
|
this_type(p).swap(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Y, class D> void reset( Y * p, D d )
|
||||||
|
{
|
||||||
|
this_type( p, d ).swap( *this );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Y, class D, class A> void reset( Y * p, D d, A a )
|
||||||
|
{
|
||||||
|
this_type( p, d, a ).swap( *this );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Y> void reset( shared_ptr<Y> const & r, T * p )
|
||||||
|
{
|
||||||
|
this_type( r, p ).swap( *this );
|
||||||
|
}
|
||||||
|
|
||||||
|
reference operator* () const // never throws
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(px != 0);
|
||||||
|
return *px;
|
||||||
|
}
|
||||||
|
|
||||||
|
T * operator-> () const // never throws
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(px != 0);
|
||||||
|
return px;
|
||||||
|
}
|
||||||
|
|
||||||
|
T * get() const // never throws
|
||||||
|
{
|
||||||
|
return px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// implicit conversion to "bool"
|
||||||
|
#include <boost/smart_ptr/detail/operator_bool.hpp>
|
||||||
|
|
||||||
|
bool unique() const // never throws
|
||||||
|
{
|
||||||
|
return pn.unique();
|
||||||
|
}
|
||||||
|
|
||||||
|
long use_count() const // never throws
|
||||||
|
{
|
||||||
|
return pn.use_count();
|
||||||
|
}
|
||||||
|
|
||||||
|
void swap(shared_ptr<T> & other) // never throws
|
||||||
|
{
|
||||||
|
std::swap(px, other.px);
|
||||||
|
pn.swap(other.pn);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Y> bool _internal_less(shared_ptr<Y> const & rhs) const
|
||||||
|
{
|
||||||
|
return pn < rhs.pn;
|
||||||
|
}
|
||||||
|
|
||||||
|
void * _internal_get_deleter( boost::detail::sp_typeinfo const & ti ) const
|
||||||
|
{
|
||||||
|
return pn.get_deleter( ti );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _internal_equiv( shared_ptr const & r ) const
|
||||||
|
{
|
||||||
|
return px == r.px && pn == r.pn;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tasteless as this may seem, making all members public allows member templates
|
||||||
|
// to work in the absence of member template friends. (Matthew Langston)
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
template<class Y> friend class shared_ptr;
|
||||||
|
template<class Y> friend class weak_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
T * px; // contained pointer
|
||||||
|
boost::detail::shared_count pn; // reference counter
|
||||||
|
|
||||||
|
}; // shared_ptr
|
||||||
|
|
||||||
|
template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b)
|
||||||
|
{
|
||||||
|
return a.get() == b.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b)
|
||||||
|
{
|
||||||
|
return a.get() != b.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
|
||||||
|
|
||||||
|
// Resolve the ambiguity between our op!= and the one in rel_ops
|
||||||
|
|
||||||
|
template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b)
|
||||||
|
{
|
||||||
|
return a.get() != b.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b)
|
||||||
|
{
|
||||||
|
return a._internal_less(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b)
|
||||||
|
{
|
||||||
|
a.swap(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r)
|
||||||
|
{
|
||||||
|
return shared_ptr<T>(r, boost::detail::static_cast_tag());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class U> shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r)
|
||||||
|
{
|
||||||
|
return shared_ptr<T>(r, boost::detail::const_cast_tag());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r)
|
||||||
|
{
|
||||||
|
return shared_ptr<T>(r, boost::detail::dynamic_cast_tag());
|
||||||
|
}
|
||||||
|
|
||||||
|
// shared_*_cast names are deprecated. Use *_pointer_cast instead.
|
||||||
|
|
||||||
|
template<class T, class U> shared_ptr<T> shared_static_cast(shared_ptr<U> const & r)
|
||||||
|
{
|
||||||
|
return shared_ptr<T>(r, boost::detail::static_cast_tag());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r)
|
||||||
|
{
|
||||||
|
return shared_ptr<T>(r, boost::detail::dynamic_cast_tag());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class U> shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r)
|
||||||
|
{
|
||||||
|
return shared_ptr<T>(r, boost::detail::polymorphic_cast_tag());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class U> shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(dynamic_cast<T *>(r.get()) == r.get());
|
||||||
|
return shared_static_cast<T>(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get_pointer() enables boost::mem_fn to recognize shared_ptr
|
||||||
|
|
||||||
|
template<class T> inline T * get_pointer(shared_ptr<T> const & p)
|
||||||
|
{
|
||||||
|
return p.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
// operator<<
|
||||||
|
|
||||||
|
#if !defined(BOOST_NO_IOSTREAM)
|
||||||
|
|
||||||
|
#if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) )
|
||||||
|
|
||||||
|
template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p)
|
||||||
|
{
|
||||||
|
os << p.get();
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// in STLport's no-iostreams mode no iostream symbols can be used
|
||||||
|
#ifndef _STLP_NO_IOSTREAMS
|
||||||
|
|
||||||
|
# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT)
|
||||||
|
// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
|
||||||
|
using std::basic_ostream;
|
||||||
|
template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p)
|
||||||
|
# else
|
||||||
|
template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p)
|
||||||
|
# endif
|
||||||
|
{
|
||||||
|
os << p.get();
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // _STLP_NO_IOSTREAMS
|
||||||
|
|
||||||
|
#endif // __GNUC__ < 3
|
||||||
|
|
||||||
|
#endif // !defined(BOOST_NO_IOSTREAM)
|
||||||
|
|
||||||
|
// get_deleter
|
||||||
|
|
||||||
|
#if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \
|
||||||
|
( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \
|
||||||
|
( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) )
|
||||||
|
|
||||||
|
// g++ 2.9x doesn't allow static_cast<X const *>(void *)
|
||||||
|
// apparently EDG 2.38 and HP aCC A.03.35 also don't accept it
|
||||||
|
|
||||||
|
template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
|
||||||
|
{
|
||||||
|
void const * q = p._internal_get_deleter(BOOST_SP_TYPEID(D));
|
||||||
|
return const_cast<D *>(static_cast<D const *>(q));
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
|
||||||
|
{
|
||||||
|
return static_cast<D *>(p._internal_get_deleter(BOOST_SP_TYPEID(D)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// atomic access
|
||||||
|
|
||||||
|
#if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
|
||||||
|
|
||||||
|
template<class T> inline bool atomic_is_lock_free( shared_ptr<T> const * /*p*/ )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p )
|
||||||
|
{
|
||||||
|
boost::detail::spinlock_pool<2>::scoped_lock lock( p );
|
||||||
|
return *p;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T> inline shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, memory_order /*mo*/ )
|
||||||
|
{
|
||||||
|
return atomic_load( p );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T> void atomic_store( shared_ptr<T> * p, shared_ptr<T> r )
|
||||||
|
{
|
||||||
|
boost::detail::spinlock_pool<2>::scoped_lock lock( p );
|
||||||
|
p->swap( r );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T> inline void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, memory_order /*mo*/ )
|
||||||
|
{
|
||||||
|
atomic_store( p, r ); // std::move( r )
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T> shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r )
|
||||||
|
{
|
||||||
|
boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
|
||||||
|
|
||||||
|
sp.lock();
|
||||||
|
p->swap( r );
|
||||||
|
sp.unlock();
|
||||||
|
|
||||||
|
return r; // return std::move( r )
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T> shared_ptr<T> atomic_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> r, memory_order /*mo*/ )
|
||||||
|
{
|
||||||
|
return atomic_exchange( p, r ); // std::move( r )
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T> bool atomic_compare_exchange( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w )
|
||||||
|
{
|
||||||
|
boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
|
||||||
|
|
||||||
|
sp.lock();
|
||||||
|
|
||||||
|
if( p->_internal_equiv( *v ) )
|
||||||
|
{
|
||||||
|
p->swap( w );
|
||||||
|
|
||||||
|
sp.unlock();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
shared_ptr<T> tmp( *p );
|
||||||
|
|
||||||
|
sp.unlock();
|
||||||
|
|
||||||
|
tmp.swap( *v );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T> inline bool atomic_compare_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w, memory_order /*success*/, memory_order /*failure*/ )
|
||||||
|
{
|
||||||
|
return atomic_compare_exchange( p, v, w ); // std::move( w )
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#ifdef BOOST_MSVC
|
||||||
|
# pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED
|
||||||
230
include/boost/smart_ptr/weak_ptr.hpp
Normal file
230
include/boost/smart_ptr/weak_ptr.hpp
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
#ifndef BOOST_SMART_PTR_WEAK_PTR_HPP_INCLUDED
|
||||||
|
#define BOOST_SMART_PTR_WEAK_PTR_HPP_INCLUDED
|
||||||
|
|
||||||
|
//
|
||||||
|
// weak_ptr.hpp
|
||||||
|
//
|
||||||
|
// Copyright (c) 2001, 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)
|
||||||
|
//
|
||||||
|
// See http://www.boost.org/libs/smart_ptr/weak_ptr.htm for documentation.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <memory> // boost.TR1 include order fix
|
||||||
|
#include <boost/smart_ptr/detail/shared_count.hpp>
|
||||||
|
#include <boost/smart_ptr/shared_ptr.hpp>
|
||||||
|
|
||||||
|
#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash
|
||||||
|
# pragma warning(push)
|
||||||
|
# pragma warning(disable:4284) // odd return type for operator->
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
template<class T> class weak_ptr
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Borland 5.5.1 specific workarounds
|
||||||
|
typedef weak_ptr<T> this_type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef T element_type;
|
||||||
|
|
||||||
|
weak_ptr(): px(0), pn() // never throws in 1.30+
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// generated copy constructor, assignment, destructor are fine
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// The "obvious" converting constructor implementation:
|
||||||
|
//
|
||||||
|
// template<class Y>
|
||||||
|
// weak_ptr(weak_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws
|
||||||
|
// {
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// has a serious problem.
|
||||||
|
//
|
||||||
|
// r.px may already have been invalidated. The px(r.px)
|
||||||
|
// conversion may require access to *r.px (virtual inheritance).
|
||||||
|
//
|
||||||
|
// It is not possible to avoid spurious access violations since
|
||||||
|
// in multithreaded programs r.px may be invalidated at any point.
|
||||||
|
//
|
||||||
|
|
||||||
|
template<class Y>
|
||||||
|
#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
|
||||||
|
|
||||||
|
weak_ptr( weak_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
weak_ptr( weak_ptr<Y> const & r )
|
||||||
|
|
||||||
|
#endif
|
||||||
|
: px(r.lock().get()), pn(r.pn) // never throws
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined( BOOST_HAS_RVALUE_REFS )
|
||||||
|
|
||||||
|
template<class Y>
|
||||||
|
#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
|
||||||
|
|
||||||
|
weak_ptr( weak_ptr<Y> && r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
weak_ptr( weak_ptr<Y> && r )
|
||||||
|
|
||||||
|
#endif
|
||||||
|
: px( r.lock().get() ), pn( static_cast< boost::detail::weak_count && >( r.pn ) ) // never throws
|
||||||
|
{
|
||||||
|
r.px = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for better efficiency in the T == Y case
|
||||||
|
weak_ptr( weak_ptr && r ): px( r.px ), pn( static_cast< boost::detail::weak_count && >( r.pn ) ) // never throws
|
||||||
|
{
|
||||||
|
r.px = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for better efficiency in the T == Y case
|
||||||
|
weak_ptr & operator=( weak_ptr && r ) // never throws
|
||||||
|
{
|
||||||
|
this_type( static_cast< weak_ptr && >( r ) ).swap( *this );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<class Y>
|
||||||
|
#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
|
||||||
|
|
||||||
|
weak_ptr( shared_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
weak_ptr( shared_ptr<Y> const & r )
|
||||||
|
|
||||||
|
#endif
|
||||||
|
: px( r.px ), pn( r.pn ) // never throws
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300)
|
||||||
|
|
||||||
|
template<class Y>
|
||||||
|
weak_ptr & operator=(weak_ptr<Y> const & r) // never throws
|
||||||
|
{
|
||||||
|
px = r.lock().get();
|
||||||
|
pn = r.pn;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined( BOOST_HAS_RVALUE_REFS )
|
||||||
|
|
||||||
|
template<class Y>
|
||||||
|
weak_ptr & operator=( weak_ptr<Y> && r )
|
||||||
|
{
|
||||||
|
this_type( static_cast< weak_ptr<Y> && >( r ) ).swap( *this );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<class Y>
|
||||||
|
weak_ptr & operator=(shared_ptr<Y> const & r) // never throws
|
||||||
|
{
|
||||||
|
px = r.px;
|
||||||
|
pn = r.pn;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
shared_ptr<T> lock() const // never throws
|
||||||
|
{
|
||||||
|
return shared_ptr<element_type>( *this, boost::detail::sp_nothrow_tag() );
|
||||||
|
}
|
||||||
|
|
||||||
|
long use_count() const // never throws
|
||||||
|
{
|
||||||
|
return pn.use_count();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool expired() const // never throws
|
||||||
|
{
|
||||||
|
return pn.use_count() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _empty() const // extension, not in std::weak_ptr
|
||||||
|
{
|
||||||
|
return pn.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset() // never throws in 1.30+
|
||||||
|
{
|
||||||
|
this_type().swap(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void swap(this_type & other) // never throws
|
||||||
|
{
|
||||||
|
std::swap(px, other.px);
|
||||||
|
pn.swap(other.pn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _internal_assign(T * px2, boost::detail::shared_count const & pn2)
|
||||||
|
{
|
||||||
|
px = px2;
|
||||||
|
pn = pn2;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Y> bool _internal_less(weak_ptr<Y> const & rhs) const
|
||||||
|
{
|
||||||
|
return pn < rhs.pn;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tasteless as this may seem, making all members public allows member templates
|
||||||
|
// to work in the absence of member template friends. (Matthew Langston)
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
template<class Y> friend class weak_ptr;
|
||||||
|
template<class Y> friend class shared_ptr;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
T * px; // contained pointer
|
||||||
|
boost::detail::weak_count pn; // reference counter
|
||||||
|
|
||||||
|
}; // weak_ptr
|
||||||
|
|
||||||
|
template<class T, class U> inline bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b)
|
||||||
|
{
|
||||||
|
return a._internal_less(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b)
|
||||||
|
{
|
||||||
|
a.swap(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#ifdef BOOST_MSVC
|
||||||
|
# pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_SMART_PTR_WEAK_PTR_HPP_INCLUDED
|
||||||
18
include/boost/weak_ptr.hpp
Normal file
18
include/boost/weak_ptr.hpp
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#ifndef BOOST_WEAK_PTR_HPP_INCLUDED
|
||||||
|
#define BOOST_WEAK_PTR_HPP_INCLUDED
|
||||||
|
|
||||||
|
//
|
||||||
|
// weak_ptr.hpp
|
||||||
|
//
|
||||||
|
// Copyright (c) 2001, 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
|
||||||
|
//
|
||||||
|
// See http://www.boost.org/libs/smart_ptr/weak_ptr.htm for documentation.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <boost/smart_ptr/weak_ptr.hpp>
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_WEAK_PTR_HPP_INCLUDED
|
||||||
39
index.htm
39
index.htm
@@ -1,39 +0,0 @@
|
|||||||
<html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
|
||||||
<title>Boost Smart Pointer Library</title>
|
|
||||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
|
||||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body bgcolor="#FFFFFF" text="#000000">
|
|
||||||
|
|
||||||
<table border="1" bgcolor="#007F7F" cellpadding="2">
|
|
||||||
<tr>
|
|
||||||
<td bgcolor="#FFFFFF"><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" width="277" height="86"></td>
|
|
||||||
<td><a href="../../index.htm"><font face="Arial" color="#FFFFFF"><big>Home</big></font></a></td>
|
|
||||||
<td><a href="../../libraries.htm"><font face="Arial" color="#FFFFFF"><big>Libraries</big></font></a></td>
|
|
||||||
<td><a href="../../people.htm"><font face="Arial" color="#FFFFFF"><big>People</big></font></a></td>
|
|
||||||
<td><a href="../../more/faq.htm"><font face="Arial" color="#FFFFFF"><big>FAQ</big></font></a></td>
|
|
||||||
<td><a href="../../more/index.htm"><font face="Arial" color="#FFFFFF"><big>More</big></font></a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<h1>Smart pointer library</h1>
|
|
||||||
<p>The header smart_ptr.hpp provides four smart pointer classes. Smart
|
|
||||||
pointers ease the management of memory dynamically allocated with C++ <strong>new</strong>
|
|
||||||
expressions.
|
|
||||||
<ul>
|
|
||||||
<li><a href="smart_ptr.htm">Documentation</a> (HTML).</li>
|
|
||||||
<li>Header <a href="../../boost/smart_ptr.hpp">smart_ptr.hpp</a></li>
|
|
||||||
<li>Test program <a href="smart_ptr_test.cpp">smart_ptr_test.cpp</a>.</li>
|
|
||||||
<li>Download <a href="../../boost_all.zip">all of Boost</a> (ZIP format).</li>
|
|
||||||
<li>Submitted by <a href="../../people/greg_colvin.htm">Greg Colvin</a> and <a href="../../people/beman_dawes.html">Beman
|
|
||||||
Dawes</a>.</li>
|
|
||||||
</ul>
|
|
||||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->02 Aug 2000<!--webbot bot="Timestamp" endspan i-checksum="14748" -->
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
15
index.html
Normal file
15
index.html
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="refresh" content="0; URL=smart_ptr.htm">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
Automatic redirection failed, please go to
|
||||||
|
<a href="smart_ptr.htm">smart_ptr.htm</a>.
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
<!--
|
||||||
|
<09> 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
|
||||||
|
-->
|
||||||
297
intrusive_ptr.html
Normal file
297
intrusive_ptr.html
Normal file
@@ -0,0 +1,297 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>intrusive_ptr</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
</head>
|
||||||
|
<body text="#000000" bgColor="#ffffff">
|
||||||
|
<h1><A href="../../index.htm"><IMG height="86" alt="boost.png (6897 bytes)" src="../../boost.png" width="277" align="middle"
|
||||||
|
border="0"></A>intrusive_ptr class template</h1>
|
||||||
|
<p>
|
||||||
|
<A href="#Introduction">Introduction</A><br>
|
||||||
|
<A href="#Synopsis">Synopsis</A><br>
|
||||||
|
<A href="#Members">Members</A><br>
|
||||||
|
<A href="#functions">Free Functions</A><br>
|
||||||
|
</p>
|
||||||
|
<h2><a name="Introduction">Introduction</a></h2>
|
||||||
|
<p>The <b>intrusive_ptr</b> class template stores a pointer to an object with an
|
||||||
|
embedded reference count. Every new <b>intrusive_ptr</b> instance increments
|
||||||
|
the reference count by using an unqualified call to the function <STRONG>intrusive_ptr_add_ref</STRONG>,
|
||||||
|
passing it the pointer as an argument. Similarly, when an <STRONG>intrusive_ptr</STRONG>
|
||||||
|
is destroyed, it calls <STRONG>intrusive_ptr_release</STRONG>; 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, <STRONG>intrusive_ptr_add_ref</STRONG>
|
||||||
|
and <STRONG>intrusive_ptr_release</STRONG> should be defined in the namespace
|
||||||
|
that corresponds to their parameter; otherwise, the definitions need to go in
|
||||||
|
namespace <STRONG>boost</STRONG>.</p>
|
||||||
|
<p>The class template is parameterized on <b>T</b>, the type of the object pointed
|
||||||
|
to. <STRONG>intrusive_ptr<T></STRONG> can be implicitly converted to <STRONG>intrusive_ptr<U></STRONG>
|
||||||
|
whenever <STRONG>T*</STRONG> can be implicitly converted to <STRONG>U*</STRONG>.</p>
|
||||||
|
<P>The main reasons to use <STRONG>intrusive_ptr</STRONG> are:</P>
|
||||||
|
<UL>
|
||||||
|
<LI>
|
||||||
|
Some existing frameworks or OSes provide objects with embedded reference
|
||||||
|
counts;
|
||||||
|
<LI>
|
||||||
|
The memory footprint of <STRONG>intrusive_ptr</STRONG>
|
||||||
|
is the same as the corresponding raw pointer;
|
||||||
|
<LI>
|
||||||
|
<STRONG>intrusive_ptr<T></STRONG> can be constructed from an arbitrary
|
||||||
|
raw pointer of type <STRONG>T *</STRONG>.</LI></UL>
|
||||||
|
<P>As a general rule, if it isn't obvious whether <STRONG>intrusive_ptr</STRONG> better
|
||||||
|
fits your needs than <STRONG>shared_ptr</STRONG>, try a <STRONG>shared_ptr</STRONG>-based
|
||||||
|
design first.</P>
|
||||||
|
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||||
|
<pre>namespace boost {
|
||||||
|
|
||||||
|
template<class T> class intrusive_ptr {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef T <A href="#element_type" >element_type</A>;
|
||||||
|
|
||||||
|
<A href="#constructors" >intrusive_ptr</A>(); // never throws
|
||||||
|
<A href="#constructors" >intrusive_ptr</A>(T * p, bool add_ref = true);
|
||||||
|
|
||||||
|
<A href="#constructors" >intrusive_ptr</A>(intrusive_ptr const & r);
|
||||||
|
template<class Y> <A href="#constructors" >intrusive_ptr</A>(intrusive_ptr<Y> const & r);
|
||||||
|
|
||||||
|
<A href="#destructor" >~intrusive_ptr</A>();
|
||||||
|
|
||||||
|
intrusive_ptr & <A href="#assignment" >operator=</A>(intrusive_ptr const & r);
|
||||||
|
template<class Y> intrusive_ptr & <A href="#assignment" >operator=</A>(intrusive_ptr<Y> const & r);
|
||||||
|
intrusive_ptr & <A href="#assignment" >operator=</A>(T * r);
|
||||||
|
|
||||||
|
void <a href="#reset" >reset</a>();
|
||||||
|
void <a href="#reset" >reset</a>(T * r);
|
||||||
|
|
||||||
|
T & <A href="#indirection" >operator*</A>() const; // never throws
|
||||||
|
T * <A href="#indirection" >operator-></A>() const; // never throws
|
||||||
|
T * <A href="#get" >get</A>() const; // never throws
|
||||||
|
|
||||||
|
operator <A href="#conversions" ><i>unspecified-bool-type</i></A>() const; // never throws
|
||||||
|
|
||||||
|
void <A href="#swap" >swap</A>(intrusive_ptr & b); // never throws
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T, class U>
|
||||||
|
bool <A href="#comparison" >operator==</A>(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b); // never throws
|
||||||
|
|
||||||
|
template<class T, class U>
|
||||||
|
bool <A href="#comparison" >operator!=</A>(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b); // never throws
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
bool <A href="#comparison" >operator==</A>(intrusive_ptr<T> const & a, T * b); // never throws
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
bool <A href="#comparison" >operator!=</A>(intrusive_ptr<T> const & a, T * b); // never throws
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
bool <A href="#comparison" >operator==</A>(T * a, intrusive_ptr<T> const & b); // never throws
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
bool <A href="#comparison" >operator!=</A>(T * a, intrusive_ptr<T> const & b); // never throws
|
||||||
|
|
||||||
|
template<class T, class U>
|
||||||
|
bool <A href="#comparison" >operator<</A>(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b); // never throws
|
||||||
|
|
||||||
|
template<class T> void <A href="#free-swap" >swap</A>(intrusive_ptr<T> & a, intrusive_ptr<T> & b); // never throws
|
||||||
|
|
||||||
|
template<class T> T * <A href="#get_pointer" >get_pointer</A>(intrusive_ptr<T> const & p); // never throws
|
||||||
|
|
||||||
|
template<class T, class U>
|
||||||
|
intrusive_ptr<T> <A href="#static_pointer_cast" >static_pointer_cast</A>(intrusive_ptr<U> const & r); // never throws
|
||||||
|
|
||||||
|
template<class T, class U>
|
||||||
|
intrusive_ptr<T> <A href="#const_pointer_cast" >const_pointer_cast</A>(intrusive_ptr<U> const & r); // never throws
|
||||||
|
|
||||||
|
template<class T, class U>
|
||||||
|
intrusive_ptr<T> <A href="#dynamic_pointer_cast" >dynamic_pointer_cast</A>(intrusive_ptr<U> const & r); // never throws
|
||||||
|
|
||||||
|
template<class E, class T, class Y>
|
||||||
|
std::basic_ostream<E, T> & <A href="#insertion-operator" >operator<<</A> (std::basic_ostream<E, T> & os, intrusive_ptr<Y> const & p);
|
||||||
|
|
||||||
|
}</pre>
|
||||||
|
<h2><a name="Members">Members</a></h2>
|
||||||
|
<h3><a name="element_type">element_type</a></h3>
|
||||||
|
<pre>typedef T element_type;</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p>Provides the type of the template parameter T.</p>
|
||||||
|
</blockquote>
|
||||||
|
<h3><a name="constructors">constructors</a></h3>
|
||||||
|
<pre>intrusive_ptr(); // never throws</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Postconditions:</b> <code>get() == 0</code>.</p>
|
||||||
|
<p><b>Throws:</b> nothing.</p>
|
||||||
|
</blockquote>
|
||||||
|
<pre>intrusive_ptr(T * p, bool add_ref = true);</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Effects:</b> <code>if(p != 0 && add_ref) intrusive_ptr_add_ref(p);</code>.</p>
|
||||||
|
<p><b>Postconditions:</b> <code>get() == p</code>.</p>
|
||||||
|
</blockquote>
|
||||||
|
<pre>intrusive_ptr(intrusive_ptr const & r);
|
||||||
|
template<class Y> intrusive_ptr(intrusive_ptr<Y> const & r);</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Effects:</b> <code>if(r.get() != 0) intrusive_ptr_add_ref(r.get());</code>.</p>
|
||||||
|
<p><b>Postconditions:</b> <code>get() == r.get()</code>.</p>
|
||||||
|
</blockquote>
|
||||||
|
<h3><a name="destructor">destructor</a></h3>
|
||||||
|
<pre>~intrusive_ptr();</pre>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P><B>Effects:</B> <code>if(get() != 0) intrusive_ptr_release(get());</code>.</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
<H3><a name="assignment">assignment</a></H3>
|
||||||
|
<pre>intrusive_ptr & operator=(intrusive_ptr const & r);
|
||||||
|
template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r);
|
||||||
|
intrusive_ptr & operator=(T * r);</pre>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P><B>Effects:</B> Equivalent to <code>intrusive_ptr(r).swap(*this)</code>.</P>
|
||||||
|
<P><B>Returns:</B> <code>*this</code>.</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
<H3><a name="reset">reset</a></H3>
|
||||||
|
<pre>void reset();</pre>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P><B>Effects:</B> Equivalent to <code>intrusive_ptr().swap(*this)</code>.</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
<pre>void reset(T * r);</pre>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P><B>Effects:</B> Equivalent to <code>intrusive_ptr(r).swap(*this)</code>.</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
<h3><a name="indirection">indirection</a></h3>
|
||||||
|
<pre>T & operator*() const; // never throws</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Requirements:</b> <code>get() != 0</code>.</p>
|
||||||
|
<p><b>Returns:</b> <code>*get()</code>.</p>
|
||||||
|
<p><b>Throws:</b> nothing.</p>
|
||||||
|
</blockquote>
|
||||||
|
<pre>T * operator->() const; // never throws</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Requirements:</b> <code>get() != 0</code>.</p>
|
||||||
|
<p><b>Returns:</b> <code>get()</code>.</p>
|
||||||
|
<p><b>Throws:</b> nothing.</p>
|
||||||
|
</blockquote>
|
||||||
|
<h3><a name="get">get</a></h3>
|
||||||
|
<pre>T * get() const; // never throws</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Returns:</b> the stored pointer.</p>
|
||||||
|
<p><b>Throws:</b> nothing.</p>
|
||||||
|
</blockquote>
|
||||||
|
<h3><a name="conversions">conversions</a></h3>
|
||||||
|
<pre>operator <i>unspecified-bool-type</i> () const; // never throws</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Returns:</b> an unspecified value that, when used in boolean contexts, is
|
||||||
|
equivalent to <code>get() != 0</code>.</p>
|
||||||
|
<p><b>Throws:</b> nothing.</p>
|
||||||
|
<P><B>Notes:</B> This conversion operator allows <b>intrusive_ptr</b> objects to be
|
||||||
|
used in boolean contexts, like <code>if (p && p->valid()) {}</code>.
|
||||||
|
The actual target type is typically a pointer to a member function, avoiding
|
||||||
|
many of the implicit conversion pitfalls.</P>
|
||||||
|
</blockquote>
|
||||||
|
<h3><a name="swap">swap</a></h3>
|
||||||
|
<pre>void swap(intrusive_ptr & b); // never throws</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Effects:</b> Exchanges the contents of the two smart pointers.</p>
|
||||||
|
<p><b>Throws:</b> nothing.</p>
|
||||||
|
</blockquote>
|
||||||
|
<h2><a name="functions">Free Functions</a></h2>
|
||||||
|
<h3><a name="comparison">comparison</a></h3>
|
||||||
|
<pre>template<class T, class U>
|
||||||
|
bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b); // never throws</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Returns:</b> <code>a.get() == b.get()</code>.</p>
|
||||||
|
<p><b>Throws:</b> nothing.</p>
|
||||||
|
</blockquote>
|
||||||
|
<pre>template<class T, class U>
|
||||||
|
bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b); // never throws</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Returns:</b> <code>a.get() != b.get()</code>.</p>
|
||||||
|
<p><b>Throws:</b> nothing.</p>
|
||||||
|
</blockquote>
|
||||||
|
<pre>template<class T, class U>
|
||||||
|
bool operator==(intrusive_ptr<T> const & a, U * b); // never throws</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Returns:</b> <code>a.get() == b</code>.</p>
|
||||||
|
<p><b>Throws:</b> nothing.</p>
|
||||||
|
</blockquote>
|
||||||
|
<pre>template<class T, class U>
|
||||||
|
bool operator!=(intrusive_ptr<T> const & a, U * b); // never throws</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Returns:</b> <code>a.get() != b</code>.</p>
|
||||||
|
<p><b>Throws:</b> nothing.</p>
|
||||||
|
</blockquote>
|
||||||
|
<pre>template<class T, class U>
|
||||||
|
bool operator==(T * a, intrusive_ptr<U> const & b); // never throws</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Returns:</b> <code>a == b.get()</code>.</p>
|
||||||
|
<p><b>Throws:</b> nothing.</p>
|
||||||
|
</blockquote>
|
||||||
|
<pre>template<class T, class U>
|
||||||
|
bool operator!=(T * a, intrusive_ptr<U> const & b); // never throws</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Returns:</b> <code>a != b.get()</code>.</p>
|
||||||
|
<p><b>Throws:</b> nothing.</p>
|
||||||
|
</blockquote>
|
||||||
|
<pre>template<class T, class U>
|
||||||
|
bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b); // never throws</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Returns:</b> <code>std::less<T *>()(a.get(), b.get())</code>.</p>
|
||||||
|
<p><b>Throws:</b> nothing.</p>
|
||||||
|
<P><B>Notes:</B> Allows <STRONG>intrusive_ptr</STRONG> objects to be used as keys
|
||||||
|
in associative containers.</P>
|
||||||
|
</blockquote>
|
||||||
|
<h3><a name="free-swap">swap</a></h3>
|
||||||
|
<pre>template<class T>
|
||||||
|
void swap(intrusive_ptr<T> & a, intrusive_ptr<T> & b); // never throws</pre>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P><B>Effects:</B> Equivalent to <code>a.swap(b)</code>.</P>
|
||||||
|
<P><B>Throws:</B> nothing.</P>
|
||||||
|
<P><B>Notes:</B> Matches the interface of <B>std::swap</B>. Provided as an aid to
|
||||||
|
generic programming.</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
<h3><a name="get_pointer">get_pointer</a></h3>
|
||||||
|
<pre>template<class T>
|
||||||
|
T * get_pointer(intrusive_ptr<T> const & p); // never throws</pre>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P><B>Returns:</B> <code>p.get()</code>.</P>
|
||||||
|
<P><B>Throws:</B> nothing.</P>
|
||||||
|
<P><B>Notes:</B> Provided as an aid to generic programming. Used by <A href="../bind/mem_fn.html">
|
||||||
|
mem_fn</A>.</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
<h3><a name="static_pointer_cast">static_pointer_cast</a></h3>
|
||||||
|
<pre>template<class T, class U>
|
||||||
|
intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & r); // never throws</pre>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P><B>Returns:</B> <code>intrusive_ptr<T>(static_cast<T*>(r.get()))</code>.</P>
|
||||||
|
<P><B>Throws:</B> nothing.</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
<h3><a name="const_pointer_cast">const_pointer_cast</a></h3>
|
||||||
|
<pre>template<class T, class U>
|
||||||
|
intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & r); // never throws</pre>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P><B>Returns:</B> <code>intrusive_ptr<T>(const_cast<T*>(r.get()))</code>.</P>
|
||||||
|
<P><B>Throws:</B> nothing.</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
<h3><a name="dynamic_pointer_cast">dynamic_pointer_cast</a></h3>
|
||||||
|
<pre>template<class T, class U>
|
||||||
|
intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & r);</pre>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P><B>Returns:</B> <code>intrusive_ptr<T>(dynamic_cast<T*>(r.get()))</code>.</P>
|
||||||
|
<P><B>Throws:</B> nothing.</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
<h3><a name="insertion-operator">operator<<</a></h3>
|
||||||
|
<pre>template<class E, class T, class Y>
|
||||||
|
std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, intrusive_ptr<Y> const & p);</pre>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<p><STRONG>Effects:</STRONG> <code>os << p.get();</code>.</p>
|
||||||
|
<P><B>Returns:</B> <code>os</code>.</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
<hr>
|
||||||
|
<p>
|
||||||
|
$Date$</p>
|
||||||
|
<p>
|
||||||
|
<small>Copyright <20> 2003-2005 Peter Dimov. Distributed under the Boost Software License, Version
|
||||||
|
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
|
||||||
|
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
119
make_shared.html
Normal file
119
make_shared.html
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>make_shared and allocate_shared</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
</head>
|
||||||
|
<body text="#000000" bgColor="#ffffff">
|
||||||
|
<h1><A href="../../index.htm"><IMG height="86" alt="boost.png (6897 bytes)" src="../../boost.png" width="277" align="middle"
|
||||||
|
border="0"></A>make_shared and allocate_shared function templates</h1>
|
||||||
|
<p><A href="#Introduction">Introduction</A><br>
|
||||||
|
<A href="#Synopsis">Synopsis</A><br>
|
||||||
|
<A href="#functions">Free Functions</A><br>
|
||||||
|
<A href="#example">Example</A><br>
|
||||||
|
<h2><a name="Introduction">Introduction</a></h2>
|
||||||
|
<p>Consistent use of <a href="shared_ptr.htm"><code>shared_ptr</code></a>
|
||||||
|
can eliminate the need to use an explicit <code>delete</code>,
|
||||||
|
but alone it provides no support in avoiding explicit <code>new</code>.
|
||||||
|
There have been repeated requests from users for a factory function that creates
|
||||||
|
an object of a given type and returns a <code>shared_ptr</code> 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
|
||||||
|
<code>shared_ptr</code>'s construction overhead.
|
||||||
|
This eliminates one of the major efficiency complaints about <code>shared_ptr</code>.
|
||||||
|
</p>
|
||||||
|
<p>The header file <boost/make_shared.hpp> provides a family of overloaded function templates,
|
||||||
|
<code>make_shared</code> and <code>allocate_shared</code>, to address this need.
|
||||||
|
<code>make_shared</code> uses the global operator <code>new</code> to allocate memory,
|
||||||
|
whereas <code>allocate_shared</code> uses an user-supplied allocator, allowing finer control.</p>
|
||||||
|
<p>
|
||||||
|
The rationale for choosing the name <code>make_shared</code> is that the expression
|
||||||
|
<code>make_shared<Widget>()</code> can be read aloud and conveys the intended meaning.</p>
|
||||||
|
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||||
|
<pre>namespace boost {
|
||||||
|
|
||||||
|
template<typename T> class shared_ptr;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
shared_ptr<T> <a href="#functions">make_shared</a>();
|
||||||
|
|
||||||
|
template<typename T, typename A>
|
||||||
|
shared_ptr<T> <a href="#functions">allocate_shared</a>( A const & );
|
||||||
|
|
||||||
|
#if defined( BOOST_HAS_VARIADIC_TMPL ) && defined( BOOST_HAS_RVALUE_REFS ) // C++0x prototypes
|
||||||
|
|
||||||
|
template<typename T, typename... Args>
|
||||||
|
shared_ptr<T> <a href="#functions">make_shared</a>( Args && ... args );
|
||||||
|
|
||||||
|
template<typename T, typename A, typename... Args>
|
||||||
|
shared_ptr<T> <a href="#functions">allocate_shared</a>( A const & a, Args && ... args );
|
||||||
|
|
||||||
|
#else // no C++0X support
|
||||||
|
|
||||||
|
template<typename T, typename Arg1 >
|
||||||
|
shared_ptr<T> <a href="#functions">make_shared</a>( Arg1 const & arg1 );
|
||||||
|
template<typename T, typename Arg1, typename Arg2 >
|
||||||
|
shared_ptr<T> <a href="#functions">make_shared</a>( Arg1 const & arg1, Arg2 const & arg2 );
|
||||||
|
// ...
|
||||||
|
template<typename T, typename Arg1, typename Arg2, ..., typename ArgN >
|
||||||
|
shared_ptr<T> <a href="#functions">make_shared</a>( Arg1 const & arg1, Arg2 const & arg2, ..., ArgN const & argN );
|
||||||
|
|
||||||
|
template<typename T, typename A, typename Arg1 >
|
||||||
|
shared_ptr<T> <a href="#functions">allocate_shared</a>( A const & a, Arg1 const & arg1 );
|
||||||
|
template<typename T, typename A, typename Arg1, typename Arg2 >
|
||||||
|
shared_ptr<T> <a href="#functions">allocate_shared</a>( Arg1 const & arg1, Arg2 const & arg2 );
|
||||||
|
// ...
|
||||||
|
template<typename T, typename A, typename Arg1, typename Arg2, ..., typename ArgN >
|
||||||
|
shared_ptr<T> <a href="#functions">allocate_shared</a>( A const & a, Arg1 const & arg1, Arg2 const & arg2, ..., ArgN const & argN );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}</pre>
|
||||||
|
<h2><a name="functions">Free Functions</a></h2>
|
||||||
|
<pre>template<class T, class... Args>
|
||||||
|
shared_ptr<T> make_shared( Args && ... args );
|
||||||
|
template<class T, class A, class... Args>
|
||||||
|
shared_ptr<T> allocate_shared( A const & a, Args && ... args );</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Requires:</b> The expression <code>new( pv ) T( std::forward<Args>(args)... )</code>,
|
||||||
|
where <code>pv</code> is a <code>void*</code> pointing to storage suitable
|
||||||
|
to hold an object of type <code>T</code>,
|
||||||
|
shall be well-formed. <code>A</code> shall be an <em>Allocator</em>,
|
||||||
|
as described in section 20.1.5 (<stong>Allocator requirements</strong>) of the C++ Standard.
|
||||||
|
The copy constructor and destructor of <code>A</code> shall not throw.</p>
|
||||||
|
<p><b>Effects:</b> Allocates memory suitable for an object of type <code>T</code>
|
||||||
|
and constructs an object in it via the placement new expression <code>new( pv ) T()</code>
|
||||||
|
or <code>new( pv ) T( std::forward<Args>(args)... )</code>.
|
||||||
|
<code>allocate_shared</code> uses a copy of <code>a</code> to allocate memory.
|
||||||
|
If an exception is thrown, has no effect.</p>
|
||||||
|
<p><b>Returns:</b> A <code>shared_ptr</code> instance that stores and owns the address
|
||||||
|
of the newly constructed object of type <code>T</code>.</p>
|
||||||
|
<p><b>Postconditions:</b> <code>get() != 0 && use_count() == 1</code>.</p>
|
||||||
|
<p><b>Throws:</b> <code>bad_alloc</code>, or an exception thrown from <code>A::allocate</code>
|
||||||
|
or the constructor of <code>T</code>.</p>
|
||||||
|
<p><b>Notes:</b> This implementation allocates the memory required for the
|
||||||
|
returned <code>shared_ptr</code> and an object of type <code>T</code> in a single
|
||||||
|
allocation. This provides efficiency equivalent to an intrusive smart pointer.</p>
|
||||||
|
<p>The prototypes shown above are used if your compiler supports rvalue references
|
||||||
|
and variadic templates. They perfectly forward the <code>args</code> parameters to
|
||||||
|
the constructors of <code>T</code>.</p>
|
||||||
|
<p>Otherwise, the implementation will fall back on
|
||||||
|
forwarding the arguments to the constructors of <code>T</code> as const references.
|
||||||
|
If you need to pass a non-const reference to a constructor of <code>T</code>,
|
||||||
|
you may do so by wrapping the parameter in a call to <code>boost::ref</code>.
|
||||||
|
In addition, you will be
|
||||||
|
limited to a maximum of 9 arguments (not counting the allocator argument of
|
||||||
|
allocate_shared).</p>
|
||||||
|
</blockquote>
|
||||||
|
<h2><a name="example">Example</a></h2>
|
||||||
|
<pre>boost::shared_ptr<std::string> x = boost::make_shared<std::string>("hello, world!");
|
||||||
|
std::cout << *x;</pre>
|
||||||
|
<hr>
|
||||||
|
<p>
|
||||||
|
$Date: 2008-05-19 15:42:39 -0400 (Mon, 19 May 2008) $</p>
|
||||||
|
<p><small>Copyright 2008 Peter Dimov. Copyright 2008 Frank Mori Hess.
|
||||||
|
Distributed under the Boost Software License,
|
||||||
|
Version 1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A>
|
||||||
|
or copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
105
pointer_cast.html
Normal file
105
pointer_cast.html
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>pointer_cast.hpp</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1><IMG height="86" alt="C++ Boost" src="../../boost.png" width="277" align="middle" border="0">Pointer
|
||||||
|
cast functions</h1>
|
||||||
|
<p>The pointer cast functions (<code>boost::static_pointer_cast</code> <code>boost::dynamic_pointer_cast</code>
|
||||||
|
<code>boost::reinterpret_pointer_cast</code> <code>boost::const_pointer_cast</code>)
|
||||||
|
provide a way to write generic pointer castings for raw pointers. The functions
|
||||||
|
are defined in <CITE><A href="../../boost/pointer_cast.hpp">boost/pointer_cast.hpp</A>.</CITE></p>
|
||||||
|
<P>There is test/example code in <CITE><A href="test/pointer_cast_test.cpp">pointer_cast_test.cpp</A></CITE>.</p>
|
||||||
|
<h2><a name="rationale">Rationale</a></h2>
|
||||||
|
<P>Boost smart pointers usually overload those functions to provide a mechanism to
|
||||||
|
emulate pointers casts. For example, <code>boost::shared_ptr<...></code> implements
|
||||||
|
a static pointer cast this way:</P>
|
||||||
|
<pre>
|
||||||
|
template<class T, class U>
|
||||||
|
shared_ptr<T> static_pointer_cast(shared_ptr<U> const &r);
|
||||||
|
</pre>
|
||||||
|
<P>Pointer cast functions from <CITE><A href="../../boost/pointer_cast.hpp">boost/pointer_cast.hpp</A></CITE>
|
||||||
|
are overloads of <code>boost::static_pointer_cast</code>, <code>boost::dynamic_pointer_cast</code>,
|
||||||
|
<code>boost::reinterpret_pointer_cast</code> and <code>boost::const_pointer_cast</code>
|
||||||
|
for raw pointers. 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.</p>
|
||||||
|
<H2><A name="synopsis">Synopsis</A></H2>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<PRE>
|
||||||
|
namespace boost {
|
||||||
|
|
||||||
|
template<class T, class U>
|
||||||
|
inline T* static_pointer_cast(U *ptr)
|
||||||
|
{ return static_cast<T*>(ptr); }
|
||||||
|
|
||||||
|
template<class T, class U>
|
||||||
|
inline T* dynamic_pointer_cast(U *ptr)
|
||||||
|
{ return dynamic_cast<T*>(ptr); }
|
||||||
|
|
||||||
|
template<class T, class U>
|
||||||
|
inline T* const_pointer_cast(U *ptr)
|
||||||
|
{ return const_cast<T*>(ptr); }
|
||||||
|
|
||||||
|
template<class T, class U>
|
||||||
|
inline T* reinterpret_pointer_cast(U *ptr)
|
||||||
|
{ return reinterpret_cast<T*>(ptr); }
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
</PRE>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
<P>As you can see from the above synopsis, the pointer cast functions are just
|
||||||
|
wrappers around standard C++ cast operators.</P>
|
||||||
|
<H2><A name="example">Example</A></H2>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<PRE>
|
||||||
|
#include <boost/pointer_cast.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
|
class base
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual ~base()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class derived: public base
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class BasePtr>
|
||||||
|
void check_if_it_is_derived(const BasePtr &ptr)
|
||||||
|
{
|
||||||
|
assert(boost::dynamic_pointer_cast<derived>(ptr) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
<I>// Create a raw and a shared_ptr</I>
|
||||||
|
|
||||||
|
base *ptr = new derived;
|
||||||
|
boost::shared_ptr<base> sptr(new derived);
|
||||||
|
|
||||||
|
<I>// Check that base pointer points actually to derived class</I>
|
||||||
|
|
||||||
|
check_if_it_is_derived(ptr);
|
||||||
|
check_if_it_is_derived(sptr);
|
||||||
|
|
||||||
|
// <EM>Ok!</EM>
|
||||||
|
|
||||||
|
delete ptr;
|
||||||
|
return 0;
|
||||||
|
}</PRE>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
<P>The example demonstrates how the generic pointer casts help us create pointer
|
||||||
|
independent code.</P>
|
||||||
|
<hr>
|
||||||
|
<p>Revised: $Date$</p>
|
||||||
|
<p>Copyright 2005 Ion Gazta<74>aga. Use, modification, and distribution are subject to
|
||||||
|
the Boost Software License, Version 1.0. (See accompanying file <A href="../../LICENSE_1_0.txt">
|
||||||
|
LICENSE_1_0.txt</A> or a copy at <<A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>>.)</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
108
pointer_to_other.html
Normal file
108
pointer_to_other.html
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>pointer_to_other.hpp</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="#ffffff" text="#000000">
|
||||||
|
<h1><img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" WIDTH="277" HEIGHT="86">Header
|
||||||
|
<a href="../../boost/pointer_to_other.hpp">boost/pointer_to_other.hpp</a></h1>
|
||||||
|
<p>
|
||||||
|
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. The utility is
|
||||||
|
defined in <cite><a href="../../boost/pointer_to_other.hpp">boost/pointer_to_other.hpp</a>.</cite></p>
|
||||||
|
<p>There is test/example code in <cite><a href="test/pointer_to_other_test.cpp">pointer_to_other_test.cpp</a></cite>.</p>
|
||||||
|
<h2><a name="contents">Contents</a></h2>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a href="#rationale">Rationale</a>
|
||||||
|
<li>
|
||||||
|
<a href="#synopsis">Synopsis</a>
|
||||||
|
<li>
|
||||||
|
<a href="#example">Example</a></li>
|
||||||
|
</ul>
|
||||||
|
<h2><a name="rationale">Rationale</a></h2>
|
||||||
|
<p>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.)</p>
|
||||||
|
<pre>template <class IntPtr>
|
||||||
|
class FloatPointerHolder
|
||||||
|
{
|
||||||
|
<em>// Let's define a pointer to a float</em>
|
||||||
|
typedef typename boost::pointer_to_other
|
||||||
|
<IntPtr, float>::type float_ptr_t;
|
||||||
|
float_ptr_t float_ptr;
|
||||||
|
};</pre>
|
||||||
|
<h2><a name="synopsis">Synopsis</a></h2>
|
||||||
|
<pre>
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
} <em>// namespace boost</em></pre>
|
||||||
|
<p>If these definitions are not correct for a specific smart pointer, we can define
|
||||||
|
a specialization of pointer_to_other.</p>
|
||||||
|
<h2><a name="example">Example</a></h2>
|
||||||
|
<pre><em>// Let's define a memory allocator that can
|
||||||
|
// work with raw and smart pointers</em>
|
||||||
|
|
||||||
|
#include <boost/pointer_to_other.hpp>
|
||||||
|
|
||||||
|
template <class VoidPtr>
|
||||||
|
class memory_allocator
|
||||||
|
{<em>
|
||||||
|
// Predefine a memory_block </em>
|
||||||
|
struct block;<em>
|
||||||
|
|
||||||
|
// 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></em>
|
||||||
|
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;
|
||||||
|
};</pre>
|
||||||
|
<p>As we can see, using pointer_to_other we can create pointer independent code.</p>
|
||||||
|
<hr>
|
||||||
|
<p>Last revised: $Date$</p>
|
||||||
|
<p><small>Copyright 2005, 2006 Ion Gazta<74>aga and Peter Dimov. Use, modification,
|
||||||
|
and distribution are subject to the Boost Software License, Version 1.0.<br>
|
||||||
|
(See accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or a
|
||||||
|
copy at < <a href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>>.)</small></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
186
scoped_array.htm
186
scoped_array.htm
@@ -1,90 +1,116 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
<html>
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>scoped_array</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="#ffffff" text="#000000">
|
||||||
|
<h1><A href="../../index.htm"><img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" width="277" height="86"
|
||||||
|
border="0"></A>scoped_array class template</h1>
|
||||||
|
<p>The <b>scoped_array</b> class template stores a pointer to a dynamically
|
||||||
|
allocated array. (Dynamically allocated arrays are allocated with the C++ <b>new[]</b>
|
||||||
|
expression.) The array pointed to is guaranteed to be deleted, either on
|
||||||
|
destruction of the <b>scoped_array</b>, or via an explicit <b>reset</b>.</p>
|
||||||
|
<p>The <b>scoped_array</b> 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 <a href="../utility/utility.htm#Class_noncopyable">
|
||||||
|
noncopyable</a>) signal its intent to retain ownership solely within the
|
||||||
|
current scope. Because it is <a href="../utility/utility.htm#Class_noncopyable">noncopyable</a>,
|
||||||
|
it is safer than <b>shared_array</b> for pointers which should not be copied.</p>
|
||||||
|
<p>Because <b>scoped_array</b> 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.</p>
|
||||||
|
<p>It cannot be used in C++ standard library containers. See <a href="shared_array.htm">
|
||||||
|
<b>shared_array</b></a> if <b>scoped_array</b> does not meet your needs.</p>
|
||||||
|
<p>It cannot correctly hold a pointer to a single object. See <a href="scoped_ptr.htm"><b>scoped_ptr</b></a>
|
||||||
|
for that usage.</p>
|
||||||
|
<p>A <b>std::vector</b> is an alternative to a <b>scoped_array</b> that is a bit
|
||||||
|
heavier duty but far more flexible. A <b>boost::array</b> is an alternative
|
||||||
|
that does not use dynamic allocation.</p>
|
||||||
|
<p>The class template is parameterized on <b>T</b>, the type of the object pointed
|
||||||
|
to. <b>T</b> must meet the smart pointer <a href="smart_ptr.htm#common_requirements">
|
||||||
|
common requirements</a>.</p>
|
||||||
|
<h2>Synopsis</h2>
|
||||||
|
<pre>namespace boost {
|
||||||
|
|
||||||
<head>
|
template<class T> class scoped_array : <a href="../utility/utility.htm#Class_noncopyable">noncopyable</a> {
|
||||||
<title>scoped_array</title>
|
|
||||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
|
||||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body bgcolor="#FFFFFF" text="#000000">
|
|
||||||
|
|
||||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">Class
|
|
||||||
<a name="scoped_array">scoped_array</a></h1>
|
|
||||||
<p>Class <strong>scoped_array</strong> stores a pointer to a dynamically
|
|
||||||
allocated array. (Dynamically allocated arrays are allocated with the C++ <tt>new[]</tt>
|
|
||||||
expression.) The array pointed to is guaranteed to be deleted,
|
|
||||||
either on destruction of the <strong>scoped_array</strong>, or via an explicit <strong>scoped_array::reset()</strong>.</p>
|
|
||||||
<p>Class<strong> scoped_array</strong> is a simple solution for simple
|
|
||||||
needs. It cannot be used in C++ Standard Library containers. See <a href="shared_array.htm"><strong>shared_array</strong></a>
|
|
||||||
if <strong>scoped_array</strong> does not meet your needs.</p>
|
|
||||||
<p>Class<strong> scoped_array</strong> cannot correctly hold a pointer to a
|
|
||||||
single object. See <a href="scoped_ptr.htm"><strong>scoped_ptr</strong></a>
|
|
||||||
for that usage.</p>
|
|
||||||
<p>Because <strong>scoped_array</strong> is so simple, in its usual
|
|
||||||
implementation every operation is as fast as a built-in array pointer and has no
|
|
||||||
more space overhead that a built-in array pointer.</p>
|
|
||||||
<p>A heavier duty alternative to a <strong>scoped_array</strong> is a <strong>scoped_ptr</strong>
|
|
||||||
to a C++ Standard Library <strong>vector</strong>.</p>
|
|
||||||
<p>The class is a template parameterized on <tt>T</tt>, the type of the object
|
|
||||||
pointed to. <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">common
|
|
||||||
requirements</a>.</p>
|
|
||||||
<h2>Class scoped_array Synopsis</h2>
|
|
||||||
<pre>#include <boost/smart_ptr.hpp>
|
|
||||||
namespace boost {
|
|
||||||
|
|
||||||
template<typename T> class scoped_array : <a href="../utility/utility.htm#noncopyable">noncopyable</a> {
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef T <a href="#scoped_array_element_type">element_type</a>;
|
typedef T <a href="#element_type">element_type</a>;
|
||||||
|
|
||||||
explicit <a href="#scoped_array_ctor">scoped_array</a>( T* p=0 ); // never throws
|
explicit <a href="#ctor">scoped_array</a>(T * p = 0); // never throws
|
||||||
<strong> </strong><a href="#scoped_array_~scoped_array">~scoped_array</a>();
|
<a href="#destructor">~scoped_array</a>(); // never throws
|
||||||
|
|
||||||
void <a href="#scoped_array_reset">reset</a>( T* p=0 );
|
void <a href="#reset">reset</a>(T * p = 0); // never throws
|
||||||
|
|
||||||
T& <a href="#scoped_array_operator[]">operator[]</a>(std::size_t i) const; // never throws
|
T & <a href="#operator[]">operator[]</a>(std::ptrdiff_t i) const; // never throws
|
||||||
T* <a href="#scoped_array_get">get</a>() const; // never throws
|
T * <a href="#get">get</a>() const; // never throws
|
||||||
|
|
||||||
|
operator <A href="#conversions" ><i>unspecified-bool-type</i></A>() const; // never throws
|
||||||
|
|
||||||
|
void <a href="#swap">swap</a>(scoped_array & b); // never throws
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<class T> void <a href="#free-swap">swap</a>(scoped_array<T> & a, scoped_array<T> & b); // never throws
|
||||||
|
|
||||||
}</pre>
|
}</pre>
|
||||||
<h2>Class scoped_array Members</h2>
|
<h2>Members</h2>
|
||||||
<h3>scoped_array <a name="scoped_array_element_type">element_type</a></h3>
|
<h3>
|
||||||
<pre>typedef T element_type;</pre>
|
<a name="element_type">element_type</a></h3>
|
||||||
<p>Provides the type of the stored pointer.</p>
|
<pre>typedef T element_type;</pre>
|
||||||
<h3><a name="scoped_array_ctor">scoped_array constructors</a></h3>
|
<p>Provides the type of the stored pointer.</p>
|
||||||
<pre>explicit scoped_array( T* p=0 ); // never throws</pre>
|
<h3><a name="ctor">constructors</a></h3>
|
||||||
<p>Constructs a <tt>scoped_array</tt>, storing a copy of <tt>p</tt>, which must
|
<pre>explicit scoped_array(T * p = 0); // never throws</pre>
|
||||||
have been allocated via a C++ <tt>new</tt>[] expression or be 0.</p>
|
<p>Constructs a <b>scoped_array</b>, storing a copy of <b>p</b>, which must have
|
||||||
<h3><a name="scoped_array_~scoped_array">scoped_array destructor</a></h3>
|
been allocated via a C++ <b>new</b>[] expression or be 0. <b>T</b> is not
|
||||||
<pre>~scoped_array();</pre>
|
required be a complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">
|
||||||
<p>Deletes the array pointed to by the stored pointer. Note that in C++ <tt>delete</tt>[]
|
common requirements</a>.</p>
|
||||||
on a pointer with a value of 0 is harmless.</p>
|
<h3><a name="destructor">destructor</a></h3>
|
||||||
<p>Does not throw exceptions.</p>
|
<pre>~scoped_array(); // never throws</pre>
|
||||||
<h3>scoped_array <a name="scoped_array_reset">reset</a></h3>
|
<p>Deletes the array pointed to by the stored pointer. Note that <b>delete[]</b> on
|
||||||
<pre>void reset( T* p=0 )();</pre>
|
a pointer with a value of 0 is harmless. The guarantee that this does not throw
|
||||||
<p>If p is not equal to the stored pointer, deletes the array pointed to by the
|
exceptions depends on the requirement that the deleted array's objects'
|
||||||
stored pointer and then stores a copy of p, which must have been allocated via a
|
destructors do not throw exceptions. See the smart pointer <a href="smart_ptr.htm#common_requirements">
|
||||||
C++ <tt>new[]</tt> expression or be 0.</p>
|
common requirements</a>.</p>
|
||||||
<p>Does not throw exceptions.</p>
|
<h3><a name="reset">reset</a></h3>
|
||||||
<h3>scoped_array <a name="scoped_array_operator[]">operator[]</a></h3>
|
<pre>void reset(T * p = 0); // never throws</pre>
|
||||||
<p><tt>T& operator[](std::size_t i) const; // never throws</tt></p>
|
<p>
|
||||||
<p>Returns a reference to element <tt>i</tt> of the array pointed to by the
|
Deletes the array pointed to by the stored pointer and then stores a copy of p,
|
||||||
stored pointer.</p>
|
which must have been allocated via a C++ <b>new[]</b> expression or be 0. The
|
||||||
<p>Behavior is undefined (and almost certainly undesirable) if <tt>get()==0</tt>,
|
guarantee that this does not throw exceptions depends on the requirement that
|
||||||
or if <tt>i</tt> is less than 0 or is greater or equal to the number of elements
|
the deleted array's objects' destructors do not throw exceptions. See the smart
|
||||||
in the array.</p>
|
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p>
|
||||||
<h3>scoped_array <a name="scoped_array_get">get</a></h3>
|
<h3><a name="operator[]">subscripting</a></h3>
|
||||||
<pre>T* get() const; // never throws</pre>
|
<pre>T & operator[](std::ptrdiff_t i) const; // never throws</pre>
|
||||||
<p>Returns the stored pointer.</p>
|
<p>Returns a reference to element <b>i</b> of the array pointed to by the stored
|
||||||
<h2>Class <a name="shared_array_example">scoped_array example</a></h2>
|
pointer. Behavior is undefined and almost certainly undesirable if the stored
|
||||||
<p>[To be supplied. In the meantime, see <a href="smart_ptr_test.cpp">smart_ptr_test.cpp</a>.]</p>
|
pointer is 0, or if <b>i</b> is less than 0 or is greater than or equal to the
|
||||||
<hr>
|
number of elements in the array.</p>
|
||||||
<p>Revised December 8, 1999</p>
|
<h3><a name="get">get</a></h3>
|
||||||
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
|
<pre>T * get() const; // never throws</pre>
|
||||||
modify, sell and distribute this document is granted provided this copyright
|
<p>Returns the stored pointer. <b>T</b> need not be a complete type. See the smart
|
||||||
notice appears in all copies. This document is provided "as is"
|
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p>
|
||||||
without express or implied warranty, and with no claim as to its suitability for
|
<h3><a name="conversions">conversions</a></h3>
|
||||||
any purpose.</p>
|
<pre>operator <i>unspecified-bool-type</i> () const; // never throws</pre>
|
||||||
|
<p>Returns an unspecified value that, when used in boolean contexts, is equivalent
|
||||||
</body>
|
to <code>get() != 0</code>.</p>
|
||||||
|
<h3><a name="swap">swap</a></h3>
|
||||||
|
<pre>void swap(scoped_array & b); // never throws</pre>
|
||||||
|
<p>Exchanges the contents of the two smart pointers. <b>T</b> need not be a
|
||||||
|
complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">common
|
||||||
|
requirements</a>.</p>
|
||||||
|
<h2><a name="functions">Free Functions</a></h2>
|
||||||
|
<h3><a name="free-swap">swap</a></h3>
|
||||||
|
<pre>template<class T> void swap(scoped_array<T> & a, scoped_array<T> & b); // never throws</pre>
|
||||||
|
<p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>.
|
||||||
|
Provided as an aid to generic programming.</p>
|
||||||
|
<hr>
|
||||||
|
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan-->
|
||||||
|
09 January 2003<!--webbot bot="Timestamp" endspan i-checksum="32310"--></p>
|
||||||
|
<p><small>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
|
||||||
|
Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version
|
||||||
|
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
|
||||||
|
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
265
scoped_ptr.htm
265
scoped_ptr.htm
@@ -1,128 +1,181 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
<html>
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>scoped_ptr</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="#ffffff" text="#000000">
|
||||||
|
<h1><A href="../../index.htm"><img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" width="277" height="86"
|
||||||
|
border="0"></A>scoped_ptr class template</h1>
|
||||||
|
<p>The <b>scoped_ptr</b> class template stores a pointer to a dynamically allocated
|
||||||
|
object. (Dynamically allocated objects are allocated with the C++ <b>new</b> expression.)
|
||||||
|
The object pointed to is guaranteed to be deleted, either on destruction of the <b>scoped_ptr</b>,
|
||||||
|
or via an explicit <b>reset</b>. See the <a href="#example">example</a>.</p>
|
||||||
|
<p>The <b>scoped_ptr</b> 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 <a href="../utility/utility.htm#Class_noncopyable">
|
||||||
|
noncopyable</a>) signal its intent to retain ownership solely within the
|
||||||
|
current scope. Because it is <a href="../utility/utility.htm#Class_noncopyable">noncopyable</a>,
|
||||||
|
it is safer than <b>shared_ptr</b> or <b>std::auto_ptr</b> for pointers which
|
||||||
|
should not be copied.</p>
|
||||||
|
<p>Because <b>scoped_ptr</b> 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.</p>
|
||||||
|
<p><STRONG>scoped_ptr</STRONG> cannot be used in C++ Standard Library containers.
|
||||||
|
Use <a href="shared_ptr.htm"><b>shared_ptr</b></a> if you need a smart pointer
|
||||||
|
that can.</p>
|
||||||
|
<p><STRONG>scoped_ptr</STRONG> cannot correctly hold a pointer to a dynamically
|
||||||
|
allocated array. See <a href="scoped_array.htm"><b>scoped_array</b></a> for
|
||||||
|
that usage.</p>
|
||||||
|
<p>The class template is parameterized on <b>T</b>, the type of the object pointed
|
||||||
|
to. <b>T</b> must meet the smart pointer <a href="smart_ptr.htm#common_requirements">
|
||||||
|
common requirements</a>.</p>
|
||||||
|
<h2>Synopsis</h2>
|
||||||
|
<pre>namespace boost {
|
||||||
|
|
||||||
<head>
|
template<class T> class scoped_ptr : <a href="../utility/utility.htm#Class_noncopyable">noncopyable</a> {
|
||||||
<title>scoped_ptr</title>
|
|
||||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
|
||||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body bgcolor="#FFFFFF" text="#000000">
|
|
||||||
|
|
||||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">Class
|
|
||||||
<a name="scoped_ptr">scoped_ptr</a></h1>
|
|
||||||
<p>Class <strong>scoped_ptr</strong> stores a pointer to a dynamically allocated
|
|
||||||
object. (Dynamically allocated objects are allocated with the C++ <tt>new</tt>
|
|
||||||
expression.) The object pointed to is guaranteed to be deleted,
|
|
||||||
either on destruction of the <strong>scoped_ptr</strong>, or via an explicit <strong>scoped_ptr::reset()</strong>.
|
|
||||||
See <a href="#scoped_ptr_example">example</a>.</p>
|
|
||||||
<p>Class<strong> scoped_ptr</strong> is a simple solution for simple
|
|
||||||
needs. It cannot be used in C++ Standard Library containers. See <a href="shared_ptr.htm"><strong>shared_ptr</strong></a>
|
|
||||||
or std::auto_ptr if <strong>scoped_ptr</strong> does not meet your needs.</p>
|
|
||||||
<p>Class<strong> scoped_ptr</strong> cannot correctly hold a pointer to a
|
|
||||||
dynamically allocated array. See <a href="scoped_array.htm"><strong>scoped_array</strong></a>
|
|
||||||
for that usage.</p>
|
|
||||||
<p>Because <strong>scoped_ptr</strong> is so simple, in its usual implementation
|
|
||||||
every operation is as fast as a built-in pointer and has no more space overhead
|
|
||||||
that a built-in pointer.</p>
|
|
||||||
<p>The class is a template parameterized on <tt>T</tt>, the type of the object
|
|
||||||
pointed to. <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">common
|
|
||||||
requirements</a>.</p>
|
|
||||||
<h2>Class scoped_ptr Synopsis</h2>
|
|
||||||
<pre>#include <boost/smart_ptr.hpp>
|
|
||||||
namespace boost {
|
|
||||||
|
|
||||||
template<typename T> class scoped_ptr : <a href="../utility/utility.htm#class noncopyable">noncopyable</a> {
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef T <a href="#scoped_ptr_element_type">element_type</a>;
|
typedef T <a href="#element_type">element_type</a>;
|
||||||
|
|
||||||
explicit <a href="#scoped_ptr_ctor">scoped_ptr</a>( T* p=0 ); // never throws
|
explicit <a href="#constructors">scoped_ptr</a>(T * p = 0); // never throws
|
||||||
<strong> </strong><a href="#scoped_ptr_~scoped_ptr">~scoped_ptr</a>();
|
<a href="#destructor">~scoped_ptr</a>(); // never throws
|
||||||
|
|
||||||
void <a href="#scoped_ptr_reset">reset</a>( T* p=0 );
|
void <a href="#reset">reset</a>(T * p = 0); // never throws
|
||||||
|
|
||||||
T& <a href="#scoped_ptr_operator*">operator*</a>() const; // never throws
|
T & <a href="#indirection">operator*</a>() const; // never throws
|
||||||
T* <a href="#scoped_ptr_operator->">operator-></a>() const; // never throws
|
T * <a href="#indirection">operator-></a>() const; // never throws
|
||||||
T* <a href="#scoped_ptr_get">get</a>() const; // never throws
|
T * <a href="#get">get</a>() const; // never throws
|
||||||
|
|
||||||
|
operator <A href="#conversions" ><i>unspecified-bool-type</i></A>() const; // never throws
|
||||||
|
|
||||||
|
void <a href="#swap">swap</a>(scoped_ptr & b); // never throws
|
||||||
};
|
};
|
||||||
}</pre>
|
|
||||||
<h2>Class scoped_ptr Members</h2>
|
|
||||||
<h3>scoped_ptr <a name="scoped_ptr_element_type">element_type</a></h3>
|
|
||||||
<pre>typedef T element_type;</pre>
|
|
||||||
<p>Provides the type of the stored pointer.</p>
|
|
||||||
<h3><a name="scoped_ptr_ctor">scoped_ptr constructors</a></h3>
|
|
||||||
<pre>explicit scoped_ptr( T* p=0 ); // never throws</pre>
|
|
||||||
<p>Constructs a <tt>scoped_ptr</tt>, storing a copy of <tt>p</tt>, which must
|
|
||||||
have been allocated via a C++ <tt>new</tt> expression or be 0..</p>
|
|
||||||
<h3><a name="scoped_ptr_~scoped_ptr">scoped_ptr destructor</a></h3>
|
|
||||||
<pre>~scoped_ptr();</pre>
|
|
||||||
<p>Deletes the object pointed to by the stored pointer. Note that in C++, <tt>delete</tt>
|
|
||||||
on a pointer with a value of 0 is harmless.</p>
|
|
||||||
<p>Does not throw exceptions.</p>
|
|
||||||
<h3>scoped_ptr <a name="scoped_ptr_reset">reset</a></h3>
|
|
||||||
<pre>void reset( T* p=0 );</pre>
|
|
||||||
<p>If p is not equal to the stored pointer, deletes the object pointed to by the
|
|
||||||
stored pointer and then stores a copy of p, which must have been allocated via a
|
|
||||||
C++ <tt>new</tt> expression or be 0.</p>
|
|
||||||
<p>Does not throw exceptions.</p>
|
|
||||||
<h3>scoped_ptr <a name="scoped_ptr_operator*">operator*</a></h3>
|
|
||||||
<pre>T& operator*() const; // never throws</pre>
|
|
||||||
<p>Returns a reference to the object pointed to by the stored pointer.</p>
|
|
||||||
<h3>scoped_ptr <a name="scoped_ptr_operator->">operator-></a> and <a name="scoped_ptr_get">get</a></h3>
|
|
||||||
<pre>T* operator->() const; // never throws
|
|
||||||
T* get() const; // never throws</pre>
|
|
||||||
<p>Both return the stored pointer.</p>
|
|
||||||
<h2>Class <a name="scoped_ptr_example">scoped_ptr example</a>s</h2>
|
|
||||||
<pre>#include <iostream>
|
|
||||||
#include <boost/smart_ptr.h>
|
|
||||||
|
|
||||||
struct Shoe { ~Shoe(){ std::cout << "Buckle my shoe" << std::endl; } };
|
template<class T> void <a href="#free-swap">swap</a>(scoped_ptr<T> & a, scoped_ptr<T> & b); // never throws
|
||||||
|
|
||||||
|
}</pre>
|
||||||
|
<h2>Members</h2>
|
||||||
|
<h3><a name="element_type">element_type</a></h3>
|
||||||
|
<pre>typedef T element_type;</pre>
|
||||||
|
<p>Provides the type of the stored pointer.</p>
|
||||||
|
<h3><a name="constructors">constructors</a></h3>
|
||||||
|
<pre>explicit scoped_ptr(T * p = 0); // never throws</pre>
|
||||||
|
<p>Constructs a <b>scoped_ptr</b>, storing a copy of <b>p</b>, which must have been
|
||||||
|
allocated via a C++ <b>new</b> expression or be 0. <b>T</b> is not required be
|
||||||
|
a complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">common
|
||||||
|
requirements</a>.</p>
|
||||||
|
<h3><a name="destructor">destructor</a></h3>
|
||||||
|
<pre>~scoped_ptr(); // never throws</pre>
|
||||||
|
<p>Destroys the object pointed to by the stored pointer, if any, as if by using <tt>delete
|
||||||
|
this->get()</tt>.</p>
|
||||||
|
<P>
|
||||||
|
The guarantee that this does not throw exceptions depends on the requirement
|
||||||
|
that the deleted object's destructor does not throw exceptions. See the smart
|
||||||
|
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</P>
|
||||||
|
<h3><a name="reset">reset</a></h3>
|
||||||
|
<pre>void reset(T * p = 0); // never throws</pre>
|
||||||
|
<p>
|
||||||
|
Deletes the object pointed to by the stored pointer and then stores a copy of
|
||||||
|
p, which must have been allocated via a C++ <b>new</b> expression or be 0. The
|
||||||
|
guarantee that this does not throw exceptions depends on the requirement that
|
||||||
|
the deleted object's destructor does not throw exceptions. See the smart
|
||||||
|
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p>
|
||||||
|
<h3><a name="indirection">indirection</a></h3>
|
||||||
|
<pre>T & operator*() const; // never throws</pre>
|
||||||
|
<p>Returns a reference to the object pointed to by the stored pointer. Behavior is
|
||||||
|
undefined if the stored pointer is 0.</p>
|
||||||
|
<pre>T * operator->() const; // never throws</pre>
|
||||||
|
<p>Returns the stored pointer. Behavior is undefined if the stored pointer is 0.</p>
|
||||||
|
<h3><a name="get">get</a></h3>
|
||||||
|
<pre>T * get() const; // never throws</pre>
|
||||||
|
<p>Returns the stored pointer. <b>T</b> need not be a complete type. See the smart
|
||||||
|
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p>
|
||||||
|
<h3><a name="conversions">conversions</a></h3>
|
||||||
|
<pre>operator <i>unspecified-bool-type</i> () const; // never throws</pre>
|
||||||
|
<p>Returns an unspecified value that, when used in boolean contexts, is equivalent
|
||||||
|
to <code>get() != 0</code>.</p>
|
||||||
|
<h3><a name="swap">swap</a></h3>
|
||||||
|
<pre>void swap(scoped_ptr & b); // never throws</pre>
|
||||||
|
<p>Exchanges the contents of the two smart pointers. <b>T</b> need not be a
|
||||||
|
complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">common
|
||||||
|
requirements</a>.</p>
|
||||||
|
<h2><a name="functions">Free Functions</a></h2>
|
||||||
|
<h3><a name="free-swap">swap</a></h3>
|
||||||
|
<pre>template<class T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b); // never throws</pre>
|
||||||
|
<p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>.
|
||||||
|
Provided as an aid to generic programming.</p>
|
||||||
|
<h2><a name="example">Example</a></h2>
|
||||||
|
<p>Here's an example that uses <b>scoped_ptr</b>.</p>
|
||||||
|
<blockquote>
|
||||||
|
<pre>#include <boost/scoped_ptr.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
struct Shoe { ~Shoe() { std::cout << "Buckle my shoe\n"; } };
|
||||||
|
|
||||||
class MyClass {
|
class MyClass {
|
||||||
boost::scoped_ptr<int> ptr;
|
boost::scoped_ptr<int> ptr;
|
||||||
public:
|
public:
|
||||||
MyClass() : ptr(new int) { *ptr = 0; }
|
MyClass() : ptr(new int) { *ptr = 0; }
|
||||||
int add_one() { return ++*ptr; }
|
int add_one() { return ++*ptr; }
|
||||||
};
|
};
|
||||||
|
|
||||||
void main() {
|
int main()
|
||||||
|
{
|
||||||
boost::scoped_ptr<Shoe> x(new Shoe);
|
boost::scoped_ptr<Shoe> x(new Shoe);
|
||||||
MyClass my_instance;
|
MyClass my_instance;
|
||||||
std::cout << my_instance.add_one() << std::endl;
|
std::cout << my_instance.add_one() << '\n';
|
||||||
std::cout << my_instance.add_one() << std::endl;
|
std::cout << my_instance.add_one() << '\n';
|
||||||
}</pre>
|
}</pre>
|
||||||
<p>The example program produces the beginning of a child's nursery rhyme as
|
</blockquote>
|
||||||
output:</p>
|
<p>The example program produces the beginning of a child's nursery rhyme:</p>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre>1
|
<pre>1
|
||||||
2
|
2
|
||||||
Buckle my shoe</pre>
|
Buckle my shoe</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
<h2>Handle/Body Idiom</h2>
|
<h2>Rationale</h2>
|
||||||
<p>One common usage of <b>shared_pointer</b> is to implement a handle/body
|
<p>The primary reason to use <b>scoped_ptr</b> rather than <b>auto_ptr</b> is to
|
||||||
structure which avoids exposing the body (implementation) in the header file:</p>
|
let readers of your code know that you intend "resource acquisition is
|
||||||
<pre>class handle
|
initialization" to be applied only for the current scope, and have no intent to
|
||||||
{
|
transfer ownership.</p>
|
||||||
public: // simple forwarding functions to the body class
|
<p>A secondary reason to use <b>scoped_ptr</b> is to prevent a later maintenance
|
||||||
void f();
|
programmer from adding a function that transfers ownership by returning the <b>auto_ptr</b>,
|
||||||
void g(int);
|
because the maintenance programmer saw <b>auto_ptr</b>, and assumed ownership
|
||||||
private:
|
could safely be transferred.</p>
|
||||||
friend class body; //incomplete class hides implementation
|
<p>Think of <b>bool</b> vs <b>int</b>. We all know that under the covers <b>bool</b>
|
||||||
boost::scoped_ptr<body> imp;
|
is usually just an <b>int</b>. Indeed, some argued against including <b>bool</b>
|
||||||
};</pre>
|
in the C++ standard because of that. But by coding <b>bool</b> rather than <b>int</b>,
|
||||||
<p>This code requires that <code>class body</code> have a trivial destructor to
|
you tell your readers what your intent is. Same with <b>scoped_ptr</b>; by
|
||||||
avoid undefined behavior. This is because the definition of <code>class
|
using it you are signaling intent.</p>
|
||||||
body</code> is not visible at the time scoped_ptr<> deletes it. See ISO
|
<p>It has been suggested that <b>scoped_ptr<T></b> is equivalent to <b>std::auto_ptr<T>
|
||||||
5.3.5/5. Note that some compilers will issue a warning even though the
|
const</b>. Ed Brey pointed out, however, that <b>reset</b> will not work on
|
||||||
above code is well defined.</p>
|
a <b>std::auto_ptr<T> const.</b></p>
|
||||||
<hr>
|
<h2><a name="Handle/Body">Handle/Body</a> Idiom</h2>
|
||||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B %Y" startspan -->24 July 2000<!--webbot bot="Timestamp" endspan i-checksum="18764" --></p>
|
<p>One common usage of <b>scoped_ptr</b> is to implement a handle/body (also called
|
||||||
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
|
pimpl) idiom which avoids exposing the body (implementation) in the header
|
||||||
modify, sell and distribute this document is granted provided this copyright
|
file.</p>
|
||||||
notice appears in all copies. This document is provided "as is"
|
<p>The <a href="example/scoped_ptr_example_test.cpp">scoped_ptr_example_test.cpp</a>
|
||||||
without express or implied warranty, and with no claim as to its suitability for
|
sample program includes a header file, <a href="example/scoped_ptr_example.hpp">scoped_ptr_example.hpp</a>,
|
||||||
any purpose.</p>
|
which uses a <b>scoped_ptr<></b> to an incomplete type to hide the
|
||||||
|
implementation. The instantiation of member functions which require a complete
|
||||||
</body>
|
type occurs in the <a href="example/scoped_ptr_example.cpp">scoped_ptr_example.cpp</a>
|
||||||
|
implementation file.</p>
|
||||||
|
<h2>Frequently Asked Questions</h2>
|
||||||
|
<p><b>Q</b>. Why doesn't <b>scoped_ptr</b> have a release() member?<br>
|
||||||
|
<b>A</b>. When reading source code, it is valuable to be able to draw
|
||||||
|
conclusions about program behavior based on the types being used. If <STRONG>scoped_ptr</STRONG>
|
||||||
|
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 <STRONG>std::auto_ptr</STRONG> where transfer of ownership
|
||||||
|
is required. (supplied by Dave Abrahams)</p>
|
||||||
|
<hr>
|
||||||
|
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B %Y" startspan -->
|
||||||
|
09 January 2003<!--webbot bot="Timestamp" endspan i-checksum="32310" --></p>
|
||||||
|
<p><small>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
|
||||||
|
Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version
|
||||||
|
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
|
||||||
|
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
335
shared_array.htm
335
shared_array.htm
@@ -1,180 +1,185 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
<html>
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>shared_array</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="#ffffff" text="#000000">
|
||||||
|
<h1><A href="../../index.htm"><img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" width="277" height="86"
|
||||||
|
border="0"></A>shared_array class template</h1>
|
||||||
|
<p>The <b>shared_array</b> class template stores a pointer to a dynamically
|
||||||
|
allocated array. (Dynamically allocated array are allocated with the C++ <b>new[]</b>
|
||||||
|
expression.) The object pointed to is guaranteed to be deleted when the last <b>shared_array</b>
|
||||||
|
pointing to it is destroyed or reset.</p>
|
||||||
|
<p>Every <b>shared_array</b> meets the <b>CopyConstructible</b> and <b>Assignable</b>
|
||||||
|
requirements of the C++ Standard Library, and so can be used in standard
|
||||||
|
library containers. Comparison operators are supplied so that <b>shared_array</b>
|
||||||
|
works with the standard library's associative containers.</p>
|
||||||
|
<p>Normally, a <b>shared_array</b> cannot correctly hold a pointer to an object
|
||||||
|
that has been allocated with the non-array form of <STRONG>new</STRONG>. See <a href="shared_ptr.htm">
|
||||||
|
<b>shared_ptr</b></a> for that usage.</p>
|
||||||
|
<p>Because the implementation uses reference counting, cycles of <b>shared_array</b>
|
||||||
|
instances will not be reclaimed. For example, if <b>main()</b> holds a <b>shared_array</b>
|
||||||
|
to <b>A</b>, which directly or indirectly holds a <b>shared_array</b> back to <b>A</b>,
|
||||||
|
<b>A</b>'s use count will be 2. Destruction of the original <b>shared_array</b>
|
||||||
|
will leave <b>A</b> dangling with a use count of 1.</p>
|
||||||
|
<p>A <b>shared_ptr</b> to a <b>std::vector</b> is an alternative to a <b>shared_array</b>
|
||||||
|
that is a bit heavier duty but far more flexible.</p>
|
||||||
|
<p>The class template is parameterized on <b>T</b>, the type of the object pointed
|
||||||
|
to. <b>T</b> must meet the smart pointer <a href="smart_ptr.htm#common_requirements">
|
||||||
|
common requirements</a>.</p>
|
||||||
|
<h2>Synopsis</h2>
|
||||||
|
<pre>namespace boost {
|
||||||
|
|
||||||
<head>
|
template<class T> class shared_array {
|
||||||
<title>shared_array</title>
|
|
||||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
|
||||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body bgcolor="#FFFFFF" text="#000000">
|
|
||||||
|
|
||||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">Class
|
|
||||||
<a name="shared_array">shared_array</a></h1>
|
|
||||||
<p>Class <strong>shared_array</strong> stores a pointer to a dynamically
|
|
||||||
allocated array. (Dynamically allocated arrays are allocated with the C++ <tt>new[]</tt>
|
|
||||||
expression.) The array pointed to is guaranteed to be deleted,
|
|
||||||
either on destruction of the <strong>shared_array</strong>, on <strong>shared_array::operator=()</strong>,
|
|
||||||
or via an explicit <strong>shared_array::reset()</strong>. See <a href="#shared_array_example">example</a>.</p>
|
|
||||||
<p>Class<strong> shared_array</strong> meets the <strong>CopyConstuctible</strong>
|
|
||||||
and <strong>Assignable</strong> requirements of the C++ Standard Library, and so
|
|
||||||
can be used in C++ Standard Library containers. A specialization of std::
|
|
||||||
less< > for boost::shared_ptr<Y> is supplied so that <strong>
|
|
||||||
shared_array</strong> works by default for Standard Library's Associative
|
|
||||||
Container Compare template parameter. For compilers not supporting partial
|
|
||||||
specialization, the user must explicitly pass the less<> functor.</p>
|
|
||||||
<p>Class<strong> shared_array</strong> cannot correctly hold a pointer to a
|
|
||||||
single object. See <a href="shared_ptr.htm"><strong>shared_array</strong></a>
|
|
||||||
for that usage.</p>
|
|
||||||
<p>Class<strong> shared_array</strong> will not work correctly with cyclic data
|
|
||||||
structures. For example, if main() holds a shared_array pointing to array A,
|
|
||||||
which directly or indirectly holds a shared_array pointing back to array A, then
|
|
||||||
array A's use_count() will be 2, and destruction of the main() shared_array will
|
|
||||||
leave array A dangling with a use_count() of 1.</p>
|
|
||||||
<p>A heavier duty alternative to a <strong>shared_array</strong> is a <strong>shared_ptr</strong>
|
|
||||||
to a C++ Standard Library <strong>vector</strong>.</p>
|
|
||||||
<p>The class is a template parameterized on <tt>T</tt>, the type of the object
|
|
||||||
pointed to. <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">Common
|
|
||||||
requirements</a>.</p>
|
|
||||||
<h2>Class shared_array Synopsis</h2>
|
|
||||||
<pre>#include <boost/smart_ptr.hpp>
|
|
||||||
namespace boost {
|
|
||||||
|
|
||||||
template<typename T> class shared_array {
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef T <a href="#shared_array_element_type">element_type</a>;
|
typedef T <a href="#element_type">element_type</a>;
|
||||||
|
|
||||||
explicit <a href="#shared_array_ctor">shared_array</a>( T* p=0 );
|
explicit <a href="#constructors">shared_array</a>(T * p = 0);
|
||||||
<a href="#shared_array_ctor">shared_array</a>( const shared_array& ); // never throws
|
template<class D> <a href="#constructors">shared_array</a>(T * p, D d);
|
||||||
<strong> </strong><a href="#shared_array_~shared_array">~shared_array</a>();
|
<a href="#destructor">~shared_array</a>(); // never throws
|
||||||
|
|
||||||
shared_array& <a href="#shared_array_operator=">operator=</a>( const shared_array& ); // never throws
|
<a href="#constructors">shared_array</a>(shared_array const & r); // never throws
|
||||||
|
|
||||||
void <a href="#shared_array_reset">reset</a>( T* p=0 );
|
shared_array & <a href="#assignment">operator=</a>(shared_array const & r); // never throws
|
||||||
|
|
||||||
T& <a href="#shared_array_operator[]">operator[]</a>(std::size_t i) const; // never throws
|
void <a href="#reset">reset</a>(T * p = 0);
|
||||||
T* <a href="#shared_array_get">get</a>() const; // never throws
|
template<class D> void <a href="#reset">reset</a>(T * p, D d);
|
||||||
|
|
||||||
long <a href="#shared_array_use_count">use_count</a>() const; // never throws
|
T & <a href="#indexing">operator[]</a>(std::ptrdiff_t i) const; // never throws
|
||||||
bool <a href="#shared_array_unique">unique</a>() const; // never throws
|
T * <a href="#get">get</a>() const; // never throws
|
||||||
|
|
||||||
void <a href="#shared_array_swap">swap</a>( shared_array<T>& other ) throw()
|
bool <a href="#unique">unique</a>() const; // never throws
|
||||||
|
long <a href="#use_count">use_count</a>() const; // never throws
|
||||||
|
|
||||||
|
operator <A href="#conversions" ><i>unspecified-bool-type</i></A>() const; // never throws
|
||||||
|
|
||||||
|
void <a href="#swap">swap</a>(shared_array<T> & b); // never throws
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<class T>
|
||||||
inline bool operator==(const shared_array<T>& a, const shared_array<T>& b)
|
bool <a href="#comparison">operator==</a>(shared_array<T> const & a, shared_array<T> const & b); // never throws
|
||||||
{ return a.get() == b.get(); }
|
template<class T>
|
||||||
|
bool <a href="#comparison">operator!=</a>(shared_array<T> const & a, shared_array<T> const & b); // never throws
|
||||||
|
template<class T>
|
||||||
|
bool <a href="#comparison">operator<</a>(shared_array<T> const & a, shared_array<T> const & b); // never throws
|
||||||
|
|
||||||
|
template<class T> void <a href="#free-swap">swap</a>(shared_array<T> & a, shared_array<T> & b); // never throws
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline bool operator!=(const shared_array<T>& a, const shared_array<T>& b)
|
|
||||||
{ return a.get() != b.get(); }
|
|
||||||
}</pre>
|
}</pre>
|
||||||
<pre>namespace std {
|
<h2>Members</h2>
|
||||||
|
<h3><a name="element_type">element_type</a></h3>
|
||||||
template<typename T>
|
<pre>typedef T element_type;</pre>
|
||||||
inline void swap(boost::shared_array<T>& a, boost::shared_array<T>& b)
|
<p>Provides the type of the stored pointer.</p>
|
||||||
{ a.swap(b); }
|
<h3><a name="constructors">constructors</a></h3>
|
||||||
|
<pre>explicit shared_array(T * p = 0);</pre>
|
||||||
template<typename T>
|
<p>Constructs a <b>shared_array</b>, storing a copy of <b>p</b>, which must be a
|
||||||
struct less< boost::shared_array<T> >
|
pointer to an array that was allocated via a C++ <b>new[]</b> expression or be
|
||||||
: binary_function<boost::shared_array<T>, boost::shared_array<T>, bool>
|
0. Afterwards, the <a href="#use_count">use count</a> is 1 (even if p == 0; see <a href="#destructor">
|
||||||
{
|
~shared_array</a>). The only exception which may be thrown by this
|
||||||
bool operator()(const boost::shared_array<T>& a,
|
constructor is <b>std::bad_alloc</b>. If an exception is thrown, <b>delete[] p</b>
|
||||||
const boost::shared_array<T>& b) const
|
is called.</p>
|
||||||
{ return less<T*>()(a.get(),b.get()); }
|
<pre>template<class D> shared_array(T * p, D d);</pre>
|
||||||
};
|
<p>Constructs a <b>shared_array</b>, storing a copy of <b>p</b> and of <b>d</b>.
|
||||||
|
Afterwards, the <a href="#use_count">use count</a> is 1. <b>D</b>'s copy
|
||||||
} // namespace std </pre>
|
constructor and destructor must not throw. When the the time comes to delete
|
||||||
<p>Specialization of std::swap uses the fast, non-throwing swap that's provided
|
the array pointed to by <b>p</b>, the object <b>d</b> is used in the statement <b>d(p)</b>.
|
||||||
as a member function instead of using the default algorithm which creates a
|
Invoking the object <b>d</b> with parameter <b>p</b> in this way must not
|
||||||
temporary and uses assignment.<br>
|
throw. The only exception which may be thrown by this constructor is <b>std::bad_alloc</b>.
|
||||||
<br>
|
If an exception is thrown, <b>d(p)</b> is called.</p>
|
||||||
Specialization of std::less allows use of shared arrays as keys in C++
|
<pre>shared_array(shared_array const & r); // never throws</pre>
|
||||||
Standard Library associative collections.<br>
|
<p>Constructs a <b>shared_array</b>, as if by storing a copy of the pointer stored
|
||||||
<br>
|
in <b>r</b>. Afterwards, the <a href="#use_count">use count</a> for all copies
|
||||||
The std::less specializations use std::less<T*> to perform the
|
is 1 more than the initial use count.</p>
|
||||||
comparison. This insures that pointers are handled correctly, since the
|
<h3><a name="destructor">destructor</a></h3>
|
||||||
standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel]
|
<pre>~shared_array(); // never throws</pre>
|
||||||
paragraph 2) but std::less<> on pointers is well-defined (20.3.3 [lib.comparisons]
|
<p>Decrements the <a href="#use_count">use count</a>. Then, if the use count is 0,
|
||||||
paragraph 8).<br>
|
deletes the array pointed to by the stored pointer. Note that <b>delete[]</b> on
|
||||||
<br>
|
a pointer with a value of 0 is harmless. <b>T</b> need not be a complete type.
|
||||||
It's still a controversial question whether supplying only std::less is better
|
The guarantee that this does not throw exceptions depends on the requirement
|
||||||
than supplying a full range of comparison operators (<, >, <=, >=).</p>
|
that the deleted object's destructor does not throw exceptions. See the smart
|
||||||
<p>The current implementation does not supply the specializations if the macro
|
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p>
|
||||||
name BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION is defined.</p>
|
<h3><a name="assignment">assignment</a></h3>
|
||||||
<h2>Class shared_array Members</h2>
|
<pre>shared_array & operator=(shared_array const & r); // never throws</pre>
|
||||||
<h3>shared_array <a name="shared_array_element_type">element_type</a></h3>
|
<p>Constructs a new <b>shared_array</b> as described <a href="#constructors">above</a>,
|
||||||
<pre>typedef T element_type;</pre>
|
then replaces this <b>shared_array</b> with the new one, destroying the
|
||||||
<p>Provides the type of the stored pointer.</p>
|
replaced object.</p>
|
||||||
<h3><a name="shared_array_ctor">shared_array constructors</a></h3>
|
<h3><a name="reset">reset</a></h3>
|
||||||
<pre>explicit shared_array( T* p=0 );</pre>
|
<pre>void reset(T * p = 0);</pre>
|
||||||
<p>Constructs a <strong>shared_array</strong>, storing a copy of <tt>p</tt>,
|
<p>Constructs a new <b>shared_array</b> as described <a href="#constructors">above</a>,
|
||||||
which must have been allocated via a C++ <tt>new</tt>[] expression or be 0.
|
then replaces this <b>shared_array</b> with the new one, destroying the
|
||||||
Afterwards, use_count() is 1 (even if p==0; see <a href="#shared_array_~shared_array">~shared_array</a>).</p>
|
replaced object. The only exception which may be thrown is <b>std::bad_alloc</b>.
|
||||||
<p>The only exception which may be thrown is <tt>std::bad_alloc</tt>. If
|
If an exception is thrown, <b>delete[] p</b> is called.</p>
|
||||||
an exception is thrown, <tt>delete[] p</tt> is called.</p>
|
<pre>template<class D> void reset(T * p, D d);</pre>
|
||||||
<pre>shared_array( const shared_array& r); // never throws</pre>
|
<p>Constructs a new <b>shared_array</b> as described <a href="#constructors">above</a>,
|
||||||
<p>Constructs a <strong>shared_array</strong>, as if by storing a copy of the
|
then replaces this <b>shared_array</b> with the new one, destroying the
|
||||||
pointer stored in <strong>r</strong>. Afterwards, <strong>use_count()</strong>
|
replaced object. <b>D</b>'s copy constructor must not throw. The only exception
|
||||||
for all copies is 1 more than the initial <strong>r.use_count()</strong>.</p>
|
which may be thrown is <b>std::bad_alloc</b>. If an exception is thrown, <b>d(p)</b>
|
||||||
<h3><a name="shared_array_~shared_array">shared_array destructor</a></h3>
|
is called.</p>
|
||||||
<pre>~shared_array();</pre>
|
<h3><a name="indexing">indexing</a></h3>
|
||||||
<p>If <strong>use_count()</strong> == 1, deletes the array pointed to by the
|
<pre>T & operator[](std::ptrdiff_t i) const; // never throws</pre>
|
||||||
stored pointer. Otherwise, <strong>use_count()</strong> for any remaining
|
<p>Returns a reference to element <b>i</b> of the array pointed to by the stored
|
||||||
copies is decremented by 1. Note that in C++ <tt>delete</tt>[] on a pointer with
|
pointer. Behavior is undefined and almost certainly undesirable if the stored
|
||||||
a value of 0 is harmless.</p>
|
pointer is 0, or if <b>i</b> is less than 0 or is greater than or equal to the
|
||||||
<p>Does not throw exceptions.</p>
|
number of elements in the array.</p>
|
||||||
<h3>shared_array <a name="shared_array_operator=">operator=</a></h3>
|
<h3><a name="get">get</a></h3>
|
||||||
<pre>shared_array& operator=( const shared_array& r); // never throws</pre>
|
<pre>T * get() const; // never throws</pre>
|
||||||
<p>First, if <strong>use_count()</strong> == 1, deletes the array pointed to by
|
<p>Returns the stored pointer. <b>T</b> need not be a complete type. See the smart
|
||||||
the stored pointer. Otherwise, <strong>use_count()</strong> for any
|
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p>
|
||||||
remaining copies is decremented by 1. Note that in C++ <tt>delete</tt>[] on a
|
<h3><a name="unique">unique</a></h3>
|
||||||
pointer with a value of 0 is harmless.</p>
|
<pre>bool unique() const; // never throws</pre>
|
||||||
<p>Then replaces the contents of <strong>this</strong>, as if by storing a copy
|
<p>Returns true if no other <b>shared_array</b> is sharing ownership of the stored
|
||||||
of the pointer stored in <strong>r</strong>. Afterwards, <strong>use_count()</strong>
|
pointer, false otherwise. <b>T</b> need not be a complete type. See the smart
|
||||||
for all copies is 1 more than the initial <strong>r.use_count()</strong>. </p>
|
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p>
|
||||||
<h3>shared_array <a name="shared_array_reset">reset</a></h3>
|
<h3><a name="use_count">use_count</a></h3>
|
||||||
<pre>void reset( T* p=0 );</pre>
|
<pre>long use_count() const; // never throws</pre>
|
||||||
<p>First, if <strong>use_count()</strong> == 1, deletes the array pointed to by
|
<p>Returns the number of <b>shared_array</b> objects sharing ownership of the
|
||||||
the stored pointer. Otherwise, <strong>use_count()</strong> for any
|
stored pointer. <b>T</b> need not be a complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">
|
||||||
remaining copies is decremented by 1. Note that in C++ <tt>delete</tt>[]
|
common requirements</a>.</p>
|
||||||
on a pointer with a value of 0 is harmless.</p>
|
<p>Because <b>use_count</b> is not necessarily efficient to implement for
|
||||||
<p>Then replaces the contents of <strong>this</strong>, as if by storing a copy
|
implementations of <b>shared_array</b> that do not use an explicit reference
|
||||||
of <strong>p</strong>, which must have been allocated via a C++ <tt>new</tt>[]
|
count, it might be removed from some future version. Thus it should be used for
|
||||||
expression or be 0. Afterwards, <strong>use_count()</strong> is 1 (even if p==0;
|
debugging purposes only, and not production code.</p>
|
||||||
see <a href="#shared_array_~shared_array">~shared_array</a>).</p>
|
<h3><a name="conversions">conversions</a></h3>
|
||||||
<p>The only exception which may be thrown is <tt>std::bad_alloc</tt>. If
|
<pre>operator <i>unspecified-bool-type</i> () const; // never throws</pre>
|
||||||
an exception is thrown, <tt>delete[] p</tt> is called.</p>
|
<p>Returns an unspecified value that, when used in boolean contexts, is equivalent
|
||||||
<h3>shared_array <a name="shared_array_operator[]">operator[]</a></h3>
|
to <code>get() != 0</code>.</p>
|
||||||
<p><tt>T& operator[](std::size_t i) const; // never throws</tt></p>
|
<h3><a name="swap">swap</a></h3>
|
||||||
<p>Returns a reference to element <tt>i</tt> of the array pointed to by the
|
<pre>void swap(shared_ptr & b); // never throws</pre>
|
||||||
stored pointer.</p>
|
<p>Exchanges the contents of the two smart pointers. <b>T</b> need not be a
|
||||||
<p>Behavior is undefined (and almost certainly undesirable) if <tt>get()==0</tt>,
|
complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">common
|
||||||
or if <tt>i</tt> is less than 0 or is greater or equal to the number of elements
|
requirements</a>.</p>
|
||||||
in the array.</p>
|
<h2><a name="functions">Free Functions</a></h2>
|
||||||
<h3>shared_array <a name="shared_array_get">get</a></h3>
|
<h3><a name="comparison">comparison</a></h3>
|
||||||
<pre>T* get() const; // never throws</pre>
|
<pre>template<class T>
|
||||||
<p>Returns the stored pointer.</p>
|
bool operator==(shared_array<T> const & a, shared_array<T> const & b); // never throws
|
||||||
<h3>shared_array<a name="shared_array_use_count"> use_count</a></h3>
|
template<class T>
|
||||||
<p><tt>long use_count() const; // never throws</tt></p>
|
bool operator!=(shared_array<T> const & a, shared_array<T> const & b); // never throws
|
||||||
<p>Returns the number of <strong>shared_arrays</strong> sharing ownership of the
|
template<class T>
|
||||||
stored pointer.</p>
|
bool operator<(shared_array<T> const & a, shared_array<T> const & b); // never throws</pre>
|
||||||
<h3>shared_array <a name="shared_array_unique">unique</a></h3>
|
<p>Compares the stored pointers of the two smart pointers. <b>T</b> need not be a
|
||||||
<p><tt>bool unique() const; // never throws</tt></p>
|
complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">common
|
||||||
<p>Returns <strong>use_count()</strong> == 1.</p>
|
requirements</a>.</p>
|
||||||
<h3><a name="shared_array_swap">shared_array swap</a></h3>
|
<p>The <b>operator<</b> overload is provided to define an ordering so that <b>shared_array</b>
|
||||||
<p><code>void swap( shared_array<T>& other ) throw()</code></p>
|
objects can be used in associative containers such as <b>std::map</b>. The
|
||||||
<p>Swaps the two smart pointers, as if by std::swap.</p>
|
implementation uses <b>std::less<T *></b> to perform the comparison. This
|
||||||
<h2>Class <a name="shared_array_example">shared_array example</a></h2>
|
ensures that the comparison is handled correctly, since the standard mandates
|
||||||
<p>[To be supplied. In the meantime, see <a href="smart_ptr_test.cpp">smart_ptr_test.cpp</a>.]</p>
|
that relational operations on pointers are unspecified (5.9 [expr.rel]
|
||||||
<hr>
|
paragraph 2) but <b>std::less<></b> on pointers is well-defined (20.3.3
|
||||||
<p>Revised December 8, 1999</p>
|
[lib.comparisons] paragraph 8).</p>
|
||||||
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
|
<h3><a name="free-swap">swap</a></h3>
|
||||||
modify, sell and distribute this document is granted provided this copyright
|
<pre>template<class T>
|
||||||
notice appears in all copies. This document is provided "as is"
|
void swap(shared_array<T> & a, shared_array<T> & b) // never throws</pre>
|
||||||
without express or implied warranty, and with no claim as to its suitability for
|
<p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>.
|
||||||
any purpose.</p>
|
Provided as an aid to generic programming.</p>
|
||||||
|
<hr>
|
||||||
</body>
|
<p>Revised
|
||||||
|
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->
|
||||||
|
09 January 2003<!--webbot bot="Timestamp" endspan i-checksum="32310" --></p>
|
||||||
|
<p><small>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
|
||||||
|
Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version
|
||||||
|
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
|
||||||
|
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
880
shared_ptr.htm
880
shared_ptr.htm
@@ -1,206 +1,722 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
<html>
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>shared_ptr</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
</head>
|
||||||
|
<body text="#000000" bgColor="#ffffff">
|
||||||
|
<h1><A href="../../index.htm"><IMG height="86" alt="boost.png (6897 bytes)" src="../../boost.png" width="277" align="middle"
|
||||||
|
border="0"></A>shared_ptr class template</h1>
|
||||||
|
<p><A href="#Introduction">Introduction</A><br>
|
||||||
|
<A href="#BestPractices">Best Practices</A><br>
|
||||||
|
<A href="#Synopsis">Synopsis</A><br>
|
||||||
|
<A href="#Members">Members</A><br>
|
||||||
|
<A href="#functions">Free Functions</A><br>
|
||||||
|
<A href="#example">Example</A><br>
|
||||||
|
<A href="#Handle/Body">Handle/Body Idiom</A><br>
|
||||||
|
<A href="#ThreadSafety">Thread Safety</A><br>
|
||||||
|
<A href="#FAQ">Frequently Asked Questions</A><br>
|
||||||
|
<A href="smarttests.htm">Smart Pointer Timings</A><br>
|
||||||
|
<A href="sp_techniques.html">Programming Techniques</A></p>
|
||||||
|
<h2><a name="Introduction">Introduction</a></h2>
|
||||||
|
<p>The <b>shared_ptr</b> class template stores a pointer to a dynamically allocated
|
||||||
|
object, typically with a C++ <EM>new-expression</EM>. The object pointed to is
|
||||||
|
guaranteed to be deleted when the last <b>shared_ptr</b> pointing to it is
|
||||||
|
destroyed or reset. See the <A href="#example">example</A>.</p>
|
||||||
|
<p>Every <b>shared_ptr</b> meets the <b>CopyConstructible</b> and <b>Assignable</b>
|
||||||
|
requirements of the C++ Standard Library, and so can be used in standard
|
||||||
|
library containers. Comparison operators are supplied so that <b>shared_ptr</b>
|
||||||
|
works with the standard library's associative containers.</p>
|
||||||
|
<p>Normally, a <b>shared_ptr</b> cannot correctly hold a pointer to a dynamically
|
||||||
|
allocated array. See <A href="shared_array.htm"><b>shared_array</b></A> for
|
||||||
|
that usage.</p>
|
||||||
|
<p>Because the implementation uses reference counting, cycles of <b>shared_ptr</b> instances
|
||||||
|
will not be reclaimed. For example, if <b>main()</b> holds a <b>shared_ptr</b> to
|
||||||
|
<b>A</b>, which directly or indirectly holds a <b>shared_ptr</b> back to <b>A</b>,
|
||||||
|
<b>A</b>'s use count will be 2. Destruction of the original <b>shared_ptr</b> will
|
||||||
|
leave <b>A</b> dangling with a use count of 1. Use <A href="weak_ptr.htm">weak_ptr</A>
|
||||||
|
to "break cycles."</p>
|
||||||
|
<p>The class template is parameterized on <b>T</b>, the type of the object pointed
|
||||||
|
to. <STRONG>shared_ptr</STRONG> and most of its member functions place no
|
||||||
|
requirements on <STRONG>T</STRONG>; it is allowed to be an incomplete type, or <STRONG>
|
||||||
|
void</STRONG>. Member functions that do place additional requirements (<A href="#constructors">constructors</A>,
|
||||||
|
<A href="#reset">reset</A>) are explicitly documented below.</p>
|
||||||
|
<P><STRONG>shared_ptr<T></STRONG> can be implicitly converted to <STRONG>shared_ptr<U></STRONG>
|
||||||
|
whenever <STRONG>T*</STRONG> can be implicitly converted to <STRONG>U*</STRONG>.
|
||||||
|
In particular, <STRONG>shared_ptr<T></STRONG> is implicitly convertible
|
||||||
|
to <STRONG>shared_ptr<T const></STRONG>, to <STRONG>shared_ptr<U></STRONG>
|
||||||
|
where <STRONG>U</STRONG> is an accessible base of <STRONG>T</STRONG>, and to <STRONG>
|
||||||
|
shared_ptr<void></STRONG>.</P>
|
||||||
|
<P><STRONG>shared_ptr</STRONG> is now part of <STRONG>TR1</STRONG>, the first C++
|
||||||
|
Library Technical Report. The latest draft of <STRONG>TR1</STRONG> is available
|
||||||
|
at the following location:</P>
|
||||||
|
<P><A href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1745.pdf">http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1745.pdf</A>
|
||||||
|
(1.36Mb PDF)</P>
|
||||||
|
<P>This implementation conforms to the TR1 specification, with the only exception
|
||||||
|
that it resides in namespace <code>boost</code> instead of <code>std::tr1</code>.</P>
|
||||||
|
<h2><a name="BestPractices">Best Practices</a></h2>
|
||||||
|
<P>A simple guideline that nearly eliminates the possibility of memory leaks is:
|
||||||
|
always use a named smart pointer variable to hold the result of <STRONG>new. </STRONG>
|
||||||
|
Every occurence of the <STRONG>new</STRONG> keyword in the code should have the
|
||||||
|
form:</P>
|
||||||
|
<PRE>shared_ptr<T> p(new Y);</PRE>
|
||||||
|
<P>It is, of course, acceptable to use another smart pointer in place of <STRONG>shared_ptr</STRONG>
|
||||||
|
above; having <STRONG>T</STRONG> and <STRONG>Y</STRONG> be the same type, or
|
||||||
|
passing arguments to <STRONG>Y</STRONG>'s constructor is also OK.</P>
|
||||||
|
<P>If you observe this guideline, it naturally follows that you will have no
|
||||||
|
explicit <STRONG>delete</STRONG>s; <STRONG>try/catch</STRONG> constructs will
|
||||||
|
be rare.</P>
|
||||||
|
<P>Avoid using unnamed <STRONG>shared_ptr</STRONG> temporaries to save typing; to
|
||||||
|
see why this is dangerous, consider this example:</P>
|
||||||
|
<PRE>void f(shared_ptr<int>, int);
|
||||||
|
int g();
|
||||||
|
|
||||||
<head>
|
void ok()
|
||||||
<title>shared_ptr</title>
|
{
|
||||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
shared_ptr<int> p(new int(2));
|
||||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
f(p, g());
|
||||||
</head>
|
}
|
||||||
|
|
||||||
<body bgcolor="#FFFFFF" text="#000000">
|
void bad()
|
||||||
|
{
|
||||||
|
f(shared_ptr<int>(new int(2)), g());
|
||||||
|
}
|
||||||
|
</PRE>
|
||||||
|
<P>The function <STRONG>ok</STRONG> follows the guideline to the letter, whereas <STRONG>
|
||||||
|
bad</STRONG> constructs the temporary <STRONG>shared_ptr</STRONG> in place,
|
||||||
|
admitting the possibility of a memory leak. Since function arguments are
|
||||||
|
evaluated in unspecified order, it is possible for <STRONG>new int(2)</STRONG> to
|
||||||
|
be evaluated first, <STRONG>g()</STRONG> second, and we may never get to the <STRONG>
|
||||||
|
shared_ptr </STRONG>constructor if <STRONG>g</STRONG> throws an exception.
|
||||||
|
See <A href="http://www.gotw.ca/gotw/056.htm">Herb Sutter's treatment</A> (also <A href="http://www.cuj.com/reference/articles/2002/0212/0212_sutter.htm">
|
||||||
|
here</A>) of the issue for more information.</P>
|
||||||
|
<P>The exception safety problem described above may also be eliminated by using
|
||||||
|
the <a href="make_shared.html"><code>make_shared</code></a>
|
||||||
|
or <a href="make_shared.html"><code>allocate_shared</code></a>
|
||||||
|
factory functions defined in boost/make_shared.hpp. These factory functions also provide
|
||||||
|
an efficiency benefit by consolidating allocations.<P>
|
||||||
|
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||||
|
<pre>namespace boost {
|
||||||
|
|
||||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">Class
|
class bad_weak_ptr: public std::exception;
|
||||||
<a name="shared_ptr">shared_ptr</a></h1>
|
|
||||||
<p>Class <strong>shared_ptr</strong> stores a pointer to a dynamically allocated
|
|
||||||
object. (Dynamically allocated objects are allocated with the C++ <tt>new</tt>
|
|
||||||
expression.) The object pointed to is guaranteed to be deleted when
|
|
||||||
the last <strong>shared_ptr</strong> pointing to it is deleted or reset.
|
|
||||||
See <a href="#shared_ptr_example">example</a>.</p>
|
|
||||||
<p>Class<strong> shared_ptr</strong> meets the <strong>CopyConstuctible</strong>
|
|
||||||
and <strong>Assignable</strong> requirements of the C++ Standard Library, and so
|
|
||||||
can be used in C++ Standard Library containers. A specialization of std::
|
|
||||||
less< > for boost::shared_ptr<Y> is supplied so that <strong>
|
|
||||||
shared_ptr</strong> works by default for Standard Library's Associative
|
|
||||||
Container Compare template parameter. For compilers not supporting partial
|
|
||||||
specialization, the user must explicitly pass the less<> functor.</p>
|
|
||||||
<p>Class<strong> shared_ptr</strong> cannot correctly hold a pointer to a
|
|
||||||
dynamically allocated array. See <a href="shared_array.htm"><strong>shared_array</strong></a>
|
|
||||||
for that usage.</p>
|
|
||||||
<p>Class<strong> shared_ptr</strong> will not work correctly with cyclic data
|
|
||||||
structures. For example, if main() holds a shared_ptr to object A, which
|
|
||||||
directly or indirectly holds a shared_ptr back to object A, then object A's
|
|
||||||
use_count() will be 2, and destruction of the main() shared_ptr will leave
|
|
||||||
object A dangling with a use_count() of 1.</p>
|
|
||||||
<p>The class is a template parameterized on <tt>T</tt>, the type of the object
|
|
||||||
pointed to. <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">Common
|
|
||||||
requirements</a>.</p>
|
|
||||||
<h2>Class shared_ptr Synopsis</h2>
|
|
||||||
<pre>#include <boost/smart_ptr.hpp>
|
|
||||||
namespace boost {
|
|
||||||
|
|
||||||
template<typename T> class shared_ptr {
|
template<class T> class <A href="weak_ptr.htm" >weak_ptr</A>;
|
||||||
|
|
||||||
|
template<class T> class shared_ptr {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef T <a href="#shared_ptr_element_type">element_type</a>;
|
|
||||||
|
|
||||||
explicit <a href="#shared_ptr_ctor">shared_ptr</a>( T* p=0 );
|
typedef T <A href="#element_type" >element_type</A>;
|
||||||
<strong> </strong><a href="#shared_ptr_~shared_ptr">~shared_ptr</a>();
|
|
||||||
|
|
||||||
<a href="#shared_ptr_ctor">shared_ptr</a>( const shared_ptr& );
|
<A href="#constructors" >shared_ptr</A>(); // never throws
|
||||||
template<typename Y>
|
template<class Y> explicit <A href="#constructors" >shared_ptr</A>(Y * p);
|
||||||
<a href="#shared_ptr_ctor">shared_ptr</a>(const shared_ptr<Y>& r); // never throws
|
template<class Y, class D> <A href="#constructors" >shared_ptr</A>(Y * p, D d);
|
||||||
template<typename Y>
|
template<class Y, class D, class A> <A href="#allocator_constructor" >shared_ptr</A>(Y * p, D d, A a);
|
||||||
<a href="#shared_ptr_ctor">shared_ptr</a>(std::auto_ptr<Y>& r);
|
<A href="#destructor" >~shared_ptr</A>(); // never throws
|
||||||
|
|
||||||
shared_ptr& <a href="#shared_ptr_operator=">operator=</a>( const shared_ptr& ); // never throws
|
<A href="#constructors" >shared_ptr</A>(shared_ptr const & r); // never throws
|
||||||
template<typename Y>
|
template<class Y> <A href="#constructors" >shared_ptr</A>(shared_ptr<Y> const & r); // never throws
|
||||||
shared_ptr& <a href="#shared_ptr_operator=">operator=</a>(const shared_ptr<Y>& r); // never throws
|
template<class Y> <A href="#constructors" >shared_ptr</A>(shared_ptr<Y> const & r, T * p); // never throws
|
||||||
template<typename Y>
|
template<class Y> explicit <A href="#constructors" >shared_ptr</A>(<A href="weak_ptr.htm" >weak_ptr</A><Y> const & r);
|
||||||
shared_ptr& <a href="#shared_ptr_operator=">operator=</a>(std::auto_ptr<Y>& r);
|
template<class Y> explicit <A href="#constructors" >shared_ptr</A>(std::auto_ptr<Y> & r);
|
||||||
|
|
||||||
void <a href="#shared_ptr_reset">reset</a>( T* p=0 );
|
shared_ptr & <A href="#assignment" >operator=</A>(shared_ptr const & r); // never throws
|
||||||
|
template<class Y> shared_ptr & <A href="#assignment" >operator=</A>(shared_ptr<Y> const & r); // never throws
|
||||||
|
template<class Y> shared_ptr & <A href="#assignment" >operator=</A>(std::auto_ptr<Y> & r);
|
||||||
|
|
||||||
T& <a href="#shared_ptr_operator*">operator*</a>() const; // never throws
|
void <A href="#reset" >reset</A>(); // never throws
|
||||||
T* <a href="#shared_ptr_operator->">operator-></a>() const; // never throws
|
template<class Y> void <A href="#reset" >reset</A>(Y * p);
|
||||||
T* <a href="#shared_ptr_get">get</a>() const; // never throws
|
template<class Y, class D> void <A href="#reset" >reset</A>(Y * p, D d);
|
||||||
|
template<class Y, class D, class A> void <A href="#reset" >reset</A>(Y * p, D d, A a);
|
||||||
|
template<class Y> void <A href="#reset" >reset</A>(shared_ptr<Y> const & r, T * p); // never throws
|
||||||
|
|
||||||
long <a href="#shared_ptr_use_count">use_count</a>() const; // never throws
|
T & <A href="#indirection" >operator*</A>() const; // never throws
|
||||||
bool <a href="#shared_ptr_unique">unique</a>() const; // never throws
|
T * <A href="#indirection" >operator-></A>() const; // never throws
|
||||||
|
T * <A href="#get" >get</A>() const; // never throws
|
||||||
|
|
||||||
void <a href="#shared_ptr_swap">swap</a>( shared_ptr<T>& other ) throw()
|
bool <A href="#unique" >unique</A>() const; // never throws
|
||||||
|
long <A href="#use_count" >use_count</A>() const; // never throws
|
||||||
|
|
||||||
|
operator <A href="#conversions" ><i>unspecified-bool-type</i></A>() const; // never throws
|
||||||
|
|
||||||
|
void <A href="#swap" >swap</A>(shared_ptr & b); // never throws
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T, typename U>
|
template<class T, class U>
|
||||||
inline bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b)
|
bool <A href="#comparison" >operator==</A>(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
|
||||||
{ return a.get() == b.get(); }
|
|
||||||
|
|
||||||
template<typename T, typename U>
|
template<class T, class U>
|
||||||
inline bool operator!=(const shared_ptr<T>& a, const shared_ptr<U>& b)
|
bool <A href="#comparison" >operator!=</A>(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
|
||||||
{ return a.get() != b.get(); }
|
|
||||||
|
template<class T, class U>
|
||||||
|
bool <A href="#comparison" >operator<</A>(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
|
||||||
|
|
||||||
|
template<class T> void <A href="#free-swap" >swap</A>(shared_ptr<T> & a, shared_ptr<T> & b); // never throws
|
||||||
|
|
||||||
|
template<class T> T * <A href="#get_pointer" >get_pointer</A>(shared_ptr<T> const & p); // never throws
|
||||||
|
|
||||||
|
template<class T, class U>
|
||||||
|
shared_ptr<T> <A href="#static_pointer_cast" >static_pointer_cast</A>(shared_ptr<U> const & r); // never throws
|
||||||
|
|
||||||
|
template<class T, class U>
|
||||||
|
shared_ptr<T> <A href="#const_pointer_cast" >const_pointer_cast</A>(shared_ptr<U> const & r); // never throws
|
||||||
|
|
||||||
|
template<class T, class U>
|
||||||
|
shared_ptr<T> <A href="#dynamic_pointer_cast" >dynamic_pointer_cast</A>(shared_ptr<U> const & r); // never throws
|
||||||
|
|
||||||
|
template<class E, class T, class Y>
|
||||||
|
std::basic_ostream<E, T> & <A href="#insertion-operator" >operator<<</A> (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p);
|
||||||
|
|
||||||
|
template<class D, class T>
|
||||||
|
D * <A href="#get_deleter">get_deleter</A>(shared_ptr<T> const & p);
|
||||||
}</pre>
|
}</pre>
|
||||||
<pre>namespace std {
|
<h2><a name="Members">Members</a></h2>
|
||||||
|
<h3><a name="element_type">element_type</a></h3>
|
||||||
|
<pre>typedef T element_type;</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p>Provides the type of the template parameter T.</p>
|
||||||
|
</blockquote>
|
||||||
|
<h3><a name="constructors">constructors</a></h3>
|
||||||
|
<pre>shared_ptr(); // never throws</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Effects:</b> Constructs an <EM>empty</EM> <b>shared_ptr</b>.</p>
|
||||||
|
<p><b>Postconditions:</b> <code>use_count() == 0 && get() == 0</code>.</p>
|
||||||
|
<p><b>Throws:</b> nothing.</p>
|
||||||
|
</blockquote>
|
||||||
|
<P><EM>[The nothrow guarantee is important, since <STRONG>reset()</STRONG> is specified
|
||||||
|
in terms of the default constructor; this implies that the constructor must not
|
||||||
|
allocate memory.]</EM></P>
|
||||||
|
<pre>template<class Y> explicit shared_ptr(Y * p);</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Requirements:</b> <b>p</b> must be convertible to <b>T *</b>. <STRONG>Y</STRONG>
|
||||||
|
must be a complete type. The expression <code>delete p</code> must be
|
||||||
|
well-formed, must not invoke undefined behavior, and must not throw exceptions.
|
||||||
|
</p>
|
||||||
|
<p><b>Effects:</b> Constructs a <b>shared_ptr</b> that <EM>owns</EM> the pointer <b>p</b>.</p>
|
||||||
|
<p><b>Postconditions:</b> <code>use_count() == 1 && get() == p</code>.</p>
|
||||||
|
<p><b>Throws:</b> <STRONG>std::bad_alloc</STRONG>, or an implementation-defined
|
||||||
|
exception when a resource other than memory could not be obtained.</p>
|
||||||
|
<p><b>Exception safety:</b> If an exception is thrown, <code>delete p</code> is
|
||||||
|
called.</p>
|
||||||
|
<P><STRONG>Notes:</STRONG> <B>p</B> must be a pointer to an object that was
|
||||||
|
allocated via a C++ <B>new</B> expression or be 0. The postcondition that <A href="#use_count">
|
||||||
|
use count</A> is 1 holds even if <b>p</b> is 0; invoking <STRONG>delete</STRONG>
|
||||||
|
on a pointer that has a value of 0 is harmless.</P>
|
||||||
|
</blockquote>
|
||||||
|
<P><EM>[This constructor has been changed to a template in order to remember the actual
|
||||||
|
pointer type passed. The destructor will call <STRONG>delete</STRONG> with the
|
||||||
|
same pointer, complete with its original type, even when <STRONG>T</STRONG> does
|
||||||
|
not have a virtual destructor, or is <STRONG>void</STRONG>.</EM></P>
|
||||||
|
<P><EM>The optional intrusive counting support has been dropped as it exposes too much
|
||||||
|
implementation details and doesn't interact well with <STRONG>weak_ptr</STRONG>.
|
||||||
|
The current implementation uses a different mechanism, <A href="enable_shared_from_this.html">
|
||||||
|
enable_shared_from_this</A>, to solve the "<STRONG>shared_ptr</STRONG> from <STRONG>
|
||||||
|
this</STRONG>" problem.</EM><EM>]</EM></P>
|
||||||
|
<a name="allocator_constructor"></a>
|
||||||
|
<pre>template<class Y, class D> shared_ptr(Y * p, D d);
|
||||||
|
template<class Y, class D, class A> shared_ptr(Y * p, D d, A a);</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Requirements:</b> <B>p</B> must be convertible to <B>T *</B>. <STRONG>D</STRONG>
|
||||||
|
must be <STRONG>CopyConstructible</STRONG>. The copy constructor and destructor
|
||||||
|
of <b>D</b> must not throw. The expression <code>d(p)</code> must be
|
||||||
|
well-formed, must not invoke undefined behavior, and must not throw exceptions. <STRONG>
|
||||||
|
A</STRONG> must be an <EM>Allocator</EM>, as described in section 20.1.5 (<STRONG>Allocator
|
||||||
|
requirements</STRONG>) of the C++ Standard.
|
||||||
|
</p>
|
||||||
|
<p><b>Effects:</b> Constructs a <b>shared_ptr</b> that <EM>owns</EM> the pointer <STRONG>
|
||||||
|
p</STRONG> and the deleter <b>d</b>. The second constructor allocates
|
||||||
|
memory using a copy of <STRONG>a</STRONG>.</p>
|
||||||
|
<p><b>Postconditions:</b> <code>use_count() == 1 && get() == p</code>.</p>
|
||||||
|
<p><b>Throws:</b> <STRONG>std::bad_alloc</STRONG>, or an implementation-defined
|
||||||
|
exception when a resource other than memory could not be obtained.</p>
|
||||||
|
<p><b>Exception safety:</b> If an exception is thrown, <code>d(p)</code> is called.</p>
|
||||||
|
<p><b>Notes:</b> When the the time comes to delete the object pointed to by <b>p</b>,
|
||||||
|
the stored copy of <STRONG>d</STRONG> is invoked with the stored copy of <STRONG>p</STRONG>
|
||||||
|
as an argument.</p>
|
||||||
|
</blockquote>
|
||||||
|
<P><EM>[Custom deallocators allow a factory function returning a <STRONG>shared_ptr</STRONG>
|
||||||
|
to insulate the user from its memory allocation strategy. Since the deallocator
|
||||||
|
is not part of the type, changing the allocation strategy does not break source
|
||||||
|
or binary compatibility, and does not require a client recompilation. For
|
||||||
|
example, a "no-op" deallocator is useful when returning a <STRONG>shared_ptr</STRONG>
|
||||||
|
to a statically allocated object, and other variations allow a <STRONG>shared_ptr</STRONG>
|
||||||
|
to be used as a wrapper for another smart pointer, easing interoperability.</EM></P>
|
||||||
|
<P><EM>The support for custom deallocators does not impose significant overhead. Other <STRONG>
|
||||||
|
shared_ptr</STRONG> features still require a deallocator to be kept.</EM></P>
|
||||||
|
<P><EM>The requirement that the copy constructor of <b>D</b> does not throw comes from
|
||||||
|
the pass by value. If the copy constructor throws, the pointer is leaked.
|
||||||
|
Removing the requirement requires a pass by (const) reference.</EM></P>
|
||||||
|
<P><EM>The main problem with pass by reference lies in its interaction with rvalues. A
|
||||||
|
const reference may still cause a copy, and will require a const operator(). A
|
||||||
|
non-const reference won't bind to an rvalue at all. A good solution to this
|
||||||
|
problem is the rvalue reference proposed in <A href="http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1377.htm">
|
||||||
|
N1377</A>/<A href="http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1385.htm">N1385</A>.]</EM></P>
|
||||||
|
<pre>shared_ptr(shared_ptr const & r); // never throws
|
||||||
|
template<class Y> shared_ptr(shared_ptr<Y> const & r); // never throws</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Effects:</b> If <b>r</b> is <EM>empty</EM>, constructs an <EM>empty</EM> <b>shared_ptr</b>;
|
||||||
|
otherwise, constructs a <b>shared_ptr</b> that <EM>shares ownership</EM> with <b>r</b>.</p>
|
||||||
|
<p><b>Postconditions:</b> <code>get() == r.get() && use_count() ==
|
||||||
|
r.use_count()</code>.</p>
|
||||||
|
<p><b>Throws:</b> nothing.</p>
|
||||||
|
</blockquote>
|
||||||
|
<pre>template<class Y> shared_ptr(shared_ptr<Y> const & r, T * p); // never throws</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Effects:</b> constructs a <b>shared_ptr</b> that <EM>shares ownership</EM> with
|
||||||
|
<b>r</b> and stores <b>p</b>.</p>
|
||||||
|
<p><b>Postconditions:</b> <code>get() == p && use_count() == r.use_count()</code>.</p>
|
||||||
|
<p><b>Throws:</b> nothing.</p>
|
||||||
|
</blockquote>
|
||||||
|
<pre>template<class Y> explicit shared_ptr(<A href="weak_ptr.htm" >weak_ptr</A><Y> const & r);</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Effects:</b> Constructs a <b>shared_ptr</b> that <EM>shares ownership</EM> with
|
||||||
|
<b>r</b> and stores a copy of the pointer stored in <STRONG>r</STRONG>.</p>
|
||||||
|
<p><b>Postconditions:</b> <code>use_count() == r.use_count()</code>.</p>
|
||||||
|
<p><b>Throws:</b> <b>bad_weak_ptr</b> when <code>r.use_count() == 0</code>.</p>
|
||||||
|
<p><b>Exception safety:</b> If an exception is thrown, the constructor has no
|
||||||
|
effect.</p>
|
||||||
|
</blockquote>
|
||||||
|
<pre>template<class Y> shared_ptr(std::auto_ptr<Y> & r);</pre>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P><B>Effects:</B> Constructs a <B>shared_ptr</B>, as if by storing a copy of <STRONG>r.release()</STRONG>.</P>
|
||||||
|
<p><b>Postconditions:</b> <code>use_count() == 1</code>.</p>
|
||||||
|
<p><b>Throws:</b> <STRONG>std::bad_alloc</STRONG>, or an implementation-defined
|
||||||
|
exception when a resource other than memory could not be obtained.</p>
|
||||||
|
<P><B>Exception safety:</B> If an exception is thrown, the constructor has no
|
||||||
|
effect.</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
<P><EM>[This constructor takes a the source <STRONG>auto_ptr</STRONG> by reference and
|
||||||
|
not by value, and cannot accept <STRONG>auto_ptr</STRONG> temporaries. This is
|
||||||
|
by design, as the constructor offers the strong guarantee; an rvalue reference
|
||||||
|
would solve this problem, too.]</EM></P>
|
||||||
|
<h3><a name="destructor">destructor</a></h3>
|
||||||
|
<pre>~shared_ptr(); // never throws</pre>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P><B>Effects:</B></P>
|
||||||
|
<UL>
|
||||||
|
<LI>
|
||||||
|
If <STRONG>*this</STRONG> is <EM>empty</EM>, or <EM>shares ownership</EM> with
|
||||||
|
another <STRONG>shared_ptr</STRONG> instance (<code>use_count() > 1</code>),
|
||||||
|
there are no side effects.
|
||||||
|
<LI>
|
||||||
|
Otherwise, if <STRONG>*this</STRONG> <EM>owns</EM> a pointer <STRONG>p</STRONG>
|
||||||
|
and a deleter <STRONG>d</STRONG>, <code>d(p)</code>
|
||||||
|
is called.
|
||||||
|
<LI>
|
||||||
|
Otherwise, <STRONG>*this</STRONG> <EM>owns</EM> a pointer <STRONG>p</STRONG>,
|
||||||
|
and <code>delete p</code> is called.</LI></UL>
|
||||||
|
<P><B>Throws:</B> nothing.</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
<H3><a name="assignment">assignment</a></H3>
|
||||||
|
<pre>shared_ptr & operator=(shared_ptr const & r); // never throws
|
||||||
|
template<class Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws
|
||||||
|
template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & r);</pre>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P><B>Effects:</B> Equivalent to <code>shared_ptr(r).swap(*this)</code>.</P>
|
||||||
|
<P><B>Returns:</B> <code>*this</code>.</P>
|
||||||
|
<P><B>Notes:</B> The use count updates caused by the temporary object construction
|
||||||
|
and destruction are not considered observable side effects, and the
|
||||||
|
implementation is free to meet the effects (and the implied guarantees) via
|
||||||
|
different means, without creating a temporary. In particular, in the example:</P>
|
||||||
|
<pre>shared_ptr<int> p(new int);
|
||||||
|
shared_ptr<void> q(p);
|
||||||
|
p = p;
|
||||||
|
q = p;
|
||||||
|
</pre>
|
||||||
|
<p>both assignments may be no-ops.</p>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
<h3><a name="reset">reset</a></h3>
|
||||||
|
<pre>void reset(); // never throws</pre>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P><B>Effects:</B> Equivalent to <code>shared_ptr().swap(*this)</code>.</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
<pre>template<class Y> void reset(Y * p);</pre>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P><B>Effects:</B> Equivalent to <code>shared_ptr(p).swap(*this)</code>.</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
<pre>template<class Y, class D> void reset(Y * p, D d);</pre>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P><B>Effects:</B> Equivalent to <code>shared_ptr(p, d).swap(*this)</code>.</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
<pre>template<class Y, class D, class A> void reset(Y * p, D d, A a);</pre>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P><B>Effects:</B> Equivalent to <code>shared_ptr(p, d, a).swap(*this)</code>.</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
<pre>template<class Y> void reset(shared_ptr<Y> const & r, T * p); // never throws</pre>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P><B>Effects:</B> Equivalent to <code>shared_ptr(r, p).swap(*this)</code>.</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
<h3><a name="indirection">indirection</a></h3>
|
||||||
|
<pre>T & operator*() const; // never throws</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Requirements:</b> The stored pointer must not be 0.</p>
|
||||||
|
<p><b>Returns:</b> a reference to the object pointed to by the stored pointer.</p>
|
||||||
|
<p><b>Throws:</b> nothing.</p>
|
||||||
|
</blockquote>
|
||||||
|
<pre>T * operator->() const; // never throws</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Requirements:</b> The stored pointer must not be 0.</p>
|
||||||
|
<p><b>Returns:</b> the stored pointer.</p>
|
||||||
|
<p><b>Throws:</b> nothing.</p>
|
||||||
|
</blockquote>
|
||||||
|
<h3><a name="get">get</a></h3>
|
||||||
|
<pre>T * get() const; // never throws</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Returns:</b> the stored pointer.</p>
|
||||||
|
<p><b>Throws:</b> nothing.</p>
|
||||||
|
</blockquote>
|
||||||
|
<h3><a name="unique">unique</a></h3>
|
||||||
|
<pre>bool unique() const; // never throws</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Returns:</b> <code>use_count() == 1</code>.</p>
|
||||||
|
<p><b>Throws:</b> nothing.</p>
|
||||||
|
<P><B>Notes:</B> <code>unique()</code> may be faster than <code>use_count()</code>.
|
||||||
|
If you are using <code>unique()</code> to implement copy on write, do not rely
|
||||||
|
on a specific value when the stored pointer is zero.</P>
|
||||||
|
</blockquote>
|
||||||
|
<h3><a name="use_count">use_count</a></h3>
|
||||||
|
<pre>long use_count() const; // never throws</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Returns:</b> the number of <b>shared_ptr</b> objects, <STRONG>*this</STRONG> included,
|
||||||
|
that <i>share ownership</i> with <b>*this</b>, or 0 when <STRONG>*this</STRONG>
|
||||||
|
is <EM>empty</EM>.</p>
|
||||||
|
<p><b>Throws:</b> nothing.</p>
|
||||||
|
<P><B>Notes:</B> <code>use_count()</code> is not necessarily efficient. Use only
|
||||||
|
for debugging and testing purposes, not for production code.</P>
|
||||||
|
</blockquote>
|
||||||
|
<h3><a name="conversions">conversions</a></h3>
|
||||||
|
<pre>operator <i>unspecified-bool-type</i> () const; // never throws</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Returns:</b> an unspecified value that, when used in boolean contexts, is
|
||||||
|
equivalent to <code>get() != 0</code>.</p>
|
||||||
|
<p><b>Throws:</b> nothing.</p>
|
||||||
|
<P><B>Notes:</B> This conversion operator allows <b>shared_ptr</b> objects to be
|
||||||
|
used in boolean contexts, like <code>if (p && p->valid()) {}</code>.
|
||||||
|
The actual target type is typically a pointer to a member function, avoiding
|
||||||
|
many of the implicit conversion pitfalls.</P>
|
||||||
|
</blockquote>
|
||||||
|
<P><EM>[The conversion to bool is not merely syntactic sugar. It allows <STRONG>shared_ptr</STRONG>s
|
||||||
|
to be declared in conditions when using <A href="#dynamic_pointer_cast">dynamic_pointer_cast</A>
|
||||||
|
or <A href="weak_ptr.htm#lock">weak_ptr::lock</A>.]</EM></P>
|
||||||
|
<h3><a name="swap">swap</a></h3>
|
||||||
|
<pre>void swap(shared_ptr & b); // never throws</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Effects:</b> Exchanges the contents of the two smart pointers.</p>
|
||||||
|
<p><b>Throws:</b> nothing.</p>
|
||||||
|
</blockquote>
|
||||||
|
<h2><a name="functions">Free Functions</a></h2>
|
||||||
|
<h3><a name="comparison">comparison</a></h3>
|
||||||
|
<pre>template<class T, class U>
|
||||||
|
bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Returns:</b> <code>a.get() == b.get()</code>.</p>
|
||||||
|
<p><b>Throws:</b> nothing.</p>
|
||||||
|
</blockquote>
|
||||||
|
<pre>template<class T, class U>
|
||||||
|
bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Returns:</b> <code>a.get() != b.get()</code>.</p>
|
||||||
|
<p><b>Throws:</b> nothing.</p>
|
||||||
|
</blockquote>
|
||||||
|
<pre>template<class T, class U>
|
||||||
|
bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Returns:</b> an unspecified value such that</p>
|
||||||
|
<UL>
|
||||||
|
<LI>
|
||||||
|
<b>operator<</b> is a strict weak ordering as described in section 25.3 <code>[lib.alg.sorting]</code>
|
||||||
|
of the C++ standard;
|
||||||
|
<LI>
|
||||||
|
under the equivalence relation defined by <STRONG>operator<</STRONG>, <code>!(a
|
||||||
|
< b) && !(b < a)</code>, two <STRONG>shared_ptr</STRONG> instances
|
||||||
|
are equivalent if and only if they <EM>share ownership</EM> or are both <EM>empty</EM>.</LI></UL>
|
||||||
|
<p><b>Throws:</b> nothing.</p>
|
||||||
|
<P><B>Notes:</B> Allows <STRONG>shared_ptr</STRONG> objects to be used as keys in
|
||||||
|
associative containers.</P>
|
||||||
|
</blockquote>
|
||||||
|
<P><EM>[<STRONG>Operator<</STRONG> has been preferred over a <STRONG>std::less </STRONG>
|
||||||
|
specialization for consistency and legality reasons, as <STRONG>std::less</STRONG>
|
||||||
|
is required to return the results of <STRONG>operator<</STRONG>, and many
|
||||||
|
standard algorithms use <STRONG>operator<</STRONG> instead of <STRONG>std::less</STRONG>
|
||||||
|
for comparisons when a predicate is not supplied. Composite objects, like <STRONG>std::pair</STRONG>,
|
||||||
|
also implement their <STRONG>operator<</STRONG> in terms of their contained
|
||||||
|
subobjects' <STRONG>operator<</STRONG>.</EM></P>
|
||||||
|
<P><EM>The rest of the comparison operators are omitted by design.]</EM></P>
|
||||||
|
<h3><a name="free-swap">swap</a></h3>
|
||||||
|
<pre>template<class T>
|
||||||
|
void swap(shared_ptr<T> & a, shared_ptr<T> & b); // never throws</pre>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P><B>Effects:</B> Equivalent to <code>a.swap(b)</code>.</P>
|
||||||
|
<P><B>Throws:</B> nothing.</P>
|
||||||
|
<P><B>Notes:</B> Matches the interface of <B>std::swap</B>. Provided as an aid to
|
||||||
|
generic programming.</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
<P><EM>[<STRONG>swap</STRONG> is defined in the same namespace as <STRONG>shared_ptr</STRONG>
|
||||||
|
as this is currently the only legal way to supply a <STRONG>swap</STRONG> function
|
||||||
|
that has a chance to be used by the standard library.]</EM></P>
|
||||||
|
<h3><a name="get_pointer">get_pointer</a></h3>
|
||||||
|
<pre>template<class T>
|
||||||
|
T * get_pointer(shared_ptr<T> const & p); // never throws</pre>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P><B>Returns:</B> <code>p.get()</code>.</P>
|
||||||
|
<P><B>Throws:</B> nothing.</P>
|
||||||
|
<P><B>Notes:</B> Provided as an aid to generic programming. Used by <A href="../bind/mem_fn.html">
|
||||||
|
mem_fn</A>.</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
<h3><a name="static_pointer_cast">static_pointer_cast</a></h3>
|
||||||
|
<pre>template<class T, class U>
|
||||||
|
shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r); // never throws</pre>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P><STRONG>Requires:</STRONG> The expression <code>static_cast<T*>(r.get())</code>
|
||||||
|
must be well-formed.</P>
|
||||||
|
<P><B>Returns:</B> If <b>r</b> is <i>empty</i>, an <i>empty</i> <b>shared_ptr<T></b>;
|
||||||
|
otherwise, a <STRONG>shared_ptr<T></STRONG> object that stores a copy of <code>
|
||||||
|
static_cast<T*>(r.get())</code> and <i>shares ownership</i> with <b>r</b>.</P>
|
||||||
|
<P><B>Throws:</B> nothing.</P>
|
||||||
|
<P><B>Notes:</B> the seemingly equivalent expression</P>
|
||||||
|
<p><code>shared_ptr<T>(static_cast<T*>(r.get()))</code></p>
|
||||||
|
<p>will eventually result in undefined behavior, attempting to delete the same
|
||||||
|
object twice.</p>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
<h3><a name="const_pointer_cast">const_pointer_cast</a></h3>
|
||||||
|
<pre>template<class T, class U>
|
||||||
|
shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r); // never throws</pre>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P><STRONG>Requires:</STRONG> The expression <code>const_cast<T*>(r.get())</code>
|
||||||
|
must be well-formed.</P>
|
||||||
|
<P><B>Returns:</B> If <b>r</b> is <i>empty</i>, an <i>empty</i> <b>shared_ptr<T></b>;
|
||||||
|
otherwise, a <STRONG>shared_ptr<T></STRONG> object that stores a copy of <code>
|
||||||
|
const_cast<T*>(r.get())</code> and <i>shares ownership</i> with <b>r</b>.</P>
|
||||||
|
<P><B>Throws:</B> nothing.</P>
|
||||||
|
<P><B>Notes:</B> the seemingly equivalent expression</P>
|
||||||
|
<p><code>shared_ptr<T>(const_cast<T*>(r.get()))</code></p>
|
||||||
|
<p>will eventually result in undefined behavior, attempting to delete the same
|
||||||
|
object twice.</p>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
<h3><a name="dynamic_pointer_cast">dynamic_pointer_cast</a></h3>
|
||||||
|
<pre>template<class T, class U>
|
||||||
|
shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r);</pre>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P><STRONG>Requires:</STRONG> The expression <CODE>dynamic_cast<T*>(r.get())</CODE>
|
||||||
|
must be well-formed and its behavior defined.</P>
|
||||||
|
<P><B>Returns:</B></P>
|
||||||
|
<UL>
|
||||||
|
<LI>
|
||||||
|
When <CODE>dynamic_cast<T*>(r.get())</CODE> returns a nonzero value, a <STRONG>
|
||||||
|
shared_ptr<T></STRONG> object that stores a copy of it and <i>shares
|
||||||
|
ownership</i> with <STRONG>r</STRONG>;
|
||||||
|
<LI>
|
||||||
|
Otherwise, an <i>empty</i> <STRONG>shared_ptr<T></STRONG> object.</LI></UL>
|
||||||
|
<P><B>Throws:</B> nothing.</P>
|
||||||
|
<P><B>Notes:</B> the seemingly equivalent expression</P>
|
||||||
|
<P><CODE>shared_ptr<T>(dynamic_cast<T*>(r.get()))</CODE></P>
|
||||||
|
<P>will eventually result in undefined behavior, attempting to delete the same
|
||||||
|
object twice.</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
<h3><a name="insertion-operator">operator<<</a></h3>
|
||||||
|
<pre>template<class E, class T, class Y>
|
||||||
|
std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p);</pre>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<p><STRONG>Effects:</STRONG> <code>os << p.get();</code>.</p>
|
||||||
|
<P><B>Returns:</B> <b>os</b>.</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
<h3><a name="get_deleter">get_deleter</a></h3>
|
||||||
|
<pre>template<class D, class T>
|
||||||
|
D * get_deleter(shared_ptr<T> const & p);</pre>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P><B>Returns:</B> If <STRONG>*this</STRONG> <EM>owns</EM> a deleter <STRONG>d</STRONG>
|
||||||
|
of type (cv-unqualified) <STRONG>D</STRONG>, returns <code>&d</code>;
|
||||||
|
otherwise returns 0.</P>
|
||||||
|
<P><B>Throws:</B> nothing.</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
<h2><a name="example">Example</a></h2>
|
||||||
|
<p>See <A href="example/shared_ptr_example.cpp">shared_ptr_example.cpp</A> for a
|
||||||
|
complete example program. The program builds a <b>std::vector</b> and <b>std::set</b>
|
||||||
|
of <b>shared_ptr</b> objects.</p>
|
||||||
|
<p>Note that after the containers have been populated, some of the <b>shared_ptr</b>
|
||||||
|
objects will have a use count of 1 rather than a use count of 2, since the set
|
||||||
|
is a <b>std::set</b> rather than a <b>std::multiset</b>, and thus does not
|
||||||
|
contain duplicate entries. Furthermore, the use count may be even higher at
|
||||||
|
various times while <b>push_back</b> and <b>insert</b> container operations are
|
||||||
|
performed. More complicated yet, the container operations may throw exceptions
|
||||||
|
under a variety of circumstances. Getting the memory management and exception
|
||||||
|
handling in this example right without a smart pointer would be a nightmare.</p>
|
||||||
|
<h2><a name="Handle/Body">Handle/Body</a> Idiom</h2>
|
||||||
|
<p>One common usage of <b>shared_ptr</b> is to implement a handle/body (also called
|
||||||
|
pimpl) idiom which avoids exposing the body (implementation) in the header
|
||||||
|
file.</p>
|
||||||
|
<p>The <A href="example/shared_ptr_example2_test.cpp">shared_ptr_example2_test.cpp</A>
|
||||||
|
sample program includes a header file, <A href="example/shared_ptr_example2.hpp">shared_ptr_example2.hpp</A>,
|
||||||
|
which uses a <b>shared_ptr<></b> to an incomplete type to hide the
|
||||||
|
implementation. The instantiation of member functions which require a complete
|
||||||
|
type occurs in the <A href="example/shared_ptr_example2.cpp">shared_ptr_example2.cpp</A>
|
||||||
|
implementation file. Note that there is no need for an explicit destructor.
|
||||||
|
Unlike ~scoped_ptr, ~shared_ptr does not require that <b>T</b> be a complete
|
||||||
|
type.</p>
|
||||||
|
<h2><a name="ThreadSafety">Thread Safety</a></h2>
|
||||||
|
<p><STRONG>shared_ptr</STRONG> objects offer the same level of thread safety as
|
||||||
|
built-in types. A <STRONG>shared_ptr</STRONG> instance can be "read" (accessed
|
||||||
|
using only const operations) simultaneously by multiple threads. Different <STRONG>shared_ptr</STRONG>
|
||||||
|
instances can be "written to" (accessed using mutable operations such as <STRONG>operator=
|
||||||
|
</STRONG>or <STRONG>reset</STRONG>) simultaneosly by multiple threads (even
|
||||||
|
when these instances are copies, and share the same reference count
|
||||||
|
underneath.)</p>
|
||||||
|
<P>Any other simultaneous accesses result in undefined behavior.</P>
|
||||||
|
<P>Examples:</P>
|
||||||
|
<pre>shared_ptr<int> p(new int(42));
|
||||||
|
|
||||||
template<typename T>
|
//--- Example 1 ---
|
||||||
inline void swap(boost::shared_ptr<T>& a, boost::shared_ptr<T>& b)
|
|
||||||
{ a.swap(b); }
|
|
||||||
|
|
||||||
template<typename T>
|
// thread A
|
||||||
struct less< boost::shared_ptr<T> >
|
shared_ptr<int> p2(p); // reads p
|
||||||
: binary_function<boost::shared_ptr<T>, boost::shared_ptr<T>, bool>
|
|
||||||
{
|
|
||||||
bool operator()(const boost::shared_ptr<T>& a,
|
|
||||||
const boost::shared_ptr<T>& b) const
|
|
||||||
{ return less<T*>()(a.get(),b.get()); }
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace std </pre>
|
// thread B
|
||||||
<p>Specialization of std::swap uses the fast, non-throwing swap that's provided
|
shared_ptr<int> p3(p); // OK, multiple reads are safe
|
||||||
as a member function instead of using the default algorithm which creates a
|
|
||||||
temporary and uses assignment.<br>
|
|
||||||
<br>
|
|
||||||
Specialization of std::less allows use of shared pointers as keys in C++
|
|
||||||
Standard Library associative collections.<br>
|
|
||||||
<br>
|
|
||||||
The std::less specializations use std::less<T*> to perform the
|
|
||||||
comparison. This insures that pointers are 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).<br>
|
|
||||||
<br>
|
|
||||||
It's still a controversial question whether supplying only std::less is better
|
|
||||||
than supplying a full range of comparison operators (<, >, <=, >=).</p>
|
|
||||||
<p>The current implementation does not supply the specializations if the macro
|
|
||||||
name BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION is defined.</p>
|
|
||||||
<p>The current implementation does not supply the member template functions if
|
|
||||||
the macro name BOOST_NO_MEMBER_TEMPLATES is defined.</p>
|
|
||||||
<h2>Class shared_ptr Members</h2>
|
|
||||||
<h3>shared_ptr <a name="shared_ptr_element_type">element_type</a></h3>
|
|
||||||
<pre>typedef T element_type;</pre>
|
|
||||||
<p>Provides the type of the stored pointer.</p>
|
|
||||||
<h3><a name="shared_ptr_ctor">shared_ptr constructors</a></h3>
|
|
||||||
<pre>explicit shared_ptr( T* p=0 );</pre>
|
|
||||||
<p>Constructs a <strong>shared_ptr</strong>, storing a copy of <tt>p</tt>, which
|
|
||||||
must have been allocated via a C++ <tt>new</tt> expression or be 0. Afterwards, <strong>use_count()</strong>
|
|
||||||
is 1 (even if p==0; see <a href="#shared_ptr_~shared_ptr">~shared_ptr</a>).</p>
|
|
||||||
<p>The only exception which may be thrown by this constructor is <tt>std::bad_alloc</tt>.
|
|
||||||
If an exception is thrown, <tt>delete p</tt> is called.</p>
|
|
||||||
<pre>shared_ptr( const shared_ptr& r); // never throws
|
|
||||||
template<typename Y>
|
|
||||||
shared_ptr(const shared_ptr<Y>& r); // never throws
|
|
||||||
template<typename Y>
|
|
||||||
shared_ptr(std::auto_ptr<Y>& r);</pre>
|
|
||||||
<p>Constructs a <strong>shared_ptr</strong>, as if by storing a copy of the
|
|
||||||
pointer stored in <strong>r</strong>. Afterwards, <strong>use_count()</strong>
|
|
||||||
for all copies is 1 more than the initial <strong>r.use_count()</strong>, or 1
|
|
||||||
in the <strong>auto_ptr</strong> case. In the <strong>auto_ptr</strong> case, <strong>r.release()</strong>
|
|
||||||
is called.</p>
|
|
||||||
<p>The only exception which may be thrown by the constructor from <strong>auto_ptr</strong>
|
|
||||||
is <tt>std::bad_alloc</tt>. If an exception is thrown, that
|
|
||||||
constructor has no effect.</p>
|
|
||||||
<h3><a name="shared_ptr_~shared_ptr">shared_ptr destructor</a></h3>
|
|
||||||
<pre>~shared_ptr();</pre>
|
|
||||||
<p>If <strong>use_count()</strong> == 1, deletes the object pointed to by the
|
|
||||||
stored pointer. Otherwise, <strong>use_count()</strong> for any remaining
|
|
||||||
copies is decremented by 1. Note that in C++ <tt>delete</tt> on a pointer
|
|
||||||
with a value of 0 is harmless.</p>
|
|
||||||
<p>Does not throw exceptions.</p>
|
|
||||||
<h3>shared_ptr <a name="shared_ptr_operator=">operator=</a></h3>
|
|
||||||
<pre>shared_ptr& operator=( const shared_ptr& r);
|
|
||||||
template<typename Y>
|
|
||||||
shared_ptr& operator=(const shared_ptr<Y>& r);
|
|
||||||
template<typename Y>
|
|
||||||
shared_ptr& operator=(std::auto_ptr<Y>& r);</pre>
|
|
||||||
<p>First, if <strong>use_count()</strong> == 1, deletes the object pointed to by
|
|
||||||
the stored pointer. Otherwise, <strong>use_count()</strong> for any
|
|
||||||
remaining copies is decremented by 1. Note that in C++ <tt>delete</tt> on
|
|
||||||
a pointer with a value of 0 is harmless.</p>
|
|
||||||
<p>Then replaces the contents of <strong>this</strong>, as if by storing a copy
|
|
||||||
of the pointer stored in <strong>r</strong>. Afterwards, <strong>use_count()</strong>
|
|
||||||
for all copies is 1 more than the initial <strong>r.use_count()</strong>, or 1
|
|
||||||
in the <strong>auto_ptr</strong> case. In the <strong>auto_ptr</strong> case, <strong>r.release()</strong>
|
|
||||||
is called.</p>
|
|
||||||
<p>The first two forms of <tt>operator=</tt> above do not throw exceptions.</p>
|
|
||||||
<p>The only exception which may be thrown by the <strong>auto_ptr</strong> form
|
|
||||||
is <tt>std::bad_alloc</tt>. If an exception is thrown, the function
|
|
||||||
has no effect.</p>
|
|
||||||
<h3>shared_ptr <a name="shared_ptr_reset">reset</a></h3>
|
|
||||||
<pre>void reset( T* p=0 );</pre>
|
|
||||||
<p>First, if <strong>use_count()</strong> == 1, deletes the object pointed to by
|
|
||||||
the stored pointer. Otherwise, <strong>use_count()</strong> for any
|
|
||||||
remaining copies is decremented by 1. </p>
|
|
||||||
<p>Then replaces the contents of <strong>this</strong>, as if by storing a copy
|
|
||||||
of <strong>p</strong>, which must have been allocated via a C++ <tt>new</tt>
|
|
||||||
expression or be 0. Afterwards, <strong>use_count()</strong> is 1 (even if p==0;
|
|
||||||
see <a href="#shared_ptr_~shared_ptr">~shared_ptr</a>). Note that in C++ <tt>delete</tt>
|
|
||||||
on a pointer with a value of 0 is harmless.</p>
|
|
||||||
<p>The only exception which may be thrown is <tt>std::bad_alloc</tt>. If
|
|
||||||
an exception is thrown, <tt>delete p</tt> is called.</p>
|
|
||||||
<h3>shared_ptr <a name="shared_ptr_operator*">operator*</a></h3>
|
|
||||||
<pre>T& operator*() const; // never throws</pre>
|
|
||||||
<p>Returns a reference to the object pointed to by the stored pointer.</p>
|
|
||||||
<h3>shared_ptr <a name="shared_ptr_operator->">operator-></a> and <a name="shared_ptr_get">get</a></h3>
|
|
||||||
<pre>T* operator->() const; // never throws
|
|
||||||
T* get() const; // never throws</pre>
|
|
||||||
<p>Both return the stored pointer.</p>
|
|
||||||
<h3>shared_ptr<a name="shared_ptr_use_count"> use_count</a></h3>
|
|
||||||
<p><tt>long use_count() const; // never throws</tt></p>
|
|
||||||
<p>Returns the number of <strong>shared_ptrs</strong> sharing ownership of the
|
|
||||||
stored pointer.</p>
|
|
||||||
<h3>shared_ptr <a name="shared_ptr_unique">unique</a></h3>
|
|
||||||
<p><tt>bool unique() const; // never throws</tt></p>
|
|
||||||
<p>Returns <strong>use_count()</strong> == 1.</p>
|
|
||||||
<h3><a name="shared_ptr_swap">shared_ptr swap</a></h3>
|
|
||||||
<p><code>void swap( shared_ptr<T>& other ) throw()</code></p>
|
|
||||||
<p>Swaps the two smart pointers, as if by std::swap.</p>
|
|
||||||
<h2>Class <a name="shared_ptr_example">shared_ptr example</a></h2>
|
|
||||||
<p>[To be supplied. In the meantime, see <a href="smart_ptr_test.cpp">smart_ptr_test.cpp</a>.]</p>
|
|
||||||
<hr>
|
|
||||||
<p>Revised December 8, 1999</p>
|
|
||||||
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
|
|
||||||
modify, sell and distribute this document is granted provided this copyright
|
|
||||||
notice appears in all copies. This document is provided "as is"
|
|
||||||
without express or implied warranty, and with no claim as to its suitability for
|
|
||||||
any purpose.</p>
|
|
||||||
|
|
||||||
</body>
|
//--- Example 2 ---
|
||||||
|
|
||||||
|
// thread A
|
||||||
|
p.reset(new int(1912)); // writes p
|
||||||
|
|
||||||
|
// thread B
|
||||||
|
p2.reset(); // OK, writes p2
|
||||||
|
|
||||||
|
//--- Example 3 ---
|
||||||
|
|
||||||
|
// thread A
|
||||||
|
p = p3; // reads p3, writes p
|
||||||
|
|
||||||
|
// thread B
|
||||||
|
p3.reset(); // writes p3; undefined, simultaneous read/write
|
||||||
|
|
||||||
|
//--- Example 4 ---
|
||||||
|
|
||||||
|
// thread A
|
||||||
|
p3 = p2; // reads p2, writes p3
|
||||||
|
|
||||||
|
// thread B
|
||||||
|
// p2 goes out of scope: undefined, the destructor is considered a "write access"
|
||||||
|
|
||||||
|
//--- Example 5 ---
|
||||||
|
|
||||||
|
// thread A
|
||||||
|
p3.reset(new int(1));
|
||||||
|
|
||||||
|
// thread B
|
||||||
|
p3.reset(new int(2)); // undefined, multiple writes
|
||||||
|
</pre>
|
||||||
|
<p> </p>
|
||||||
|
<P>Starting with Boost release 1.33.0, <STRONG>shared_ptr</STRONG> uses a lock-free
|
||||||
|
implementation on the following platforms:</P>
|
||||||
|
<UL>
|
||||||
|
<LI>
|
||||||
|
GNU GCC on x86 or x86-64;
|
||||||
|
<LI>
|
||||||
|
GNU GCC on IA64;
|
||||||
|
<LI>
|
||||||
|
Metrowerks CodeWarrior on PowerPC;
|
||||||
|
<LI>
|
||||||
|
GNU GCC on PowerPC;
|
||||||
|
<LI>
|
||||||
|
Windows.</LI></UL>
|
||||||
|
<P>If your program is single-threaded and does not link to any libraries that might
|
||||||
|
have used <STRONG>shared_ptr</STRONG> in its default configuration, you can <STRONG>
|
||||||
|
#define</STRONG> the macro <STRONG>BOOST_SP_DISABLE_THREADS</STRONG> on a
|
||||||
|
project-wide basis to switch to ordinary non-atomic reference count updates.</P>
|
||||||
|
<P>(Defining <STRONG>BOOST_SP_DISABLE_THREADS</STRONG> in some, but not all,
|
||||||
|
translation units is technically a violation of the One Definition Rule and
|
||||||
|
undefined behavior. Nevertheless, the implementation attempts to do its best to
|
||||||
|
accommodate the request to use non-atomic updates in those translation units.
|
||||||
|
No guarantees, though.)</P>
|
||||||
|
<P>You can define the macro <STRONG>BOOST_SP_USE_PTHREADS</STRONG> to turn off the
|
||||||
|
lock-free platform-specific implementation and fall back to the generic <STRONG>pthread_mutex_t</STRONG>-based
|
||||||
|
code.</P>
|
||||||
|
<h2><a name="FAQ">Frequently Asked Questions</a></h2>
|
||||||
|
<P><B>Q.</B> There are several variations of shared pointers, with different
|
||||||
|
tradeoffs; why does the smart pointer library supply only a single
|
||||||
|
implementation? It would be useful to be able to experiment with each type so
|
||||||
|
as to find the most suitable for the job at hand?</P>
|
||||||
|
<P>
|
||||||
|
<b>A.</b> An important goal of <STRONG>shared_ptr</STRONG> is to provide a
|
||||||
|
standard shared-ownership pointer. Having a single pointer type is important
|
||||||
|
for stable library interfaces, since different shared pointers typically cannot
|
||||||
|
interoperate, i.e. a reference counted pointer (used by library A) cannot share
|
||||||
|
ownership with a linked pointer (used by library B.)<BR>
|
||||||
|
</P>
|
||||||
|
<P><B>Q.</B> Why doesn't <B>shared_ptr</B> have template parameters supplying
|
||||||
|
traits or policies to allow extensive user customization?</P>
|
||||||
|
<P>
|
||||||
|
<B>A.</B> Parameterization discourages users. The <B>shared_ptr</B> template is
|
||||||
|
carefully crafted to meet common needs without extensive parameterization. Some
|
||||||
|
day a highly configurable smart pointer may be invented that is also very easy
|
||||||
|
to use and very hard to misuse. Until then, <B>shared_ptr</B> is the smart
|
||||||
|
pointer of choice for a wide range of applications. (Those interested in policy
|
||||||
|
based smart pointers should read <A href="http://www.awprofessional.com/bookstore/product.asp?isbn=0201704315&rl=1">
|
||||||
|
Modern C++ Design</A> by Andrei Alexandrescu.)<BR>
|
||||||
|
</P>
|
||||||
|
<P><B>Q.</B> I am not convinced. Default parameters can be used where appropriate
|
||||||
|
to hide the complexity. Again, why not policies?</P>
|
||||||
|
<P>
|
||||||
|
<B>A.</B> Template parameters affect the type. See the answer to the first
|
||||||
|
question above.<BR>
|
||||||
|
</P>
|
||||||
|
<P><B>Q.</B> Why doesn't <b>shared_ptr</b> use a linked list implementation?</P>
|
||||||
|
<P>
|
||||||
|
<b>A.</b> A linked list implementation does not offer enough advantages to
|
||||||
|
offset the added cost of an extra pointer. See <A href="smarttests.htm">timings</A>
|
||||||
|
page. In addition, it is expensive to make a linked list implementation thread
|
||||||
|
safe.<BR>
|
||||||
|
</P>
|
||||||
|
<P><b>Q.</b> Why doesn't <b>shared_ptr</b> (or any of the other Boost smart
|
||||||
|
pointers) supply an automatic conversion to <b>T*</b>?</P>
|
||||||
|
<P>
|
||||||
|
<b>A.</b> Automatic conversion is believed to be too error prone.<BR>
|
||||||
|
</P>
|
||||||
|
<P><B>Q.</B> Why does <b>shared_ptr</b> supply use_count()?</P>
|
||||||
|
<P>
|
||||||
|
<b>A.</b> As an aid to writing test cases and debugging displays. One of the
|
||||||
|
progenitors had use_count(), and it was useful in tracking down bugs in a
|
||||||
|
complex project that turned out to have cyclic-dependencies.<BR>
|
||||||
|
</P>
|
||||||
|
<P><B>Q.</B> Why doesn't <b>shared_ptr</b> specify complexity requirements?</P>
|
||||||
|
<P>
|
||||||
|
<b>A.</b> Because complexity requirements limit implementors and complicate the
|
||||||
|
specification without apparent benefit to <b>shared_ptr</b> users. For example,
|
||||||
|
error-checking implementations might become non-conforming if they had to meet
|
||||||
|
stringent complexity requirements.<BR>
|
||||||
|
</P>
|
||||||
|
<P><b>Q.</b> Why doesn't <b>shared_ptr</b> provide a release() function?</P>
|
||||||
|
<P>
|
||||||
|
<b>A.</b> <b>shared_ptr</b> cannot give away ownership unless it's unique()
|
||||||
|
because the other copy will still destroy the object.</P>
|
||||||
|
<p>Consider:</p>
|
||||||
|
<blockquote><pre>shared_ptr<int> a(new int);
|
||||||
|
shared_ptr<int> b(a); // a.use_count() == b.use_count() == 2
|
||||||
|
|
||||||
|
int * p = a.release();
|
||||||
|
|
||||||
|
// Who owns p now? b will still call delete on it in its destructor.</pre>
|
||||||
|
</blockquote>
|
||||||
|
<p>Furthermore, the pointer returned by <code>release()</code> would be difficult
|
||||||
|
to deallocate reliably, as the source <b>shared_ptr</b> could have been created
|
||||||
|
with a custom deleter.<BR>
|
||||||
|
</p>
|
||||||
|
<P><b>Q.</b> Why is <code>operator->()</code> const, but its return value is a
|
||||||
|
non-const pointer to the element type?</P>
|
||||||
|
<P>
|
||||||
|
<b>A.</b> Shallow copy pointers, including raw pointers, typically don't
|
||||||
|
propagate constness. It makes little sense for them to do so, as you can always
|
||||||
|
obtain a non-const pointer from a const one and then proceed to modify the
|
||||||
|
object through it.<b>shared_ptr</b> is "as close to raw pointers as possible
|
||||||
|
but no closer".<BR>
|
||||||
|
<BR>
|
||||||
|
</P>
|
||||||
|
<hr>
|
||||||
|
<p>
|
||||||
|
$Date$</p>
|
||||||
|
<p><small>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
|
||||||
|
Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License,
|
||||||
|
Version 1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A>
|
||||||
|
or copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
310
smart_ptr.htm
310
smart_ptr.htm
@@ -1,138 +1,196 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
<html>
|
<html>
|
||||||
|
<head>
|
||||||
<head>
|
<title>Smart Pointers</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
</head>
|
||||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
<body bgcolor="#ffffff" text="#000000">
|
||||||
<title>Smart Pointer Classes</title>
|
<h1><A href="../../index.htm"><img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" width="277" height="86"
|
||||||
</head>
|
border="0"></A>Smart Pointers</h1>
|
||||||
|
<p><a href="#Introduction">Introduction</a><br>
|
||||||
<body bgcolor="#FFFFFF" text="#000000">
|
<a href="#common_requirements">Common Requirements</a><br>
|
||||||
|
<a href="#Exception_Safety">Exception Safety</a><br>
|
||||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">Smart
|
<a href="#Exception-specifications">Exception-specifications</a><br>
|
||||||
Pointers</h1>
|
<a href="#History">History and Acknowledgements</a><br>
|
||||||
<p>Smart pointers are classes which store pointers to dynamically allocated
|
<a href="#References">References</a></p>
|
||||||
(heap) objects. They behave much like built-in C++ pointers except that
|
<h2><a name="Introduction">Introduction</a></h2>
|
||||||
they automatically delete the object pointed to at the appropriate
|
<p>Smart pointers are objects which store pointers to dynamically allocated (heap)
|
||||||
time. Smart pointers are particularly useful in the face of exceptions as
|
objects. They behave much like built-in C++ pointers except that they
|
||||||
they ensure proper destruction of dynamically allocated objects. They can also
|
automatically delete the object pointed to at the appropriate time. Smart
|
||||||
be used to keep track of dynamically allocated objects shared by multiple
|
pointers are particularly useful in the face of exceptions as they ensure
|
||||||
owners.</p>
|
proper destruction of dynamically allocated objects. They can also be used to
|
||||||
<p>Conceptually, smart pointers are seen as owning the object pointed to, and
|
keep track of dynamically allocated objects shared by multiple owners.</p>
|
||||||
thus responsible for deletion of the object when it is no longer needed.</p>
|
<p>Conceptually, smart pointers are seen as owning the object pointed to, and thus
|
||||||
<p>The header <a href="../../boost/smart_ptr.hpp">boost/smart_ptr.hpp</a>
|
responsible for deletion of the object when it is no longer needed.</p>
|
||||||
provides four smart pointer template classes:</p>
|
<p>The smart pointer library provides six smart pointer class templates:</p>
|
||||||
<div align="left">
|
<div align="left">
|
||||||
<table border="1" cellpadding="4" cellspacing="4">
|
<table border="1" cellpadding="4" cellspacing="0">
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td><a href="scoped_ptr.htm"><b>scoped_ptr</b></a></td>
|
||||||
<p align="left"><a href="scoped_ptr.htm"><strong>scoped_ptr</strong></a></td>
|
<td><a href="../../boost/scoped_ptr.hpp"><boost/scoped_ptr.hpp></a></td>
|
||||||
<td>Simple sole ownership of single objects.</td>
|
<td>Simple sole ownership of single objects. Noncopyable.</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="scoped_array.htm"><strong>scoped_array</strong></a></td>
|
<td><a href="scoped_array.htm"><b>scoped_array</b></a></td>
|
||||||
<td>Simple sole ownership of arrays.</td>
|
<td><a href="../../boost/scoped_array.hpp"><boost/scoped_array.hpp></a></td>
|
||||||
|
<td>Simple sole ownership of arrays. Noncopyable.</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="shared_ptr.htm"><strong>shared_ptr</strong></a></td>
|
<td><a href="shared_ptr.htm"><b>shared_ptr</b></a></td>
|
||||||
<td>Object ownership shared among multiple pointers</td>
|
<td><a href="../../boost/shared_ptr.hpp"><boost/shared_ptr.hpp></a></td>
|
||||||
|
<td>Object ownership shared among multiple pointers.</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="shared_array.htm"><strong>shared_array</strong></a></td>
|
<td><a href="shared_array.htm"><b>shared_array</b></a></td>
|
||||||
|
<td><a href="../../boost/shared_array.hpp"><boost/shared_array.hpp></a></td>
|
||||||
<td>Array ownership shared among multiple pointers.</td>
|
<td>Array ownership shared among multiple pointers.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><a href="weak_ptr.htm"><b>weak_ptr</b></a></td>
|
||||||
|
<td><a href="../../boost/weak_ptr.hpp"><boost/weak_ptr.hpp></a></td>
|
||||||
|
<td>Non-owning observers of an object owned by <b>shared_ptr</b>.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><a href="intrusive_ptr.html"><b>intrusive_ptr</b></a></td>
|
||||||
|
<td><a href="../../boost/intrusive_ptr.hpp"><boost/intrusive_ptr.hpp></a></td>
|
||||||
|
<td>Shared ownership of objects with an embedded reference count.</td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<p>These classes are designed to complement the C++ Standard Library <tt>auto_ptr</tt>
|
<p>These templates are designed to complement the <b>std::auto_ptr</b> template.</p>
|
||||||
class.</p>
|
<p>They are examples of the "resource acquisition is initialization" idiom
|
||||||
<p>They are examples of the "resource acquisition is initialization"
|
described in Bjarne Stroustrup's "The C++ Programming Language", 3rd edition,
|
||||||
idiom described in Bjarne Stroustrup's "The C++ Programming Language",
|
Section 14.4, Resource Management.</p>
|
||||||
3rd edition, Section 14.4, Resource Management.</p>
|
<p>Additionally, the smart pointer library provides efficient factory functions
|
||||||
<p>A test program (<a href="smart_ptr_test.cpp">smart_ptr_test.cpp</a>) is
|
for creating <code>shared_ptr</code> objects:</p>
|
||||||
provided to verify correct operation.</p>
|
<div align="left">
|
||||||
<p>A page on <a href="smarttests.htm">Smart Pointer Timings</a> will be of
|
<table border="1" cellpadding="4" cellspacing="0">
|
||||||
interest to those curious about performance issues.</p>
|
<tr>
|
||||||
<h2><a name="Common requirements">Common requirements</a></h2>
|
<td><a href="make_shared.html"><b>make_shared and allocate_shared</b></a></td>
|
||||||
<p>These smart pointer classes have a template parameter, <tt>T</tt>, which
|
<td><a href="../../boost/make_shared.hpp"><boost/make_shared.hpp></a></td>
|
||||||
specifies the type of the object pointed to by the smart pointer. The
|
<td>Efficient creation of <code>shared_ptr</code> objects.</td>
|
||||||
behavior of all four classes is undefined if the destructor or operator delete
|
</tr>
|
||||||
for objects of type <tt>T</tt> throws exceptions.</p>
|
</table>
|
||||||
<h2>Exception safety</h2>
|
</div>
|
||||||
<p>Several functions in these smart pointer classes are specified as having
|
<p>A test program, <a href="test/smart_ptr_test.cpp">smart_ptr_test.cpp</a>, is
|
||||||
"no effect" or "no effect except such-and-such" if an
|
provided to verify correct operation.</p>
|
||||||
exception is thrown. This means that when an exception is thrown by
|
<p>A page on <a href="compatibility.htm">compatibility</a> with older versions of
|
||||||
an object of one of these classes, the entire program state remains the same as
|
the Boost smart pointer library describes some of the changes since earlier
|
||||||
it was prior to the function call which resulted in the exception being
|
versions of the smart pointer implementation.</p>
|
||||||
thrown. This amounts to a guarantee that there are no detectable side
|
<p>A page on <a href="smarttests.htm">smart pointer timings</a> will be of interest
|
||||||
effects. Other functions never throw exceptions. The only exception
|
to those curious about performance issues.</p>
|
||||||
ever thrown by functions which do throw (assuming <tt>T</tt> meets the <a href="#Common requirements">Common
|
<P>A page on <A href="sp_techniques.html">smart pointer programming techniques</A> lists
|
||||||
requirements</a>) is <tt>std::bad_alloc</tt>, and that is thrown only by
|
some advanced applications of <code>shared_ptr</code> and <code>weak_ptr</code>.</P>
|
||||||
functions which are explicitly documented as possibly throwing <tt>std::bad_alloc</tt>.</p>
|
<h2><a name="common_requirements">Common Requirements</a></h2>
|
||||||
<h2>Exception-specifications</h2>
|
<p>These smart pointer class templates have a template parameter, <b>T</b>, which
|
||||||
<p>Exception-specifications are not used; see <a href="../../more/lib_guide.htm#Exception-specification">exception-specification
|
specifies the type of the object pointed to by the smart pointer. The behavior
|
||||||
rationale</a>.</p>
|
of the smart pointer templates is undefined if the destructor or <b>operator delete</b>
|
||||||
<p>All four classes contain member functions which can never throw exceptions,
|
for objects of type <b>T</b> throw exceptions.</p>
|
||||||
because they neither throw exceptions themselves nor call other functions which
|
<p><b>T</b> may be an incomplete type at the point of smart pointer declaration.
|
||||||
may throw exceptions. These members are indicated by a comment: <kbd>//
|
Unless otherwise specified, it is required that <b>T</b> be a complete type at
|
||||||
never throws</kbd>. </p>
|
points of smart pointer instantiation. Implementations are required to diagnose
|
||||||
<p>Functions which destroy objects of the pointed to type are prohibited from
|
(treat as an error) all violations of this requirement, including deletion of
|
||||||
throwing exceptions by the <a href="#Common requirements">Common requirements</a>.</p>
|
an incomplete type. See the description of the <a href="../utility/utility.htm#checked_delete">
|
||||||
<h2>History and acknowledgements</h2>
|
<b>checked_delete</b></a> function template.</p>
|
||||||
<p>November, 1999. Darin Adler provided operator ==, operator !=, and std::swap
|
<P>Note that <STRONG>shared_ptr</STRONG> does not have this restriction, as most of
|
||||||
and std::less specializations for shared types.</p>
|
its member functions do not require <STRONG>T</STRONG> to be a complete type.</P>
|
||||||
<p>September, 1999. Luis Coelho provided shared_ptr::swap and shared_array::swap</p>
|
<h3>Rationale</h3>
|
||||||
<p>May, 1999. In April and May, 1999, Valentin Bonnard and David Abrahams
|
<p>The requirements on <b>T</b> are carefully crafted to maximize safety yet allow
|
||||||
made a number of suggestions resulting in numerous improvements. See the
|
handle-body (also called pimpl) and similar idioms. In these idioms a smart
|
||||||
revision history in <a href="../../boost/smart_ptr.hpp"><tt>smart_ptr.hpp</tt></a>
|
pointer may appear in translation units where <b>T</b> is an incomplete type.
|
||||||
for the specific changes made as a result of their constructive criticism.</p>
|
This separates interface from implementation and hides implementation from
|
||||||
<p>Oct, 1998. In 1994 Greg Colvin proposed to the C++ Standards Committee
|
translation units which merely use the interface. Examples described in the
|
||||||
classes named <strong>auto_ptr</strong> and <strong>counted_ptr</strong> which
|
documentation for specific smart pointers illustrate use of smart pointers in
|
||||||
were very similar to what we now call <strong>scoped_ptr</strong> and <strong>shared_ptr</strong>.
|
these idioms.</p>
|
||||||
The committee document was 94-168/N0555, Exception Safe Smart Pointers. In
|
<p>Note that <b>scoped_ptr</b> requires that <b>T</b> be a complete type at
|
||||||
one of the very few cases where the Library Working Group's recommendations were
|
destruction time, but <b>shared_ptr</b> does not.</p>
|
||||||
not followed by the full committee, <strong>counted_ptr</strong> was rejected
|
<h2><a name="Exception_Safety">Exception Safety</a></h2>
|
||||||
and surprising transfer-of-ownership semantics were added to <strong>auto-ptr</strong>.</p>
|
<p>Several functions in these smart pointer classes are specified as having "no
|
||||||
<p>Beman Dawes proposed reviving the original semantics under the names <strong>safe_ptr</strong>
|
effect" or "no effect except such-and-such" if an exception is thrown. This
|
||||||
and <strong>counted_ptr</strong> at an October, 1998, meeting of Per Andersson,
|
means that when an exception is thrown by an object of one of these classes,
|
||||||
Matt Austern, Greg Colvin, Sean Corfield, Pete Becker, Nico Josuttis, Dietmar
|
the entire program state remains the same as it was prior to the function call
|
||||||
K<EFBFBD>hl, Nathan Myers, Chichiang Wan and Judy Ward. During the discussion,
|
which resulted in the exception being thrown. This amounts to a guarantee that
|
||||||
the four class names were finalized, it was decided that there was no need to
|
there are no detectable side effects. Other functions never throw exceptions.
|
||||||
exactly follow the <strong>std::auto_ptr</strong> interface, and various
|
The only exception ever thrown by functions which do throw (assuming <b>T</b> meets
|
||||||
function signatures and semantics were finalized.</p>
|
the <a href="#common_requirements">common requirements</a>) is <b>std::bad_alloc</b>,
|
||||||
<p>Over the next three months, several implementations were considered for <strong>shared_ptr</strong>,
|
and that is thrown only by functions which are explicitly documented as
|
||||||
and discussed on the <a href="http://www.boost.org">boost.org</a> mailing
|
possibly throwing <b>std::bad_alloc</b>.</p>
|
||||||
list. The implementation questions revolved around the reference count
|
<h2><a name="Exception-specifications">Exception-specifications</a></h2>
|
||||||
which must be kept, either attached to the pointed to object, or detached
|
<p>Exception-specifications are not used; see <a href="http://www.boost.org/more/lib_guide.htm#Exception-specification">
|
||||||
elsewhere. Each of those variants have themselves two major variants:
|
exception-specification rationale</a>.</p>
|
||||||
<ul>
|
<p>All the smart pointer templates contain member functions which can never throw
|
||||||
<li>Direct detached: the shared_ptr contains a pointer to the object, and a
|
exceptions, because they neither throw exceptions themselves nor call other
|
||||||
pointer to the count.</li>
|
functions which may throw exceptions. These members are indicated by a comment: <code>
|
||||||
<li>Indirect detached: the shared_ptr contains a pointer to a helper object,
|
// never throws</code>.
|
||||||
which in turn contains a pointer to the object and the count.</li>
|
</p>
|
||||||
<li>Embedded attached: the count is a member of the object pointed to.</li>
|
<p>Functions which destroy objects of the pointed to type are prohibited from
|
||||||
<li>Placement attached: the count is attached via operator new manipulations.</li>
|
throwing exceptions by the <a href="#common_requirements">common requirements</a>.</p>
|
||||||
</ul>
|
<h2><a name="History">History</a> and Acknowledgements</h2>
|
||||||
<p>Each implementation technique has advantages and disadvantages. We went
|
<p>January 2002. Peter Dimov reworked all four classes, adding features, fixing
|
||||||
so far as to run various timings of the direct and indirect approaches, and
|
bugs, and splitting them into four separate headers, and added <b>weak_ptr</b>.
|
||||||
found that at least on Intel Pentium chips there was very little measurable
|
See the <a href="compatibility.htm">compatibility</a> page for a summary of the
|
||||||
difference. Kevlin Henney provided a paper he wrote on "Counted Body
|
changes.</p>
|
||||||
Techniques." Dietmar K<>hl suggested an elegant partial template
|
<p>May 2001. Vladimir Prus suggested requiring a complete type on destruction.
|
||||||
specialization technique to allow users to choose which implementation they
|
Refinement evolved in discussions including Dave Abrahams, Greg Colvin, Beman
|
||||||
preferred, and that was also experimented with.</p>
|
Dawes, Rainer Deyke, Peter Dimov, John Maddock, Vladimir Prus, Shankar Sai, and
|
||||||
<p>But Greg Colvin and Jerry Schwarz argued that "parameterization will
|
others.</p>
|
||||||
discourage users", and in the end we choose to supply only the direct
|
<p>November 1999. Darin Adler provided <b>operator ==</b>, <b>operator !=</b>, and <b>std::swap</b>
|
||||||
implementation.</p>
|
and <b>std::less</b> specializations for shared types.</p>
|
||||||
<p>See the Revision History section of the header for further contributors.</p>
|
<p>September 1999. Luis Coelho provided <b>shared_ptr::swap</b> and <b>shared_array::swap</b></p>
|
||||||
<hr>
|
<p>May 1999. In April and May, 1999, Valentin Bonnard and David Abrahams made a
|
||||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan
|
number of suggestions resulting in numerous improvements.</p>
|
||||||
-->24 Jul 2000<!--webbot bot="Timestamp" endspan i-checksum="14986"
|
<p>October 1998. Beman Dawes proposed reviving the original semantics under the
|
||||||
--></p>
|
names <b>safe_ptr</b> and <b>counted_ptr</b>, meeting of Per Andersson, Matt
|
||||||
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
|
Austern, Greg Colvin, Sean Corfield, Pete Becker, Nico Josuttis, Dietmar Kühl,
|
||||||
modify, sell and distribute this document is granted provided this copyright
|
Nathan Myers, Chichiang Wan and Judy Ward. During the discussion, the four new
|
||||||
notice appears in all copies. This document is provided "as is"
|
class names were finalized, it was decided that there was no need to exactly
|
||||||
without express or implied warranty, and with no claim as to its suitability for
|
follow the <b>std::auto_ptr</b> interface, and various function signatures and
|
||||||
any purpose.</p>
|
semantics were finalized.</p>
|
||||||
|
<p>Over the next three months, several implementations were considered for <b>shared_ptr</b>,
|
||||||
</body>
|
and discussed on the <a href="http://www.boost.org">boost.org</a> 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:
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
Direct detached: the shared_ptr contains a pointer to the object, and a pointer
|
||||||
|
to the count.
|
||||||
|
<li>
|
||||||
|
Indirect detached: the shared_ptr contains a pointer to a helper object, which
|
||||||
|
in turn contains a pointer to the object and the count.
|
||||||
|
<li>
|
||||||
|
Embedded attached: the count is a member of the object pointed to.
|
||||||
|
<li>
|
||||||
|
Placement attached: the count is attached via operator new manipulations.</li>
|
||||||
|
</ul>
|
||||||
|
<p>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.</p>
|
||||||
|
<p>But Greg Colvin and Jerry Schwarz argued that "parameterization will discourage
|
||||||
|
users", and in the end we choose to supply only the direct implementation.</p>
|
||||||
|
<p>Summer, 1994. Greg Colvin proposed to the C++ Standards Committee classes named <b>auto_ptr</b>
|
||||||
|
and <b>counted_ptr</b> which were very similar to what we now call <b>scoped_ptr</b>
|
||||||
|
and <b>shared_ptr</b>. <a href="#Col-94">[Col-94]</a> In one of the very few
|
||||||
|
cases where the Library Working Group's recommendations were not followed by
|
||||||
|
the full committee, <b>counted_ptr</b> was rejected and surprising
|
||||||
|
transfer-of-ownership semantics were added to <b>auto_ptr</b>.</p>
|
||||||
|
<h2><a name="References">References</a></h2>
|
||||||
|
<p>[<a name="Col-94">Col-94</a>] Gregory Colvin, <a href="http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/1994/N0555.pdf">
|
||||||
|
Exception Safe Smart Pointers</a>, C++ committee document 94-168/N0555,
|
||||||
|
July, 1994.</p>
|
||||||
|
<p>[<a name="E&D-94">E&D-94</a>] John R. Ellis & David L. Detlefs, <a href="http://www.usenix.org/publications/library/proceedings/c++94/full_papers/ellis.a">
|
||||||
|
Safe, Efficient Garbage Collection for C++</a>, Usenix Proceedings,
|
||||||
|
February, 1994. This paper includes an extensive discussion of weak pointers
|
||||||
|
and an extensive bibliography.</p>
|
||||||
|
<hr>
|
||||||
|
<p>$Date$</p>
|
||||||
|
<p><small>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
|
||||||
|
Distributed under the Boost Software License, Version 1.0. See accompanying
|
||||||
|
file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or copy at
|
||||||
|
<A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,263 +0,0 @@
|
|||||||
// smart pointer test program ----------------------------------------------//
|
|
||||||
|
|
||||||
// (C) Copyright Beman Dawes 1998, 1999. Permission to copy, use, modify, sell
|
|
||||||
// and distribute this software is granted provided this copyright notice
|
|
||||||
// appears in all copies. This software is provided "as is" without express or
|
|
||||||
// implied warranty, and with no claim as to its suitability for any purpose.
|
|
||||||
|
|
||||||
// Revision History
|
|
||||||
// 29 Nov 99 added std::swap and associative container tests (Darin Adler)
|
|
||||||
// 25 Sep 99 added swap tests
|
|
||||||
// 20 Jul 99 header name changed to .hpp
|
|
||||||
// 20 Apr 99 additional error tests added.
|
|
||||||
|
|
||||||
#include <boost/smart_ptr.hpp>
|
|
||||||
#include <cassert>
|
|
||||||
#include <cstring>
|
|
||||||
#include <iostream>
|
|
||||||
#include <set>
|
|
||||||
|
|
||||||
#ifdef NDEBUG
|
|
||||||
#error This test program makes no sense if NDEBUG is defined
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using boost::scoped_ptr;
|
|
||||||
using boost::scoped_array;
|
|
||||||
using boost::shared_ptr;
|
|
||||||
using boost::shared_array;
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
void ck( const T* v1, T v2 ) { assert( *v1 == v2 ); }
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
int UDT_use_count; // independent of pointer maintained counts
|
|
||||||
}
|
|
||||||
|
|
||||||
// user defined type -------------------------------------------------------//
|
|
||||||
|
|
||||||
class UDT {
|
|
||||||
long value_;
|
|
||||||
public:
|
|
||||||
explicit UDT( long value=0 ) : value_(value) { ++UDT_use_count; }
|
|
||||||
~UDT() {
|
|
||||||
--UDT_use_count;
|
|
||||||
cout << "UDT with value " << value_ << " being destroyed" << endl;
|
|
||||||
}
|
|
||||||
long value() const { return value_; }
|
|
||||||
void value( long v ) { value_ = v;; }
|
|
||||||
}; // UDT
|
|
||||||
|
|
||||||
// main --------------------------------------------------------------------//
|
|
||||||
|
|
||||||
// This isn't a very systematic test; it just hits some of the basics.
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
|
|
||||||
assert( UDT_use_count == 0 ); // reality check
|
|
||||||
|
|
||||||
// test scoped_ptr with a built-in type
|
|
||||||
long * lp = new long;
|
|
||||||
scoped_ptr<long> sp ( lp );
|
|
||||||
assert( sp.get() == lp );
|
|
||||||
assert( lp == sp.get() );
|
|
||||||
assert( &*sp == lp );
|
|
||||||
|
|
||||||
*sp = 1234568901L;
|
|
||||||
assert( *sp == 1234568901L );
|
|
||||||
assert( *lp == 1234568901L );
|
|
||||||
ck( static_cast<long*>(sp.get()), 1234568901L );
|
|
||||||
ck( lp, *sp );
|
|
||||||
|
|
||||||
sp.reset();
|
|
||||||
assert( sp.get() == 0 );
|
|
||||||
|
|
||||||
// test scoped_ptr with a user defined type
|
|
||||||
scoped_ptr<UDT> udt_sp ( new UDT( 999888777 ) );
|
|
||||||
assert( udt_sp->value() == 999888777 );
|
|
||||||
udt_sp.reset();
|
|
||||||
udt_sp.reset( new UDT( 111222333 ) );
|
|
||||||
assert( udt_sp->value() == 111222333 );
|
|
||||||
udt_sp.reset( new UDT( 333222111 ) );
|
|
||||||
assert( udt_sp->value() == 333222111 );
|
|
||||||
|
|
||||||
// test scoped_array with a build-in type
|
|
||||||
char * sap = new char [ 100 ];
|
|
||||||
scoped_array<char> sa ( sap );
|
|
||||||
assert( sa.get() == sap );
|
|
||||||
assert( sap == sa.get() );
|
|
||||||
|
|
||||||
strcpy( sa.get(), "Hot Dog with mustard and relish" );
|
|
||||||
assert( strcmp( sa.get(), "Hot Dog with mustard and relish" ) == 0 );
|
|
||||||
assert( strcmp( sap, "Hot Dog with mustard and relish" ) == 0 );
|
|
||||||
|
|
||||||
assert( sa[0] == 'H' );
|
|
||||||
assert( sa[30] == 'h' );
|
|
||||||
|
|
||||||
sa[0] = 'N';
|
|
||||||
sa[4] = 'd';
|
|
||||||
assert( strcmp( sap, "Not dog with mustard and relish" ) == 0 );
|
|
||||||
|
|
||||||
sa.reset();
|
|
||||||
assert( sa.get() == 0 );
|
|
||||||
|
|
||||||
// test shared_ptr with a built-in type
|
|
||||||
int * ip = new int;
|
|
||||||
shared_ptr<int> cp ( ip );
|
|
||||||
assert( ip == cp.get() );
|
|
||||||
assert( cp.use_count() == 1 );
|
|
||||||
|
|
||||||
*cp = 54321;
|
|
||||||
assert( *cp == 54321 );
|
|
||||||
assert( *ip == 54321 );
|
|
||||||
ck( static_cast<int*>(cp.get()), 54321 );
|
|
||||||
ck( static_cast<int*>(ip), *cp );
|
|
||||||
|
|
||||||
shared_ptr<int> cp2 ( cp );
|
|
||||||
assert( ip == cp2.get() );
|
|
||||||
assert( cp.use_count() == 2 );
|
|
||||||
assert( cp2.use_count() == 2 );
|
|
||||||
|
|
||||||
assert( *cp == 54321 );
|
|
||||||
assert( *cp2 == 54321 );
|
|
||||||
ck( static_cast<int*>(cp2.get()), 54321 );
|
|
||||||
ck( static_cast<int*>(ip), *cp2 );
|
|
||||||
|
|
||||||
shared_ptr<int> cp3 ( cp );
|
|
||||||
assert( cp.use_count() == 3 );
|
|
||||||
assert( cp2.use_count() == 3 );
|
|
||||||
assert( cp3.use_count() == 3 );
|
|
||||||
cp.reset();
|
|
||||||
assert( cp2.use_count() == 2 );
|
|
||||||
assert( cp3.use_count() == 2 );
|
|
||||||
assert( cp.use_count() == 1 );
|
|
||||||
cp.reset( new int );
|
|
||||||
*cp = 98765;
|
|
||||||
assert( *cp == 98765 );
|
|
||||||
*cp3 = 87654;
|
|
||||||
assert( *cp3 == 87654 );
|
|
||||||
assert( *cp2 == 87654 );
|
|
||||||
cp.swap( cp3 );
|
|
||||||
assert( *cp == 87654 );
|
|
||||||
assert( *cp2 == 87654 );
|
|
||||||
assert( *cp3 == 98765 );
|
|
||||||
cp.swap( cp3 );
|
|
||||||
assert( *cp == 98765 );
|
|
||||||
assert( *cp2 == 87654 );
|
|
||||||
assert( *cp3 == 87654 );
|
|
||||||
cp2 = cp2;
|
|
||||||
assert( cp2.use_count() == 2 );
|
|
||||||
assert( *cp2 == 87654 );
|
|
||||||
cp = cp2;
|
|
||||||
assert( cp2.use_count() == 3 );
|
|
||||||
assert( *cp2 == 87654 );
|
|
||||||
assert( cp.use_count() == 3 );
|
|
||||||
assert( *cp == 87654 );
|
|
||||||
|
|
||||||
shared_ptr<int> cp4;
|
|
||||||
swap( cp2, cp4 );
|
|
||||||
assert( cp4.use_count() == 3 );
|
|
||||||
assert( *cp4 == 87654 );
|
|
||||||
assert( cp2.get() == 0 );
|
|
||||||
|
|
||||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
||||||
set< shared_ptr<int> > scp;
|
|
||||||
scp.insert(cp4);
|
|
||||||
assert( scp.find(cp4) != scp.end() );
|
|
||||||
assert( scp.find(cp4) == scp.find( shared_ptr<int>(cp4) ) );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// test shared_array with a built-in type
|
|
||||||
char * cap = new char [ 100 ];
|
|
||||||
shared_array<char> ca ( cap );
|
|
||||||
assert( ca.get() == cap );
|
|
||||||
assert( cap == ca.get() );
|
|
||||||
assert( &ca[0] == cap );
|
|
||||||
|
|
||||||
strcpy( ca.get(), "Hot Dog with mustard and relish" );
|
|
||||||
assert( strcmp( ca.get(), "Hot Dog with mustard and relish" ) == 0 );
|
|
||||||
assert( strcmp( cap, "Hot Dog with mustard and relish" ) == 0 );
|
|
||||||
|
|
||||||
assert( ca[0] == 'H' );
|
|
||||||
assert( ca[30] == 'h' );
|
|
||||||
|
|
||||||
shared_array<char> ca2 ( ca );
|
|
||||||
shared_array<char> ca3 ( ca2 );
|
|
||||||
|
|
||||||
ca[0] = 'N';
|
|
||||||
ca[4] = 'd';
|
|
||||||
assert( strcmp( ca.get(), "Not dog with mustard and relish" ) == 0 );
|
|
||||||
assert( strcmp( ca2.get(), "Not dog with mustard and relish" ) == 0 );
|
|
||||||
assert( strcmp( ca3.get(), "Not dog with mustard and relish" ) == 0 );
|
|
||||||
assert( ca.use_count() == 3 );
|
|
||||||
assert( ca2.use_count() == 3 );
|
|
||||||
assert( ca3.use_count() == 3 );
|
|
||||||
ca2.reset();
|
|
||||||
assert( ca.use_count() == 2 );
|
|
||||||
assert( ca3.use_count() == 2 );
|
|
||||||
assert( ca2.use_count() == 1 );
|
|
||||||
|
|
||||||
ca.reset();
|
|
||||||
assert( ca.get() == 0 );
|
|
||||||
|
|
||||||
shared_array<char> ca4;
|
|
||||||
swap( ca3, ca4 );
|
|
||||||
assert( ca4.use_count() == 1 );
|
|
||||||
assert( strcmp( ca4.get(), "Not dog with mustard and relish" ) == 0 );
|
|
||||||
assert( ca3.get() == 0 );
|
|
||||||
|
|
||||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
||||||
set< shared_array<char> > sca;
|
|
||||||
sca.insert(ca4);
|
|
||||||
assert( sca.find(ca4) != sca.end() );
|
|
||||||
assert( sca.find(ca4) == sca.find( shared_array<char>(ca4) ) );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// test shared_array with user defined type
|
|
||||||
shared_array<UDT> udta ( new UDT[3] );
|
|
||||||
|
|
||||||
udta[0].value( 111 );
|
|
||||||
udta[1].value( 222 );
|
|
||||||
udta[2].value( 333 );
|
|
||||||
shared_array<UDT> udta2 ( udta );
|
|
||||||
|
|
||||||
assert( udta[0].value() == 111 );
|
|
||||||
assert( udta[1].value() == 222 );
|
|
||||||
assert( udta[2].value() == 333 );
|
|
||||||
assert( udta2[0].value() == 111 );
|
|
||||||
assert( udta2[1].value() == 222 );
|
|
||||||
assert( udta2[2].value() == 333 );
|
|
||||||
udta2.reset();
|
|
||||||
assert( udta2.get() == 0 );
|
|
||||||
assert( udta.use_count() == 1 );
|
|
||||||
assert( udta2.use_count() == 1 );
|
|
||||||
|
|
||||||
assert( UDT_use_count == 4 ); // reality check
|
|
||||||
|
|
||||||
// test shared_ptr with a user defined type
|
|
||||||
UDT * up = new UDT;
|
|
||||||
shared_ptr<UDT> sup ( up );
|
|
||||||
assert( up == sup.get() );
|
|
||||||
assert( sup.use_count() == 1 );
|
|
||||||
|
|
||||||
sup->value( 54321 ) ;
|
|
||||||
assert( sup->value() == 54321 );
|
|
||||||
assert( up->value() == 54321 );
|
|
||||||
|
|
||||||
shared_ptr<UDT> sup2;
|
|
||||||
sup2 = sup;
|
|
||||||
assert( sup2->value() == 54321 );
|
|
||||||
assert( sup.use_count() == 2 );
|
|
||||||
assert( sup2.use_count() == 2 );
|
|
||||||
sup2 = sup2;
|
|
||||||
assert( sup2->value() == 54321 );
|
|
||||||
assert( sup.use_count() == 2 );
|
|
||||||
assert( sup2.use_count() == 2 );
|
|
||||||
|
|
||||||
cout << "OK" << endl;
|
|
||||||
|
|
||||||
new char[12345]; // deliberate memory leak to verify leaks detected
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
} // main
|
|
||||||
|
|
||||||
@@ -1,13 +1,15 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>boost: smart pointer tests</title>
|
<title>Smart Pointer Timings</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
<!--
|
</head>
|
||||||
-->
|
|
||||||
<body bgcolor="#FFFFFF">
|
<body bgcolor="#FFFFFF">
|
||||||
|
|
||||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" WIDTH="277" HEIGHT="86">Smart
|
<h1><img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" WIDTH="277" HEIGHT="86">Smart Pointer Timings</h1>
|
||||||
Pointers Timings </h1>
|
|
||||||
|
|
||||||
<p>In late January 2000, Mark Borgerding put forward a suggestion to boost for
|
<p>In late January 2000, Mark Borgerding put forward a suggestion to boost for
|
||||||
a new design of smart pointer whereby an intrusive doubly linked list is used
|
a new design of smart pointer whereby an intrusive doubly linked list is used
|
||||||
@@ -19,9 +21,10 @@ Pointers Timings </h1>
|
|||||||
mailing list and the tests which this page describes were performed to provide
|
mailing list and the tests which this page describes were performed to provide
|
||||||
a guide for current and future investigations into smart pointer implementation
|
a guide for current and future investigations into smart pointer implementation
|
||||||
strategies.</p>
|
strategies.</p>
|
||||||
<p>Thanks are due to <a href="../../people/dave_abrahams.htm"> Dave Abrahams</a>,
|
<p>Thanks are due to <a href="http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a>,
|
||||||
<a href="../../people/gavin_collings.htm"> Gavin Collings</a>, <a href="../../people/greg_colvin.htm"> Greg Colvin</a> and
|
Gavin Collings,
|
||||||
<a href="../../people/beman_dawes.html"> Beman Dawes</a>
|
<a href="http://www.boost.org/people/greg_colvin.htm">Greg Colvin</a> and
|
||||||
|
<a href="http://www.boost.org/people/beman_dawes.html">Beman Dawes</a>
|
||||||
for test code and trial implementations, the final version of which can be found
|
for test code and trial implementations, the final version of which can be found
|
||||||
in .zip format <a href="smarttest.zip">here</a>.</p>
|
in .zip format <a href="smarttest.zip">here</a>.</p>
|
||||||
<h2>Description</h2>
|
<h2>Description</h2>
|
||||||
@@ -75,7 +78,7 @@ Pointers Timings </h1>
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td width="20"> </td>
|
<td width="20"> </td>
|
||||||
<td><img src="msvcspeed.gif" width="560" height="355"></td>
|
<td><img src="msvcspeed.gif" width="560" height="355" alt="MSVC speed graph"></td>
|
||||||
<td width="20"> </td>
|
<td width="20"> </td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -85,7 +88,7 @@ Pointers Timings </h1>
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td> </td>
|
<td> </td>
|
||||||
<td><img src="gccspeed.gif" width="560" height="355"></td>
|
<td><img src="gccspeed.gif" width="560" height="355" alt="GCC speed graph"></td>
|
||||||
<td> </td>
|
<td> </td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -530,7 +533,7 @@ Pointers Timings </h1>
|
|||||||
spreads its information as in the case of linked pointer.</li>
|
spreads its information as in the case of linked pointer.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<hr>
|
<hr>
|
||||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %b %Y" startspan -->21 Feb 2000<!--webbot bot="Timestamp" endspan i-checksum="14372" -->
|
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->19 August 2001<!--webbot bot="Timestamp" endspan i-checksum="14767" -->
|
||||||
</p>
|
</p>
|
||||||
<p><EFBFBD> Copyright Gavin Collings 2000. Permission to copy, use, modify, sell
|
<p><EFBFBD> Copyright Gavin Collings 2000. Permission to copy, use, modify, sell
|
||||||
and distribute this document is granted provided this copyright notice appears in all
|
and distribute this document is granted provided this copyright notice appears in all
|
||||||
|
|||||||
765
sp_techniques.html
Normal file
765
sp_techniques.html
Normal file
@@ -0,0 +1,765 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Smart Pointer Programming Techniques</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
</head>
|
||||||
|
<body text="#000000" bgColor="#ffffff">
|
||||||
|
<h1><A href="../../index.htm"><IMG height="86" alt="boost.png (6897 bytes)" src="../../boost.png" width="277" align="middle"
|
||||||
|
border="0"></A>Smart Pointer Programming Techniques</h1>
|
||||||
|
<p><A href="#incomplete">Using incomplete classes for implementation hiding</A><br>
|
||||||
|
<A href="#pimpl">The "Pimpl" idiom</A><br>
|
||||||
|
<A href="#abstract">Using abstract classes for implementation hiding</A><br>
|
||||||
|
<A href="#preventing_delete">Preventing <code>delete px.get()</code></A><br>
|
||||||
|
<A href="#array">Using a <code>shared_ptr</code> to hold a pointer to an array</A><br>
|
||||||
|
<A href="#encapsulation">Encapsulating allocation details, wrapping factory
|
||||||
|
functions</A><br>
|
||||||
|
<A href="#static">Using a <code>shared_ptr</code> to hold a pointer to a statically
|
||||||
|
allocated object</A><br>
|
||||||
|
<A href="#com">Using a <code>shared_ptr</code> to hold a pointer to a COM object</A><br>
|
||||||
|
<A href="#intrusive">Using a <code>shared_ptr</code> to hold a pointer to an object
|
||||||
|
with an embedded reference count</A><br>
|
||||||
|
<A href="#another_sp">Using a <code>shared_ptr</code> to hold another shared
|
||||||
|
ownership smart pointer</A><br>
|
||||||
|
<A href="#from_raw">Obtaining a <code>shared_ptr</code> from a raw pointer</A><br>
|
||||||
|
<A href="#in_constructor">Obtaining a <code>shared_ptr</code> (<code>weak_ptr</code>)
|
||||||
|
to <code>this</code> in a constructor</A><br>
|
||||||
|
<A href="#from_this">Obtaining a <code>shared_ptr</code> to <code>this</code></A><br>
|
||||||
|
<A href="#handle">Using <code>shared_ptr</code> as a smart counted handle</A><br>
|
||||||
|
<A href="#on_block_exit">Using <code>shared_ptr</code> to execute code on block
|
||||||
|
exit</A><br>
|
||||||
|
<A href="#pvoid">Using <code>shared_ptr<void></code> to hold an arbitrary
|
||||||
|
object</A><br>
|
||||||
|
<A href="#extra_data">Associating arbitrary data with heterogeneous <code>shared_ptr</code>
|
||||||
|
instances</A><br>
|
||||||
|
<A href="#as_lock">Using <code>shared_ptr</code> as a CopyConstructible mutex lock</A><br>
|
||||||
|
<A href="#wrapper">Using <code>shared_ptr</code> to wrap member function calls</A><br>
|
||||||
|
<A href="#delayed">Delayed deallocation</A><br>
|
||||||
|
<A href="#weak_without_shared">Weak pointers to objects not managed by a <code>shared_ptr</code></A><br>
|
||||||
|
</p>
|
||||||
|
<h2><A name="incomplete">Using incomplete classes for implementation hiding</A></h2>
|
||||||
|
<p>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:</p>
|
||||||
|
<pre>class FILE;
|
||||||
|
|
||||||
|
FILE * fopen(char const * name, char const * mode);
|
||||||
|
void fread(FILE * f, void * data, size_t size);
|
||||||
|
void fclose(FILE * f);
|
||||||
|
</pre>
|
||||||
|
<p>It is possible to express the above interface using <code>shared_ptr</code>,
|
||||||
|
eliminating the need to manually call <code>fclose</code>:</p>
|
||||||
|
<pre>class FILE;
|
||||||
|
|
||||||
|
shared_ptr<FILE> fopen(char const * name, char const * mode);
|
||||||
|
void fread(shared_ptr<FILE> f, void * data, size_t size);
|
||||||
|
</pre>
|
||||||
|
<p>This technique relies on <code>shared_ptr</code>'s ability to execute a custom
|
||||||
|
deleter, eliminating the explicit call to <code>fclose</code>, and on the fact
|
||||||
|
that <code>shared_ptr<X></code> can be copied and destroyed when <code>X</code>
|
||||||
|
is incomplete.</p>
|
||||||
|
<h2><A name="pimpl">The "Pimpl" idiom</A></h2>
|
||||||
|
<p>A C++ 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. <code>shared_ptr</code> can be used to implement a "Pimpl":</p>
|
||||||
|
<pre>// 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);
|
||||||
|
};
|
||||||
|
</pre>
|
||||||
|
<pre>// 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);
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
<p>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, <code>
|
||||||
|
file</code> is <code>CopyConstructible</code> and <code>Assignable</code>,
|
||||||
|
allowing its use in standard containers.</p>
|
||||||
|
<h2><A name="abstract">Using abstract classes for implementation hiding</A></h2>
|
||||||
|
<p>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, <code>shared_ptr</code> can be used as the return type of
|
||||||
|
the factory functions:</p>
|
||||||
|
<pre>// X.hpp:
|
||||||
|
|
||||||
|
class X
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void f() = 0;
|
||||||
|
virtual void g() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
~X() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
shared_ptr<X> createX();
|
||||||
|
</pre>
|
||||||
|
<pre>-- 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;
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
<p>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 <code>X</code>;
|
||||||
|
the <code>shared_ptr<X></code> instance returned from <code>createX</code>
|
||||||
|
will correctly call <code>~X_impl</code>.</p>
|
||||||
|
<h2><A name="preventing_delete">Preventing <code>delete px.get()</code></A></h2>
|
||||||
|
<p>It is often desirable to prevent client code from deleting a pointer that is
|
||||||
|
being managed by <code>shared_ptr</code>. The previous technique showed one
|
||||||
|
possible approach, using a protected destructor. Another alternative is to use
|
||||||
|
a private deleter:</p>
|
||||||
|
<pre>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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</pre>
|
||||||
|
<h2><A name="array">Using a <code>shared_ptr</code> to hold a pointer to an array</A></h2>
|
||||||
|
<p>A <code>shared_ptr</code> can be used to hold a pointer to an array allocated
|
||||||
|
with <code>new[]</code>:</p>
|
||||||
|
<pre>shared_ptr<X> px(new X[1], <A href="../utility/checked_delete.html" >checked_array_deleter</A><X>());
|
||||||
|
</pre>
|
||||||
|
<p>Note, however, that <code><A href="shared_array.htm">shared_array</A></code> is
|
||||||
|
often preferable, if this is an option. It has an array-specific interface,
|
||||||
|
without <code>operator*</code> and <code>operator-></code>, and does not
|
||||||
|
allow pointer conversions.</p>
|
||||||
|
<h2><A name="encapsulation">Encapsulating allocation details, wrapping factory
|
||||||
|
functions</A></h2>
|
||||||
|
<p><code>shared_ptr</code> can be used in creating C++ 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 <code>CreateX</code> might allocate <code>X</code> from its own private
|
||||||
|
heap, <code>~X</code> may be inaccessible, or <code>X</code> may be incomplete:</p>
|
||||||
|
<pre>X * CreateX();
|
||||||
|
void DestroyX(X *);
|
||||||
|
</pre>
|
||||||
|
<p>The only way to reliably destroy a pointer returned by <code>CreateX</code> is
|
||||||
|
to call <code>DestroyX</code>.</p>
|
||||||
|
<P>Here is how a <code>shared_ptr</code>-based wrapper may look like:</P>
|
||||||
|
<pre>shared_ptr<X> createX()
|
||||||
|
{
|
||||||
|
shared_ptr<X> px(CreateX(), DestroyX);
|
||||||
|
return px;
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
<p>Client code that calls <code>createX</code> still does not need to know how the
|
||||||
|
object has been allocated, but now the destruction is automatic.</p>
|
||||||
|
<h2><A name="static">Using a <code>shared_ptr</code> to hold a pointer to a statically
|
||||||
|
allocated object</A></h2>
|
||||||
|
<p>Sometimes it is desirable to create a <code>shared_ptr</code> to an already
|
||||||
|
existing object, so that the <code>shared_ptr</code> does not attempt to
|
||||||
|
destroy the object when there are no more references left. As an example, the
|
||||||
|
factory function:</p>
|
||||||
|
<pre>shared_ptr<X> createX();
|
||||||
|
</pre>
|
||||||
|
<p>in certain situations may need to return a pointer to a statically allocated <code>X</code>
|
||||||
|
instance.</p>
|
||||||
|
<P>The solution is to use a custom deleter that does nothing:</P>
|
||||||
|
<pre>struct null_deleter
|
||||||
|
{
|
||||||
|
void operator()(void const *) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static X x;
|
||||||
|
|
||||||
|
shared_ptr<X> createX()
|
||||||
|
{
|
||||||
|
shared_ptr<X> px(&x, null_deleter());
|
||||||
|
return px;
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
<p>The same technique works for any object known to outlive the pointer.</p>
|
||||||
|
<h2><A name="com">Using a <code>shared_ptr</code> to hold a pointer to a COM Object</A></h2>
|
||||||
|
<p>Background: COM objects have an embedded reference count and two member
|
||||||
|
functions that manipulate it. <code>AddRef()</code> increments the count. <code>Release()</code>
|
||||||
|
decrements the count and destroys itself when the count drops to zero.</p>
|
||||||
|
<P>It is possible to hold a pointer to a COM object in a <code>shared_ptr</code>:</P>
|
||||||
|
<pre>shared_ptr<IWhatever> make_shared_from_COM(IWhatever * p)
|
||||||
|
{
|
||||||
|
p->AddRef();
|
||||||
|
shared_ptr<IWhatever> pw(p, <A href="../bind/mem_fn.html" >mem_fn</A>(&IWhatever::Release));
|
||||||
|
return pw;
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
<p>Note, however, that <code>shared_ptr</code> copies created from <code>pw</code> will
|
||||||
|
not "register" in the embedded count of the COM object; they will share the
|
||||||
|
single reference created in <code>make_shared_from_COM</code>. Weak pointers
|
||||||
|
created from <code>pw</code> will be invalidated when the last <code>shared_ptr</code>
|
||||||
|
is destroyed, regardless of whether the COM object itself is still alive.</p>
|
||||||
|
<P>As <A href="../bind/mem_fn.html#Q3">explained</A> in the <code>mem_fn</code> documentation,
|
||||||
|
you need to <A href="../bind/mem_fn.html#stdcall">#define
|
||||||
|
BOOST_MEM_FN_ENABLE_STDCALL</A> first.</P>
|
||||||
|
<h2><A name="intrusive">Using a <code>shared_ptr</code> to hold a pointer to an object
|
||||||
|
with an embedded reference count</A></h2>
|
||||||
|
<p>This is a generalization of the above technique. The example assumes that the
|
||||||
|
object implements the two functions required by <code><A href="intrusive_ptr.html">intrusive_ptr</A></code>,
|
||||||
|
<code>intrusive_ptr_add_ref</code> and <code>intrusive_ptr_release</code>:</p>
|
||||||
|
<pre>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;
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
<h2><A name="another_sp">Using a <code>shared_ptr</code> to hold another shared
|
||||||
|
ownership smart pointer</A></h2>
|
||||||
|
<p>One of the design goals of <code>shared_ptr</code> is to be used in library
|
||||||
|
interfaces. It is possible to encounter a situation where a library takes a <code>shared_ptr</code>
|
||||||
|
argument, but the object at hand is being managed by a different reference
|
||||||
|
counted or linked smart pointer.</p>
|
||||||
|
<P>It is possible to exploit <code>shared_ptr</code>'s custom deleter feature to
|
||||||
|
wrap this existing smart pointer behind a <code>shared_ptr</code> facade:</P>
|
||||||
|
<pre>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;
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
<p>One subtle point is that deleters are not allowed to throw exceptions, and the
|
||||||
|
above example as written assumes that <code>p_.reset()</code> doesn't throw. If
|
||||||
|
this is not the case, <code>p_.reset()</code> should be wrapped in a <code>try {}
|
||||||
|
catch(...) {}</code> block that ignores exceptions. In the (usually
|
||||||
|
unlikely) event when an exception is thrown and ignored, <code>p_</code> will
|
||||||
|
be released when the lifetime of the deleter ends. This happens when all
|
||||||
|
references, including weak pointers, are destroyed or reset.</p>
|
||||||
|
<P>Another twist is that it is possible, given the above <code>shared_ptr</code> instance,
|
||||||
|
to recover the original smart pointer, using <code><A href="shared_ptr.htm#get_deleter">
|
||||||
|
get_deleter</A></code>:</P>
|
||||||
|
<pre>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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
<h2><A name="from_raw">Obtaining a <code>shared_ptr</code> from a raw pointer</A></h2>
|
||||||
|
<p>Sometimes it is necessary to obtain a <code>shared_ptr</code> given a raw
|
||||||
|
pointer to an object that is already managed by another <code>shared_ptr</code>
|
||||||
|
instance. Example:</p>
|
||||||
|
<pre>void f(X * p)
|
||||||
|
{
|
||||||
|
shared_ptr<X> px(<i>???</i>);
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
<p>Inside <code>f</code>, we'd like to create a <code>shared_ptr</code> to <code>*p</code>.</p>
|
||||||
|
<P>In the general case, this problem has no solution. One approach is to modify <code>f</code>
|
||||||
|
to take a <code>shared_ptr</code>, if possible:</P>
|
||||||
|
<pre>void f(shared_ptr<X> px);
|
||||||
|
</pre>
|
||||||
|
<p>The same transformation can be used for nonvirtual member functions, to convert
|
||||||
|
the implicit <code>this</code>:</p>
|
||||||
|
<pre>void X::f(int m);
|
||||||
|
</pre>
|
||||||
|
<p>would become a free function with a <code>shared_ptr</code> first argument:</p>
|
||||||
|
<pre>void f(shared_ptr<X> this_, int m);
|
||||||
|
</pre>
|
||||||
|
<p>If <code>f</code> cannot be changed, but <code>X</code> uses intrusive counting,
|
||||||
|
use <code><A href="#intrusive">make_shared_from_intrusive</A></code> described
|
||||||
|
above. Or, if it's known that the <code>shared_ptr</code> created in <code>f</code>
|
||||||
|
will never outlive the object, use <A href="#static">a null deleter</A>.</p>
|
||||||
|
<h2><A name="in_constructor">Obtaining a <code>shared_ptr</code> (<code>weak_ptr</code>)
|
||||||
|
to <code>this</code> in a constructor</A></h2>
|
||||||
|
<p>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:</p>
|
||||||
|
<pre>class X
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
X()
|
||||||
|
{
|
||||||
|
shared_ptr<X> this_(<i>???</i>);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</pre>
|
||||||
|
<p>In the general case, the problem cannot be solved. The <code>X</code> instance
|
||||||
|
being constructed can be an automatic variable or a static variable; it can be
|
||||||
|
created on the heap:</p>
|
||||||
|
<pre>shared_ptr<X> px(new X);</pre>
|
||||||
|
<P>but at construction time, <code>px</code> does not exist yet, and it is
|
||||||
|
impossible to create another <code>shared_ptr</code> instance that shares
|
||||||
|
ownership with it.</P>
|
||||||
|
<P>Depending on context, if the inner <code>shared_ptr</code> <code>this_</code> doesn't
|
||||||
|
need to keep the object alive, use a <code>null_deleter</code> as explained <A href="#static">
|
||||||
|
here</A> and <A href="#weak_without_shared">here</A>. If <code>X</code> is
|
||||||
|
supposed to always live on the heap, and be managed by a <code>shared_ptr</code>,
|
||||||
|
use a static factory function:</P>
|
||||||
|
<pre>class X
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
X() { ... }
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
static shared_ptr<X> create()
|
||||||
|
{
|
||||||
|
shared_ptr<X> px(new X);
|
||||||
|
// use px as 'this_'
|
||||||
|
return px;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</pre>
|
||||||
|
<h2><A name="from_this">Obtaining a <code>shared_ptr</code> to <code>this</code></A></h2>
|
||||||
|
<p>Sometimes it is needed to obtain a <code>shared_ptr</code> from <code>this</code>
|
||||||
|
in a virtual member function under the assumption that <code>this</code> is
|
||||||
|
already managed by a <code>shared_ptr</code>. The transformations <A href="#from_raw">
|
||||||
|
described in the previous technique</A> cannot be applied.</p>
|
||||||
|
<P>A typical example:</P>
|
||||||
|
<pre>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(<i>???</i>);
|
||||||
|
return px;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</pre>
|
||||||
|
<p>The solution is to keep a weak pointer to <code>this</code> as a member in <code>impl</code>:</p>
|
||||||
|
<pre>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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</pre>
|
||||||
|
<p>The library now includes a helper class template <code><A href="enable_shared_from_this.html">
|
||||||
|
enable_shared_from_this</A></code> that can be used to encapsulate the
|
||||||
|
solution:</p>
|
||||||
|
<pre>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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
<p>Note that you no longer need to manually initialize the <code>weak_ptr</code> member
|
||||||
|
in <code><A href="enable_shared_from_this.html">enable_shared_from_this</A></code>.
|
||||||
|
Constructing a <code>shared_ptr</code> to <code>impl</code> takes care of that.</p>
|
||||||
|
<h2><A name="handle">Using <code>shared_ptr</code> as a smart counted handle</A></h2>
|
||||||
|
<p>Some library interfaces use opaque handles, a variation of the <A href="#incomplete">
|
||||||
|
incomplete class technique</A> described above. An example:</p>
|
||||||
|
<pre>typedef void * HANDLE;
|
||||||
|
HANDLE CreateProcess();
|
||||||
|
void CloseHandle(HANDLE);
|
||||||
|
</pre>
|
||||||
|
<p>Instead of a raw pointer, it is possible to use <code>shared_ptr</code> as the
|
||||||
|
handle and get reference counting and automatic resource management for free:</p>
|
||||||
|
<pre>typedef shared_ptr<void> handle;
|
||||||
|
|
||||||
|
handle createProcess()
|
||||||
|
{
|
||||||
|
shared_ptr<void> pv(CreateProcess(), CloseHandle);
|
||||||
|
return pv;
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
<h2><A name="on_block_exit">Using <code>shared_ptr</code> to execute code on block exit</A></h2>
|
||||||
|
<p><code>shared_ptr<void></code> can automatically execute cleanup code when
|
||||||
|
control leaves a scope.</p>
|
||||||
|
<UL>
|
||||||
|
<LI>
|
||||||
|
Executing <code>f(p)</code>, where <code>p</code> is a pointer:</LI></UL>
|
||||||
|
<pre> shared_ptr<void> guard(p, f);
|
||||||
|
</pre>
|
||||||
|
<UL>
|
||||||
|
<LI>
|
||||||
|
Executing arbitrary code: <code>f(x, y)</code>:</LI></UL>
|
||||||
|
<pre> shared_ptr<void> guard(static_cast<void*>(0), <A href="../bind/bind.html" >bind</A>(f, x, y));
|
||||||
|
</pre>
|
||||||
|
<P>For a more thorough treatment, see the article "Simplify Your Exception-Safe
|
||||||
|
Code" by Andrei Alexandrescu and Petru Marginean, available online at <A href="http://www.cuj.com/experts/1812/alexandr.htm?topic=experts">
|
||||||
|
http://www.cuj.com/experts/1812/alexandr.htm?topic=experts</A>.</P>
|
||||||
|
<h2><A name="pvoid">Using <code>shared_ptr<void></code> to hold an arbitrary
|
||||||
|
object</A></h2>
|
||||||
|
<p><code>shared_ptr<void></code> can act as a generic object pointer similar
|
||||||
|
to <code>void*</code>. When a <code>shared_ptr<void></code> instance
|
||||||
|
constructed as:</p>
|
||||||
|
<pre> shared_ptr<void> pv(new X);
|
||||||
|
</pre>
|
||||||
|
<p>is destroyed, it will correctly dispose of the <code>X</code> object by
|
||||||
|
executing <code>~X</code>.</p>
|
||||||
|
<p>This propery can be used in much the same manner as a raw <code>void*</code> is
|
||||||
|
used to temporarily strip type information from an object pointer. A <code>shared_ptr<void></code>
|
||||||
|
can later be cast back to the correct type by using <code><A href="shared_ptr.htm#static_pointer_cast">
|
||||||
|
static_pointer_cast</A></code>.</p>
|
||||||
|
<h2><A name="extra_data">Associating arbitrary data with heterogeneous <code>shared_ptr</code>
|
||||||
|
instances</A></h2>
|
||||||
|
<p><code>shared_ptr</code> and <code>weak_ptr</code> support <code>operator<</code>
|
||||||
|
comparisons required by standard associative containers such as <code>std::map</code>.
|
||||||
|
This can be used to non-intrusively associate arbitrary data with objects
|
||||||
|
managed by <code>shared_ptr</code>:</p>
|
||||||
|
<pre>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;
|
||||||
|
</pre>
|
||||||
|
<h2><A name="as_lock">Using <code>shared_ptr</code> as a CopyConstructible mutex lock</A></h2>
|
||||||
|
<p>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 <code>shared_ptr</code>
|
||||||
|
as a mutex lock:</p>
|
||||||
|
<pre>class mutex
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
void lock();
|
||||||
|
void unlock();
|
||||||
|
};
|
||||||
|
|
||||||
|
shared_ptr<mutex> lock(mutex & m)
|
||||||
|
{
|
||||||
|
m.lock();
|
||||||
|
return shared_ptr<mutex>(&m, mem_fn(&mutex::unlock));
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
<p>Better yet, the <code>shared_ptr</code> instance acting as a lock can be
|
||||||
|
encapsulated in a dedicated <code>shared_lock</code> class:</p>
|
||||||
|
<pre>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)) {}
|
||||||
|
};
|
||||||
|
</pre>
|
||||||
|
<p><code>shared_lock</code> can now be used as:</p>
|
||||||
|
<pre> shared_lock lock(m);
|
||||||
|
</pre>
|
||||||
|
<p>Note that <code>shared_lock</code> is not templated on the mutex type, thanks to <code>
|
||||||
|
shared_ptr<void></code>'s ability to hide type information.</p>
|
||||||
|
<h2><A name="wrapper">Using <code>shared_ptr</code> to wrap member function calls</A></h2>
|
||||||
|
<p><code>shared_ptr</code> implements the ownership semantics required from the <code>Wrap</code>/<code>CallProxy</code>
|
||||||
|
scheme described in Bjarne Stroustrup's article "Wrapping C++ Member Function
|
||||||
|
Calls" (available online at <A href="http://www.research.att.com/~bs/wrapper.pdf">http://www.research.att.com/~bs/wrapper.pdf</A>).
|
||||||
|
An implementation is given below:</p>
|
||||||
|
<pre>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_, <A href="../bind/mem_fn.html" >mem_fn</A>(&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();
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
<h2><A name="delayed">Delayed deallocation</A></h2>
|
||||||
|
<p>In some situations, a single <code>px.reset()</code> can trigger an expensive
|
||||||
|
deallocation in a performance-critical region:</p>
|
||||||
|
<pre>class X; // ~X is expensive
|
||||||
|
|
||||||
|
class Y
|
||||||
|
{
|
||||||
|
shared_ptr<X> px;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void f()
|
||||||
|
{
|
||||||
|
px.reset();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</pre>
|
||||||
|
<p>The solution is to postpone the potential deallocation by moving <code>px</code>
|
||||||
|
to a dedicated free list that can be periodically emptied when performance and
|
||||||
|
response times are not an issue:</p>
|
||||||
|
<pre>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
|
||||||
|
</pre>
|
||||||
|
<p>Another variation is to move the free list logic to the construction point by
|
||||||
|
using a delayed deleter:</p>
|
||||||
|
<pre>struct delayed_deleter
|
||||||
|
{
|
||||||
|
template<class T> void operator()(T * p)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
shared_ptr<void> pv(p);
|
||||||
|
free_list.push_back(pv);
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</pre>
|
||||||
|
<h2><A name="weak_without_shared">Weak pointers to objects not managed by a <code>shared_ptr</code></A></h2>
|
||||||
|
<p>Make the object hold a <code>shared_ptr</code> to itself, using a <code>null_deleter</code>:</p>
|
||||||
|
<pre>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_; }
|
||||||
|
};
|
||||||
|
</pre>
|
||||||
|
<p>When the object's lifetime ends, <code>X::this_</code> will be destroyed, and
|
||||||
|
all weak pointers will automatically expire.</p>
|
||||||
|
<hr>
|
||||||
|
<p>$Date$</p>
|
||||||
|
<p><small>Copyright <20> 2003 Peter Dimov. Distributed under the Boost Software License, Version
|
||||||
|
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
|
||||||
|
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
270
src/sp_collector.cpp
Normal file
270
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
src/sp_debug_hooks.cpp
Normal file
243
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)
|
||||||
67
test/Jamfile.v2
Normal file
67
test/Jamfile.v2
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
# Boost.SmartPtr Library test Jamfile
|
||||||
|
#
|
||||||
|
# Copyright (c) 2003-2007 Peter Dimov
|
||||||
|
# Copyright (c) 2003 Dave Abrahams
|
||||||
|
#
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
# bring in rules for testing
|
||||||
|
import testing ;
|
||||||
|
|
||||||
|
{
|
||||||
|
test-suite "smart_ptr"
|
||||||
|
: [ run smart_ptr_test.cpp ]
|
||||||
|
[ run shared_ptr_basic_test.cpp : : : <toolset>gcc:<cxxflags>-Wno-non-virtual-dtor ]
|
||||||
|
[ run shared_ptr_test.cpp : : : <toolset>gcc:<cxxflags>-Wno-non-virtual-dtor ]
|
||||||
|
[ run weak_ptr_test.cpp ]
|
||||||
|
[ run weak_ptr_move_test.cpp ]
|
||||||
|
[ run shared_from_this_test.cpp : : : <toolset>gcc:<cxxflags>-Wno-non-virtual-dtor ]
|
||||||
|
[ run get_deleter_test.cpp ]
|
||||||
|
[ run intrusive_ptr_test.cpp ]
|
||||||
|
[ run intrusive_ptr_move_test.cpp ]
|
||||||
|
[ run atomic_count_test.cpp ]
|
||||||
|
[ run lw_mutex_test.cpp ]
|
||||||
|
[ compile-fail shared_ptr_assign_fail.cpp ]
|
||||||
|
[ compile-fail shared_ptr_delete_fail.cpp ]
|
||||||
|
[ compile-fail shared_ptr_compare_fail.cpp ]
|
||||||
|
[ run shared_ptr_alloc2_test.cpp ]
|
||||||
|
[ run pointer_cast_test.cpp ]
|
||||||
|
[ compile pointer_to_other_test.cpp ]
|
||||||
|
[ run auto_ptr_rv_test.cpp ]
|
||||||
|
[ run shared_ptr_alias_test.cpp ]
|
||||||
|
[ run shared_ptr_rv_test.cpp ]
|
||||||
|
[ run shared_ptr_move_test.cpp ]
|
||||||
|
[ compile-fail shared_ptr_pv_fail.cpp ]
|
||||||
|
[ run sp_unary_addr_test.cpp ]
|
||||||
|
[ compile-fail scoped_ptr_eq_fail.cpp ]
|
||||||
|
[ compile-fail scoped_array_eq_fail.cpp ]
|
||||||
|
[ run esft_regtest.cpp ]
|
||||||
|
[ run yield_k_test.cpp ]
|
||||||
|
[ run yield_k_test.cpp : : : <threading>multi : yield_k_test.mt ]
|
||||||
|
[ run spinlock_test.cpp ]
|
||||||
|
[ run spinlock_try_test.cpp ]
|
||||||
|
[ run spinlock_try_test.cpp : : : <threading>multi : spinlock_try_test.mt ]
|
||||||
|
[ run spinlock_pool_test.cpp ]
|
||||||
|
[ run make_shared_test.cpp ]
|
||||||
|
[ run make_shared_perfect_forwarding_test.cpp ]
|
||||||
|
[ run sp_convertible_test.cpp ]
|
||||||
|
[ run wp_convertible_test.cpp ]
|
||||||
|
[ run ip_convertible_test.cpp ]
|
||||||
|
[ run allocate_shared_test.cpp ]
|
||||||
|
[ run sp_atomic_test.cpp ]
|
||||||
|
[ run esft_void_test.cpp ]
|
||||||
|
[ run esft_second_ptr_test.cpp ]
|
||||||
|
[ run make_shared_esft_test.cpp ]
|
||||||
|
[ run allocate_shared_esft_test.cpp ]
|
||||||
|
[ run sp_recursive_assign_test.cpp ]
|
||||||
|
[ run sp_recursive_assign2_test.cpp ]
|
||||||
|
[ run sp_recursive_assign_rv_test.cpp ]
|
||||||
|
[ run sp_recursive_assign2_rv_test.cpp ]
|
||||||
|
[ run esft_constructor_test.cpp ]
|
||||||
|
[ compile-fail auto_ptr_lv_fail.cpp ]
|
||||||
|
[ run atomic_count_test2.cpp ]
|
||||||
|
[ run sp_typeinfo_test.cpp ]
|
||||||
|
;
|
||||||
|
}
|
||||||
264
test/allocate_shared_esft_test.cpp
Normal file
264
test/allocate_shared_esft_test.cpp
Normal file
@@ -0,0 +1,264 @@
|
|||||||
|
// allocate_shared_esft_test.cpp
|
||||||
|
//
|
||||||
|
// Copyright 2007-2009 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/detail/lightweight_test.hpp>
|
||||||
|
#include <boost/make_shared.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <boost/enable_shared_from_this.hpp>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class X: public boost::enable_shared_from_this<X>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
X( X const & );
|
||||||
|
X & operator=( X const & );
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
static int instances;
|
||||||
|
|
||||||
|
explicit X( int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0 )
|
||||||
|
{
|
||||||
|
++instances;
|
||||||
|
}
|
||||||
|
|
||||||
|
~X()
|
||||||
|
{
|
||||||
|
--instances;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int X::instances = 0;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
BOOST_TEST( X::instances == 0 );
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>() );
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
boost::shared_ptr< X > qx = px->shared_from_this();
|
||||||
|
|
||||||
|
BOOST_TEST( px == qx );
|
||||||
|
BOOST_TEST( !( px < qx ) && !( qx < px ) );
|
||||||
|
|
||||||
|
px.reset();
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
}
|
||||||
|
catch( boost::bad_weak_ptr const& )
|
||||||
|
{
|
||||||
|
BOOST_ERROR( "px->shared_from_this() failed" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 0 );
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1 );
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
boost::shared_ptr< X > qx = px->shared_from_this();
|
||||||
|
|
||||||
|
BOOST_TEST( px == qx );
|
||||||
|
BOOST_TEST( !( px < qx ) && !( qx < px ) );
|
||||||
|
|
||||||
|
px.reset();
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
}
|
||||||
|
catch( boost::bad_weak_ptr const& )
|
||||||
|
{
|
||||||
|
BOOST_ERROR( "px->shared_from_this() failed" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 0 );
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2 );
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
boost::shared_ptr< X > qx = px->shared_from_this();
|
||||||
|
|
||||||
|
BOOST_TEST( px == qx );
|
||||||
|
BOOST_TEST( !( px < qx ) && !( qx < px ) );
|
||||||
|
|
||||||
|
px.reset();
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
}
|
||||||
|
catch( boost::bad_weak_ptr const& )
|
||||||
|
{
|
||||||
|
BOOST_ERROR( "px->shared_from_this() failed" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 0 );
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3 );
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
boost::shared_ptr< X > qx = px->shared_from_this();
|
||||||
|
|
||||||
|
BOOST_TEST( px == qx );
|
||||||
|
BOOST_TEST( !( px < qx ) && !( qx < px ) );
|
||||||
|
|
||||||
|
px.reset();
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
}
|
||||||
|
catch( boost::bad_weak_ptr const& )
|
||||||
|
{
|
||||||
|
BOOST_ERROR( "px->shared_from_this() failed" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 0 );
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4 );
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
boost::shared_ptr< X > qx = px->shared_from_this();
|
||||||
|
|
||||||
|
BOOST_TEST( px == qx );
|
||||||
|
BOOST_TEST( !( px < qx ) && !( qx < px ) );
|
||||||
|
|
||||||
|
px.reset();
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
}
|
||||||
|
catch( boost::bad_weak_ptr const& )
|
||||||
|
{
|
||||||
|
BOOST_ERROR( "px->shared_from_this() failed" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 0 );
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5 );
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
boost::shared_ptr< X > qx = px->shared_from_this();
|
||||||
|
|
||||||
|
BOOST_TEST( px == qx );
|
||||||
|
BOOST_TEST( !( px < qx ) && !( qx < px ) );
|
||||||
|
|
||||||
|
px.reset();
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
}
|
||||||
|
catch( boost::bad_weak_ptr const& )
|
||||||
|
{
|
||||||
|
BOOST_ERROR( "px->shared_from_this() failed" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 0 );
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6 );
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
boost::shared_ptr< X > qx = px->shared_from_this();
|
||||||
|
|
||||||
|
BOOST_TEST( px == qx );
|
||||||
|
BOOST_TEST( !( px < qx ) && !( qx < px ) );
|
||||||
|
|
||||||
|
px.reset();
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
}
|
||||||
|
catch( boost::bad_weak_ptr const& )
|
||||||
|
{
|
||||||
|
BOOST_ERROR( "px->shared_from_this() failed" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 0 );
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7 );
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
boost::shared_ptr< X > qx = px->shared_from_this();
|
||||||
|
|
||||||
|
BOOST_TEST( px == qx );
|
||||||
|
BOOST_TEST( !( px < qx ) && !( qx < px ) );
|
||||||
|
|
||||||
|
px.reset();
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
}
|
||||||
|
catch( boost::bad_weak_ptr const& )
|
||||||
|
{
|
||||||
|
BOOST_ERROR( "px->shared_from_this() failed" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 0 );
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8 );
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
boost::shared_ptr< X > qx = px->shared_from_this();
|
||||||
|
|
||||||
|
BOOST_TEST( px == qx );
|
||||||
|
BOOST_TEST( !( px < qx ) && !( qx < px ) );
|
||||||
|
|
||||||
|
px.reset();
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
}
|
||||||
|
catch( boost::bad_weak_ptr const& )
|
||||||
|
{
|
||||||
|
BOOST_ERROR( "px->shared_from_this() failed" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 0 );
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8, 9 );
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
boost::shared_ptr< X > qx = px->shared_from_this();
|
||||||
|
|
||||||
|
BOOST_TEST( px == qx );
|
||||||
|
BOOST_TEST( !( px < qx ) && !( qx < px ) );
|
||||||
|
|
||||||
|
px.reset();
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
}
|
||||||
|
catch( boost::bad_weak_ptr const& )
|
||||||
|
{
|
||||||
|
BOOST_ERROR( "px->shared_from_this() failed" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 0 );
|
||||||
|
|
||||||
|
return boost::report_errors();
|
||||||
|
}
|
||||||
204
test/allocate_shared_test.cpp
Normal file
204
test/allocate_shared_test.cpp
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
// allocate_shared_test.cpp
|
||||||
|
//
|
||||||
|
// Copyright 2007-2009 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/detail/lightweight_test.hpp>
|
||||||
|
#include <boost/make_shared.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <boost/weak_ptr.hpp>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
class X
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
X( X const & );
|
||||||
|
X & operator=( X const & );
|
||||||
|
|
||||||
|
void * operator new( std::size_t n )
|
||||||
|
{
|
||||||
|
// lack of this definition causes link errors on Comeau C++
|
||||||
|
BOOST_ERROR( "private X::new called" );
|
||||||
|
return ::operator new( n );
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete( void * p )
|
||||||
|
{
|
||||||
|
// lack of this definition causes link errors on MSVC
|
||||||
|
BOOST_ERROR( "private X::delete called" );
|
||||||
|
::operator delete( p );
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
static int instances;
|
||||||
|
|
||||||
|
int v;
|
||||||
|
|
||||||
|
explicit X( int a1 = 0, int a2 = 0, int a3 = 0, int a4 = 0, int a5 = 0, int a6 = 0, int a7 = 0, int a8 = 0, int a9 = 0 ): v( a1+a2+a3+a4+a5+a6+a7+a8+a9 )
|
||||||
|
{
|
||||||
|
++instances;
|
||||||
|
}
|
||||||
|
|
||||||
|
~X()
|
||||||
|
{
|
||||||
|
--instances;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int X::instances = 0;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
boost::shared_ptr< int > pi = boost::allocate_shared< int >( std::allocator<int>() );
|
||||||
|
|
||||||
|
BOOST_TEST( pi.get() != 0 );
|
||||||
|
BOOST_TEST( *pi == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::shared_ptr< int > pi = boost::allocate_shared< int >( std::allocator<int>(), 5 );
|
||||||
|
|
||||||
|
BOOST_TEST( pi.get() != 0 );
|
||||||
|
BOOST_TEST( *pi == 5 );
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 0 );
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator<void>() );
|
||||||
|
boost::weak_ptr<X> wp( pi );
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
BOOST_TEST( pi.get() != 0 );
|
||||||
|
BOOST_TEST( pi->v == 0 );
|
||||||
|
|
||||||
|
pi.reset();
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator<void>(), 1 );
|
||||||
|
boost::weak_ptr<X> wp( pi );
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
BOOST_TEST( pi.get() != 0 );
|
||||||
|
BOOST_TEST( pi->v == 1 );
|
||||||
|
|
||||||
|
pi.reset();
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator<void>(), 1, 2 );
|
||||||
|
boost::weak_ptr<X> wp( pi );
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
BOOST_TEST( pi.get() != 0 );
|
||||||
|
BOOST_TEST( pi->v == 1+2 );
|
||||||
|
|
||||||
|
pi.reset();
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3 );
|
||||||
|
boost::weak_ptr<X> wp( pi );
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
BOOST_TEST( pi.get() != 0 );
|
||||||
|
BOOST_TEST( pi->v == 1+2+3 );
|
||||||
|
|
||||||
|
pi.reset();
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4 );
|
||||||
|
boost::weak_ptr<X> wp( pi );
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
BOOST_TEST( pi.get() != 0 );
|
||||||
|
BOOST_TEST( pi->v == 1+2+3+4 );
|
||||||
|
|
||||||
|
pi.reset();
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5 );
|
||||||
|
boost::weak_ptr<X> wp( pi );
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
BOOST_TEST( pi.get() != 0 );
|
||||||
|
BOOST_TEST( pi->v == 1+2+3+4+5 );
|
||||||
|
|
||||||
|
pi.reset();
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6 );
|
||||||
|
boost::weak_ptr<X> wp( pi );
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
BOOST_TEST( pi.get() != 0 );
|
||||||
|
BOOST_TEST( pi->v == 1+2+3+4+5+6 );
|
||||||
|
|
||||||
|
pi.reset();
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7 );
|
||||||
|
boost::weak_ptr<X> wp( pi );
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
BOOST_TEST( pi.get() != 0 );
|
||||||
|
BOOST_TEST( pi->v == 1+2+3+4+5+6+7 );
|
||||||
|
|
||||||
|
pi.reset();
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8 );
|
||||||
|
boost::weak_ptr<X> wp( pi );
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
BOOST_TEST( pi.get() != 0 );
|
||||||
|
BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8 );
|
||||||
|
|
||||||
|
pi.reset();
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8, 9 );
|
||||||
|
boost::weak_ptr<X> wp( pi );
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
BOOST_TEST( pi.get() != 0 );
|
||||||
|
BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8+9 );
|
||||||
|
|
||||||
|
pi.reset();
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
return boost::report_errors();
|
||||||
|
}
|
||||||
40
test/atomic_count_test.cpp
Normal file
40
test/atomic_count_test.cpp
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
//
|
||||||
|
// atomic_count_test.cpp
|
||||||
|
//
|
||||||
|
// 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/detail/atomic_count.hpp>
|
||||||
|
#include <boost/detail/lightweight_test.hpp>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
boost::detail::atomic_count n( 4 );
|
||||||
|
|
||||||
|
BOOST_TEST( n == 4L );
|
||||||
|
|
||||||
|
++n;
|
||||||
|
|
||||||
|
BOOST_TEST( n == 5L );
|
||||||
|
BOOST_TEST( --n != 0L );
|
||||||
|
|
||||||
|
boost::detail::atomic_count m( 0 );
|
||||||
|
|
||||||
|
BOOST_TEST( m == 0 );
|
||||||
|
|
||||||
|
++m;
|
||||||
|
|
||||||
|
BOOST_TEST( m == 1 );
|
||||||
|
|
||||||
|
++m;
|
||||||
|
|
||||||
|
BOOST_TEST( m == 2 );
|
||||||
|
BOOST_TEST( --m != 0 );
|
||||||
|
BOOST_TEST( --m == 0 );
|
||||||
|
|
||||||
|
return boost::report_errors();
|
||||||
|
}
|
||||||
55
test/atomic_count_test2.cpp
Normal file
55
test/atomic_count_test2.cpp
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
//
|
||||||
|
// atomic_count_test2.cpp
|
||||||
|
//
|
||||||
|
// Copyright 2009 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/detail/atomic_count.hpp>
|
||||||
|
#include <boost/detail/lightweight_test.hpp>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
boost::detail::atomic_count n( 4 );
|
||||||
|
|
||||||
|
BOOST_TEST( n == 4 );
|
||||||
|
|
||||||
|
BOOST_TEST( ++n == 5 );
|
||||||
|
BOOST_TEST( ++n == 6 );
|
||||||
|
|
||||||
|
BOOST_TEST( n == 6 );
|
||||||
|
|
||||||
|
BOOST_TEST( --n == 5 );
|
||||||
|
BOOST_TEST( --n == 4 );
|
||||||
|
|
||||||
|
BOOST_TEST( n == 4 );
|
||||||
|
|
||||||
|
boost::detail::atomic_count m( 0 );
|
||||||
|
|
||||||
|
BOOST_TEST( m == 0 );
|
||||||
|
|
||||||
|
BOOST_TEST( ++m == 1 );
|
||||||
|
BOOST_TEST( ++m == 2 );
|
||||||
|
|
||||||
|
BOOST_TEST( m == 2 );
|
||||||
|
|
||||||
|
BOOST_TEST( --m == 1 );
|
||||||
|
BOOST_TEST( --m == 0 );
|
||||||
|
|
||||||
|
BOOST_TEST( m == 0 );
|
||||||
|
|
||||||
|
BOOST_TEST( --m == -1 );
|
||||||
|
BOOST_TEST( --m == -2 );
|
||||||
|
|
||||||
|
BOOST_TEST( m == -2 );
|
||||||
|
|
||||||
|
BOOST_TEST( ++m == -1 );
|
||||||
|
BOOST_TEST( ++m == 0 );
|
||||||
|
|
||||||
|
BOOST_TEST( m == 0 );
|
||||||
|
|
||||||
|
return boost::report_errors();
|
||||||
|
}
|
||||||
32
test/auto_ptr_lv_fail.cpp
Normal file
32
test/auto_ptr_lv_fail.cpp
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#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
|
||||||
|
|
||||||
|
//
|
||||||
|
// auto_ptr_lv_fail.cpp - a negative test for converting an auto_ptr to shared_ptr
|
||||||
|
//
|
||||||
|
// Copyright 2009 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 <memory>
|
||||||
|
|
||||||
|
void f( boost::shared_ptr<int> )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::auto_ptr<int> p;
|
||||||
|
f( p ); // must fail
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
111
test/auto_ptr_rv_test.cpp
Normal file
111
test/auto_ptr_rv_test.cpp
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
//
|
||||||
|
// auto_ptr_rv_test.cpp
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <boost/detail/lightweight_test.hpp>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
struct X
|
||||||
|
{
|
||||||
|
static long instances;
|
||||||
|
|
||||||
|
X()
|
||||||
|
{
|
||||||
|
++instances;
|
||||||
|
}
|
||||||
|
|
||||||
|
~X()
|
||||||
|
{
|
||||||
|
--instances;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::auto_ptr<X> create()
|
||||||
|
{
|
||||||
|
return std::auto_ptr<X>( new X );
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
X( X const & );
|
||||||
|
X & operator=( X const & );
|
||||||
|
};
|
||||||
|
|
||||||
|
long X::instances = 0;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
BOOST_TEST( X::instances == 0 );
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::shared_ptr<X> p( X::create() );
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
|
||||||
|
p = X::create();
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
|
||||||
|
p.reset();
|
||||||
|
BOOST_TEST( X::instances == 0 );
|
||||||
|
|
||||||
|
p = X::create();
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 0 );
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::shared_ptr<X const> p( X::create() );
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
|
||||||
|
p = X::create();
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
|
||||||
|
p.reset();
|
||||||
|
BOOST_TEST( X::instances == 0 );
|
||||||
|
|
||||||
|
p = X::create();
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 0 );
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::shared_ptr<void> p( X::create() );
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
|
||||||
|
p = X::create();
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
|
||||||
|
p.reset();
|
||||||
|
BOOST_TEST( X::instances == 0 );
|
||||||
|
|
||||||
|
p = X::create();
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 0 );
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::shared_ptr<void const> p( X::create() );
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
|
||||||
|
p = X::create();
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
|
||||||
|
p.reset();
|
||||||
|
BOOST_TEST( X::instances == 0 );
|
||||||
|
|
||||||
|
p = X::create();
|
||||||
|
BOOST_TEST( X::instances == 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_TEST( X::instances == 0 );
|
||||||
|
|
||||||
|
return boost::report_errors();
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user