File: | usr/include/boost/smart_ptr/shared_ptr.hpp |
Warning: | line 785, column 9 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | // Copyright (C) 2012-2024 Internet Systems Consortium, Inc. ("ISC") | |||
2 | // | |||
3 | // This Source Code Form is subject to the terms of the Mozilla Public | |||
4 | // License, v. 2.0. If a copy of the MPL was not distributed with this | |||
5 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. | |||
6 | ||||
7 | #include <config.h> | |||
8 | ||||
9 | #include <asiolink/io_address.h> | |||
10 | #include <asiolink/addr_utilities.h> | |||
11 | #include <dhcp/option_space.h> | |||
12 | #include <dhcpsrv/dhcpsrv_log.h> | |||
13 | #include <dhcpsrv/flq_allocation_state.h> | |||
14 | #include <dhcpsrv/flq_allocator.h> | |||
15 | #include <dhcpsrv/iterative_allocation_state.h> | |||
16 | #include <dhcpsrv/iterative_allocator.h> | |||
17 | #include <dhcpsrv/random_allocation_state.h> | |||
18 | #include <dhcpsrv/random_allocator.h> | |||
19 | #include <dhcpsrv/shared_network.h> | |||
20 | #include <dhcpsrv/subnet.h> | |||
21 | #include <util/multi_threading_mgr.h> | |||
22 | ||||
23 | #include <boost/lexical_cast.hpp> | |||
24 | #include <boost/make_shared.hpp> | |||
25 | ||||
26 | #include <algorithm> | |||
27 | #include <limits> | |||
28 | #include <sstream> | |||
29 | ||||
30 | using namespace isc::asiolink; | |||
31 | using namespace isc::data; | |||
32 | using namespace isc::dhcp; | |||
33 | using namespace isc::util; | |||
34 | ||||
35 | using namespace std; | |||
36 | ||||
37 | namespace { | |||
38 | ||||
39 | /// @brief Function used in calls to std::upper_bound to check | |||
40 | /// if the specified prefix is lower than the first address a pool. | |||
41 | /// | |||
42 | /// @return true if prefix is lower than the first address in the pool. | |||
43 | bool | |||
44 | prefixLessThanFirstAddress(const IOAddress& prefix, | |||
45 | const PoolPtr& pool) { | |||
46 | return (prefix < pool->getFirstAddress()); | |||
47 | } | |||
48 | ||||
49 | /// @brief Function used in calls to std::sort to compare first | |||
50 | /// prefixes of the two pools. | |||
51 | /// | |||
52 | /// @param pool1 First pool. | |||
53 | /// @param pool2 Second pool. | |||
54 | /// | |||
55 | /// @return true if first prefix of the first pool is smaller than | |||
56 | /// the first address of the second pool. | |||
57 | bool | |||
58 | comparePoolFirstAddress(const PoolPtr& pool1, | |||
59 | const PoolPtr& pool2) { | |||
60 | return (pool1->getFirstAddress() < pool2->getFirstAddress()); | |||
61 | } | |||
62 | ||||
63 | } | |||
64 | ||||
65 | namespace isc { | |||
66 | namespace dhcp { | |||
67 | ||||
68 | Subnet::Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len, | |||
69 | const SubnetID id) | |||
70 | : id_(id), prefix_(prefix), prefix_len_(len), shared_network_name_() { | |||
71 | if ((id == SUBNET_ID_GLOBAL) || (id == SUBNET_ID_UNUSED)) { | |||
72 | isc_throw(BadValue,do { std::ostringstream oss__; oss__ << "Invalid id specified for subnet: " << id; throw BadValue("../../../src/lib/dhcpsrv/subnet.cc" , 73, oss__.str().c_str()); } while (1) | |||
73 | "Invalid id specified for subnet: " << id)do { std::ostringstream oss__; oss__ << "Invalid id specified for subnet: " << id; throw BadValue("../../../src/lib/dhcpsrv/subnet.cc" , 73, oss__.str().c_str()); } while (1); | |||
74 | } | |||
75 | if ((prefix.isV6() && len > 128) || (prefix.isV4() && len > 32)) { | |||
76 | isc_throw(BadValue,do { std::ostringstream oss__; oss__ << "Invalid prefix length specified for subnet: " << len; throw BadValue("../../../src/lib/dhcpsrv/subnet.cc" , 77, oss__.str().c_str()); } while (1) | |||
77 | "Invalid prefix length specified for subnet: " << len)do { std::ostringstream oss__; oss__ << "Invalid prefix length specified for subnet: " << len; throw BadValue("../../../src/lib/dhcpsrv/subnet.cc" , 77, oss__.str().c_str()); } while (1); | |||
78 | } | |||
79 | } | |||
80 | ||||
81 | bool | |||
82 | Subnet::inRange(const isc::asiolink::IOAddress& addr) const { | |||
83 | IOAddress first = firstAddrInPrefix(prefix_, prefix_len_); | |||
84 | IOAddress last = lastAddrInPrefix(prefix_, prefix_len_); | |||
85 | ||||
86 | return ((first <= addr) && (addr <= last)); | |||
87 | } | |||
88 | ||||
89 | std::string | |||
90 | Subnet::toText() const { | |||
91 | std::stringstream tmp; | |||
92 | tmp << prefix_ << "/" << static_cast<unsigned int>(prefix_len_); | |||
93 | return (tmp.str()); | |||
94 | } | |||
95 | ||||
96 | uint128_t | |||
97 | Subnet::getPoolCapacity(Lease::Type type) const { | |||
98 | switch (type) { | |||
99 | case Lease::TYPE_V4: | |||
100 | case Lease::TYPE_NA: | |||
101 | return sumPoolCapacity(pools_); | |||
102 | case Lease::TYPE_TA: | |||
103 | return sumPoolCapacity(pools_ta_); | |||
104 | case Lease::TYPE_PD: | |||
105 | return sumPoolCapacity(pools_pd_); | |||
106 | default: | |||
107 | isc_throw(BadValue, "Unsupported pool type: "do { std::ostringstream oss__; oss__ << "Unsupported pool type: " << static_cast<int>(type); throw BadValue("../../../src/lib/dhcpsrv/subnet.cc" , 108, oss__.str().c_str()); } while (1) | |||
108 | << static_cast<int>(type))do { std::ostringstream oss__; oss__ << "Unsupported pool type: " << static_cast<int>(type); throw BadValue("../../../src/lib/dhcpsrv/subnet.cc" , 108, oss__.str().c_str()); } while (1); | |||
109 | } | |||
110 | } | |||
111 | ||||
112 | uint128_t | |||
113 | Subnet::getPoolCapacity(Lease::Type type, | |||
114 | const ClientClasses& client_classes) const { | |||
115 | switch (type) { | |||
116 | case Lease::TYPE_V4: | |||
117 | case Lease::TYPE_NA: | |||
118 | return sumPoolCapacity(pools_, client_classes); | |||
119 | case Lease::TYPE_TA: | |||
120 | return sumPoolCapacity(pools_ta_, client_classes); | |||
121 | case Lease::TYPE_PD: | |||
122 | return sumPoolCapacity(pools_pd_, client_classes); | |||
123 | default: | |||
124 | isc_throw(BadValue, "Unsupported pool type: "do { std::ostringstream oss__; oss__ << "Unsupported pool type: " << static_cast<int>(type); throw BadValue("../../../src/lib/dhcpsrv/subnet.cc" , 125, oss__.str().c_str()); } while (1) | |||
125 | << static_cast<int>(type))do { std::ostringstream oss__; oss__ << "Unsupported pool type: " << static_cast<int>(type); throw BadValue("../../../src/lib/dhcpsrv/subnet.cc" , 125, oss__.str().c_str()); } while (1); | |||
126 | } | |||
127 | } | |||
128 | ||||
129 | uint128_t | |||
130 | Subnet::getPoolCapacity(Lease::Type type, | |||
131 | const ClientClasses& client_classes, | |||
132 | Allocator::PrefixLenMatchType prefix_length_match, | |||
133 | uint8_t hint_prefix_length) const { | |||
134 | switch (type) { | |||
135 | case Lease::TYPE_V4: | |||
136 | case Lease::TYPE_NA: | |||
137 | return sumPoolCapacity(pools_, client_classes); | |||
138 | case Lease::TYPE_TA: | |||
139 | return sumPoolCapacity(pools_ta_, client_classes); | |||
140 | case Lease::TYPE_PD: | |||
141 | return sumPoolCapacity(pools_pd_, client_classes, prefix_length_match, | |||
142 | hint_prefix_length); | |||
143 | default: | |||
144 | isc_throw(BadValue, "Unsupported pool type: "do { std::ostringstream oss__; oss__ << "Unsupported pool type: " << static_cast<int>(type); throw BadValue("../../../src/lib/dhcpsrv/subnet.cc" , 145, oss__.str().c_str()); } while (1) | |||
145 | << static_cast<int>(type))do { std::ostringstream oss__; oss__ << "Unsupported pool type: " << static_cast<int>(type); throw BadValue("../../../src/lib/dhcpsrv/subnet.cc" , 145, oss__.str().c_str()); } while (1); | |||
146 | } | |||
147 | } | |||
148 | ||||
149 | uint128_t | |||
150 | Subnet::sumPoolCapacity(const PoolCollection& pools) const { | |||
151 | uint128_t sum(0); | |||
152 | for (auto const& p : pools) { | |||
153 | uint128_t const c(p->getCapacity()); | |||
154 | ||||
155 | // Check if we can add it. If sum + c > UINT128_MAX, then we would have | |||
156 | // overflown if we tried to add it. | |||
157 | if (c > numeric_limits<uint128_t>::max() - sum) { | |||
158 | return (numeric_limits<uint128_t>::max()); | |||
159 | } | |||
160 | ||||
161 | sum += c; | |||
162 | } | |||
163 | ||||
164 | return (sum); | |||
165 | } | |||
166 | ||||
167 | uint128_t | |||
168 | Subnet::sumPoolCapacity(const PoolCollection& pools, | |||
169 | const ClientClasses& client_classes) const { | |||
170 | uint128_t sum(0); | |||
171 | for (auto const& p : pools) { | |||
172 | if (!p->clientSupported(client_classes)) { | |||
173 | continue; | |||
174 | } | |||
175 | ||||
176 | uint128_t const c(p->getCapacity()); | |||
177 | ||||
178 | // Check if we can add it. If sum + c > UINT128_MAX, then we would have | |||
179 | // overflown if we tried to add it. | |||
180 | if (c > numeric_limits<uint128_t>::max() - sum) { | |||
181 | return (numeric_limits<uint128_t>::max()); | |||
182 | } | |||
183 | ||||
184 | sum += c; | |||
185 | } | |||
186 | ||||
187 | return (sum); | |||
188 | } | |||
189 | ||||
190 | uint128_t | |||
191 | Subnet::sumPoolCapacity(const PoolCollection& pools, | |||
192 | const ClientClasses& client_classes, | |||
193 | Allocator::PrefixLenMatchType prefix_length_match, | |||
194 | uint8_t hint_prefix_length) const { | |||
195 | uint128_t sum(0); | |||
196 | for (auto const& p : pools) { | |||
197 | if (!p->clientSupported(client_classes)) { | |||
198 | continue; | |||
199 | } | |||
200 | ||||
201 | if (!Allocator::isValidPrefixPool(prefix_length_match, p, | |||
202 | hint_prefix_length)) { | |||
203 | continue; | |||
204 | } | |||
205 | ||||
206 | uint128_t const c(p->getCapacity()); | |||
207 | ||||
208 | // Check if we can add it. If sum + c > UINT128_MAX, then we would have | |||
209 | // overflown if we tried to add it. | |||
210 | if (c > numeric_limits<uint128_t>::max() - sum) { | |||
211 | return (numeric_limits<uint128_t>::max()); | |||
212 | } | |||
213 | ||||
214 | sum += c; | |||
215 | } | |||
216 | ||||
217 | return (sum); | |||
218 | } | |||
219 | ||||
220 | std::pair<IOAddress, uint8_t> | |||
221 | Subnet::parsePrefixCommon(const std::string& prefix) { | |||
222 | auto pos = prefix.find('/'); | |||
223 | if ((pos == std::string::npos) || | |||
224 | (pos == prefix.size() - 1) || | |||
225 | (pos == 0)) { | |||
226 | isc_throw(BadValue, "unable to parse invalid prefix " << prefix)do { std::ostringstream oss__; oss__ << "unable to parse invalid prefix " << prefix; throw BadValue("../../../src/lib/dhcpsrv/subnet.cc" , 226, oss__.str().c_str()); } while (1); | |||
227 | } | |||
228 | ||||
229 | try { | |||
230 | IOAddress address(prefix.substr(0, pos)); | |||
231 | int length = boost::lexical_cast<int>(prefix.substr(pos + 1)); | |||
232 | return (std::make_pair(address, static_cast<int>(length))); | |||
233 | ||||
234 | } catch (...) { | |||
235 | isc_throw(BadValue, "unable to parse invalid prefix " << prefix)do { std::ostringstream oss__; oss__ << "unable to parse invalid prefix " << prefix; throw BadValue("../../../src/lib/dhcpsrv/subnet.cc" , 235, oss__.str().c_str()); } while (1); | |||
236 | } | |||
237 | } | |||
238 | ||||
239 | ||||
240 | void Subnet4::checkType(Lease::Type type) const { | |||
241 | if (type != Lease::TYPE_V4) { | |||
242 | isc_throw(BadValue, "Only TYPE_V4 is allowed for Subnet4")do { std::ostringstream oss__; oss__ << "Only TYPE_V4 is allowed for Subnet4" ; throw BadValue("../../../src/lib/dhcpsrv/subnet.cc", 242, oss__ .str().c_str()); } while (1); | |||
243 | } | |||
244 | } | |||
245 | ||||
246 | Subnet4::Subnet4(const IOAddress& prefix, uint8_t length, | |||
247 | const Triplet<uint32_t>& t1, | |||
248 | const Triplet<uint32_t>& t2, | |||
249 | const Triplet<uint32_t>& valid_lifetime, | |||
250 | const SubnetID id) | |||
251 | : Subnet(prefix, length, id), Network4() { | |||
252 | if (!prefix.isV4()) { | |||
253 | isc_throw(BadValue, "Non IPv4 prefix " << prefix.toText()do { std::ostringstream oss__; oss__ << "Non IPv4 prefix " << prefix.toText() << " specified in subnet4"; throw BadValue("../../../src/lib/dhcpsrv/subnet.cc", 254, oss__.str ().c_str()); } while (1) | |||
254 | << " specified in subnet4")do { std::ostringstream oss__; oss__ << "Non IPv4 prefix " << prefix.toText() << " specified in subnet4"; throw BadValue("../../../src/lib/dhcpsrv/subnet.cc", 254, oss__.str ().c_str()); } while (1); | |||
255 | } | |||
256 | // Timers. | |||
257 | setT1(t1); | |||
258 | setT2(t2); | |||
259 | setValid(valid_lifetime); | |||
260 | } | |||
261 | ||||
262 | Subnet4Ptr | |||
263 | Subnet4::create(const IOAddress& prefix, uint8_t length, | |||
264 | const Triplet<uint32_t>& t1, | |||
265 | const Triplet<uint32_t>& t2, | |||
266 | const Triplet<uint32_t>& valid_lifetime, | |||
267 | const SubnetID id) { | |||
268 | Subnet4Ptr subnet = boost::make_shared<Subnet4> | |||
269 | (prefix, length, t1, t2, valid_lifetime, id); | |||
270 | subnet->setAllocator(Lease::TYPE_V4, | |||
271 | boost::make_shared<IterativeAllocator> | |||
272 | (Lease::TYPE_V4, subnet)); | |||
273 | subnet->setAllocationState(Lease::TYPE_V4, | |||
274 | SubnetIterativeAllocationState::create(subnet)); | |||
275 | ||||
276 | return (subnet); | |||
277 | } | |||
278 | ||||
279 | ConstSubnet4Ptr | |||
280 | Subnet4::getNextSubnet(const ConstSubnet4Ptr& first_subnet) const { | |||
281 | SharedNetwork4Ptr network; | |||
282 | getSharedNetwork(network); | |||
283 | if (network) { | |||
284 | return (network->getNextSubnet(first_subnet, getID())); | |||
285 | } | |||
286 | ||||
287 | return (Subnet4Ptr()); | |||
288 | } | |||
289 | ||||
290 | ConstSubnet4Ptr | |||
291 | Subnet4::getNextSubnet(const ConstSubnet4Ptr& first_subnet, | |||
292 | const ClientClasses& client_classes) const { | |||
293 | SharedNetwork4Ptr network; | |||
294 | getSharedNetwork(network); | |||
295 | // We can only get next subnet if shared network has been defined for | |||
296 | // the current subnet. | |||
297 | if (network) { | |||
298 | ConstSubnet4Ptr subnet; | |||
299 | do { | |||
300 | // Use subnet identifier of this subnet if this is the first | |||
301 | // time we're calling getNextSubnet. Otherwise, use the | |||
302 | // subnet id of the previously returned subnet. | |||
303 | SubnetID subnet_id = subnet ? subnet->getID() : getID(); | |||
304 | subnet = network->getNextSubnet(first_subnet, subnet_id); | |||
305 | // If client classes match the subnet, return it. Otherwise, | |||
306 | // try another subnet. | |||
307 | if (subnet && subnet->clientSupported(client_classes)) { | |||
308 | return (subnet); | |||
309 | } | |||
310 | } while (subnet); | |||
311 | } | |||
312 | ||||
313 | // No subnet found. | |||
314 | return (Subnet4Ptr()); | |||
315 | } | |||
316 | ||||
317 | ||||
318 | bool | |||
319 | Subnet4::clientSupported(const isc::dhcp::ClientClasses& client_classes) const { | |||
320 | NetworkPtr network; | |||
321 | getSharedNetwork(network); | |||
322 | if (network && !network->clientSupported(client_classes)) { | |||
323 | return (false); | |||
324 | } | |||
325 | ||||
326 | return (Network4::clientSupported(client_classes)); | |||
327 | } | |||
328 | ||||
329 | const PoolCollection& Subnet::getPools(Lease::Type type) const { | |||
330 | // check if the type is valid (and throw if it isn't) | |||
331 | checkType(type); | |||
332 | ||||
333 | switch (type) { | |||
334 | case Lease::TYPE_V4: | |||
335 | case Lease::TYPE_NA: | |||
336 | return (pools_); | |||
337 | case Lease::TYPE_TA: | |||
338 | return (pools_ta_); | |||
339 | case Lease::TYPE_PD: | |||
340 | return (pools_pd_); | |||
341 | default: | |||
342 | isc_throw(BadValue, "Unsupported pool type: "do { std::ostringstream oss__; oss__ << "Unsupported pool type: " << static_cast<int>(type); throw BadValue("../../../src/lib/dhcpsrv/subnet.cc" , 343, oss__.str().c_str()); } while (1) | |||
343 | << static_cast<int>(type))do { std::ostringstream oss__; oss__ << "Unsupported pool type: " << static_cast<int>(type); throw BadValue("../../../src/lib/dhcpsrv/subnet.cc" , 343, oss__.str().c_str()); } while (1); | |||
344 | } | |||
345 | } | |||
346 | ||||
347 | PoolCollection& Subnet::getPoolsWritable(Lease::Type type) { | |||
348 | // check if the type is valid (and throw if it isn't) | |||
349 | checkType(type); | |||
350 | ||||
351 | switch (type) { | |||
352 | case Lease::TYPE_V4: | |||
353 | case Lease::TYPE_NA: | |||
354 | return (pools_); | |||
355 | case Lease::TYPE_TA: | |||
356 | return (pools_ta_); | |||
357 | case Lease::TYPE_PD: | |||
358 | return (pools_pd_); | |||
359 | default: | |||
360 | isc_throw(BadValue, "Invalid pool type specified: "do { std::ostringstream oss__; oss__ << "Invalid pool type specified: " << static_cast<int>(type); throw BadValue("../../../src/lib/dhcpsrv/subnet.cc" , 361, oss__.str().c_str()); } while (1) | |||
361 | << static_cast<int>(type))do { std::ostringstream oss__; oss__ << "Invalid pool type specified: " << static_cast<int>(type); throw BadValue("../../../src/lib/dhcpsrv/subnet.cc" , 361, oss__.str().c_str()); } while (1); | |||
362 | } | |||
363 | } | |||
364 | ||||
365 | AllocatorPtr | |||
366 | Subnet::getAllocator(Lease::Type type) const { | |||
367 | auto alloc = allocators_.find(type); | |||
368 | ||||
369 | if (alloc == allocators_.end()) { | |||
370 | isc_throw(BadValue, "no allocator initialized for pool type "do { std::ostringstream oss__; oss__ << "no allocator initialized for pool type " << Lease::typeToText(type); throw BadValue("../../../src/lib/dhcpsrv/subnet.cc" , 371, oss__.str().c_str()); } while (1) | |||
371 | << Lease::typeToText(type))do { std::ostringstream oss__; oss__ << "no allocator initialized for pool type " << Lease::typeToText(type); throw BadValue("../../../src/lib/dhcpsrv/subnet.cc" , 371, oss__.str().c_str()); } while (1); | |||
372 | } | |||
373 | return (alloc->second); | |||
374 | } | |||
375 | ||||
376 | void | |||
377 | Subnet::setAllocator(Lease::Type type, const AllocatorPtr& allocator) { | |||
378 | allocators_[type] = allocator; | |||
379 | } | |||
380 | ||||
381 | SubnetAllocationStatePtr | |||
382 | Subnet::getAllocationState(Lease::Type type) const { | |||
383 | auto state = allocation_states_.find(type); | |||
384 | ||||
385 | if (state == allocation_states_.end()) { | |||
386 | isc_throw(BadValue, "no allocation state initialized for pool type "do { std::ostringstream oss__; oss__ << "no allocation state initialized for pool type " << Lease::typeToText(type); throw BadValue("../../../src/lib/dhcpsrv/subnet.cc" , 387, oss__.str().c_str()); } while (1) | |||
387 | << Lease::typeToText(type))do { std::ostringstream oss__; oss__ << "no allocation state initialized for pool type " << Lease::typeToText(type); throw BadValue("../../../src/lib/dhcpsrv/subnet.cc" , 387, oss__.str().c_str()); } while (1); | |||
388 | } | |||
389 | return (state->second); | |||
390 | } | |||
391 | ||||
392 | void | |||
393 | Subnet::setAllocationState(Lease::Type type, const SubnetAllocationStatePtr& allocation_state) { | |||
394 | allocation_states_[type] = allocation_state; | |||
395 | } | |||
396 | ||||
397 | const PoolPtr Subnet::getPool(Lease::Type type, const isc::asiolink::IOAddress& hint, | |||
398 | bool anypool /* true */) const { | |||
399 | // check if the type is valid (and throw if it isn't) | |||
400 | checkType(type); | |||
401 | ||||
402 | auto const& pools = getPools(type); | |||
403 | ||||
404 | PoolPtr candidate; | |||
405 | ||||
406 | if (!pools.empty()) { | |||
407 | // Pools are sorted by their first prefixes. For example: 2001::, | |||
408 | // 2001::db8::, 3000:: etc. If our hint is 2001:db8:5:: we want to | |||
409 | // find the pool with the longest matching prefix, so: 2001:db8::, | |||
410 | // rather than 2001::. upper_bound returns the first pool with a prefix | |||
411 | // that is greater than 2001:db8:5::, i.e. 3000::. To find the longest | |||
412 | // matching prefix we use decrement operator to go back by one item. | |||
413 | // If returned iterator points to begin it means that prefixes in all | |||
414 | // pools are greater than out prefix, and thus there is no match. | |||
415 | auto ub = | |||
416 | std::upper_bound(pools.begin(), pools.end(), hint, | |||
417 | prefixLessThanFirstAddress); | |||
418 | ||||
419 | if (ub != pools.begin()) { | |||
420 | --ub; | |||
421 | if ((*ub)->inRange(hint)) { | |||
422 | candidate = *ub; | |||
423 | } | |||
424 | } | |||
425 | ||||
426 | // If we don't find anything better, then let's just use the first pool | |||
427 | if (!candidate && anypool) { | |||
428 | candidate = *pools.begin(); | |||
429 | } | |||
430 | } | |||
431 | ||||
432 | // Return a pool or NULL if no match found. | |||
433 | return (candidate); | |||
434 | } | |||
435 | ||||
436 | void | |||
437 | Subnet::initAllocatorsAfterConfigure() { | |||
438 | for (auto const& allocator : allocators_) { | |||
439 | allocator.second->initAfterConfigure(); | |||
440 | } | |||
441 | } | |||
442 | ||||
443 | const PoolPtr Subnet::getPool(Lease::Type type, | |||
444 | const ClientClasses& client_classes, | |||
445 | const isc::asiolink::IOAddress& hint) const { | |||
446 | // check if the type is valid (and throw if it isn't) | |||
447 | checkType(type); | |||
448 | ||||
449 | auto const& pools = getPools(type); | |||
450 | ||||
451 | PoolPtr candidate; | |||
452 | ||||
453 | if (!pools.empty()) { | |||
454 | auto ub = | |||
455 | std::upper_bound(pools.begin(), pools.end(), hint, | |||
456 | prefixLessThanFirstAddress); | |||
457 | ||||
458 | if (ub != pools.begin()) { | |||
459 | --ub; | |||
460 | if ((*ub)->inRange(hint) && | |||
461 | (*ub)->clientSupported(client_classes)) { | |||
462 | candidate = *ub; | |||
463 | } | |||
464 | } | |||
465 | } | |||
466 | ||||
467 | // Return a pool or NULL if no match found. | |||
468 | return (candidate); | |||
469 | } | |||
470 | ||||
471 | void | |||
472 | Subnet::addPool(const PoolPtr& pool) { | |||
473 | // check if the type is valid (and throw if it isn't) | |||
474 | checkType(pool->getType()); | |||
475 | ||||
476 | // Check that the pool is in range with a subnet only if this is | |||
477 | // not a pool of IPv6 prefixes. The IPv6 prefixes delegated for | |||
478 | // the particular subnet don't need to match the prefix of the | |||
479 | // subnet. | |||
480 | if (pool->getType() != Lease::TYPE_PD) { | |||
481 | if (!inRange(pool->getFirstAddress()) || !inRange(pool->getLastAddress())) { | |||
482 | isc_throw(BadValue, "a pool of type "do { std::ostringstream oss__; oss__ << "a pool of type " << Lease::typeToText(pool->getType()) << ", with the following address range: " << pool->getFirstAddress() << "-" << pool ->getLastAddress() << " does not match" << " the prefix of a subnet: " << prefix_ << "/" << static_cast<int> (prefix_len_) << " to which it is being added"; throw BadValue ("../../../src/lib/dhcpsrv/subnet.cc", 489, oss__.str().c_str ()); } while (1) | |||
483 | << Lease::typeToText(pool->getType())do { std::ostringstream oss__; oss__ << "a pool of type " << Lease::typeToText(pool->getType()) << ", with the following address range: " << pool->getFirstAddress() << "-" << pool ->getLastAddress() << " does not match" << " the prefix of a subnet: " << prefix_ << "/" << static_cast<int> (prefix_len_) << " to which it is being added"; throw BadValue ("../../../src/lib/dhcpsrv/subnet.cc", 489, oss__.str().c_str ()); } while (1) | |||
484 | << ", with the following address range: "do { std::ostringstream oss__; oss__ << "a pool of type " << Lease::typeToText(pool->getType()) << ", with the following address range: " << pool->getFirstAddress() << "-" << pool ->getLastAddress() << " does not match" << " the prefix of a subnet: " << prefix_ << "/" << static_cast<int> (prefix_len_) << " to which it is being added"; throw BadValue ("../../../src/lib/dhcpsrv/subnet.cc", 489, oss__.str().c_str ()); } while (1) | |||
485 | << pool->getFirstAddress() << "-"do { std::ostringstream oss__; oss__ << "a pool of type " << Lease::typeToText(pool->getType()) << ", with the following address range: " << pool->getFirstAddress() << "-" << pool ->getLastAddress() << " does not match" << " the prefix of a subnet: " << prefix_ << "/" << static_cast<int> (prefix_len_) << " to which it is being added"; throw BadValue ("../../../src/lib/dhcpsrv/subnet.cc", 489, oss__.str().c_str ()); } while (1) | |||
486 | << pool->getLastAddress() << " does not match"do { std::ostringstream oss__; oss__ << "a pool of type " << Lease::typeToText(pool->getType()) << ", with the following address range: " << pool->getFirstAddress() << "-" << pool ->getLastAddress() << " does not match" << " the prefix of a subnet: " << prefix_ << "/" << static_cast<int> (prefix_len_) << " to which it is being added"; throw BadValue ("../../../src/lib/dhcpsrv/subnet.cc", 489, oss__.str().c_str ()); } while (1) | |||
487 | << " the prefix of a subnet: "do { std::ostringstream oss__; oss__ << "a pool of type " << Lease::typeToText(pool->getType()) << ", with the following address range: " << pool->getFirstAddress() << "-" << pool ->getLastAddress() << " does not match" << " the prefix of a subnet: " << prefix_ << "/" << static_cast<int> (prefix_len_) << " to which it is being added"; throw BadValue ("../../../src/lib/dhcpsrv/subnet.cc", 489, oss__.str().c_str ()); } while (1) | |||
488 | << prefix_ << "/" << static_cast<int>(prefix_len_)do { std::ostringstream oss__; oss__ << "a pool of type " << Lease::typeToText(pool->getType()) << ", with the following address range: " << pool->getFirstAddress() << "-" << pool ->getLastAddress() << " does not match" << " the prefix of a subnet: " << prefix_ << "/" << static_cast<int> (prefix_len_) << " to which it is being added"; throw BadValue ("../../../src/lib/dhcpsrv/subnet.cc", 489, oss__.str().c_str ()); } while (1) | |||
489 | << " to which it is being added")do { std::ostringstream oss__; oss__ << "a pool of type " << Lease::typeToText(pool->getType()) << ", with the following address range: " << pool->getFirstAddress() << "-" << pool ->getLastAddress() << " does not match" << " the prefix of a subnet: " << prefix_ << "/" << static_cast<int> (prefix_len_) << " to which it is being added"; throw BadValue ("../../../src/lib/dhcpsrv/subnet.cc", 489, oss__.str().c_str ()); } while (1); | |||
490 | ||||
491 | } | |||
492 | } | |||
493 | ||||
494 | bool overlaps = false; | |||
495 | if (pool->getType() == Lease::TYPE_V4) { | |||
496 | overlaps = poolOverlaps(Lease::TYPE_V4, pool); | |||
497 | ||||
498 | } else { | |||
499 | overlaps = | |||
500 | poolOverlaps(Lease::TYPE_NA, pool) || | |||
501 | poolOverlaps(Lease::TYPE_PD, pool) || | |||
502 | poolOverlaps(Lease::TYPE_TA, pool); | |||
503 | } | |||
504 | ||||
505 | if (overlaps) { | |||
506 | isc_throw(BadValue,"a pool of type "do { std::ostringstream oss__; oss__ << "a pool of type " << Lease::typeToText(pool->getType()) << ", with the following address range: " << pool->getFirstAddress() << "-" << pool ->getLastAddress() << " overlaps with " "an existing pool in the subnet: " << prefix_ << "/" << static_cast<int> (prefix_len_) << " to which it is being added"; throw BadValue ("../../../src/lib/dhcpsrv/subnet.cc", 513, oss__.str().c_str ()); } while (1) | |||
507 | << Lease::typeToText(pool->getType())do { std::ostringstream oss__; oss__ << "a pool of type " << Lease::typeToText(pool->getType()) << ", with the following address range: " << pool->getFirstAddress() << "-" << pool ->getLastAddress() << " overlaps with " "an existing pool in the subnet: " << prefix_ << "/" << static_cast<int> (prefix_len_) << " to which it is being added"; throw BadValue ("../../../src/lib/dhcpsrv/subnet.cc", 513, oss__.str().c_str ()); } while (1) | |||
508 | << ", with the following address range: "do { std::ostringstream oss__; oss__ << "a pool of type " << Lease::typeToText(pool->getType()) << ", with the following address range: " << pool->getFirstAddress() << "-" << pool ->getLastAddress() << " overlaps with " "an existing pool in the subnet: " << prefix_ << "/" << static_cast<int> (prefix_len_) << " to which it is being added"; throw BadValue ("../../../src/lib/dhcpsrv/subnet.cc", 513, oss__.str().c_str ()); } while (1) | |||
509 | << pool->getFirstAddress() << "-"do { std::ostringstream oss__; oss__ << "a pool of type " << Lease::typeToText(pool->getType()) << ", with the following address range: " << pool->getFirstAddress() << "-" << pool ->getLastAddress() << " overlaps with " "an existing pool in the subnet: " << prefix_ << "/" << static_cast<int> (prefix_len_) << " to which it is being added"; throw BadValue ("../../../src/lib/dhcpsrv/subnet.cc", 513, oss__.str().c_str ()); } while (1) | |||
510 | << pool->getLastAddress() << " overlaps with "do { std::ostringstream oss__; oss__ << "a pool of type " << Lease::typeToText(pool->getType()) << ", with the following address range: " << pool->getFirstAddress() << "-" << pool ->getLastAddress() << " overlaps with " "an existing pool in the subnet: " << prefix_ << "/" << static_cast<int> (prefix_len_) << " to which it is being added"; throw BadValue ("../../../src/lib/dhcpsrv/subnet.cc", 513, oss__.str().c_str ()); } while (1) | |||
511 | "an existing pool in the subnet: "do { std::ostringstream oss__; oss__ << "a pool of type " << Lease::typeToText(pool->getType()) << ", with the following address range: " << pool->getFirstAddress() << "-" << pool ->getLastAddress() << " overlaps with " "an existing pool in the subnet: " << prefix_ << "/" << static_cast<int> (prefix_len_) << " to which it is being added"; throw BadValue ("../../../src/lib/dhcpsrv/subnet.cc", 513, oss__.str().c_str ()); } while (1) | |||
512 | << prefix_ << "/" << static_cast<int>(prefix_len_)do { std::ostringstream oss__; oss__ << "a pool of type " << Lease::typeToText(pool->getType()) << ", with the following address range: " << pool->getFirstAddress() << "-" << pool ->getLastAddress() << " overlaps with " "an existing pool in the subnet: " << prefix_ << "/" << static_cast<int> (prefix_len_) << " to which it is being added"; throw BadValue ("../../../src/lib/dhcpsrv/subnet.cc", 513, oss__.str().c_str ()); } while (1) | |||
513 | << " to which it is being added")do { std::ostringstream oss__; oss__ << "a pool of type " << Lease::typeToText(pool->getType()) << ", with the following address range: " << pool->getFirstAddress() << "-" << pool ->getLastAddress() << " overlaps with " "an existing pool in the subnet: " << prefix_ << "/" << static_cast<int> (prefix_len_) << " to which it is being added"; throw BadValue ("../../../src/lib/dhcpsrv/subnet.cc", 513, oss__.str().c_str ()); } while (1); | |||
514 | } | |||
515 | ||||
516 | PoolCollection& pools_writable = getPoolsWritable(pool->getType()); | |||
517 | ||||
518 | // Add the pool to the appropriate pools collection | |||
519 | pools_writable.push_back(pool); | |||
520 | ||||
521 | // Sort pools by first address. | |||
522 | std::sort(pools_writable.begin(), pools_writable.end(), | |||
523 | comparePoolFirstAddress); | |||
524 | } | |||
525 | ||||
526 | void | |||
527 | Subnet::delPools(Lease::Type type) { | |||
528 | getPoolsWritable(type).clear(); | |||
529 | } | |||
530 | ||||
531 | bool | |||
532 | Subnet::inPool(Lease::Type type, const isc::asiolink::IOAddress& addr) const { | |||
533 | ||||
534 | // Let's start with checking if it even belongs to that subnet. | |||
535 | if ((type != Lease::TYPE_PD) && !inRange(addr)) { | |||
536 | return (false); | |||
537 | } | |||
538 | ||||
539 | auto const& pools = getPools(type); | |||
540 | for (auto const& pool : pools) { | |||
541 | if (pool->inRange(addr)) { | |||
542 | return (true); | |||
543 | } | |||
544 | } | |||
545 | // There's no pool that address belongs to | |||
546 | return (false); | |||
547 | } | |||
548 | ||||
549 | bool | |||
550 | Subnet::inPool(Lease::Type type, | |||
551 | const isc::asiolink::IOAddress& addr, | |||
552 | const ClientClasses& client_classes) const { | |||
553 | ||||
554 | // Let's start with checking if it even belongs to that subnet. | |||
555 | if ((type != Lease::TYPE_PD) && !inRange(addr)) { | |||
556 | return (false); | |||
557 | } | |||
558 | ||||
559 | auto const& pools = getPools(type); | |||
560 | for (auto const& pool : pools) { | |||
561 | if (!pool->clientSupported(client_classes)) { | |||
562 | continue; | |||
563 | } | |||
564 | if (pool->inRange(addr)) { | |||
565 | return (true); | |||
566 | } | |||
567 | } | |||
568 | // There's no pool that address belongs to | |||
569 | return (false); | |||
570 | } | |||
571 | ||||
572 | bool | |||
573 | Subnet::poolOverlaps(const Lease::Type& pool_type, const PoolPtr& pool) const { | |||
574 | auto const& pools = getPools(pool_type); | |||
575 | ||||
576 | // If no pools, we don't overlap. Nothing to do. | |||
577 | if (pools.empty()) { | |||
578 | return (false); | |||
579 | } | |||
580 | ||||
581 | // We're going to insert a new pool, likely between two existing pools. | |||
582 | // So we're going to end up with the following case: | |||
583 | // |<---- pool1 ---->| |<-------- pool2 ------>| |<-- pool3 -->| | |||
584 | // F1 L1 F2 L2 F3 L3 | |||
585 | // where pool1 and pool3 are existing pools, pool2 is a pool being | |||
586 | // inserted and "F"/"L" mark first and last address in the pools | |||
587 | // respectively. So the following conditions must be fulfilled: | |||
588 | // F2 > L1 and L2 < F3. Obviously, for any pool: F < L. | |||
589 | ||||
590 | // Search for pool3. We use F2 and upper_bound to find the F3 (upper_bound | |||
591 | // returns first pool in the sorted container which first address is | |||
592 | // greater than F2). prefixLessThanPoolAddress with the first argument | |||
593 | // set to "true" is the custom comparison function for upper_bound, which | |||
594 | // compares F2 with the first addresses of the existing pools. | |||
595 | auto const pool3_it = | |||
596 | std::upper_bound(pools.begin(), pools.end(), pool->getFirstAddress(), | |||
597 | prefixLessThanFirstAddress); | |||
598 | ||||
599 | // The upper_bound function returns a first pool which first address is | |||
600 | // greater than the address F2. However, it is also possible that there is a | |||
601 | // pool which first address is equal to F2. Such pool is also in conflict | |||
602 | // with a new pool. If the returned value is pools.begin() it means that all | |||
603 | // pools have greater first address than F2, thus none of the pools can have | |||
604 | // first address equal to F2. Otherwise, we'd need to check them for | |||
605 | // equality. However any pool has first address <= last address, so checking | |||
606 | // that the new pool first address is greater than the pool before pool3 | |||
607 | // last address is enough. We now have to find the pool1. This pool should | |||
608 | // be right before the pool3 if there is any pool before pool3. | |||
609 | if (pool3_it != pools.begin()) { | |||
610 | PoolPtr pool1 = *(pool3_it - 1); | |||
611 | // F2 must be greater than L1, otherwise pools will overlap. | |||
612 | if (pool->getFirstAddress() <= pool1->getLastAddress()) { | |||
613 | return (true); | |||
614 | } | |||
615 | } | |||
616 | ||||
617 | // If returned value is unequal pools.end() it means that there is a pool3, | |||
618 | // with F3 > F2. | |||
619 | if (pool3_it != pools.end()) { | |||
620 | // Let's store the pointer to this pool. | |||
621 | PoolPtr pool3 = *pool3_it; | |||
622 | // F3 must be greater than L2, otherwise pools will overlap. | |||
623 | if (pool3->getFirstAddress() <= pool->getLastAddress()) { | |||
624 | return (true); | |||
625 | } | |||
626 | } | |||
627 | ||||
628 | return (false); | |||
629 | } | |||
630 | ||||
631 | Subnet6::Subnet6(const IOAddress& prefix, uint8_t length, | |||
632 | const Triplet<uint32_t>& t1, | |||
633 | const Triplet<uint32_t>& t2, | |||
634 | const Triplet<uint32_t>& preferred_lifetime, | |||
635 | const Triplet<uint32_t>& valid_lifetime, | |||
636 | const SubnetID id) | |||
637 | : Subnet(prefix, length, id), Network6() { | |||
638 | if (!prefix.isV6()) { | |||
639 | isc_throw(BadValue, "Non IPv6 prefix " << prefixdo { std::ostringstream oss__; oss__ << "Non IPv6 prefix " << prefix << " specified in subnet6"; throw BadValue ("../../../src/lib/dhcpsrv/subnet.cc", 640, oss__.str().c_str ()); } while (1) | |||
640 | << " specified in subnet6")do { std::ostringstream oss__; oss__ << "Non IPv6 prefix " << prefix << " specified in subnet6"; throw BadValue ("../../../src/lib/dhcpsrv/subnet.cc", 640, oss__.str().c_str ()); } while (1); | |||
641 | } | |||
642 | ||||
643 | // Timers. | |||
644 | setT1(t1); | |||
645 | setT2(t2); | |||
646 | setPreferred(preferred_lifetime); | |||
647 | setValid(valid_lifetime); | |||
648 | } | |||
649 | ||||
650 | Subnet6Ptr | |||
651 | Subnet6::create(const IOAddress& prefix, uint8_t length, | |||
652 | const Triplet<uint32_t>& t1, | |||
653 | const Triplet<uint32_t>& t2, | |||
654 | const Triplet<uint32_t>& preferred_lifetime, | |||
655 | const Triplet<uint32_t>& valid_lifetime, | |||
656 | const SubnetID id) { | |||
657 | Subnet6Ptr subnet = boost::make_shared<Subnet6> | |||
| ||||
658 | (prefix, length, t1, t2, preferred_lifetime, valid_lifetime, id); | |||
659 | // IA_NA | |||
660 | subnet->setAllocator(Lease::TYPE_NA, | |||
661 | boost::make_shared<IterativeAllocator> | |||
662 | (Lease::TYPE_NA, subnet)); | |||
663 | subnet->setAllocationState(Lease::TYPE_NA, | |||
664 | SubnetIterativeAllocationState::create(subnet)); | |||
665 | // IA_TA | |||
666 | subnet->setAllocator(Lease::TYPE_TA, | |||
667 | boost::make_shared<IterativeAllocator> | |||
668 | (Lease::TYPE_TA, subnet)); | |||
669 | subnet->setAllocationState(Lease::TYPE_TA, | |||
670 | SubnetIterativeAllocationState::create(subnet)); | |||
671 | // IA_PD | |||
672 | subnet->setAllocator(Lease::TYPE_PD, | |||
673 | boost::make_shared<IterativeAllocator> | |||
674 | (Lease::TYPE_PD, subnet)); | |||
675 | subnet->setAllocationState(Lease::TYPE_PD, | |||
676 | SubnetIterativeAllocationState::create(subnet)); | |||
677 | return (subnet); | |||
678 | } | |||
679 | ||||
680 | void Subnet6::checkType(Lease::Type type) const { | |||
681 | if ((type != Lease::TYPE_NA) && (type != Lease::TYPE_TA) && (type != Lease::TYPE_PD)) { | |||
682 | isc_throw(BadValue, "Invalid Pool type: " << Lease::typeToText(type)do { std::ostringstream oss__; oss__ << "Invalid Pool type: " << Lease::typeToText(type) << "(" << static_cast <int>(type) << "), must be TYPE_NA, TYPE_TA or TYPE_PD for Subnet6" ; throw BadValue("../../../src/lib/dhcpsrv/subnet.cc", 684, oss__ .str().c_str()); } while (1) | |||
683 | << "(" << static_cast<int>(type)do { std::ostringstream oss__; oss__ << "Invalid Pool type: " << Lease::typeToText(type) << "(" << static_cast <int>(type) << "), must be TYPE_NA, TYPE_TA or TYPE_PD for Subnet6" ; throw BadValue("../../../src/lib/dhcpsrv/subnet.cc", 684, oss__ .str().c_str()); } while (1) | |||
684 | << "), must be TYPE_NA, TYPE_TA or TYPE_PD for Subnet6")do { std::ostringstream oss__; oss__ << "Invalid Pool type: " << Lease::typeToText(type) << "(" << static_cast <int>(type) << "), must be TYPE_NA, TYPE_TA or TYPE_PD for Subnet6" ; throw BadValue("../../../src/lib/dhcpsrv/subnet.cc", 684, oss__ .str().c_str()); } while (1); | |||
685 | } | |||
686 | } | |||
687 | ||||
688 | ConstSubnet6Ptr | |||
689 | Subnet6::getNextSubnet(const ConstSubnet6Ptr& first_subnet) const { | |||
690 | SharedNetwork6Ptr network; | |||
691 | getSharedNetwork(network); | |||
692 | if (network) { | |||
693 | return (network->getNextSubnet(first_subnet, getID())); | |||
694 | } | |||
695 | ||||
696 | return (Subnet6Ptr()); | |||
697 | } | |||
698 | ||||
699 | ConstSubnet6Ptr | |||
700 | Subnet6::getNextSubnet(const ConstSubnet6Ptr& first_subnet, | |||
701 | const ClientClasses& client_classes) const { | |||
702 | SharedNetwork6Ptr network; | |||
703 | getSharedNetwork(network); | |||
704 | // We can only get next subnet if shared network has been defined for | |||
705 | // the current subnet. | |||
706 | if (network) { | |||
707 | ConstSubnet6Ptr subnet; | |||
708 | do { | |||
709 | // Use subnet identifier of this subnet if this is the first | |||
710 | // time we're calling getNextSubnet. Otherwise, use the | |||
711 | // subnet id of the previously returned subnet. | |||
712 | SubnetID subnet_id = subnet ? subnet->getID() : getID(); | |||
713 | subnet = network->getNextSubnet(first_subnet, subnet_id); | |||
714 | // If client classes match the subnet, return it. Otherwise, | |||
715 | // try another subnet. | |||
716 | if (subnet && subnet->clientSupported(client_classes)) { | |||
717 | return (subnet); | |||
718 | } | |||
719 | } while (subnet); | |||
720 | } | |||
721 | ||||
722 | // No subnet found. | |||
723 | return (Subnet6Ptr()); | |||
724 | } | |||
725 | ||||
726 | bool | |||
727 | Subnet6::clientSupported(const isc::dhcp::ClientClasses& client_classes) const { | |||
728 | NetworkPtr network; | |||
729 | getSharedNetwork(network); | |||
730 | if (network && !network->clientSupported(client_classes)) { | |||
731 | return (false); | |||
732 | } | |||
733 | ||||
734 | return (Network6::clientSupported(client_classes)); | |||
735 | } | |||
736 | ||||
737 | data::ElementPtr | |||
738 | Subnet::toElement() const { | |||
739 | ElementPtr map = Element::createMap(); | |||
740 | ||||
741 | // Add user-context | |||
742 | contextToElement(map); | |||
743 | ||||
744 | // Set subnet id | |||
745 | SubnetID id = getID(); | |||
746 | map->set("id", Element::create(static_cast<long long>(id))); | |||
747 | ||||
748 | // Set subnet | |||
749 | map->set("subnet", Element::create(toText())); | |||
750 | ||||
751 | return (map); | |||
752 | } | |||
753 | ||||
754 | void | |||
755 | Subnet4::createAllocators() { | |||
756 | auto allocator_type = getAllocatorType(); | |||
757 | if (allocator_type.empty()) { | |||
758 | allocator_type = getDefaultAllocatorType(); | |||
759 | } | |||
760 | if (allocator_type == "random") { | |||
761 | setAllocator(Lease::TYPE_V4, | |||
762 | boost::make_shared<RandomAllocator> | |||
763 | (Lease::TYPE_V4, shared_from_this())); | |||
764 | setAllocationState(Lease::TYPE_V4, SubnetAllocationStatePtr()); | |||
765 | ||||
766 | for (auto const& pool : pools_) { | |||
767 | pool->setAllocationState(PoolRandomAllocationState::create(pool)); | |||
768 | } | |||
769 | ||||
770 | } else if (allocator_type == "flq") { | |||
771 | setAllocator(Lease::TYPE_V4, | |||
772 | boost::make_shared<FreeLeaseQueueAllocator> | |||
773 | (Lease::TYPE_V4, shared_from_this())); | |||
774 | setAllocationState(Lease::TYPE_V4, SubnetAllocationStatePtr()); | |||
775 | ||||
776 | for (auto const& pool : pools_) { | |||
777 | pool->setAllocationState(PoolFreeLeaseQueueAllocationState::create(pool)); | |||
778 | } | |||
779 | ||||
780 | } else { | |||
781 | setAllocator(Lease::TYPE_V4, | |||
782 | boost::make_shared<IterativeAllocator> | |||
783 | (Lease::TYPE_V4, shared_from_this())); | |||
784 | setAllocationState(Lease::TYPE_V4, | |||
785 | SubnetIterativeAllocationState::create(shared_from_this())); | |||
786 | ||||
787 | for (auto const& pool : pools_) { | |||
788 | pool->setAllocationState(PoolIterativeAllocationState::create(pool)); | |||
789 | } | |||
790 | } | |||
791 | } | |||
792 | ||||
793 | data::ElementPtr | |||
794 | Subnet4::toElement() const { | |||
795 | // Prepare the map | |||
796 | ElementPtr map = Subnet::toElement(); | |||
797 | ElementPtr network_map = Network4::toElement(); | |||
798 | ||||
799 | merge(map, network_map); | |||
800 | ||||
801 | // Set DHCP4o6 | |||
802 | const Cfg4o6& d4o6 = get4o6(); | |||
803 | isc::data::merge(map, d4o6.toElement()); | |||
804 | ||||
805 | // Set pools | |||
806 | auto const& pools = getPools(Lease::TYPE_V4); | |||
807 | ElementPtr pool_list = Element::createList(); | |||
808 | for (auto const& pool : pools) { | |||
809 | // Add the formatted pool to the list | |||
810 | pool_list->add(pool->toElement()); | |||
811 | } | |||
812 | map->set("pools", pool_list); | |||
813 | ||||
814 | return (map); | |||
815 | } | |||
816 | ||||
817 | std::pair<IOAddress, uint8_t> | |||
818 | Subnet4::parsePrefix(const std::string& prefix) { | |||
819 | std::pair<IOAddress, uint8_t> parsed = Subnet::parsePrefixCommon(prefix); | |||
820 | if (!parsed.first.isV4() || parsed.first.isV4Zero() || | |||
821 | (parsed.second > 32) || (parsed.second == 0)) { | |||
822 | isc_throw(BadValue, "unable to parse invalid IPv4 prefix " << prefix)do { std::ostringstream oss__; oss__ << "unable to parse invalid IPv4 prefix " << prefix; throw BadValue("../../../src/lib/dhcpsrv/subnet.cc" , 822, oss__.str().c_str()); } while (1); | |||
823 | } | |||
824 | return (parsed); | |||
825 | } | |||
826 | ||||
827 | void | |||
828 | Subnet6::createAllocators() { | |||
829 | auto allocator_type = getAllocatorType(); | |||
830 | if (allocator_type.empty()) { | |||
831 | allocator_type = getDefaultAllocatorType(); | |||
832 | } | |||
833 | if (allocator_type == "random") { | |||
834 | setAllocator(Lease::TYPE_NA, | |||
835 | boost::make_shared<RandomAllocator> | |||
836 | (Lease::TYPE_NA, shared_from_this())); | |||
837 | setAllocator(Lease::TYPE_TA, | |||
838 | boost::make_shared<RandomAllocator> | |||
839 | (Lease::TYPE_TA, shared_from_this())); | |||
840 | setAllocationState(Lease::TYPE_NA, SubnetAllocationStatePtr()); | |||
841 | setAllocationState(Lease::TYPE_TA, SubnetAllocationStatePtr()); | |||
842 | ||||
843 | } else if (allocator_type == "flq") { | |||
844 | isc_throw(BadValue, "Free Lease Queue allocator is not supported for IPv6 address pools")do { std::ostringstream oss__; oss__ << "Free Lease Queue allocator is not supported for IPv6 address pools" ; throw BadValue("../../../src/lib/dhcpsrv/subnet.cc", 844, oss__ .str().c_str()); } while (1); | |||
845 | ||||
846 | } else { | |||
847 | setAllocator(Lease::TYPE_NA, | |||
848 | boost::make_shared<IterativeAllocator> | |||
849 | (Lease::TYPE_NA, shared_from_this())); | |||
850 | setAllocationState(Lease::TYPE_NA, SubnetIterativeAllocationState::create(shared_from_this())); | |||
851 | setAllocationState(Lease::TYPE_TA, SubnetIterativeAllocationState::create(shared_from_this())); | |||
852 | } | |||
853 | ||||
854 | auto pd_allocator_type = getPdAllocatorType(); | |||
855 | if (pd_allocator_type.empty()) { | |||
856 | pd_allocator_type = getDefaultPdAllocatorType(); | |||
857 | } | |||
858 | // Repeat the same for the delegated prefix allocator. | |||
859 | if (pd_allocator_type == "random") { | |||
860 | setAllocator(Lease::TYPE_PD, | |||
861 | boost::make_shared<RandomAllocator> | |||
862 | (Lease::TYPE_PD, shared_from_this())); | |||
863 | setAllocationState(Lease::TYPE_PD, SubnetAllocationStatePtr()); | |||
864 | ||||
865 | } else if (pd_allocator_type == "flq") { | |||
866 | setAllocator(Lease::TYPE_PD, | |||
867 | boost::make_shared<FreeLeaseQueueAllocator> | |||
868 | (Lease::TYPE_PD, shared_from_this())); | |||
869 | setAllocationState(Lease::TYPE_PD, SubnetAllocationStatePtr()); | |||
870 | ||||
871 | } else { | |||
872 | setAllocator(Lease::TYPE_PD, | |||
873 | boost::make_shared<IterativeAllocator> | |||
874 | (Lease::TYPE_PD, shared_from_this())); | |||
875 | setAllocationState(Lease::TYPE_PD, SubnetIterativeAllocationState::create(shared_from_this())); | |||
876 | } | |||
877 | // Create allocation states for NA pools. | |||
878 | for (auto const& pool : pools_) { | |||
879 | if (allocator_type == "random") { | |||
880 | pool->setAllocationState(PoolRandomAllocationState::create(pool)); | |||
881 | } else { | |||
882 | pool->setAllocationState(PoolIterativeAllocationState::create(pool)); | |||
883 | } | |||
884 | } | |||
885 | // Create allocation states for TA pools. | |||
886 | for (auto const& pool : pools_ta_) { | |||
887 | if (allocator_type == "random") { | |||
888 | pool->setAllocationState(PoolRandomAllocationState::create(pool)); | |||
889 | } else { | |||
890 | pool->setAllocationState(PoolIterativeAllocationState::create(pool)); | |||
891 | } | |||
892 | } | |||
893 | // Create allocation states for PD pools. | |||
894 | for (auto const& pool : pools_pd_) { | |||
895 | if (pd_allocator_type == "random") { | |||
896 | pool->setAllocationState(PoolRandomAllocationState::create(pool)); | |||
897 | } else if (pd_allocator_type == "flq") { | |||
898 | pool->setAllocationState(PoolFreeLeaseQueueAllocationState::create(pool)); | |||
899 | } else { | |||
900 | pool->setAllocationState(PoolIterativeAllocationState::create(pool)); | |||
901 | } | |||
902 | } | |||
903 | } | |||
904 | ||||
905 | data::ElementPtr | |||
906 | Subnet6::toElement() const { | |||
907 | // Prepare the map | |||
908 | ElementPtr map = Subnet::toElement(); | |||
909 | ElementPtr network_map = Network6::toElement(); | |||
910 | ||||
911 | merge(map, network_map); | |||
912 | ||||
913 | // Set pools | |||
914 | auto const& pools = getPools(Lease::TYPE_NA); | |||
915 | ElementPtr pool_list = Element::createList(); | |||
916 | for (auto const& pool : pools) { | |||
917 | // Add the formatted pool to the list | |||
918 | pool_list->add(pool->toElement()); | |||
919 | } | |||
920 | map->set("pools", pool_list); | |||
921 | ||||
922 | // Set pd-pools | |||
923 | auto const& pdpools = getPools(Lease::TYPE_PD); | |||
924 | ElementPtr pdpool_list = Element::createList(); | |||
925 | for (auto const& pool : pdpools) { | |||
926 | // Add the formatted pool to the list | |||
927 | pdpool_list->add(pool->toElement()); | |||
928 | } | |||
929 | map->set("pd-pools", pdpool_list); | |||
930 | ||||
931 | return (map); | |||
932 | } | |||
933 | ||||
934 | std::pair<IOAddress, uint8_t> | |||
935 | Subnet6::parsePrefix(const std::string& prefix) { | |||
936 | std::pair<IOAddress, uint8_t> parsed = Subnet::parsePrefixCommon(prefix); | |||
937 | if (!parsed.first.isV6() || parsed.first.isV6Zero() || | |||
938 | (parsed.second > 128) || (parsed.second == 0)) { | |||
939 | isc_throw(BadValue, "unable to parse invalid IPv6 prefix " << prefix)do { std::ostringstream oss__; oss__ << "unable to parse invalid IPv6 prefix " << prefix; throw BadValue("../../../src/lib/dhcpsrv/subnet.cc" , 939, oss__.str().c_str()); } while (1); | |||
940 | } | |||
941 | return (parsed); | |||
942 | } | |||
943 | ||||
944 | } // namespace dhcp | |||
945 | } // namespace isc |
1 | #ifndef BOOST_SMART_PTR_MAKE_SHARED_OBJECT_HPP_INCLUDED |
2 | #define BOOST_SMART_PTR_MAKE_SHARED_OBJECT_HPP_INCLUDED |
3 | |
4 | // make_shared_object.hpp |
5 | // |
6 | // Copyright (c) 2007, 2008, 2012 Peter Dimov |
7 | // |
8 | // Distributed under the Boost Software License, Version 1.0. |
9 | // See accompanying file LICENSE_1_0.txt or copy at |
10 | // http://www.boost.org/LICENSE_1_0.txt |
11 | // |
12 | // See http://www.boost.org/libs/smart_ptr/ for documentation. |
13 | |
14 | #include <boost/smart_ptr/detail/requires_cxx11.hpp> |
15 | #include <boost/config.hpp> |
16 | #include <boost/move/core.hpp> |
17 | #include <boost/move/utility_core.hpp> |
18 | #include <boost/smart_ptr/shared_ptr.hpp> |
19 | #include <boost/smart_ptr/detail/sp_forward.hpp> |
20 | #include <boost/smart_ptr/detail/sp_noexcept.hpp> |
21 | #include <boost/type_traits/type_with_alignment.hpp> |
22 | #include <boost/type_traits/alignment_of.hpp> |
23 | #include <cstddef> |
24 | #include <new> |
25 | |
26 | namespace boost |
27 | { |
28 | |
29 | namespace detail |
30 | { |
31 | |
32 | template< std::size_t N, std::size_t A > struct sp_aligned_storage |
33 | { |
34 | union type |
35 | { |
36 | char data_[ N ]; |
37 | typename boost::type_with_alignment< A >::type align_; |
38 | }; |
39 | }; |
40 | |
41 | template< class T > class sp_ms_deleter |
42 | { |
43 | private: |
44 | |
45 | typedef typename sp_aligned_storage< sizeof( T ), ::boost::alignment_of< T >::value >::type storage_type; |
46 | |
47 | bool initialized_; |
48 | storage_type storage_; |
49 | |
50 | private: |
51 | |
52 | void destroy() BOOST_SP_NOEXCEPTnoexcept |
53 | { |
54 | if( initialized_ ) |
55 | { |
56 | #if defined( __GNUC__4 ) |
57 | |
58 | // fixes incorrect aliasing warning |
59 | T * p = reinterpret_cast< T* >( storage_.data_ ); |
60 | p->~T(); |
61 | |
62 | #else |
63 | |
64 | reinterpret_cast< T* >( storage_.data_ )->~T(); |
65 | |
66 | #endif |
67 | |
68 | initialized_ = false; |
69 | } |
70 | } |
71 | |
72 | public: |
73 | |
74 | sp_ms_deleter() BOOST_SP_NOEXCEPTnoexcept : initialized_( false ) |
75 | { |
76 | } |
77 | |
78 | template<class A> explicit sp_ms_deleter( A const & ) BOOST_SP_NOEXCEPTnoexcept : initialized_( false ) |
79 | { |
80 | } |
81 | |
82 | // optimization: do not copy storage_ |
83 | sp_ms_deleter( sp_ms_deleter const & ) BOOST_SP_NOEXCEPTnoexcept : initialized_( false ) |
84 | { |
85 | } |
86 | |
87 | ~sp_ms_deleter() BOOST_SP_NOEXCEPTnoexcept |
88 | { |
89 | destroy(); |
90 | } |
91 | |
92 | void operator()( T * ) BOOST_SP_NOEXCEPTnoexcept |
93 | { |
94 | destroy(); |
95 | } |
96 | |
97 | static void operator_fn( T* ) BOOST_SP_NOEXCEPTnoexcept // operator() can't be static |
98 | { |
99 | } |
100 | |
101 | void * address() BOOST_SP_NOEXCEPTnoexcept |
102 | { |
103 | return storage_.data_; |
104 | } |
105 | |
106 | void set_initialized() BOOST_SP_NOEXCEPTnoexcept |
107 | { |
108 | initialized_ = true; |
109 | } |
110 | }; |
111 | |
112 | template< class T, class A > class sp_as_deleter |
113 | { |
114 | private: |
115 | |
116 | typedef typename sp_aligned_storage< sizeof( T ), ::boost::alignment_of< T >::value >::type storage_type; |
117 | |
118 | storage_type storage_; |
119 | A a_; |
120 | bool initialized_; |
121 | |
122 | private: |
123 | |
124 | void destroy() BOOST_SP_NOEXCEPTnoexcept |
125 | { |
126 | if( initialized_ ) |
127 | { |
128 | T * p = reinterpret_cast< T* >( storage_.data_ ); |
129 | |
130 | #if !defined( BOOST_NO_CXX11_ALLOCATOR ) |
131 | |
132 | std::allocator_traits<A>::destroy( a_, p ); |
133 | |
134 | #else |
135 | |
136 | p->~T(); |
137 | |
138 | #endif |
139 | |
140 | initialized_ = false; |
141 | } |
142 | } |
143 | |
144 | public: |
145 | |
146 | sp_as_deleter( A const & a ) BOOST_SP_NOEXCEPTnoexcept : a_( a ), initialized_( false ) |
147 | { |
148 | } |
149 | |
150 | // optimization: do not copy storage_ |
151 | sp_as_deleter( sp_as_deleter const & r ) BOOST_SP_NOEXCEPTnoexcept : a_( r.a_), initialized_( false ) |
152 | { |
153 | } |
154 | |
155 | ~sp_as_deleter() BOOST_SP_NOEXCEPTnoexcept |
156 | { |
157 | destroy(); |
158 | } |
159 | |
160 | void operator()( T * ) BOOST_SP_NOEXCEPTnoexcept |
161 | { |
162 | destroy(); |
163 | } |
164 | |
165 | static void operator_fn( T* ) BOOST_SP_NOEXCEPTnoexcept // operator() can't be static |
166 | { |
167 | } |
168 | |
169 | void * address() BOOST_SP_NOEXCEPTnoexcept |
170 | { |
171 | return storage_.data_; |
172 | } |
173 | |
174 | void set_initialized() BOOST_SP_NOEXCEPTnoexcept |
175 | { |
176 | initialized_ = true; |
177 | } |
178 | }; |
179 | |
180 | template< class T > struct sp_if_not_array |
181 | { |
182 | typedef boost::shared_ptr< T > type; |
183 | }; |
184 | |
185 | #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) |
186 | |
187 | template< class T > struct sp_if_not_array< T[] > |
188 | { |
189 | }; |
190 | |
191 | #if !defined( BOOST_BORLANDC ) || !BOOST_WORKAROUND( BOOST_BORLANDC, < 0x600 )((1 + 0 == 0) && (BOOST_BORLANDC != 0) && (1 % (( (BOOST_BORLANDC < 0x600) ) + 1))) |
192 | |
193 | template< class T, std::size_t N > struct sp_if_not_array< T[N] > |
194 | { |
195 | }; |
196 | |
197 | #endif |
198 | |
199 | #endif |
200 | |
201 | } // namespace detail |
202 | |
203 | #if !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING ) |
204 | # define BOOST_SP_MSD( T ) boost::detail::sp_inplace_tag< boost::detail::sp_ms_deleter< T > >() |
205 | #else |
206 | # define BOOST_SP_MSD( T ) boost::detail::sp_ms_deleter< T >() |
207 | #endif |
208 | |
209 | // _noinit versions |
210 | |
211 | template< class T > typename boost::detail::sp_if_not_array< T >::type make_shared_noinit() |
212 | { |
213 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); |
214 | |
215 | boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() ); |
216 | |
217 | void * pv = pd->address(); |
218 | |
219 | ::new( pv ) T; |
220 | pd->set_initialized(); |
221 | |
222 | T * pt2 = static_cast< T* >( pv ); |
223 | |
224 | boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); |
225 | return boost::shared_ptr< T >( pt, pt2 ); |
226 | } |
227 | |
228 | template< class T, class A > typename boost::detail::sp_if_not_array< T >::type allocate_shared_noinit( A const & a ) |
229 | { |
230 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); |
231 | |
232 | boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() ); |
233 | |
234 | void * pv = pd->address(); |
235 | |
236 | ::new( pv ) T; |
237 | pd->set_initialized(); |
238 | |
239 | T * pt2 = static_cast< T* >( pv ); |
240 | |
241 | boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); |
242 | return boost::shared_ptr< T >( pt, pt2 ); |
243 | } |
244 | |
245 | #if !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) |
246 | |
247 | // Variadic templates, rvalue reference |
248 | |
249 | template< class T, class... Args > typename boost::detail::sp_if_not_array< T >::type make_shared( Args && ... args ) |
250 | { |
251 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); |
252 | |
253 | boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() ); |
254 | |
255 | void * pv = pd->address(); |
256 | |
257 | ::new( pv ) T( boost::detail::sp_forward<Args>( args )... ); |
258 | pd->set_initialized(); |
259 | |
260 | T * pt2 = static_cast< T* >( pv ); |
261 | |
262 | boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); |
263 | return boost::shared_ptr< T >( pt, pt2 ); |
264 | } |
265 | |
266 | template< class T, class A, class... Args > typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, Args && ... args ) |
267 | { |
268 | #if !defined( BOOST_NO_CXX11_ALLOCATOR ) |
269 | |
270 | typedef typename std::allocator_traits<A>::template rebind_alloc<T> A2; |
271 | A2 a2( a ); |
272 | |
273 | typedef boost::detail::sp_as_deleter< T, A2 > D; |
274 | |
275 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_inplace_tag<D>(), a2 ); |
276 | |
277 | #else |
278 | |
279 | typedef boost::detail::sp_ms_deleter< T > D; |
280 | |
281 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_inplace_tag<D>(), a ); |
282 | |
283 | #endif |
284 | |
285 | D * pd = static_cast< D* >( pt._internal_get_untyped_deleter() ); |
286 | void * pv = pd->address(); |
287 | |
288 | #if !defined( BOOST_NO_CXX11_ALLOCATOR ) |
289 | |
290 | std::allocator_traits<A2>::construct( a2, static_cast< T* >( pv ), boost::detail::sp_forward<Args>( args )... ); |
291 | |
292 | #else |
293 | |
294 | ::new( pv ) T( boost::detail::sp_forward<Args>( args )... ); |
295 | |
296 | #endif |
297 | |
298 | pd->set_initialized(); |
299 | |
300 | T * pt2 = static_cast< T* >( pv ); |
301 | |
302 | boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); |
303 | return boost::shared_ptr< T >( pt, pt2 ); |
304 | } |
305 | |
306 | #else // !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) |
307 | |
308 | // Common zero-argument versions |
309 | |
310 | template< class T > typename boost::detail::sp_if_not_array< T >::type make_shared() |
311 | { |
312 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); |
313 | |
314 | boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() ); |
315 | |
316 | void * pv = pd->address(); |
317 | |
318 | ::new( pv ) T(); |
319 | pd->set_initialized(); |
320 | |
321 | T * pt2 = static_cast< T* >( pv ); |
322 | |
323 | boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); |
324 | return boost::shared_ptr< T >( pt, pt2 ); |
325 | } |
326 | |
327 | template< class T, class A > typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a ) |
328 | { |
329 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); |
330 | |
331 | boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() ); |
332 | |
333 | void * pv = pd->address(); |
334 | |
335 | ::new( pv ) T(); |
336 | pd->set_initialized(); |
337 | |
338 | T * pt2 = static_cast< T* >( pv ); |
339 | |
340 | boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); |
341 | return boost::shared_ptr< T >( pt, pt2 ); |
342 | } |
343 | |
344 | // C++03 version |
345 | |
346 | template< class T, class A1 > |
347 | typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1)A1 && a1 ) |
348 | { |
349 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); |
350 | |
351 | boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() ); |
352 | |
353 | void * pv = pd->address(); |
354 | |
355 | ::new( pv ) T( |
356 | boost::forward<A1>( a1 ) |
357 | ); |
358 | |
359 | pd->set_initialized(); |
360 | |
361 | T * pt2 = static_cast< T* >( pv ); |
362 | |
363 | boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); |
364 | return boost::shared_ptr< T >( pt, pt2 ); |
365 | } |
366 | |
367 | template< class T, class A, class A1 > |
368 | typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1)A1 && a1 ) |
369 | { |
370 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); |
371 | |
372 | boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() ); |
373 | |
374 | void * pv = pd->address(); |
375 | |
376 | ::new( pv ) T( |
377 | boost::forward<A1>( a1 ) |
378 | ); |
379 | |
380 | pd->set_initialized(); |
381 | |
382 | T * pt2 = static_cast< T* >( pv ); |
383 | |
384 | boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); |
385 | return boost::shared_ptr< T >( pt, pt2 ); |
386 | } |
387 | |
388 | template< class T, class A1, class A2 > |
389 | typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2 ) |
390 | { |
391 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); |
392 | |
393 | boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() ); |
394 | |
395 | void * pv = pd->address(); |
396 | |
397 | ::new( pv ) T( |
398 | boost::forward<A1>( a1 ), |
399 | boost::forward<A2>( a2 ) |
400 | ); |
401 | |
402 | pd->set_initialized(); |
403 | |
404 | T * pt2 = static_cast< T* >( pv ); |
405 | |
406 | boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); |
407 | return boost::shared_ptr< T >( pt, pt2 ); |
408 | } |
409 | |
410 | template< class T, class A, class A1, class A2 > |
411 | typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2 ) |
412 | { |
413 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); |
414 | |
415 | boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() ); |
416 | |
417 | void * pv = pd->address(); |
418 | |
419 | ::new( pv ) T( |
420 | boost::forward<A1>( a1 ), |
421 | boost::forward<A2>( a2 ) |
422 | ); |
423 | |
424 | pd->set_initialized(); |
425 | |
426 | T * pt2 = static_cast< T* >( pv ); |
427 | |
428 | boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); |
429 | return boost::shared_ptr< T >( pt, pt2 ); |
430 | } |
431 | |
432 | template< class T, class A1, class A2, class A3 > |
433 | typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2, BOOST_FWD_REF(A3)A3 && a3 ) |
434 | { |
435 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); |
436 | |
437 | boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() ); |
438 | |
439 | void * pv = pd->address(); |
440 | |
441 | ::new( pv ) T( |
442 | boost::forward<A1>( a1 ), |
443 | boost::forward<A2>( a2 ), |
444 | boost::forward<A3>( a3 ) |
445 | ); |
446 | |
447 | pd->set_initialized(); |
448 | |
449 | T * pt2 = static_cast< T* >( pv ); |
450 | |
451 | boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); |
452 | return boost::shared_ptr< T >( pt, pt2 ); |
453 | } |
454 | |
455 | template< class T, class A, class A1, class A2, class A3 > |
456 | typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2, BOOST_FWD_REF(A3)A3 && a3 ) |
457 | { |
458 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); |
459 | |
460 | boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() ); |
461 | |
462 | void * pv = pd->address(); |
463 | |
464 | ::new( pv ) T( |
465 | boost::forward<A1>( a1 ), |
466 | boost::forward<A2>( a2 ), |
467 | boost::forward<A3>( a3 ) |
468 | ); |
469 | |
470 | pd->set_initialized(); |
471 | |
472 | T * pt2 = static_cast< T* >( pv ); |
473 | |
474 | boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); |
475 | return boost::shared_ptr< T >( pt, pt2 ); |
476 | } |
477 | |
478 | template< class T, class A1, class A2, class A3, class A4 > |
479 | typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2, BOOST_FWD_REF(A3)A3 && a3, BOOST_FWD_REF(A4)A4 && a4 ) |
480 | { |
481 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); |
482 | |
483 | boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() ); |
484 | |
485 | void * pv = pd->address(); |
486 | |
487 | ::new( pv ) T( |
488 | boost::forward<A1>( a1 ), |
489 | boost::forward<A2>( a2 ), |
490 | boost::forward<A3>( a3 ), |
491 | boost::forward<A4>( a4 ) |
492 | ); |
493 | |
494 | pd->set_initialized(); |
495 | |
496 | T * pt2 = static_cast< T* >( pv ); |
497 | |
498 | boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); |
499 | return boost::shared_ptr< T >( pt, pt2 ); |
500 | } |
501 | |
502 | template< class T, class A, class A1, class A2, class A3, class A4 > |
503 | typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2, BOOST_FWD_REF(A3)A3 && a3, BOOST_FWD_REF(A4)A4 && a4 ) |
504 | { |
505 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); |
506 | |
507 | boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() ); |
508 | |
509 | void * pv = pd->address(); |
510 | |
511 | ::new( pv ) T( |
512 | boost::forward<A1>( a1 ), |
513 | boost::forward<A2>( a2 ), |
514 | boost::forward<A3>( a3 ), |
515 | boost::forward<A4>( a4 ) |
516 | ); |
517 | |
518 | pd->set_initialized(); |
519 | |
520 | T * pt2 = static_cast< T* >( pv ); |
521 | |
522 | boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); |
523 | return boost::shared_ptr< T >( pt, pt2 ); |
524 | } |
525 | |
526 | template< class T, class A1, class A2, class A3, class A4, class A5 > |
527 | typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2, BOOST_FWD_REF(A3)A3 && a3, BOOST_FWD_REF(A4)A4 && a4, BOOST_FWD_REF(A5)A5 && a5 ) |
528 | { |
529 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); |
530 | |
531 | boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() ); |
532 | |
533 | void * pv = pd->address(); |
534 | |
535 | ::new( pv ) T( |
536 | boost::forward<A1>( a1 ), |
537 | boost::forward<A2>( a2 ), |
538 | boost::forward<A3>( a3 ), |
539 | boost::forward<A4>( a4 ), |
540 | boost::forward<A5>( a5 ) |
541 | ); |
542 | |
543 | pd->set_initialized(); |
544 | |
545 | T * pt2 = static_cast< T* >( pv ); |
546 | |
547 | boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); |
548 | return boost::shared_ptr< T >( pt, pt2 ); |
549 | } |
550 | |
551 | template< class T, class A, class A1, class A2, class A3, class A4, class A5 > |
552 | typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2, BOOST_FWD_REF(A3)A3 && a3, BOOST_FWD_REF(A4)A4 && a4, BOOST_FWD_REF(A5)A5 && a5 ) |
553 | { |
554 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); |
555 | |
556 | boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() ); |
557 | |
558 | void * pv = pd->address(); |
559 | |
560 | ::new( pv ) T( |
561 | boost::forward<A1>( a1 ), |
562 | boost::forward<A2>( a2 ), |
563 | boost::forward<A3>( a3 ), |
564 | boost::forward<A4>( a4 ), |
565 | boost::forward<A5>( a5 ) |
566 | ); |
567 | |
568 | pd->set_initialized(); |
569 | |
570 | T * pt2 = static_cast< T* >( pv ); |
571 | |
572 | boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); |
573 | return boost::shared_ptr< T >( pt, pt2 ); |
574 | } |
575 | |
576 | template< class T, class A1, class A2, class A3, class A4, class A5, class A6 > |
577 | typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2, BOOST_FWD_REF(A3)A3 && a3, BOOST_FWD_REF(A4)A4 && a4, BOOST_FWD_REF(A5)A5 && a5, BOOST_FWD_REF(A6)A6 && a6 ) |
578 | { |
579 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); |
580 | |
581 | boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() ); |
582 | |
583 | void * pv = pd->address(); |
584 | |
585 | ::new( pv ) T( |
586 | boost::forward<A1>( a1 ), |
587 | boost::forward<A2>( a2 ), |
588 | boost::forward<A3>( a3 ), |
589 | boost::forward<A4>( a4 ), |
590 | boost::forward<A5>( a5 ), |
591 | boost::forward<A6>( a6 ) |
592 | ); |
593 | |
594 | pd->set_initialized(); |
595 | |
596 | T * pt2 = static_cast< T* >( pv ); |
597 | |
598 | boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); |
599 | return boost::shared_ptr< T >( pt, pt2 ); |
600 | } |
601 | |
602 | template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6 > |
603 | typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2, BOOST_FWD_REF(A3)A3 && a3, BOOST_FWD_REF(A4)A4 && a4, BOOST_FWD_REF(A5)A5 && a5, BOOST_FWD_REF(A6)A6 && a6 ) |
604 | { |
605 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); |
606 | |
607 | boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() ); |
608 | |
609 | void * pv = pd->address(); |
610 | |
611 | ::new( pv ) T( |
612 | boost::forward<A1>( a1 ), |
613 | boost::forward<A2>( a2 ), |
614 | boost::forward<A3>( a3 ), |
615 | boost::forward<A4>( a4 ), |
616 | boost::forward<A5>( a5 ), |
617 | boost::forward<A6>( a6 ) |
618 | ); |
619 | |
620 | pd->set_initialized(); |
621 | |
622 | T * pt2 = static_cast< T* >( pv ); |
623 | |
624 | boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); |
625 | return boost::shared_ptr< T >( pt, pt2 ); |
626 | } |
627 | |
628 | template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 > |
629 | typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2, BOOST_FWD_REF(A3)A3 && a3, BOOST_FWD_REF(A4)A4 && a4, BOOST_FWD_REF(A5)A5 && a5, BOOST_FWD_REF(A6)A6 && a6, BOOST_FWD_REF(A7)A7 && a7 ) |
630 | { |
631 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); |
632 | |
633 | boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() ); |
634 | |
635 | void * pv = pd->address(); |
636 | |
637 | ::new( pv ) T( |
638 | boost::forward<A1>( a1 ), |
639 | boost::forward<A2>( a2 ), |
640 | boost::forward<A3>( a3 ), |
641 | boost::forward<A4>( a4 ), |
642 | boost::forward<A5>( a5 ), |
643 | boost::forward<A6>( a6 ), |
644 | boost::forward<A7>( a7 ) |
645 | ); |
646 | |
647 | pd->set_initialized(); |
648 | |
649 | T * pt2 = static_cast< T* >( pv ); |
650 | |
651 | boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); |
652 | return boost::shared_ptr< T >( pt, pt2 ); |
653 | } |
654 | |
655 | template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7 > |
656 | typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2, BOOST_FWD_REF(A3)A3 && a3, BOOST_FWD_REF(A4)A4 && a4, BOOST_FWD_REF(A5)A5 && a5, BOOST_FWD_REF(A6)A6 && a6, BOOST_FWD_REF(A7)A7 && a7 ) |
657 | { |
658 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); |
659 | |
660 | boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() ); |
661 | |
662 | void * pv = pd->address(); |
663 | |
664 | ::new( pv ) T( |
665 | boost::forward<A1>( a1 ), |
666 | boost::forward<A2>( a2 ), |
667 | boost::forward<A3>( a3 ), |
668 | boost::forward<A4>( a4 ), |
669 | boost::forward<A5>( a5 ), |
670 | boost::forward<A6>( a6 ), |
671 | boost::forward<A7>( a7 ) |
672 | ); |
673 | |
674 | pd->set_initialized(); |
675 | |
676 | T * pt2 = static_cast< T* >( pv ); |
677 | |
678 | boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); |
679 | return boost::shared_ptr< T >( pt, pt2 ); |
680 | } |
681 | |
682 | template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 > |
683 | typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2, BOOST_FWD_REF(A3)A3 && a3, BOOST_FWD_REF(A4)A4 && a4, BOOST_FWD_REF(A5)A5 && a5, BOOST_FWD_REF(A6)A6 && a6, BOOST_FWD_REF(A7)A7 && a7, BOOST_FWD_REF(A8)A8 && a8 ) |
684 | { |
685 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); |
686 | |
687 | boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() ); |
688 | |
689 | void * pv = pd->address(); |
690 | |
691 | ::new( pv ) T( |
692 | boost::forward<A1>( a1 ), |
693 | boost::forward<A2>( a2 ), |
694 | boost::forward<A3>( a3 ), |
695 | boost::forward<A4>( a4 ), |
696 | boost::forward<A5>( a5 ), |
697 | boost::forward<A6>( a6 ), |
698 | boost::forward<A7>( a7 ), |
699 | boost::forward<A8>( a8 ) |
700 | ); |
701 | |
702 | pd->set_initialized(); |
703 | |
704 | T * pt2 = static_cast< T* >( pv ); |
705 | |
706 | boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); |
707 | return boost::shared_ptr< T >( pt, pt2 ); |
708 | } |
709 | |
710 | template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 > |
711 | typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2, BOOST_FWD_REF(A3)A3 && a3, BOOST_FWD_REF(A4)A4 && a4, BOOST_FWD_REF(A5)A5 && a5, BOOST_FWD_REF(A6)A6 && a6, BOOST_FWD_REF(A7)A7 && a7, BOOST_FWD_REF(A8)A8 && a8 ) |
712 | { |
713 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); |
714 | |
715 | boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() ); |
716 | |
717 | void * pv = pd->address(); |
718 | |
719 | ::new( pv ) T( |
720 | boost::forward<A1>( a1 ), |
721 | boost::forward<A2>( a2 ), |
722 | boost::forward<A3>( a3 ), |
723 | boost::forward<A4>( a4 ), |
724 | boost::forward<A5>( a5 ), |
725 | boost::forward<A6>( a6 ), |
726 | boost::forward<A7>( a7 ), |
727 | boost::forward<A8>( a8 ) |
728 | ); |
729 | |
730 | pd->set_initialized(); |
731 | |
732 | T * pt2 = static_cast< T* >( pv ); |
733 | |
734 | boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); |
735 | return boost::shared_ptr< T >( pt, pt2 ); |
736 | } |
737 | |
738 | template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 > |
739 | typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2, BOOST_FWD_REF(A3)A3 && a3, BOOST_FWD_REF(A4)A4 && a4, BOOST_FWD_REF(A5)A5 && a5, BOOST_FWD_REF(A6)A6 && a6, BOOST_FWD_REF(A7)A7 && a7, BOOST_FWD_REF(A8)A8 && a8, BOOST_FWD_REF(A9)A9 && a9 ) |
740 | { |
741 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); |
742 | |
743 | boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() ); |
744 | |
745 | void * pv = pd->address(); |
746 | |
747 | ::new( pv ) T( |
748 | boost::forward<A1>( a1 ), |
749 | boost::forward<A2>( a2 ), |
750 | boost::forward<A3>( a3 ), |
751 | boost::forward<A4>( a4 ), |
752 | boost::forward<A5>( a5 ), |
753 | boost::forward<A6>( a6 ), |
754 | boost::forward<A7>( a7 ), |
755 | boost::forward<A8>( a8 ), |
756 | boost::forward<A9>( a9 ) |
757 | ); |
758 | |
759 | pd->set_initialized(); |
760 | |
761 | T * pt2 = static_cast< T* >( pv ); |
762 | |
763 | boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); |
764 | return boost::shared_ptr< T >( pt, pt2 ); |
765 | } |
766 | |
767 | template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 > |
768 | typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2, BOOST_FWD_REF(A3)A3 && a3, BOOST_FWD_REF(A4)A4 && a4, BOOST_FWD_REF(A5)A5 && a5, BOOST_FWD_REF(A6)A6 && a6, BOOST_FWD_REF(A7)A7 && a7, BOOST_FWD_REF(A8)A8 && a8, BOOST_FWD_REF(A9)A9 && a9 ) |
769 | { |
770 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); |
771 | |
772 | boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() ); |
773 | |
774 | void * pv = pd->address(); |
775 | |
776 | ::new( pv ) T( |
777 | boost::forward<A1>( a1 ), |
778 | boost::forward<A2>( a2 ), |
779 | boost::forward<A3>( a3 ), |
780 | boost::forward<A4>( a4 ), |
781 | boost::forward<A5>( a5 ), |
782 | boost::forward<A6>( a6 ), |
783 | boost::forward<A7>( a7 ), |
784 | boost::forward<A8>( a8 ), |
785 | boost::forward<A9>( a9 ) |
786 | ); |
787 | |
788 | pd->set_initialized(); |
789 | |
790 | T * pt2 = static_cast< T* >( pv ); |
791 | |
792 | boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); |
793 | return boost::shared_ptr< T >( pt, pt2 ); |
794 | } |
795 | |
796 | #endif // !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) |
797 | |
798 | #undef BOOST_SP_MSD |
799 | |
800 | } // namespace boost |
801 | |
802 | #endif // #ifndef BOOST_SMART_PTR_MAKE_SHARED_OBJECT_HPP_INCLUDED |
1 | #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED | ||||||||||||||
2 | #define BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED | ||||||||||||||
3 | |||||||||||||||
4 | // | ||||||||||||||
5 | // shared_ptr.hpp | ||||||||||||||
6 | // | ||||||||||||||
7 | // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. | ||||||||||||||
8 | // Copyright (c) 2001-2008 Peter Dimov | ||||||||||||||
9 | // | ||||||||||||||
10 | // Distributed under the Boost Software License, Version 1.0. (See | ||||||||||||||
11 | // accompanying file LICENSE_1_0.txt or copy at | ||||||||||||||
12 | // http://www.boost.org/LICENSE_1_0.txt) | ||||||||||||||
13 | // | ||||||||||||||
14 | // See http://www.boost.org/libs/smart_ptr/ for documentation. | ||||||||||||||
15 | // | ||||||||||||||
16 | |||||||||||||||
17 | #include <boost/smart_ptr/detail/requires_cxx11.hpp> | ||||||||||||||
18 | #include <boost/smart_ptr/detail/shared_count.hpp> | ||||||||||||||
19 | #include <boost/smart_ptr/detail/sp_convertible.hpp> | ||||||||||||||
20 | #include <boost/smart_ptr/detail/sp_nullptr_t.hpp> | ||||||||||||||
21 | #include <boost/smart_ptr/detail/sp_disable_deprecated.hpp> | ||||||||||||||
22 | #include <boost/smart_ptr/detail/sp_noexcept.hpp> | ||||||||||||||
23 | #include <boost/core/checked_delete.hpp> | ||||||||||||||
24 | #include <boost/throw_exception.hpp> | ||||||||||||||
25 | #include <boost/assert.hpp> | ||||||||||||||
26 | #include <boost/config.hpp> | ||||||||||||||
27 | #include <boost/config/workaround.hpp> | ||||||||||||||
28 | |||||||||||||||
29 | #if !defined(BOOST_SP_NO_ATOMIC_ACCESS) | ||||||||||||||
30 | #include <boost/smart_ptr/detail/spinlock_pool.hpp> | ||||||||||||||
31 | #endif | ||||||||||||||
32 | |||||||||||||||
33 | #include <algorithm> // for std::swap | ||||||||||||||
34 | #include <functional> // for std::less | ||||||||||||||
35 | #include <typeinfo> // for std::bad_cast | ||||||||||||||
36 | #include <cstddef> // for std::size_t | ||||||||||||||
37 | #include <memory> // for std::auto_ptr | ||||||||||||||
38 | |||||||||||||||
39 | #if !defined(BOOST_NO_IOSTREAM) | ||||||||||||||
40 | #if !defined(BOOST_NO_IOSFWD) | ||||||||||||||
41 | #include <iosfwd> // for std::basic_ostream | ||||||||||||||
42 | #else | ||||||||||||||
43 | #include <ostream> | ||||||||||||||
44 | #endif | ||||||||||||||
45 | #endif | ||||||||||||||
46 | |||||||||||||||
47 | #if defined( BOOST_SP_DISABLE_DEPRECATED ) | ||||||||||||||
48 | #pragma GCC diagnostic push | ||||||||||||||
49 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" | ||||||||||||||
50 | #endif | ||||||||||||||
51 | |||||||||||||||
52 | namespace boost | ||||||||||||||
53 | { | ||||||||||||||
54 | |||||||||||||||
55 | template<class T> class shared_ptr; | ||||||||||||||
56 | template<class T> class weak_ptr; | ||||||||||||||
57 | template<class T> class enable_shared_from_this; | ||||||||||||||
58 | class enable_shared_from_raw; | ||||||||||||||
59 | |||||||||||||||
60 | namespace movelib | ||||||||||||||
61 | { | ||||||||||||||
62 | |||||||||||||||
63 | template< class T, class D > class unique_ptr; | ||||||||||||||
64 | |||||||||||||||
65 | } // namespace movelib | ||||||||||||||
66 | |||||||||||||||
67 | namespace detail | ||||||||||||||
68 | { | ||||||||||||||
69 | |||||||||||||||
70 | // sp_element, element_type | ||||||||||||||
71 | |||||||||||||||
72 | template< class T > struct sp_element | ||||||||||||||
73 | { | ||||||||||||||
74 | typedef T type; | ||||||||||||||
75 | }; | ||||||||||||||
76 | |||||||||||||||
77 | #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | ||||||||||||||
78 | |||||||||||||||
79 | template< class T > struct sp_element< T[] > | ||||||||||||||
80 | { | ||||||||||||||
81 | typedef T type; | ||||||||||||||
82 | }; | ||||||||||||||
83 | |||||||||||||||
84 | #if !defined( BOOST_BORLANDC ) || !BOOST_WORKAROUND( BOOST_BORLANDC, < 0x600 )((1 + 0 == 0) && (BOOST_BORLANDC != 0) && (1 % (( (BOOST_BORLANDC < 0x600) ) + 1))) | ||||||||||||||
85 | |||||||||||||||
86 | template< class T, std::size_t N > struct sp_element< T[N] > | ||||||||||||||
87 | { | ||||||||||||||
88 | typedef T type; | ||||||||||||||
89 | }; | ||||||||||||||
90 | |||||||||||||||
91 | #endif | ||||||||||||||
92 | |||||||||||||||
93 | #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | ||||||||||||||
94 | |||||||||||||||
95 | // sp_dereference, return type of operator* | ||||||||||||||
96 | |||||||||||||||
97 | template< class T > struct sp_dereference | ||||||||||||||
98 | { | ||||||||||||||
99 | typedef T & type; | ||||||||||||||
100 | }; | ||||||||||||||
101 | |||||||||||||||
102 | template<> struct sp_dereference< void > | ||||||||||||||
103 | { | ||||||||||||||
104 | typedef void type; | ||||||||||||||
105 | }; | ||||||||||||||
106 | |||||||||||||||
107 | #if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS) | ||||||||||||||
108 | |||||||||||||||
109 | template<> struct sp_dereference< void const > | ||||||||||||||
110 | { | ||||||||||||||
111 | typedef void type; | ||||||||||||||
112 | }; | ||||||||||||||
113 | |||||||||||||||
114 | template<> struct sp_dereference< void volatile > | ||||||||||||||
115 | { | ||||||||||||||
116 | typedef void type; | ||||||||||||||
117 | }; | ||||||||||||||
118 | |||||||||||||||
119 | template<> struct sp_dereference< void const volatile > | ||||||||||||||
120 | { | ||||||||||||||
121 | typedef void type; | ||||||||||||||
122 | }; | ||||||||||||||
123 | |||||||||||||||
124 | #endif // !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS) | ||||||||||||||
125 | |||||||||||||||
126 | #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | ||||||||||||||
127 | |||||||||||||||
128 | template< class T > struct sp_dereference< T[] > | ||||||||||||||
129 | { | ||||||||||||||
130 | typedef void type; | ||||||||||||||
131 | }; | ||||||||||||||
132 | |||||||||||||||
133 | #if !defined( BOOST_BORLANDC ) || !BOOST_WORKAROUND( BOOST_BORLANDC, < 0x600 )((1 + 0 == 0) && (BOOST_BORLANDC != 0) && (1 % (( (BOOST_BORLANDC < 0x600) ) + 1))) | ||||||||||||||
134 | |||||||||||||||
135 | template< class T, std::size_t N > struct sp_dereference< T[N] > | ||||||||||||||
136 | { | ||||||||||||||
137 | typedef void type; | ||||||||||||||
138 | }; | ||||||||||||||
139 | |||||||||||||||
140 | #endif | ||||||||||||||
141 | |||||||||||||||
142 | #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | ||||||||||||||
143 | |||||||||||||||
144 | // sp_member_access, return type of operator-> | ||||||||||||||
145 | |||||||||||||||
146 | template< class T > struct sp_member_access | ||||||||||||||
147 | { | ||||||||||||||
148 | typedef T * type; | ||||||||||||||
149 | }; | ||||||||||||||
150 | |||||||||||||||
151 | #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | ||||||||||||||
152 | |||||||||||||||
153 | template< class T > struct sp_member_access< T[] > | ||||||||||||||
154 | { | ||||||||||||||
155 | typedef void type; | ||||||||||||||
156 | }; | ||||||||||||||
157 | |||||||||||||||
158 | #if !defined( BOOST_BORLANDC ) || !BOOST_WORKAROUND( BOOST_BORLANDC, < 0x600 )((1 + 0 == 0) && (BOOST_BORLANDC != 0) && (1 % (( (BOOST_BORLANDC < 0x600) ) + 1))) | ||||||||||||||
159 | |||||||||||||||
160 | template< class T, std::size_t N > struct sp_member_access< T[N] > | ||||||||||||||
161 | { | ||||||||||||||
162 | typedef void type; | ||||||||||||||
163 | }; | ||||||||||||||
164 | |||||||||||||||
165 | #endif | ||||||||||||||
166 | |||||||||||||||
167 | #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | ||||||||||||||
168 | |||||||||||||||
169 | // sp_array_access, return type of operator[] | ||||||||||||||
170 | |||||||||||||||
171 | template< class T > struct sp_array_access | ||||||||||||||
172 | { | ||||||||||||||
173 | typedef void type; | ||||||||||||||
174 | }; | ||||||||||||||
175 | |||||||||||||||
176 | #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | ||||||||||||||
177 | |||||||||||||||
178 | template< class T > struct sp_array_access< T[] > | ||||||||||||||
179 | { | ||||||||||||||
180 | typedef T & type; | ||||||||||||||
181 | }; | ||||||||||||||
182 | |||||||||||||||
183 | #if !defined( BOOST_BORLANDC ) || !BOOST_WORKAROUND( BOOST_BORLANDC, < 0x600 )((1 + 0 == 0) && (BOOST_BORLANDC != 0) && (1 % (( (BOOST_BORLANDC < 0x600) ) + 1))) | ||||||||||||||
184 | |||||||||||||||
185 | template< class T, std::size_t N > struct sp_array_access< T[N] > | ||||||||||||||
186 | { | ||||||||||||||
187 | typedef T & type; | ||||||||||||||
188 | }; | ||||||||||||||
189 | |||||||||||||||
190 | #endif | ||||||||||||||
191 | |||||||||||||||
192 | #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | ||||||||||||||
193 | |||||||||||||||
194 | // sp_extent, for operator[] index check | ||||||||||||||
195 | |||||||||||||||
196 | template< class T > struct sp_extent | ||||||||||||||
197 | { | ||||||||||||||
198 | enum _vt { value = 0 }; | ||||||||||||||
199 | }; | ||||||||||||||
200 | |||||||||||||||
201 | #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | ||||||||||||||
202 | |||||||||||||||
203 | template< class T, std::size_t N > struct sp_extent< T[N] > | ||||||||||||||
204 | { | ||||||||||||||
205 | enum _vt { value = N }; | ||||||||||||||
206 | }; | ||||||||||||||
207 | |||||||||||||||
208 | #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | ||||||||||||||
209 | |||||||||||||||
210 | // enable_shared_from_this support | ||||||||||||||
211 | |||||||||||||||
212 | 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 ) | ||||||||||||||
213 | { | ||||||||||||||
214 | if( pe
| ||||||||||||||
215 | { | ||||||||||||||
216 | pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) ); | ||||||||||||||
217 | } | ||||||||||||||
218 | } | ||||||||||||||
219 | |||||||||||||||
220 | template< class X, class Y > inline void sp_enable_shared_from_this( boost::shared_ptr<X> * ppx, Y const * py, boost::enable_shared_from_raw const * pe ); | ||||||||||||||
221 | |||||||||||||||
222 | #ifdef _MANAGED | ||||||||||||||
223 | |||||||||||||||
224 | // Avoid C4793, ... causes native code generation | ||||||||||||||
225 | |||||||||||||||
226 | struct sp_any_pointer | ||||||||||||||
227 | { | ||||||||||||||
228 | template<class T> sp_any_pointer( T* ) {} | ||||||||||||||
229 | }; | ||||||||||||||
230 | |||||||||||||||
231 | inline void sp_enable_shared_from_this( sp_any_pointer, sp_any_pointer, sp_any_pointer ) | ||||||||||||||
232 | { | ||||||||||||||
233 | } | ||||||||||||||
234 | |||||||||||||||
235 | #else // _MANAGED | ||||||||||||||
236 | |||||||||||||||
237 | inline void sp_enable_shared_from_this( ... ) | ||||||||||||||
238 | { | ||||||||||||||
239 | } | ||||||||||||||
240 | |||||||||||||||
241 | #endif // _MANAGED | ||||||||||||||
242 | |||||||||||||||
243 | #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR ) | ||||||||||||||
244 | |||||||||||||||
245 | // rvalue auto_ptr support based on a technique by Dave Abrahams | ||||||||||||||
246 | |||||||||||||||
247 | template< class T, class R > struct sp_enable_if_auto_ptr | ||||||||||||||
248 | { | ||||||||||||||
249 | }; | ||||||||||||||
250 | |||||||||||||||
251 | template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R > | ||||||||||||||
252 | { | ||||||||||||||
253 | typedef R type; | ||||||||||||||
254 | }; | ||||||||||||||
255 | |||||||||||||||
256 | #endif | ||||||||||||||
257 | |||||||||||||||
258 | // sp_assert_convertible | ||||||||||||||
259 | |||||||||||||||
260 | template< class Y, class T > inline void sp_assert_convertible() BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
261 | { | ||||||||||||||
262 | #if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) | ||||||||||||||
263 | |||||||||||||||
264 | // static_assert( sp_convertible< Y, T >::value ); | ||||||||||||||
265 | typedef char tmp[ sp_convertible< Y, T >::value? 1: -1 ]; | ||||||||||||||
266 | (void)sizeof( tmp ); | ||||||||||||||
267 | |||||||||||||||
268 | #else | ||||||||||||||
269 | |||||||||||||||
270 | T* p = static_cast< Y* >( 0 ); | ||||||||||||||
271 | (void)p; | ||||||||||||||
272 | |||||||||||||||
273 | #endif | ||||||||||||||
274 | } | ||||||||||||||
275 | |||||||||||||||
276 | // pointer constructor helper | ||||||||||||||
277 | |||||||||||||||
278 | template< class T, class Y > inline void sp_pointer_construct( boost::shared_ptr< T > * ppx, Y * p, boost::detail::shared_count & pn ) | ||||||||||||||
279 | { | ||||||||||||||
280 | boost::detail::shared_count( p ).swap( pn ); | ||||||||||||||
281 | boost::detail::sp_enable_shared_from_this( ppx, p, p ); | ||||||||||||||
282 | } | ||||||||||||||
283 | |||||||||||||||
284 | #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | ||||||||||||||
285 | |||||||||||||||
286 | template< class T, class Y > inline void sp_pointer_construct( boost::shared_ptr< T[] > * /*ppx*/, Y * p, boost::detail::shared_count & pn ) | ||||||||||||||
287 | { | ||||||||||||||
288 | sp_assert_convertible< Y[], T[] >(); | ||||||||||||||
289 | boost::detail::shared_count( p, boost::checked_array_deleter< T >() ).swap( pn ); | ||||||||||||||
290 | } | ||||||||||||||
291 | |||||||||||||||
292 | template< class T, std::size_t N, class Y > inline void sp_pointer_construct( boost::shared_ptr< T[N] > * /*ppx*/, Y * p, boost::detail::shared_count & pn ) | ||||||||||||||
293 | { | ||||||||||||||
294 | sp_assert_convertible< Y[N], T[N] >(); | ||||||||||||||
295 | boost::detail::shared_count( p, boost::checked_array_deleter< T >() ).swap( pn ); | ||||||||||||||
296 | } | ||||||||||||||
297 | |||||||||||||||
298 | #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | ||||||||||||||
299 | |||||||||||||||
300 | // deleter constructor helper | ||||||||||||||
301 | |||||||||||||||
302 | template< class T, class Y > inline void sp_deleter_construct( boost::shared_ptr< T > * ppx, Y * p ) | ||||||||||||||
303 | { | ||||||||||||||
304 | boost::detail::sp_enable_shared_from_this( ppx, p, p ); | ||||||||||||||
305 | } | ||||||||||||||
306 | |||||||||||||||
307 | #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | ||||||||||||||
308 | |||||||||||||||
309 | template< class T, class Y > inline void sp_deleter_construct( boost::shared_ptr< T[] > * /*ppx*/, Y * /*p*/ ) | ||||||||||||||
310 | { | ||||||||||||||
311 | sp_assert_convertible< Y[], T[] >(); | ||||||||||||||
312 | } | ||||||||||||||
313 | |||||||||||||||
314 | template< class T, std::size_t N, class Y > inline void sp_deleter_construct( boost::shared_ptr< T[N] > * /*ppx*/, Y * /*p*/ ) | ||||||||||||||
315 | { | ||||||||||||||
316 | sp_assert_convertible< Y[N], T[N] >(); | ||||||||||||||
317 | } | ||||||||||||||
318 | |||||||||||||||
319 | #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | ||||||||||||||
320 | |||||||||||||||
321 | struct sp_internal_constructor_tag | ||||||||||||||
322 | { | ||||||||||||||
323 | }; | ||||||||||||||
324 | |||||||||||||||
325 | } // namespace detail | ||||||||||||||
326 | |||||||||||||||
327 | |||||||||||||||
328 | // | ||||||||||||||
329 | // shared_ptr | ||||||||||||||
330 | // | ||||||||||||||
331 | // An enhanced relative of scoped_ptr with reference counted copy semantics. | ||||||||||||||
332 | // The object pointed to is deleted when the last shared_ptr pointing to it | ||||||||||||||
333 | // is destroyed or reset. | ||||||||||||||
334 | // | ||||||||||||||
335 | |||||||||||||||
336 | template<class T> class shared_ptr | ||||||||||||||
337 | { | ||||||||||||||
338 | private: | ||||||||||||||
339 | |||||||||||||||
340 | // Borland 5.5.1 specific workaround | ||||||||||||||
341 | typedef shared_ptr<T> this_type; | ||||||||||||||
342 | |||||||||||||||
343 | public: | ||||||||||||||
344 | |||||||||||||||
345 | typedef typename boost::detail::sp_element< T >::type element_type; | ||||||||||||||
346 | |||||||||||||||
347 | BOOST_CONSTEXPRconstexpr shared_ptr() BOOST_SP_NOEXCEPTnoexcept : px( 0 ), pn() | ||||||||||||||
348 | { | ||||||||||||||
349 | } | ||||||||||||||
350 | |||||||||||||||
351 | #if !defined( BOOST_NO_CXX11_NULLPTR ) | ||||||||||||||
352 | |||||||||||||||
353 | BOOST_CONSTEXPRconstexpr shared_ptr( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPTnoexcept : px( 0 ), pn() | ||||||||||||||
354 | { | ||||||||||||||
355 | } | ||||||||||||||
356 | |||||||||||||||
357 | #endif | ||||||||||||||
358 | |||||||||||||||
359 | BOOST_CONSTEXPRconstexpr shared_ptr( boost::detail::sp_internal_constructor_tag, element_type * px_, boost::detail::shared_count const & pn_ ) BOOST_SP_NOEXCEPTnoexcept : px( px_ ), pn( pn_ ) | ||||||||||||||
360 | { | ||||||||||||||
361 | } | ||||||||||||||
362 | |||||||||||||||
363 | #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) | ||||||||||||||
364 | |||||||||||||||
365 | BOOST_CONSTEXPRconstexpr shared_ptr( boost::detail::sp_internal_constructor_tag, element_type * px_, boost::detail::shared_count && pn_ ) BOOST_SP_NOEXCEPTnoexcept : px( px_ ), pn( std::move( pn_ ) ) | ||||||||||||||
366 | { | ||||||||||||||
367 | } | ||||||||||||||
368 | |||||||||||||||
369 | #endif | ||||||||||||||
370 | |||||||||||||||
371 | template<class Y> | ||||||||||||||
372 | explicit shared_ptr( Y * p ): px( p ), pn() // Y must be complete | ||||||||||||||
373 | { | ||||||||||||||
374 | boost::detail::sp_pointer_construct( this, p, pn ); | ||||||||||||||
375 | } | ||||||||||||||
376 | |||||||||||||||
377 | // | ||||||||||||||
378 | // Requirements: D's copy/move constructors must not throw | ||||||||||||||
379 | // | ||||||||||||||
380 | // shared_ptr will release p by calling d(p) | ||||||||||||||
381 | // | ||||||||||||||
382 | |||||||||||||||
383 | #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) | ||||||||||||||
384 | |||||||||||||||
385 | template<class Y, class D> shared_ptr( Y * p, D d ): px( p ), pn( p, static_cast< D&& >( d ) ) | ||||||||||||||
386 | { | ||||||||||||||
387 | boost::detail::sp_deleter_construct( this, p ); | ||||||||||||||
388 | } | ||||||||||||||
389 | |||||||||||||||
390 | #else | ||||||||||||||
391 | |||||||||||||||
392 | template<class Y, class D> shared_ptr( Y * p, D d ): px( p ), pn( p, d ) | ||||||||||||||
393 | { | ||||||||||||||
394 | boost::detail::sp_deleter_construct( this, p ); | ||||||||||||||
395 | } | ||||||||||||||
396 | |||||||||||||||
397 | #endif | ||||||||||||||
398 | |||||||||||||||
399 | #if !defined( BOOST_NO_CXX11_NULLPTR ) | ||||||||||||||
400 | |||||||||||||||
401 | #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) | ||||||||||||||
402 | |||||||||||||||
403 | template<class D> shared_ptr( boost::detail::sp_nullptr_t p, D d ): px( p ), pn( p, static_cast< D&& >( d ) ) | ||||||||||||||
404 | { | ||||||||||||||
405 | } | ||||||||||||||
406 | |||||||||||||||
407 | #else | ||||||||||||||
408 | |||||||||||||||
409 | template<class D> shared_ptr( boost::detail::sp_nullptr_t p, D d ): px( p ), pn( p, d ) | ||||||||||||||
410 | { | ||||||||||||||
411 | } | ||||||||||||||
412 | |||||||||||||||
413 | #endif | ||||||||||||||
414 | |||||||||||||||
415 | #endif | ||||||||||||||
416 | |||||||||||||||
417 | // As above, but with allocator. A's copy constructor shall not throw. | ||||||||||||||
418 | |||||||||||||||
419 | #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) | ||||||||||||||
420 | |||||||||||||||
421 | template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, static_cast< D&& >( d ), a ) | ||||||||||||||
422 | { | ||||||||||||||
423 | boost::detail::sp_deleter_construct( this, p ); | ||||||||||||||
424 | } | ||||||||||||||
425 | |||||||||||||||
426 | #else | ||||||||||||||
427 | |||||||||||||||
428 | template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a ) | ||||||||||||||
429 | { | ||||||||||||||
430 | boost::detail::sp_deleter_construct( this, p ); | ||||||||||||||
431 | } | ||||||||||||||
432 | |||||||||||||||
433 | #endif | ||||||||||||||
434 | |||||||||||||||
435 | #if !defined( BOOST_NO_CXX11_NULLPTR ) | ||||||||||||||
436 | |||||||||||||||
437 | #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) | ||||||||||||||
438 | |||||||||||||||
439 | template<class D, class A> shared_ptr( boost::detail::sp_nullptr_t p, D d, A a ): px( p ), pn( p, static_cast< D&& >( d ), a ) | ||||||||||||||
440 | { | ||||||||||||||
441 | } | ||||||||||||||
442 | |||||||||||||||
443 | #else | ||||||||||||||
444 | |||||||||||||||
445 | template<class D, class A> shared_ptr( boost::detail::sp_nullptr_t p, D d, A a ): px( p ), pn( p, d, a ) | ||||||||||||||
446 | { | ||||||||||||||
447 | } | ||||||||||||||
448 | |||||||||||||||
449 | #endif | ||||||||||||||
450 | |||||||||||||||
451 | #endif | ||||||||||||||
452 | |||||||||||||||
453 | // generated copy constructor, destructor are fine... | ||||||||||||||
454 | |||||||||||||||
455 | #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) | ||||||||||||||
456 | |||||||||||||||
457 | // ... except in C++0x, move disables the implicit copy | ||||||||||||||
458 | |||||||||||||||
459 | shared_ptr( shared_ptr const & r ) BOOST_SP_NOEXCEPTnoexcept : px( r.px ), pn( r.pn ) | ||||||||||||||
460 | { | ||||||||||||||
461 | } | ||||||||||||||
462 | |||||||||||||||
463 | #endif | ||||||||||||||
464 | |||||||||||||||
465 | template<class Y> | ||||||||||||||
466 | explicit shared_ptr( weak_ptr<Y> const & r ): pn( r.pn ) // may throw | ||||||||||||||
467 | { | ||||||||||||||
468 | boost::detail::sp_assert_convertible< Y, T >(); | ||||||||||||||
469 | |||||||||||||||
470 | // it is now safe to copy r.px, as pn(r.pn) did not throw | ||||||||||||||
471 | px = r.px; | ||||||||||||||
472 | } | ||||||||||||||
473 | |||||||||||||||
474 | template<class Y> | ||||||||||||||
475 | shared_ptr( weak_ptr<Y> const & r, boost::detail::sp_nothrow_tag ) | ||||||||||||||
476 | BOOST_SP_NOEXCEPTnoexcept : px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() ) | ||||||||||||||
477 | { | ||||||||||||||
478 | if( !pn.empty() ) | ||||||||||||||
479 | { | ||||||||||||||
480 | px = r.px; | ||||||||||||||
481 | } | ||||||||||||||
482 | } | ||||||||||||||
483 | |||||||||||||||
484 | template<class Y> | ||||||||||||||
485 | #if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) | ||||||||||||||
486 | |||||||||||||||
487 | shared_ptr( shared_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() ) | ||||||||||||||
488 | |||||||||||||||
489 | #else | ||||||||||||||
490 | |||||||||||||||
491 | shared_ptr( shared_ptr<Y> const & r ) | ||||||||||||||
492 | |||||||||||||||
493 | #endif | ||||||||||||||
494 | BOOST_SP_NOEXCEPTnoexcept : px( r.px ), pn( r.pn ) | ||||||||||||||
495 | { | ||||||||||||||
496 | boost::detail::sp_assert_convertible< Y, T >(); | ||||||||||||||
497 | } | ||||||||||||||
498 | |||||||||||||||
499 | // aliasing | ||||||||||||||
500 | template< class Y > | ||||||||||||||
501 | shared_ptr( shared_ptr<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPTnoexcept : px( p ), pn( r.pn ) | ||||||||||||||
502 | { | ||||||||||||||
503 | } | ||||||||||||||
504 | |||||||||||||||
505 | #ifndef BOOST_NO_AUTO_PTR | ||||||||||||||
506 | |||||||||||||||
507 | template<class Y> | ||||||||||||||
508 | explicit shared_ptr( std::auto_ptr<Y> & r ): px(r.get()), pn() | ||||||||||||||
509 | { | ||||||||||||||
510 | boost::detail::sp_assert_convertible< Y, T >(); | ||||||||||||||
511 | |||||||||||||||
512 | Y * tmp = r.get(); | ||||||||||||||
513 | pn = boost::detail::shared_count( r ); | ||||||||||||||
514 | |||||||||||||||
515 | boost::detail::sp_deleter_construct( this, tmp ); | ||||||||||||||
516 | } | ||||||||||||||
517 | |||||||||||||||
518 | #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) | ||||||||||||||
519 | |||||||||||||||
520 | template<class Y> | ||||||||||||||
521 | shared_ptr( std::auto_ptr<Y> && r ): px(r.get()), pn() | ||||||||||||||
522 | { | ||||||||||||||
523 | boost::detail::sp_assert_convertible< Y, T >(); | ||||||||||||||
524 | |||||||||||||||
525 | Y * tmp = r.get(); | ||||||||||||||
526 | pn = boost::detail::shared_count( r ); | ||||||||||||||
527 | |||||||||||||||
528 | boost::detail::sp_deleter_construct( this, tmp ); | ||||||||||||||
529 | } | ||||||||||||||
530 | |||||||||||||||
531 | #elif !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | ||||||||||||||
532 | |||||||||||||||
533 | template<class Ap> | ||||||||||||||
534 | explicit shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr<Ap, int>::type = 0 ): px( r.get() ), pn() | ||||||||||||||
535 | { | ||||||||||||||
536 | typedef typename Ap::element_type Y; | ||||||||||||||
537 | |||||||||||||||
538 | boost::detail::sp_assert_convertible< Y, T >(); | ||||||||||||||
539 | |||||||||||||||
540 | Y * tmp = r.get(); | ||||||||||||||
541 | pn = boost::detail::shared_count( r ); | ||||||||||||||
542 | |||||||||||||||
543 | boost::detail::sp_deleter_construct( this, tmp ); | ||||||||||||||
544 | } | ||||||||||||||
545 | |||||||||||||||
546 | #endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||||||||||||
547 | |||||||||||||||
548 | #endif // BOOST_NO_AUTO_PTR | ||||||||||||||
549 | |||||||||||||||
550 | #if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) | ||||||||||||||
551 | |||||||||||||||
552 | template< class Y, class D > | ||||||||||||||
553 | shared_ptr( std::unique_ptr< Y, D > && r ): px( r.get() ), pn() | ||||||||||||||
554 | { | ||||||||||||||
555 | boost::detail::sp_assert_convertible< Y, T >(); | ||||||||||||||
556 | |||||||||||||||
557 | typename std::unique_ptr< Y, D >::pointer tmp = r.get(); | ||||||||||||||
558 | |||||||||||||||
559 | if( tmp != 0 ) | ||||||||||||||
560 | { | ||||||||||||||
561 | pn = boost::detail::shared_count( r ); | ||||||||||||||
562 | boost::detail::sp_deleter_construct( this, tmp ); | ||||||||||||||
563 | } | ||||||||||||||
564 | } | ||||||||||||||
565 | |||||||||||||||
566 | #endif | ||||||||||||||
567 | |||||||||||||||
568 | template< class Y, class D > | ||||||||||||||
569 | shared_ptr( boost::movelib::unique_ptr< Y, D > r ): px( r.get() ), pn() | ||||||||||||||
570 | { | ||||||||||||||
571 | boost::detail::sp_assert_convertible< Y, T >(); | ||||||||||||||
572 | |||||||||||||||
573 | typename boost::movelib::unique_ptr< Y, D >::pointer tmp = r.get(); | ||||||||||||||
574 | |||||||||||||||
575 | if( tmp != 0 ) | ||||||||||||||
576 | { | ||||||||||||||
577 | pn = boost::detail::shared_count( r ); | ||||||||||||||
578 | boost::detail::sp_deleter_construct( this, tmp ); | ||||||||||||||
579 | } | ||||||||||||||
580 | } | ||||||||||||||
581 | |||||||||||||||
582 | // assignment | ||||||||||||||
583 | |||||||||||||||
584 | shared_ptr & operator=( shared_ptr const & r ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
585 | { | ||||||||||||||
586 | this_type(r).swap(*this); | ||||||||||||||
587 | return *this; | ||||||||||||||
588 | } | ||||||||||||||
589 | |||||||||||||||
590 | #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1400) | ||||||||||||||
591 | |||||||||||||||
592 | template<class Y> | ||||||||||||||
593 | shared_ptr & operator=(shared_ptr<Y> const & r) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
594 | { | ||||||||||||||
595 | this_type(r).swap(*this); | ||||||||||||||
596 | return *this; | ||||||||||||||
597 | } | ||||||||||||||
598 | |||||||||||||||
599 | #endif | ||||||||||||||
600 | |||||||||||||||
601 | #ifndef BOOST_NO_AUTO_PTR | ||||||||||||||
602 | |||||||||||||||
603 | template<class Y> | ||||||||||||||
604 | shared_ptr & operator=( std::auto_ptr<Y> & r ) | ||||||||||||||
605 | { | ||||||||||||||
606 | this_type( r ).swap( *this ); | ||||||||||||||
607 | return *this; | ||||||||||||||
608 | } | ||||||||||||||
609 | |||||||||||||||
610 | #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) | ||||||||||||||
611 | |||||||||||||||
612 | template<class Y> | ||||||||||||||
613 | shared_ptr & operator=( std::auto_ptr<Y> && r ) | ||||||||||||||
614 | { | ||||||||||||||
615 | this_type( static_cast< std::auto_ptr<Y> && >( r ) ).swap( *this ); | ||||||||||||||
616 | return *this; | ||||||||||||||
617 | } | ||||||||||||||
618 | |||||||||||||||
619 | #elif !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | ||||||||||||||
620 | |||||||||||||||
621 | template<class Ap> | ||||||||||||||
622 | typename boost::detail::sp_enable_if_auto_ptr< Ap, shared_ptr & >::type operator=( Ap r ) | ||||||||||||||
623 | { | ||||||||||||||
624 | this_type( r ).swap( *this ); | ||||||||||||||
625 | return *this; | ||||||||||||||
626 | } | ||||||||||||||
627 | |||||||||||||||
628 | #endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||||||||||||
629 | |||||||||||||||
630 | #endif // BOOST_NO_AUTO_PTR | ||||||||||||||
631 | |||||||||||||||
632 | #if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) | ||||||||||||||
633 | |||||||||||||||
634 | template<class Y, class D> | ||||||||||||||
635 | shared_ptr & operator=( std::unique_ptr<Y, D> && r ) | ||||||||||||||
636 | { | ||||||||||||||
637 | this_type( static_cast< std::unique_ptr<Y, D> && >( r ) ).swap(*this); | ||||||||||||||
638 | return *this; | ||||||||||||||
639 | } | ||||||||||||||
640 | |||||||||||||||
641 | #endif | ||||||||||||||
642 | |||||||||||||||
643 | template<class Y, class D> | ||||||||||||||
644 | shared_ptr & operator=( boost::movelib::unique_ptr<Y, D> r ) | ||||||||||||||
645 | { | ||||||||||||||
646 | // this_type( static_cast< unique_ptr<Y, D> && >( r ) ).swap( *this ); | ||||||||||||||
647 | |||||||||||||||
648 | boost::detail::sp_assert_convertible< Y, T >(); | ||||||||||||||
649 | |||||||||||||||
650 | typename boost::movelib::unique_ptr< Y, D >::pointer p = r.get(); | ||||||||||||||
651 | |||||||||||||||
652 | shared_ptr tmp; | ||||||||||||||
653 | |||||||||||||||
654 | if( p != 0 ) | ||||||||||||||
655 | { | ||||||||||||||
656 | tmp.px = p; | ||||||||||||||
657 | tmp.pn = boost::detail::shared_count( r ); | ||||||||||||||
658 | |||||||||||||||
659 | boost::detail::sp_deleter_construct( &tmp, p ); | ||||||||||||||
660 | } | ||||||||||||||
661 | |||||||||||||||
662 | tmp.swap( *this ); | ||||||||||||||
663 | |||||||||||||||
664 | return *this; | ||||||||||||||
665 | } | ||||||||||||||
666 | |||||||||||||||
667 | // Move support | ||||||||||||||
668 | |||||||||||||||
669 | #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) | ||||||||||||||
670 | |||||||||||||||
671 | shared_ptr( shared_ptr && r ) BOOST_SP_NOEXCEPTnoexcept : px( r.px ), pn( static_cast< boost::detail::shared_count && >( r.pn ) ) | ||||||||||||||
672 | { | ||||||||||||||
673 | r.px = 0; | ||||||||||||||
674 | } | ||||||||||||||
675 | |||||||||||||||
676 | template<class Y> | ||||||||||||||
677 | #if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) | ||||||||||||||
678 | |||||||||||||||
679 | shared_ptr( shared_ptr<Y> && r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() ) | ||||||||||||||
680 | |||||||||||||||
681 | #else | ||||||||||||||
682 | |||||||||||||||
683 | shared_ptr( shared_ptr<Y> && r ) | ||||||||||||||
684 | |||||||||||||||
685 | #endif | ||||||||||||||
686 | BOOST_SP_NOEXCEPTnoexcept : px( r.px ), pn( static_cast< boost::detail::shared_count && >( r.pn ) ) | ||||||||||||||
687 | { | ||||||||||||||
688 | boost::detail::sp_assert_convertible< Y, T >(); | ||||||||||||||
689 | r.px = 0; | ||||||||||||||
690 | } | ||||||||||||||
691 | |||||||||||||||
692 | shared_ptr & operator=( shared_ptr && r ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
693 | { | ||||||||||||||
694 | this_type( static_cast< shared_ptr && >( r ) ).swap( *this ); | ||||||||||||||
695 | return *this; | ||||||||||||||
696 | } | ||||||||||||||
697 | |||||||||||||||
698 | template<class Y> | ||||||||||||||
699 | shared_ptr & operator=( shared_ptr<Y> && r ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
700 | { | ||||||||||||||
701 | this_type( static_cast< shared_ptr<Y> && >( r ) ).swap( *this ); | ||||||||||||||
702 | return *this; | ||||||||||||||
703 | } | ||||||||||||||
704 | |||||||||||||||
705 | // aliasing move | ||||||||||||||
706 | template<class Y> | ||||||||||||||
707 | shared_ptr( shared_ptr<Y> && r, element_type * p ) BOOST_SP_NOEXCEPTnoexcept : px( p ), pn() | ||||||||||||||
708 | { | ||||||||||||||
709 | pn.swap( r.pn ); | ||||||||||||||
710 | r.px = 0; | ||||||||||||||
711 | } | ||||||||||||||
712 | |||||||||||||||
713 | #endif | ||||||||||||||
714 | |||||||||||||||
715 | #if !defined( BOOST_NO_CXX11_NULLPTR ) | ||||||||||||||
716 | |||||||||||||||
717 | shared_ptr & operator=( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
718 | { | ||||||||||||||
719 | this_type().swap(*this); | ||||||||||||||
720 | return *this; | ||||||||||||||
721 | } | ||||||||||||||
722 | |||||||||||||||
723 | #endif | ||||||||||||||
724 | |||||||||||||||
725 | void reset() BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
726 | { | ||||||||||||||
727 | this_type().swap(*this); | ||||||||||||||
728 | } | ||||||||||||||
729 | |||||||||||||||
730 | template<class Y> void reset( Y * p ) // Y must be complete | ||||||||||||||
731 | { | ||||||||||||||
732 | BOOST_ASSERT( p == 0 || p != px )(static_cast <bool> (p == 0 || p != px) ? void (0) : __assert_fail ("p == 0 || p != px", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); // catch self-reset errors | ||||||||||||||
733 | this_type( p ).swap( *this ); | ||||||||||||||
734 | } | ||||||||||||||
735 | |||||||||||||||
736 | #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) | ||||||||||||||
737 | |||||||||||||||
738 | template<class Y, class D> void reset( Y * p, D d ) | ||||||||||||||
739 | { | ||||||||||||||
740 | this_type( p, static_cast< D&& >( d ) ).swap( *this ); | ||||||||||||||
741 | } | ||||||||||||||
742 | |||||||||||||||
743 | template<class Y, class D, class A> void reset( Y * p, D d, A a ) | ||||||||||||||
744 | { | ||||||||||||||
745 | this_type( p, static_cast< D&& >( d ), a ).swap( *this ); | ||||||||||||||
746 | } | ||||||||||||||
747 | |||||||||||||||
748 | #else | ||||||||||||||
749 | |||||||||||||||
750 | template<class Y, class D> void reset( Y * p, D d ) | ||||||||||||||
751 | { | ||||||||||||||
752 | this_type( p, d ).swap( *this ); | ||||||||||||||
753 | } | ||||||||||||||
754 | |||||||||||||||
755 | template<class Y, class D, class A> void reset( Y * p, D d, A a ) | ||||||||||||||
756 | { | ||||||||||||||
757 | this_type( p, d, a ).swap( *this ); | ||||||||||||||
758 | } | ||||||||||||||
759 | |||||||||||||||
760 | #endif | ||||||||||||||
761 | |||||||||||||||
762 | template<class Y> void reset( shared_ptr<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
763 | { | ||||||||||||||
764 | this_type( r, p ).swap( *this ); | ||||||||||||||
765 | } | ||||||||||||||
766 | |||||||||||||||
767 | #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) | ||||||||||||||
768 | |||||||||||||||
769 | template<class Y> void reset( shared_ptr<Y> && r, element_type * p ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
770 | { | ||||||||||||||
771 | this_type( static_cast< shared_ptr<Y> && >( r ), p ).swap( *this ); | ||||||||||||||
772 | } | ||||||||||||||
773 | |||||||||||||||
774 | #endif | ||||||||||||||
775 | |||||||||||||||
776 | typename boost::detail::sp_dereference< T >::type operator* () const BOOST_SP_NOEXCEPT_WITH_ASSERTnoexcept | ||||||||||||||
777 | { | ||||||||||||||
778 | BOOST_ASSERT( px != 0 )(static_cast <bool> (px != 0) ? void (0) : __assert_fail ("px != 0", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); | ||||||||||||||
779 | return *px; | ||||||||||||||
780 | } | ||||||||||||||
781 | |||||||||||||||
782 | typename boost::detail::sp_member_access< T >::type operator-> () const BOOST_SP_NOEXCEPT_WITH_ASSERTnoexcept | ||||||||||||||
783 | { | ||||||||||||||
784 | BOOST_ASSERT( px != 0 )(static_cast <bool> (px != 0) ? void (0) : __assert_fail ("px != 0", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); | ||||||||||||||
785 | return px; | ||||||||||||||
| |||||||||||||||
786 | } | ||||||||||||||
787 | |||||||||||||||
788 | typename boost::detail::sp_array_access< T >::type operator[] ( std::ptrdiff_t i ) const BOOST_SP_NOEXCEPT_WITH_ASSERTnoexcept | ||||||||||||||
789 | { | ||||||||||||||
790 | BOOST_ASSERT( px != 0 )(static_cast <bool> (px != 0) ? void (0) : __assert_fail ("px != 0", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); | ||||||||||||||
791 | BOOST_ASSERT( i >= 0 && ( i < boost::detail::sp_extent< T >::value || boost::detail::sp_extent< T >::value == 0 ) )(static_cast <bool> (i >= 0 && ( i < boost ::detail::sp_extent< T >::value || boost::detail::sp_extent < T >::value == 0 )) ? void (0) : __assert_fail ("i >= 0 && ( i < boost::detail::sp_extent< T >::value || boost::detail::sp_extent< T >::value == 0 )" , __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); | ||||||||||||||
792 | |||||||||||||||
793 | return static_cast< typename boost::detail::sp_array_access< T >::type >( px[ i ] ); | ||||||||||||||
794 | } | ||||||||||||||
795 | |||||||||||||||
796 | element_type * get() const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
797 | { | ||||||||||||||
798 | return px; | ||||||||||||||
799 | } | ||||||||||||||
800 | |||||||||||||||
801 | // implicit conversion to "bool" | ||||||||||||||
802 | #include <boost/smart_ptr/detail/operator_bool.hpp> | ||||||||||||||
803 | |||||||||||||||
804 | bool unique() const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
805 | { | ||||||||||||||
806 | return pn.unique(); | ||||||||||||||
807 | } | ||||||||||||||
808 | |||||||||||||||
809 | long use_count() const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
810 | { | ||||||||||||||
811 | return pn.use_count(); | ||||||||||||||
812 | } | ||||||||||||||
813 | |||||||||||||||
814 | void swap( shared_ptr & other ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
815 | { | ||||||||||||||
816 | std::swap(px, other.px); | ||||||||||||||
817 | pn.swap(other.pn); | ||||||||||||||
818 | } | ||||||||||||||
819 | |||||||||||||||
820 | template<class Y> bool owner_before( shared_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
821 | { | ||||||||||||||
822 | return pn < rhs.pn; | ||||||||||||||
823 | } | ||||||||||||||
824 | |||||||||||||||
825 | template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
826 | { | ||||||||||||||
827 | return pn < rhs.pn; | ||||||||||||||
828 | } | ||||||||||||||
829 | |||||||||||||||
830 | template<class Y> bool owner_equals( shared_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
831 | { | ||||||||||||||
832 | return pn == rhs.pn; | ||||||||||||||
833 | } | ||||||||||||||
834 | |||||||||||||||
835 | template<class Y> bool owner_equals( weak_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
836 | { | ||||||||||||||
837 | return pn == rhs.pn; | ||||||||||||||
838 | } | ||||||||||||||
839 | |||||||||||||||
840 | std::size_t owner_hash_value() const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
841 | { | ||||||||||||||
842 | return pn.hash_value(); | ||||||||||||||
843 | } | ||||||||||||||
844 | |||||||||||||||
845 | void * _internal_get_deleter( boost::detail::sp_typeinfo_ const & ti ) const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
846 | { | ||||||||||||||
847 | return pn.get_deleter( ti ); | ||||||||||||||
848 | } | ||||||||||||||
849 | |||||||||||||||
850 | void * _internal_get_local_deleter( boost::detail::sp_typeinfo_ const & ti ) const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
851 | { | ||||||||||||||
852 | return pn.get_local_deleter( ti ); | ||||||||||||||
853 | } | ||||||||||||||
854 | |||||||||||||||
855 | void * _internal_get_untyped_deleter() const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
856 | { | ||||||||||||||
857 | return pn.get_untyped_deleter(); | ||||||||||||||
858 | } | ||||||||||||||
859 | |||||||||||||||
860 | bool _internal_equiv( shared_ptr const & r ) const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
861 | { | ||||||||||||||
862 | return px == r.px && pn == r.pn; | ||||||||||||||
863 | } | ||||||||||||||
864 | |||||||||||||||
865 | boost::detail::shared_count _internal_count() const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
866 | { | ||||||||||||||
867 | return pn; | ||||||||||||||
868 | } | ||||||||||||||
869 | |||||||||||||||
870 | // Tasteless as this may seem, making all members public allows member templates | ||||||||||||||
871 | // to work in the absence of member template friends. (Matthew Langston) | ||||||||||||||
872 | |||||||||||||||
873 | #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS | ||||||||||||||
874 | |||||||||||||||
875 | private: | ||||||||||||||
876 | |||||||||||||||
877 | template<class Y> friend class shared_ptr; | ||||||||||||||
878 | template<class Y> friend class weak_ptr; | ||||||||||||||
879 | |||||||||||||||
880 | |||||||||||||||
881 | #endif | ||||||||||||||
882 | |||||||||||||||
883 | element_type * px; // contained pointer | ||||||||||||||
884 | boost::detail::shared_count pn; // reference counter | ||||||||||||||
885 | |||||||||||||||
886 | }; // shared_ptr | ||||||||||||||
887 | |||||||||||||||
888 | template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
889 | { | ||||||||||||||
890 | return a.get() == b.get(); | ||||||||||||||
891 | } | ||||||||||||||
892 | |||||||||||||||
893 | template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
894 | { | ||||||||||||||
895 | return a.get() != b.get(); | ||||||||||||||
896 | } | ||||||||||||||
897 | |||||||||||||||
898 | #if __GNUC__4 == 2 && __GNUC_MINOR__2 <= 96 | ||||||||||||||
899 | |||||||||||||||
900 | // Resolve the ambiguity between our op!= and the one in rel_ops | ||||||||||||||
901 | |||||||||||||||
902 | template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
903 | { | ||||||||||||||
904 | return a.get() != b.get(); | ||||||||||||||
905 | } | ||||||||||||||
906 | |||||||||||||||
907 | #endif | ||||||||||||||
908 | |||||||||||||||
909 | #if !defined( BOOST_NO_CXX11_NULLPTR ) | ||||||||||||||
910 | |||||||||||||||
911 | template<class T> inline bool operator==( shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
912 | { | ||||||||||||||
913 | return p.get() == 0; | ||||||||||||||
914 | } | ||||||||||||||
915 | |||||||||||||||
916 | template<class T> inline bool operator==( boost::detail::sp_nullptr_t, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
917 | { | ||||||||||||||
918 | return p.get() == 0; | ||||||||||||||
919 | } | ||||||||||||||
920 | |||||||||||||||
921 | template<class T> inline bool operator!=( shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
922 | { | ||||||||||||||
923 | return p.get() != 0; | ||||||||||||||
924 | } | ||||||||||||||
925 | |||||||||||||||
926 | template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
927 | { | ||||||||||||||
928 | return p.get() != 0; | ||||||||||||||
929 | } | ||||||||||||||
930 | |||||||||||||||
931 | #endif | ||||||||||||||
932 | |||||||||||||||
933 | template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
934 | { | ||||||||||||||
935 | return a.owner_before( b ); | ||||||||||||||
936 | } | ||||||||||||||
937 | |||||||||||||||
938 | template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
939 | { | ||||||||||||||
940 | a.swap(b); | ||||||||||||||
941 | } | ||||||||||||||
942 | |||||||||||||||
943 | template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> const & r ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
944 | { | ||||||||||||||
945 | (void) static_cast< T* >( static_cast< U* >( 0 ) ); | ||||||||||||||
946 | |||||||||||||||
947 | typedef typename shared_ptr<T>::element_type E; | ||||||||||||||
948 | |||||||||||||||
949 | E * p = static_cast< E* >( r.get() ); | ||||||||||||||
950 | return shared_ptr<T>( r, p ); | ||||||||||||||
951 | } | ||||||||||||||
952 | |||||||||||||||
953 | template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> const & r ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
954 | { | ||||||||||||||
955 | (void) const_cast< T* >( static_cast< U* >( 0 ) ); | ||||||||||||||
956 | |||||||||||||||
957 | typedef typename shared_ptr<T>::element_type E; | ||||||||||||||
958 | |||||||||||||||
959 | E * p = const_cast< E* >( r.get() ); | ||||||||||||||
960 | return shared_ptr<T>( r, p ); | ||||||||||||||
961 | } | ||||||||||||||
962 | |||||||||||||||
963 | template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> const & r ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
964 | { | ||||||||||||||
965 | (void) dynamic_cast< T* >( static_cast< U* >( 0 ) ); | ||||||||||||||
966 | |||||||||||||||
967 | typedef typename shared_ptr<T>::element_type E; | ||||||||||||||
968 | |||||||||||||||
969 | E * p = dynamic_cast< E* >( r.get() ); | ||||||||||||||
970 | return p? shared_ptr<T>( r, p ): shared_ptr<T>(); | ||||||||||||||
971 | } | ||||||||||||||
972 | |||||||||||||||
973 | template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U> const & r ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
974 | { | ||||||||||||||
975 | (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) ); | ||||||||||||||
976 | |||||||||||||||
977 | typedef typename shared_ptr<T>::element_type E; | ||||||||||||||
978 | |||||||||||||||
979 | E * p = reinterpret_cast< E* >( r.get() ); | ||||||||||||||
980 | return shared_ptr<T>( r, p ); | ||||||||||||||
981 | } | ||||||||||||||
982 | |||||||||||||||
983 | #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) | ||||||||||||||
984 | |||||||||||||||
985 | template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> && r ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
986 | { | ||||||||||||||
987 | (void) static_cast< T* >( static_cast< U* >( 0 ) ); | ||||||||||||||
988 | |||||||||||||||
989 | typedef typename shared_ptr<T>::element_type E; | ||||||||||||||
990 | |||||||||||||||
991 | E * p = static_cast< E* >( r.get() ); | ||||||||||||||
992 | return shared_ptr<T>( std::move(r), p ); | ||||||||||||||
993 | } | ||||||||||||||
994 | |||||||||||||||
995 | template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> && r ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
996 | { | ||||||||||||||
997 | (void) const_cast< T* >( static_cast< U* >( 0 ) ); | ||||||||||||||
998 | |||||||||||||||
999 | typedef typename shared_ptr<T>::element_type E; | ||||||||||||||
1000 | |||||||||||||||
1001 | E * p = const_cast< E* >( r.get() ); | ||||||||||||||
1002 | return shared_ptr<T>( std::move(r), p ); | ||||||||||||||
1003 | } | ||||||||||||||
1004 | |||||||||||||||
1005 | template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> && r ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
1006 | { | ||||||||||||||
1007 | (void) dynamic_cast< T* >( static_cast< U* >( 0 ) ); | ||||||||||||||
1008 | |||||||||||||||
1009 | typedef typename shared_ptr<T>::element_type E; | ||||||||||||||
1010 | |||||||||||||||
1011 | E * p = dynamic_cast< E* >( r.get() ); | ||||||||||||||
1012 | return p? shared_ptr<T>( std::move(r), p ): shared_ptr<T>(); | ||||||||||||||
1013 | } | ||||||||||||||
1014 | |||||||||||||||
1015 | template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U> && r ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
1016 | { | ||||||||||||||
1017 | (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) ); | ||||||||||||||
1018 | |||||||||||||||
1019 | typedef typename shared_ptr<T>::element_type E; | ||||||||||||||
1020 | |||||||||||||||
1021 | E * p = reinterpret_cast< E* >( r.get() ); | ||||||||||||||
1022 | return shared_ptr<T>( std::move(r), p ); | ||||||||||||||
1023 | } | ||||||||||||||
1024 | |||||||||||||||
1025 | #endif // !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) | ||||||||||||||
1026 | |||||||||||||||
1027 | // get_pointer() enables boost::mem_fn to recognize shared_ptr | ||||||||||||||
1028 | |||||||||||||||
1029 | template<class T> inline typename shared_ptr<T>::element_type * get_pointer(shared_ptr<T> const & p) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
1030 | { | ||||||||||||||
1031 | return p.get(); | ||||||||||||||
1032 | } | ||||||||||||||
1033 | |||||||||||||||
1034 | // operator<< | ||||||||||||||
1035 | |||||||||||||||
1036 | #if !defined(BOOST_NO_IOSTREAM) | ||||||||||||||
1037 | |||||||||||||||
1038 | #if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__4) && (__GNUC__4 < 3) ) | ||||||||||||||
1039 | |||||||||||||||
1040 | template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p) | ||||||||||||||
1041 | { | ||||||||||||||
1042 | os << p.get(); | ||||||||||||||
1043 | return os; | ||||||||||||||
1044 | } | ||||||||||||||
1045 | |||||||||||||||
1046 | #else | ||||||||||||||
1047 | |||||||||||||||
1048 | // in STLport's no-iostreams mode no iostream symbols can be used | ||||||||||||||
1049 | #ifndef _STLP_NO_IOSTREAMS | ||||||||||||||
1050 | |||||||||||||||
1051 | # if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT)((1 + 0 == 0) && (BOOST_MSVC != 0) && (1 % (( (BOOST_MSVC < 1300 && __SGI_STL_PORT) ) + 1))) | ||||||||||||||
1052 | // MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL | ||||||||||||||
1053 | using std::basic_ostream; | ||||||||||||||
1054 | template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p) | ||||||||||||||
1055 | # else | ||||||||||||||
1056 | template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p) | ||||||||||||||
1057 | # endif | ||||||||||||||
1058 | { | ||||||||||||||
1059 | os << p.get(); | ||||||||||||||
1060 | return os; | ||||||||||||||
1061 | } | ||||||||||||||
1062 | |||||||||||||||
1063 | #endif // _STLP_NO_IOSTREAMS | ||||||||||||||
1064 | |||||||||||||||
1065 | #endif // __GNUC__ < 3 | ||||||||||||||
1066 | |||||||||||||||
1067 | #endif // !defined(BOOST_NO_IOSTREAM) | ||||||||||||||
1068 | |||||||||||||||
1069 | // get_deleter | ||||||||||||||
1070 | |||||||||||||||
1071 | namespace detail | ||||||||||||||
1072 | { | ||||||||||||||
1073 | |||||||||||||||
1074 | template<class D, class T> D * basic_get_deleter( shared_ptr<T> const & p ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
1075 | { | ||||||||||||||
1076 | return static_cast<D *>( p._internal_get_deleter(BOOST_SP_TYPEID_(D)typeid(D)) ); | ||||||||||||||
1077 | } | ||||||||||||||
1078 | |||||||||||||||
1079 | template<class D, class T> D * basic_get_local_deleter( D *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPTnoexcept; | ||||||||||||||
1080 | template<class D, class T> D const * basic_get_local_deleter( D const *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPTnoexcept; | ||||||||||||||
1081 | |||||||||||||||
1082 | class esft2_deleter_wrapper | ||||||||||||||
1083 | { | ||||||||||||||
1084 | private: | ||||||||||||||
1085 | |||||||||||||||
1086 | shared_ptr<void const volatile> deleter_; | ||||||||||||||
1087 | |||||||||||||||
1088 | public: | ||||||||||||||
1089 | |||||||||||||||
1090 | esft2_deleter_wrapper() BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
1091 | { | ||||||||||||||
1092 | } | ||||||||||||||
1093 | |||||||||||||||
1094 | template< class T > void set_deleter( shared_ptr<T> const & deleter ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
1095 | { | ||||||||||||||
1096 | deleter_ = deleter; | ||||||||||||||
1097 | } | ||||||||||||||
1098 | |||||||||||||||
1099 | template<typename D> D* get_deleter() const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
1100 | { | ||||||||||||||
1101 | return boost::detail::basic_get_deleter<D>( deleter_ ); | ||||||||||||||
1102 | } | ||||||||||||||
1103 | |||||||||||||||
1104 | template< class T> void operator()( T* ) BOOST_SP_NOEXCEPT_WITH_ASSERTnoexcept | ||||||||||||||
1105 | { | ||||||||||||||
1106 | BOOST_ASSERT( deleter_.use_count() <= 1 )(static_cast <bool> (deleter_.use_count() <= 1) ? void (0) : __assert_fail ("deleter_.use_count() <= 1", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); | ||||||||||||||
1107 | deleter_.reset(); | ||||||||||||||
1108 | } | ||||||||||||||
1109 | }; | ||||||||||||||
1110 | |||||||||||||||
1111 | } // namespace detail | ||||||||||||||
1112 | |||||||||||||||
1113 | template<class D, class T> D * get_deleter( shared_ptr<T> const & p ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
1114 | { | ||||||||||||||
1115 | D * d = boost::detail::basic_get_deleter<D>( p ); | ||||||||||||||
1116 | |||||||||||||||
1117 | if( d == 0 ) | ||||||||||||||
1118 | { | ||||||||||||||
1119 | d = boost::detail::basic_get_local_deleter( d, p ); | ||||||||||||||
1120 | } | ||||||||||||||
1121 | |||||||||||||||
1122 | if( d == 0 ) | ||||||||||||||
1123 | { | ||||||||||||||
1124 | boost::detail::esft2_deleter_wrapper *del_wrapper = boost::detail::basic_get_deleter<boost::detail::esft2_deleter_wrapper>(p); | ||||||||||||||
1125 | // The following get_deleter method call is fully qualified because | ||||||||||||||
1126 | // older versions of gcc (2.95, 3.2.3) fail to compile it when written del_wrapper->get_deleter<D>() | ||||||||||||||
1127 | if(del_wrapper) d = del_wrapper->::boost::detail::esft2_deleter_wrapper::get_deleter<D>(); | ||||||||||||||
1128 | } | ||||||||||||||
1129 | |||||||||||||||
1130 | return d; | ||||||||||||||
1131 | } | ||||||||||||||
1132 | |||||||||||||||
1133 | // atomic access | ||||||||||||||
1134 | |||||||||||||||
1135 | #if !defined(BOOST_SP_NO_ATOMIC_ACCESS) | ||||||||||||||
1136 | |||||||||||||||
1137 | template<class T> inline bool atomic_is_lock_free( shared_ptr<T> const * /*p*/ ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
1138 | { | ||||||||||||||
1139 | return false; | ||||||||||||||
1140 | } | ||||||||||||||
1141 | |||||||||||||||
1142 | template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
1143 | { | ||||||||||||||
1144 | boost::detail::spinlock_pool<2>::scoped_lock lock( p ); | ||||||||||||||
1145 | return *p; | ||||||||||||||
1146 | } | ||||||||||||||
1147 | |||||||||||||||
1148 | template<class T, class M> inline shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, /*memory_order mo*/ M ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
1149 | { | ||||||||||||||
1150 | return atomic_load( p ); | ||||||||||||||
1151 | } | ||||||||||||||
1152 | |||||||||||||||
1153 | template<class T> void atomic_store( shared_ptr<T> * p, shared_ptr<T> r ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
1154 | { | ||||||||||||||
1155 | boost::detail::spinlock_pool<2>::scoped_lock lock( p ); | ||||||||||||||
1156 | p->swap( r ); | ||||||||||||||
1157 | } | ||||||||||||||
1158 | |||||||||||||||
1159 | template<class T, class M> inline void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, /*memory_order mo*/ M ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
1160 | { | ||||||||||||||
1161 | atomic_store( p, r ); // std::move( r ) | ||||||||||||||
1162 | } | ||||||||||||||
1163 | |||||||||||||||
1164 | template<class T> shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
1165 | { | ||||||||||||||
1166 | boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p ); | ||||||||||||||
1167 | |||||||||||||||
1168 | sp.lock(); | ||||||||||||||
1169 | p->swap( r ); | ||||||||||||||
1170 | sp.unlock(); | ||||||||||||||
1171 | |||||||||||||||
1172 | return r; // return std::move( r ) | ||||||||||||||
1173 | } | ||||||||||||||
1174 | |||||||||||||||
1175 | template<class T, class M> shared_ptr<T> inline atomic_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> r, /*memory_order mo*/ M ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
1176 | { | ||||||||||||||
1177 | return atomic_exchange( p, r ); // std::move( r ) | ||||||||||||||
1178 | } | ||||||||||||||
1179 | |||||||||||||||
1180 | template<class T> bool atomic_compare_exchange( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
1181 | { | ||||||||||||||
1182 | boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p ); | ||||||||||||||
1183 | |||||||||||||||
1184 | sp.lock(); | ||||||||||||||
1185 | |||||||||||||||
1186 | if( p->_internal_equiv( *v ) ) | ||||||||||||||
1187 | { | ||||||||||||||
1188 | p->swap( w ); | ||||||||||||||
1189 | |||||||||||||||
1190 | sp.unlock(); | ||||||||||||||
1191 | |||||||||||||||
1192 | return true; | ||||||||||||||
1193 | } | ||||||||||||||
1194 | else | ||||||||||||||
1195 | { | ||||||||||||||
1196 | shared_ptr<T> tmp( *p ); | ||||||||||||||
1197 | |||||||||||||||
1198 | sp.unlock(); | ||||||||||||||
1199 | |||||||||||||||
1200 | tmp.swap( *v ); | ||||||||||||||
1201 | return false; | ||||||||||||||
1202 | } | ||||||||||||||
1203 | } | ||||||||||||||
1204 | |||||||||||||||
1205 | template<class T, class M> inline bool atomic_compare_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w, /*memory_order success*/ M, /*memory_order failure*/ M ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
1206 | { | ||||||||||||||
1207 | return atomic_compare_exchange( p, v, w ); // std::move( w ) | ||||||||||||||
1208 | } | ||||||||||||||
1209 | |||||||||||||||
1210 | #endif // !defined(BOOST_SP_NO_ATOMIC_ACCESS) | ||||||||||||||
1211 | |||||||||||||||
1212 | // hash_value | ||||||||||||||
1213 | |||||||||||||||
1214 | template< class T > struct hash; | ||||||||||||||
1215 | |||||||||||||||
1216 | template< class T > std::size_t hash_value( boost::shared_ptr<T> const & p ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
1217 | { | ||||||||||||||
1218 | return boost::hash< typename boost::shared_ptr<T>::element_type* >()( p.get() ); | ||||||||||||||
1219 | } | ||||||||||||||
1220 | |||||||||||||||
1221 | } // namespace boost | ||||||||||||||
1222 | |||||||||||||||
1223 | // std::hash | ||||||||||||||
1224 | |||||||||||||||
1225 | #if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) | ||||||||||||||
1226 | |||||||||||||||
1227 | namespace std | ||||||||||||||
1228 | { | ||||||||||||||
1229 | |||||||||||||||
1230 | template<class T> struct hash< ::boost::shared_ptr<T> > | ||||||||||||||
1231 | { | ||||||||||||||
1232 | std::size_t operator()( ::boost::shared_ptr<T> const & p ) const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
1233 | { | ||||||||||||||
1234 | return std::hash< typename ::boost::shared_ptr<T>::element_type* >()( p.get() ); | ||||||||||||||
1235 | } | ||||||||||||||
1236 | }; | ||||||||||||||
1237 | |||||||||||||||
1238 | } // namespace std | ||||||||||||||
1239 | |||||||||||||||
1240 | #endif // #if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) | ||||||||||||||
1241 | |||||||||||||||
1242 | #include <boost/smart_ptr/detail/local_sp_deleter.hpp> | ||||||||||||||
1243 | |||||||||||||||
1244 | namespace boost | ||||||||||||||
1245 | { | ||||||||||||||
1246 | |||||||||||||||
1247 | namespace detail | ||||||||||||||
1248 | { | ||||||||||||||
1249 | |||||||||||||||
1250 | template<class D, class T> D * basic_get_local_deleter( D *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
1251 | { | ||||||||||||||
1252 | return static_cast<D *>( p._internal_get_local_deleter( BOOST_SP_TYPEID_(local_sp_deleter<D>)typeid(local_sp_deleter<D>) ) ); | ||||||||||||||
1253 | } | ||||||||||||||
1254 | |||||||||||||||
1255 | template<class D, class T> D const * basic_get_local_deleter( D const *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
1256 | { | ||||||||||||||
1257 | return static_cast<D *>( p._internal_get_local_deleter( BOOST_SP_TYPEID_(local_sp_deleter<D>)typeid(local_sp_deleter<D>) ) ); | ||||||||||||||
1258 | } | ||||||||||||||
1259 | |||||||||||||||
1260 | } // namespace detail | ||||||||||||||
1261 | |||||||||||||||
1262 | #if defined(__cpp_deduction_guides201703L) | ||||||||||||||
1263 | |||||||||||||||
1264 | template<class T> shared_ptr( weak_ptr<T> ) -> shared_ptr<T>; | ||||||||||||||
1265 | template<class T, class D> shared_ptr( std::unique_ptr<T, D> ) -> shared_ptr<T>; | ||||||||||||||
1266 | |||||||||||||||
1267 | #endif | ||||||||||||||
1268 | |||||||||||||||
1269 | } // namespace boost | ||||||||||||||
1270 | |||||||||||||||
1271 | #if defined( BOOST_SP_DISABLE_DEPRECATED ) | ||||||||||||||
1272 | #pragma GCC diagnostic pop | ||||||||||||||
1273 | #endif | ||||||||||||||
1274 | |||||||||||||||
1275 | #endif // #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED |
1 | #ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED | ||||||||||||||
2 | #define BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED | ||||||||||||||
3 | |||||||||||||||
4 | // MS compatible compilers support #pragma once | ||||||||||||||
5 | |||||||||||||||
6 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) | ||||||||||||||
7 | # pragma once | ||||||||||||||
8 | #endif | ||||||||||||||
9 | |||||||||||||||
10 | // | ||||||||||||||
11 | // detail/shared_count.hpp | ||||||||||||||
12 | // | ||||||||||||||
13 | // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. | ||||||||||||||
14 | // Copyright 2004-2005 Peter Dimov | ||||||||||||||
15 | // | ||||||||||||||
16 | // Distributed under the Boost Software License, Version 1.0. (See | ||||||||||||||
17 | // accompanying file LICENSE_1_0.txt or copy at | ||||||||||||||
18 | // http://www.boost.org/LICENSE_1_0.txt) | ||||||||||||||
19 | // | ||||||||||||||
20 | |||||||||||||||
21 | #if defined(__BORLANDC__) && !defined(__clang__1) | ||||||||||||||
22 | # pragma warn -8027 // Functions containing try are not expanded inline | ||||||||||||||
23 | #endif | ||||||||||||||
24 | |||||||||||||||
25 | #include <boost/smart_ptr/bad_weak_ptr.hpp> | ||||||||||||||
26 | #include <boost/smart_ptr/detail/sp_counted_base.hpp> | ||||||||||||||
27 | #include <boost/smart_ptr/detail/sp_counted_impl.hpp> | ||||||||||||||
28 | #include <boost/smart_ptr/detail/sp_disable_deprecated.hpp> | ||||||||||||||
29 | #include <boost/smart_ptr/detail/sp_noexcept.hpp> | ||||||||||||||
30 | #include <boost/core/checked_delete.hpp> | ||||||||||||||
31 | #include <boost/throw_exception.hpp> | ||||||||||||||
32 | #include <boost/core/addressof.hpp> | ||||||||||||||
33 | #include <boost/config.hpp> | ||||||||||||||
34 | #include <boost/config/workaround.hpp> | ||||||||||||||
35 | #include <boost/cstdint.hpp> | ||||||||||||||
36 | #include <memory> // std::auto_ptr | ||||||||||||||
37 | #include <functional> // std::less | ||||||||||||||
38 | #include <cstddef> // std::size_t | ||||||||||||||
39 | |||||||||||||||
40 | #ifdef BOOST_NO_EXCEPTIONS | ||||||||||||||
41 | # include <new> // std::bad_alloc | ||||||||||||||
42 | #endif | ||||||||||||||
43 | |||||||||||||||
44 | #if defined( BOOST_SP_DISABLE_DEPRECATED ) | ||||||||||||||
45 | #pragma GCC diagnostic push | ||||||||||||||
46 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" | ||||||||||||||
47 | #endif | ||||||||||||||
48 | |||||||||||||||
49 | namespace boost | ||||||||||||||
50 | { | ||||||||||||||
51 | |||||||||||||||
52 | namespace movelib | ||||||||||||||
53 | { | ||||||||||||||
54 | |||||||||||||||
55 | template< class T, class D > class unique_ptr; | ||||||||||||||
56 | |||||||||||||||
57 | } // namespace movelib | ||||||||||||||
58 | |||||||||||||||
59 | namespace detail | ||||||||||||||
60 | { | ||||||||||||||
61 | |||||||||||||||
62 | #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||||||||||||
63 | |||||||||||||||
64 | int const shared_count_id = 0x2C35F101; | ||||||||||||||
65 | int const weak_count_id = 0x298C38A4; | ||||||||||||||
66 | |||||||||||||||
67 | #endif | ||||||||||||||
68 | |||||||||||||||
69 | struct sp_nothrow_tag {}; | ||||||||||||||
70 | |||||||||||||||
71 | template< class D > struct sp_inplace_tag | ||||||||||||||
72 | { | ||||||||||||||
73 | }; | ||||||||||||||
74 | |||||||||||||||
75 | template< class T > class sp_reference_wrapper | ||||||||||||||
76 | { | ||||||||||||||
77 | public: | ||||||||||||||
78 | |||||||||||||||
79 | explicit sp_reference_wrapper( T & t): t_( boost::addressof( t ) ) | ||||||||||||||
80 | { | ||||||||||||||
81 | } | ||||||||||||||
82 | |||||||||||||||
83 | template< class Y > void operator()( Y * p ) const | ||||||||||||||
84 | { | ||||||||||||||
85 | (*t_)( p ); | ||||||||||||||
86 | } | ||||||||||||||
87 | |||||||||||||||
88 | private: | ||||||||||||||
89 | |||||||||||||||
90 | T * t_; | ||||||||||||||
91 | }; | ||||||||||||||
92 | |||||||||||||||
93 | template< class D > struct sp_convert_reference | ||||||||||||||
94 | { | ||||||||||||||
95 | typedef D type; | ||||||||||||||
96 | }; | ||||||||||||||
97 | |||||||||||||||
98 | template< class D > struct sp_convert_reference< D& > | ||||||||||||||
99 | { | ||||||||||||||
100 | typedef sp_reference_wrapper< D > type; | ||||||||||||||
101 | }; | ||||||||||||||
102 | |||||||||||||||
103 | template<class T> std::size_t sp_hash_pointer( T* p ) BOOST_NOEXCEPTnoexcept | ||||||||||||||
104 | { | ||||||||||||||
105 | boost::uintptr_t v = reinterpret_cast<boost::uintptr_t>( p ); | ||||||||||||||
106 | |||||||||||||||
107 | // match boost::hash<T*> | ||||||||||||||
108 | return static_cast<std::size_t>( v + ( v >> 3 ) ); | ||||||||||||||
109 | } | ||||||||||||||
110 | |||||||||||||||
111 | class weak_count; | ||||||||||||||
112 | |||||||||||||||
113 | class shared_count | ||||||||||||||
114 | { | ||||||||||||||
115 | private: | ||||||||||||||
116 | |||||||||||||||
117 | sp_counted_base * pi_; | ||||||||||||||
118 | |||||||||||||||
119 | #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||||||||||||
120 | int id_; | ||||||||||||||
121 | #endif | ||||||||||||||
122 | |||||||||||||||
123 | friend class weak_count; | ||||||||||||||
124 | |||||||||||||||
125 | public: | ||||||||||||||
126 | |||||||||||||||
127 | BOOST_CONSTEXPRconstexpr shared_count() BOOST_SP_NOEXCEPTnoexcept: pi_(0) | ||||||||||||||
128 | #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||||||||||||
129 | , id_(shared_count_id) | ||||||||||||||
130 | #endif | ||||||||||||||
131 | { | ||||||||||||||
132 | } | ||||||||||||||
133 | |||||||||||||||
134 | BOOST_CONSTEXPRconstexpr explicit shared_count( sp_counted_base * pi ) BOOST_SP_NOEXCEPTnoexcept: pi_( pi ) | ||||||||||||||
135 | #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||||||||||||
136 | , id_(shared_count_id) | ||||||||||||||
137 | #endif | ||||||||||||||
138 | { | ||||||||||||||
139 | } | ||||||||||||||
140 | |||||||||||||||
141 | template<class Y> explicit shared_count( Y * p ): pi_( 0 ) | ||||||||||||||
142 | #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||||||||||||
143 | , id_(shared_count_id) | ||||||||||||||
144 | #endif | ||||||||||||||
145 | { | ||||||||||||||
146 | #ifndef BOOST_NO_EXCEPTIONS | ||||||||||||||
147 | |||||||||||||||
148 | try | ||||||||||||||
149 | { | ||||||||||||||
150 | pi_ = new sp_counted_impl_p<Y>( p ); | ||||||||||||||
151 | } | ||||||||||||||
152 | catch(...) | ||||||||||||||
153 | { | ||||||||||||||
154 | boost::checked_delete( p ); | ||||||||||||||
155 | throw; | ||||||||||||||
156 | } | ||||||||||||||
157 | |||||||||||||||
158 | #else | ||||||||||||||
159 | |||||||||||||||
160 | pi_ = new sp_counted_impl_p<Y>( p ); | ||||||||||||||
161 | |||||||||||||||
162 | if( pi_ == 0 ) | ||||||||||||||
163 | { | ||||||||||||||
164 | boost::checked_delete( p ); | ||||||||||||||
165 | boost::throw_exception( std::bad_alloc() ); | ||||||||||||||
166 | } | ||||||||||||||
167 | |||||||||||||||
168 | #endif | ||||||||||||||
169 | } | ||||||||||||||
170 | |||||||||||||||
171 | #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1200 )((1 + 0 == 0) && (BOOST_MSVC != 0) && (1 % (( (BOOST_MSVC <= 1200) ) + 1))) | ||||||||||||||
172 | template<class Y, class D> shared_count( Y * p, D d ): pi_(0) | ||||||||||||||
173 | #else | ||||||||||||||
174 | template<class P, class D> shared_count( P p, D d ): pi_(0) | ||||||||||||||
175 | #endif | ||||||||||||||
176 | #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||||||||||||
177 | , id_(shared_count_id) | ||||||||||||||
178 | #endif | ||||||||||||||
179 | { | ||||||||||||||
180 | #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1200 )((1 + 0 == 0) && (BOOST_MSVC != 0) && (1 % (( (BOOST_MSVC <= 1200) ) + 1))) | ||||||||||||||
181 | typedef Y* P; | ||||||||||||||
182 | #endif | ||||||||||||||
183 | #ifndef BOOST_NO_EXCEPTIONS | ||||||||||||||
184 | |||||||||||||||
185 | try | ||||||||||||||
186 | { | ||||||||||||||
187 | pi_ = new sp_counted_impl_pd<P, D>(p, d); | ||||||||||||||
188 | } | ||||||||||||||
189 | catch(...) | ||||||||||||||
190 | { | ||||||||||||||
191 | d(p); // delete p | ||||||||||||||
192 | throw; | ||||||||||||||
193 | } | ||||||||||||||
194 | |||||||||||||||
195 | #else | ||||||||||||||
196 | |||||||||||||||
197 | pi_ = new sp_counted_impl_pd<P, D>(p, d); | ||||||||||||||
198 | |||||||||||||||
199 | if(pi_ == 0) | ||||||||||||||
200 | { | ||||||||||||||
201 | d(p); // delete p | ||||||||||||||
202 | boost::throw_exception(std::bad_alloc()); | ||||||||||||||
203 | } | ||||||||||||||
204 | |||||||||||||||
205 | #endif | ||||||||||||||
206 | } | ||||||||||||||
207 | |||||||||||||||
208 | #if !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING ) | ||||||||||||||
209 | |||||||||||||||
210 | template< class P, class D > shared_count( P p, sp_inplace_tag<D> ): pi_( 0 ) | ||||||||||||||
211 | #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||||||||||||
212 | , id_(shared_count_id) | ||||||||||||||
213 | #endif | ||||||||||||||
214 | { | ||||||||||||||
215 | #ifndef BOOST_NO_EXCEPTIONS | ||||||||||||||
216 | |||||||||||||||
217 | try | ||||||||||||||
218 | { | ||||||||||||||
219 | pi_ = new sp_counted_impl_pd< P, D >( p ); | ||||||||||||||
220 | } | ||||||||||||||
221 | catch( ... ) | ||||||||||||||
222 | { | ||||||||||||||
223 | D::operator_fn( p ); // delete p | ||||||||||||||
224 | throw; | ||||||||||||||
225 | } | ||||||||||||||
226 | |||||||||||||||
227 | #else | ||||||||||||||
228 | |||||||||||||||
229 | pi_ = new sp_counted_impl_pd< P, D >( p ); | ||||||||||||||
230 | |||||||||||||||
231 | if( pi_ == 0 ) | ||||||||||||||
232 | { | ||||||||||||||
233 | D::operator_fn( p ); // delete p | ||||||||||||||
234 | boost::throw_exception( std::bad_alloc() ); | ||||||||||||||
235 | } | ||||||||||||||
236 | |||||||||||||||
237 | #endif // #ifndef BOOST_NO_EXCEPTIONS | ||||||||||||||
238 | } | ||||||||||||||
239 | |||||||||||||||
240 | #endif // !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING ) | ||||||||||||||
241 | |||||||||||||||
242 | template<class P, class D, class A> shared_count( P p, D d, A a ): pi_( 0 ) | ||||||||||||||
243 | #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||||||||||||
244 | , id_(shared_count_id) | ||||||||||||||
245 | #endif | ||||||||||||||
246 | { | ||||||||||||||
247 | typedef sp_counted_impl_pda<P, D, A> impl_type; | ||||||||||||||
248 | |||||||||||||||
249 | #if !defined( BOOST_NO_CXX11_ALLOCATOR ) | ||||||||||||||
250 | |||||||||||||||
251 | typedef typename std::allocator_traits<A>::template rebind_alloc< impl_type > A2; | ||||||||||||||
252 | |||||||||||||||
253 | #else | ||||||||||||||
254 | |||||||||||||||
255 | typedef typename A::template rebind< impl_type >::other A2; | ||||||||||||||
256 | |||||||||||||||
257 | #endif | ||||||||||||||
258 | |||||||||||||||
259 | A2 a2( a ); | ||||||||||||||
260 | |||||||||||||||
261 | #ifndef BOOST_NO_EXCEPTIONS | ||||||||||||||
262 | |||||||||||||||
263 | try | ||||||||||||||
264 | { | ||||||||||||||
265 | pi_ = a2.allocate( 1 ); | ||||||||||||||
266 | ::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a ); | ||||||||||||||
267 | } | ||||||||||||||
268 | catch(...) | ||||||||||||||
269 | { | ||||||||||||||
270 | d( p ); | ||||||||||||||
271 | |||||||||||||||
272 | if( pi_ != 0 ) | ||||||||||||||
273 | { | ||||||||||||||
274 | a2.deallocate( static_cast< impl_type* >( pi_ ), 1 ); | ||||||||||||||
275 | } | ||||||||||||||
276 | |||||||||||||||
277 | throw; | ||||||||||||||
278 | } | ||||||||||||||
279 | |||||||||||||||
280 | #else | ||||||||||||||
281 | |||||||||||||||
282 | pi_ = a2.allocate( 1 ); | ||||||||||||||
283 | |||||||||||||||
284 | if( pi_ != 0 ) | ||||||||||||||
285 | { | ||||||||||||||
286 | ::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a ); | ||||||||||||||
287 | } | ||||||||||||||
288 | else | ||||||||||||||
289 | { | ||||||||||||||
290 | d( p ); | ||||||||||||||
291 | boost::throw_exception( std::bad_alloc() ); | ||||||||||||||
292 | } | ||||||||||||||
293 | |||||||||||||||
294 | #endif | ||||||||||||||
295 | } | ||||||||||||||
296 | |||||||||||||||
297 | #if !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING ) | ||||||||||||||
298 | |||||||||||||||
299 | template< class P, class D, class A > shared_count( P p, sp_inplace_tag< D >, A a ): pi_( 0 ) | ||||||||||||||
300 | #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||||||||||||
301 | , id_(shared_count_id) | ||||||||||||||
302 | #endif | ||||||||||||||
303 | { | ||||||||||||||
304 | typedef sp_counted_impl_pda< P, D, A > impl_type; | ||||||||||||||
305 | |||||||||||||||
306 | #if !defined( BOOST_NO_CXX11_ALLOCATOR ) | ||||||||||||||
307 | |||||||||||||||
308 | typedef typename std::allocator_traits<A>::template rebind_alloc< impl_type > A2; | ||||||||||||||
309 | |||||||||||||||
310 | #else | ||||||||||||||
311 | |||||||||||||||
312 | typedef typename A::template rebind< impl_type >::other A2; | ||||||||||||||
313 | |||||||||||||||
314 | #endif | ||||||||||||||
315 | |||||||||||||||
316 | A2 a2( a ); | ||||||||||||||
317 | |||||||||||||||
318 | #ifndef BOOST_NO_EXCEPTIONS | ||||||||||||||
319 | |||||||||||||||
320 | try | ||||||||||||||
321 | { | ||||||||||||||
322 | pi_ = a2.allocate( 1 ); | ||||||||||||||
323 | ::new( static_cast< void* >( pi_ ) ) impl_type( p, a ); | ||||||||||||||
324 | } | ||||||||||||||
325 | catch(...) | ||||||||||||||
326 | { | ||||||||||||||
327 | D::operator_fn( p ); | ||||||||||||||
328 | |||||||||||||||
329 | if( pi_ != 0 ) | ||||||||||||||
330 | { | ||||||||||||||
331 | a2.deallocate( static_cast< impl_type* >( pi_ ), 1 ); | ||||||||||||||
332 | } | ||||||||||||||
333 | |||||||||||||||
334 | throw; | ||||||||||||||
335 | } | ||||||||||||||
336 | |||||||||||||||
337 | #else | ||||||||||||||
338 | |||||||||||||||
339 | pi_ = a2.allocate( 1 ); | ||||||||||||||
340 | |||||||||||||||
341 | if( pi_ != 0 ) | ||||||||||||||
342 | { | ||||||||||||||
343 | ::new( static_cast< void* >( pi_ ) ) impl_type( p, a ); | ||||||||||||||
344 | } | ||||||||||||||
345 | else | ||||||||||||||
346 | { | ||||||||||||||
347 | D::operator_fn( p ); | ||||||||||||||
348 | boost::throw_exception( std::bad_alloc() ); | ||||||||||||||
349 | } | ||||||||||||||
350 | |||||||||||||||
351 | #endif // #ifndef BOOST_NO_EXCEPTIONS | ||||||||||||||
352 | } | ||||||||||||||
353 | |||||||||||||||
354 | #endif // !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING ) | ||||||||||||||
355 | |||||||||||||||
356 | #ifndef BOOST_NO_AUTO_PTR | ||||||||||||||
357 | |||||||||||||||
358 | // auto_ptr<Y> is special cased to provide the strong guarantee | ||||||||||||||
359 | |||||||||||||||
360 | template<class Y> | ||||||||||||||
361 | explicit shared_count( std::auto_ptr<Y> & r ): pi_( new sp_counted_impl_p<Y>( r.get() ) ) | ||||||||||||||
362 | #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||||||||||||
363 | , id_(shared_count_id) | ||||||||||||||
364 | #endif | ||||||||||||||
365 | { | ||||||||||||||
366 | #ifdef BOOST_NO_EXCEPTIONS | ||||||||||||||
367 | |||||||||||||||
368 | if( pi_ == 0 ) | ||||||||||||||
369 | { | ||||||||||||||
370 | boost::throw_exception(std::bad_alloc()); | ||||||||||||||
371 | } | ||||||||||||||
372 | |||||||||||||||
373 | #endif | ||||||||||||||
374 | |||||||||||||||
375 | r.release(); | ||||||||||||||
376 | } | ||||||||||||||
377 | |||||||||||||||
378 | #endif | ||||||||||||||
379 | |||||||||||||||
380 | #if !defined( BOOST_NO_CXX11_SMART_PTR ) | ||||||||||||||
381 | |||||||||||||||
382 | template<class Y, class D> | ||||||||||||||
383 | explicit shared_count( std::unique_ptr<Y, D> & r ): pi_( 0 ) | ||||||||||||||
384 | #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||||||||||||
385 | , id_(shared_count_id) | ||||||||||||||
386 | #endif | ||||||||||||||
387 | { | ||||||||||||||
388 | typedef typename sp_convert_reference<D>::type D2; | ||||||||||||||
389 | |||||||||||||||
390 | D2 d2( static_cast<D&&>( r.get_deleter() ) ); | ||||||||||||||
391 | pi_ = new sp_counted_impl_pd< typename std::unique_ptr<Y, D>::pointer, D2 >( r.get(), d2 ); | ||||||||||||||
392 | |||||||||||||||
393 | #ifdef BOOST_NO_EXCEPTIONS | ||||||||||||||
394 | |||||||||||||||
395 | if( pi_ == 0 ) | ||||||||||||||
396 | { | ||||||||||||||
397 | boost::throw_exception( std::bad_alloc() ); | ||||||||||||||
398 | } | ||||||||||||||
399 | |||||||||||||||
400 | #endif | ||||||||||||||
401 | |||||||||||||||
402 | r.release(); | ||||||||||||||
403 | } | ||||||||||||||
404 | |||||||||||||||
405 | #endif | ||||||||||||||
406 | |||||||||||||||
407 | template<class Y, class D> | ||||||||||||||
408 | explicit shared_count( boost::movelib::unique_ptr<Y, D> & r ): pi_( 0 ) | ||||||||||||||
409 | #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||||||||||||
410 | , id_(shared_count_id) | ||||||||||||||
411 | #endif | ||||||||||||||
412 | { | ||||||||||||||
413 | typedef typename sp_convert_reference<D>::type D2; | ||||||||||||||
414 | |||||||||||||||
415 | D2 d2( r.get_deleter() ); | ||||||||||||||
416 | pi_ = new sp_counted_impl_pd< typename boost::movelib::unique_ptr<Y, D>::pointer, D2 >( r.get(), d2 ); | ||||||||||||||
417 | |||||||||||||||
418 | #ifdef BOOST_NO_EXCEPTIONS | ||||||||||||||
419 | |||||||||||||||
420 | if( pi_ == 0 ) | ||||||||||||||
421 | { | ||||||||||||||
422 | boost::throw_exception( std::bad_alloc() ); | ||||||||||||||
423 | } | ||||||||||||||
424 | |||||||||||||||
425 | #endif | ||||||||||||||
426 | |||||||||||||||
427 | r.release(); | ||||||||||||||
428 | } | ||||||||||||||
429 | |||||||||||||||
430 | ~shared_count() /*BOOST_SP_NOEXCEPT*/ | ||||||||||||||
431 | { | ||||||||||||||
432 | if( pi_ != 0 ) pi_->release(); | ||||||||||||||
433 | #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||||||||||||
434 | id_ = 0; | ||||||||||||||
435 | #endif | ||||||||||||||
436 | } | ||||||||||||||
437 | |||||||||||||||
438 | shared_count(shared_count const & r) BOOST_SP_NOEXCEPTnoexcept: pi_(r.pi_) | ||||||||||||||
439 | #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||||||||||||
440 | , id_(shared_count_id) | ||||||||||||||
441 | #endif | ||||||||||||||
442 | { | ||||||||||||||
443 | if( pi_ != 0 ) pi_->add_ref_copy(); | ||||||||||||||
444 | } | ||||||||||||||
445 | |||||||||||||||
446 | #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) | ||||||||||||||
447 | |||||||||||||||
448 | shared_count(shared_count && r) BOOST_SP_NOEXCEPTnoexcept: pi_(r.pi_) | ||||||||||||||
449 | #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||||||||||||
450 | , id_(shared_count_id) | ||||||||||||||
451 | #endif | ||||||||||||||
452 | { | ||||||||||||||
453 | r.pi_ = 0; | ||||||||||||||
454 | } | ||||||||||||||
455 | |||||||||||||||
456 | #endif | ||||||||||||||
457 | |||||||||||||||
458 | explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0 | ||||||||||||||
459 | shared_count( weak_count const & r, sp_nothrow_tag ) BOOST_SP_NOEXCEPTnoexcept; // constructs an empty *this when r.use_count() == 0 | ||||||||||||||
460 | |||||||||||||||
461 | shared_count & operator= (shared_count const & r) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
462 | { | ||||||||||||||
463 | sp_counted_base * tmp = r.pi_; | ||||||||||||||
464 | |||||||||||||||
465 | if( tmp != pi_ ) | ||||||||||||||
466 | { | ||||||||||||||
467 | if( tmp != 0 ) tmp->add_ref_copy(); | ||||||||||||||
468 | if( pi_ != 0 ) pi_->release(); | ||||||||||||||
469 | pi_ = tmp; | ||||||||||||||
470 | } | ||||||||||||||
471 | |||||||||||||||
472 | return *this; | ||||||||||||||
473 | } | ||||||||||||||
474 | |||||||||||||||
475 | void swap(shared_count & r) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
476 | { | ||||||||||||||
477 | sp_counted_base * tmp = r.pi_; | ||||||||||||||
478 | r.pi_ = pi_; | ||||||||||||||
479 | pi_ = tmp; | ||||||||||||||
480 | } | ||||||||||||||
481 | |||||||||||||||
482 | long use_count() const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
483 | { | ||||||||||||||
484 | return pi_ != 0? pi_->use_count(): 0; | ||||||||||||||
485 | } | ||||||||||||||
486 | |||||||||||||||
487 | bool unique() const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
488 | { | ||||||||||||||
489 | return use_count() == 1; | ||||||||||||||
490 | } | ||||||||||||||
491 | |||||||||||||||
492 | bool empty() const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
493 | { | ||||||||||||||
494 | return pi_ == 0; | ||||||||||||||
495 | } | ||||||||||||||
496 | |||||||||||||||
497 | bool operator==( shared_count const & r ) const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
498 | { | ||||||||||||||
499 | return pi_ == r.pi_; | ||||||||||||||
500 | } | ||||||||||||||
501 | |||||||||||||||
502 | bool operator==( weak_count const & r ) const BOOST_SP_NOEXCEPTnoexcept; | ||||||||||||||
503 | |||||||||||||||
504 | bool operator<( shared_count const & r ) const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
505 | { | ||||||||||||||
506 | return std::less<sp_counted_base *>()( pi_, r.pi_ ); | ||||||||||||||
507 | } | ||||||||||||||
508 | |||||||||||||||
509 | bool operator<( weak_count const & r ) const BOOST_SP_NOEXCEPTnoexcept; | ||||||||||||||
510 | |||||||||||||||
511 | void * get_deleter( sp_typeinfo_ const & ti ) const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
512 | { | ||||||||||||||
513 | return pi_? pi_->get_deleter( ti ): 0; | ||||||||||||||
514 | } | ||||||||||||||
515 | |||||||||||||||
516 | void * get_local_deleter( sp_typeinfo_ const & ti ) const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
517 | { | ||||||||||||||
518 | return pi_? pi_->get_local_deleter( ti ): 0; | ||||||||||||||
519 | } | ||||||||||||||
520 | |||||||||||||||
521 | void * get_untyped_deleter() const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
522 | { | ||||||||||||||
523 | return pi_? pi_->get_untyped_deleter(): 0; | ||||||||||||||
524 | } | ||||||||||||||
525 | |||||||||||||||
526 | std::size_t hash_value() const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
527 | { | ||||||||||||||
528 | return sp_hash_pointer( pi_ ); | ||||||||||||||
529 | } | ||||||||||||||
530 | }; | ||||||||||||||
531 | |||||||||||||||
532 | |||||||||||||||
533 | class weak_count | ||||||||||||||
534 | { | ||||||||||||||
535 | private: | ||||||||||||||
536 | |||||||||||||||
537 | sp_counted_base * pi_; | ||||||||||||||
538 | |||||||||||||||
539 | #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||||||||||||
540 | int id_; | ||||||||||||||
541 | #endif | ||||||||||||||
542 | |||||||||||||||
543 | friend class shared_count; | ||||||||||||||
544 | |||||||||||||||
545 | public: | ||||||||||||||
546 | |||||||||||||||
547 | BOOST_CONSTEXPRconstexpr weak_count() BOOST_SP_NOEXCEPTnoexcept: pi_(0) | ||||||||||||||
548 | #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||||||||||||
549 | , id_(weak_count_id) | ||||||||||||||
550 | #endif | ||||||||||||||
551 | { | ||||||||||||||
552 | } | ||||||||||||||
553 | |||||||||||||||
554 | weak_count(shared_count const & r) BOOST_SP_NOEXCEPTnoexcept: pi_(r.pi_) | ||||||||||||||
555 | #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||||||||||||
556 | , id_(weak_count_id) | ||||||||||||||
557 | #endif | ||||||||||||||
558 | { | ||||||||||||||
559 | if(pi_ != 0) pi_->weak_add_ref(); | ||||||||||||||
560 | } | ||||||||||||||
561 | |||||||||||||||
562 | weak_count(weak_count const & r) BOOST_SP_NOEXCEPTnoexcept: pi_(r.pi_) | ||||||||||||||
563 | #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||||||||||||
564 | , id_(weak_count_id) | ||||||||||||||
565 | #endif | ||||||||||||||
566 | { | ||||||||||||||
567 | if(pi_ != 0) pi_->weak_add_ref(); | ||||||||||||||
568 | } | ||||||||||||||
569 | |||||||||||||||
570 | // Move support | ||||||||||||||
571 | |||||||||||||||
572 | #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) | ||||||||||||||
573 | |||||||||||||||
574 | weak_count(weak_count && r) BOOST_SP_NOEXCEPTnoexcept: pi_(r.pi_) | ||||||||||||||
575 | #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||||||||||||
576 | , id_(weak_count_id) | ||||||||||||||
577 | #endif | ||||||||||||||
578 | { | ||||||||||||||
579 | r.pi_ = 0; | ||||||||||||||
580 | } | ||||||||||||||
581 | |||||||||||||||
582 | #endif | ||||||||||||||
583 | |||||||||||||||
584 | ~weak_count() /*BOOST_SP_NOEXCEPT*/ | ||||||||||||||
585 | { | ||||||||||||||
586 | if(pi_
| ||||||||||||||
587 | #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||||||||||||
588 | id_ = 0; | ||||||||||||||
589 | #endif | ||||||||||||||
590 | } | ||||||||||||||
591 | |||||||||||||||
592 | weak_count & operator= (shared_count const & r) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
593 | { | ||||||||||||||
594 | sp_counted_base * tmp = r.pi_; | ||||||||||||||
595 | |||||||||||||||
596 | if( tmp != pi_ ) | ||||||||||||||
597 | { | ||||||||||||||
598 | if(tmp != 0) tmp->weak_add_ref(); | ||||||||||||||
599 | if(pi_ != 0) pi_->weak_release(); | ||||||||||||||
600 | pi_ = tmp; | ||||||||||||||
601 | } | ||||||||||||||
602 | |||||||||||||||
603 | return *this; | ||||||||||||||
604 | } | ||||||||||||||
605 | |||||||||||||||
606 | weak_count & operator= (weak_count const & r) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
607 | { | ||||||||||||||
608 | sp_counted_base * tmp = r.pi_; | ||||||||||||||
609 | |||||||||||||||
610 | if( tmp != pi_ ) | ||||||||||||||
611 | { | ||||||||||||||
612 | if(tmp != 0) tmp->weak_add_ref(); | ||||||||||||||
613 | if(pi_ != 0) pi_->weak_release(); | ||||||||||||||
614 | pi_ = tmp; | ||||||||||||||
615 | } | ||||||||||||||
616 | |||||||||||||||
617 | return *this; | ||||||||||||||
618 | } | ||||||||||||||
619 | |||||||||||||||
620 | void swap(weak_count & r) BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
621 | { | ||||||||||||||
622 | sp_counted_base * tmp = r.pi_; | ||||||||||||||
623 | r.pi_ = pi_; | ||||||||||||||
624 | pi_ = tmp; | ||||||||||||||
625 | } | ||||||||||||||
626 | |||||||||||||||
627 | long use_count() const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
628 | { | ||||||||||||||
629 | return pi_ != 0? pi_->use_count(): 0; | ||||||||||||||
630 | } | ||||||||||||||
631 | |||||||||||||||
632 | bool empty() const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
633 | { | ||||||||||||||
634 | return pi_ == 0; | ||||||||||||||
635 | } | ||||||||||||||
636 | |||||||||||||||
637 | bool operator==( weak_count const & r ) const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
638 | { | ||||||||||||||
639 | return pi_ == r.pi_; | ||||||||||||||
640 | } | ||||||||||||||
641 | |||||||||||||||
642 | bool operator==( shared_count const & r ) const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
643 | { | ||||||||||||||
644 | return pi_ == r.pi_; | ||||||||||||||
645 | } | ||||||||||||||
646 | |||||||||||||||
647 | bool operator<( weak_count const & r ) const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
648 | { | ||||||||||||||
649 | return std::less<sp_counted_base *>()( pi_, r.pi_ ); | ||||||||||||||
650 | } | ||||||||||||||
651 | |||||||||||||||
652 | bool operator<( shared_count const & r ) const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
653 | { | ||||||||||||||
654 | return std::less<sp_counted_base *>()( pi_, r.pi_ ); | ||||||||||||||
655 | } | ||||||||||||||
656 | |||||||||||||||
657 | std::size_t hash_value() const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
658 | { | ||||||||||||||
659 | return sp_hash_pointer( pi_ ); | ||||||||||||||
660 | } | ||||||||||||||
661 | }; | ||||||||||||||
662 | |||||||||||||||
663 | inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ ) | ||||||||||||||
664 | #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||||||||||||
665 | , id_(shared_count_id) | ||||||||||||||
666 | #endif | ||||||||||||||
667 | { | ||||||||||||||
668 | if( pi_ == 0 || !pi_->add_ref_lock() ) | ||||||||||||||
669 | { | ||||||||||||||
670 | boost::throw_exception( boost::bad_weak_ptr() ); | ||||||||||||||
671 | } | ||||||||||||||
672 | } | ||||||||||||||
673 | |||||||||||||||
674 | inline shared_count::shared_count( weak_count const & r, sp_nothrow_tag ) BOOST_SP_NOEXCEPTnoexcept: pi_( r.pi_ ) | ||||||||||||||
675 | #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||||||||||||
676 | , id_(shared_count_id) | ||||||||||||||
677 | #endif | ||||||||||||||
678 | { | ||||||||||||||
679 | if( pi_ != 0 && !pi_->add_ref_lock() ) | ||||||||||||||
680 | { | ||||||||||||||
681 | pi_ = 0; | ||||||||||||||
682 | } | ||||||||||||||
683 | } | ||||||||||||||
684 | |||||||||||||||
685 | inline bool shared_count::operator==( weak_count const & r ) const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
686 | { | ||||||||||||||
687 | return pi_ == r.pi_; | ||||||||||||||
688 | } | ||||||||||||||
689 | |||||||||||||||
690 | inline bool shared_count::operator<( weak_count const & r ) const BOOST_SP_NOEXCEPTnoexcept | ||||||||||||||
691 | { | ||||||||||||||
692 | return std::less<sp_counted_base *>()( pi_, r.pi_ ); | ||||||||||||||
693 | } | ||||||||||||||
694 | |||||||||||||||
695 | } // namespace detail | ||||||||||||||
696 | |||||||||||||||
697 | } // namespace boost | ||||||||||||||
698 | |||||||||||||||
699 | #if defined( BOOST_SP_DISABLE_DEPRECATED ) | ||||||||||||||
700 | #pragma GCC diagnostic pop | ||||||||||||||
701 | #endif | ||||||||||||||
702 | |||||||||||||||
703 | #if defined(__BORLANDC__) && !defined(__clang__1) | ||||||||||||||
704 | # pragma warn .8027 // Functions containing try are not expanded inline | ||||||||||||||
705 | #endif | ||||||||||||||
706 | |||||||||||||||
707 | #endif // #ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED |
1 | #ifndef BOOST_SMART_PTR_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED |
2 | #define BOOST_SMART_PTR_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED |
3 | |
4 | // |
5 | // enable_shared_from_this.hpp |
6 | // |
7 | // Copyright 2002, 2009 Peter Dimov |
8 | // |
9 | // Distributed under the Boost Software License, Version 1.0. |
10 | // See accompanying file LICENSE_1_0.txt or copy at |
11 | // http://www.boost.org/LICENSE_1_0.txt |
12 | // |
13 | // See http://www.boost.org/libs/smart_ptr/ for documentation. |
14 | // |
15 | |
16 | #include <boost/smart_ptr/detail/requires_cxx11.hpp> |
17 | #include <boost/smart_ptr/weak_ptr.hpp> |
18 | #include <boost/smart_ptr/shared_ptr.hpp> |
19 | #include <boost/smart_ptr/detail/sp_noexcept.hpp> |
20 | #include <boost/assert.hpp> |
21 | #include <boost/config.hpp> |
22 | |
23 | namespace boost |
24 | { |
25 | |
26 | template<class T> class enable_shared_from_this |
27 | { |
28 | protected: |
29 | |
30 | BOOST_CONSTEXPRconstexpr enable_shared_from_this() BOOST_SP_NOEXCEPTnoexcept |
31 | { |
32 | } |
33 | |
34 | BOOST_CONSTEXPRconstexpr enable_shared_from_this(enable_shared_from_this const &) BOOST_SP_NOEXCEPTnoexcept |
35 | { |
36 | } |
37 | |
38 | enable_shared_from_this & operator=(enable_shared_from_this const &) BOOST_SP_NOEXCEPTnoexcept |
39 | { |
40 | return *this; |
41 | } |
42 | |
43 | ~enable_shared_from_this() BOOST_SP_NOEXCEPTnoexcept // ~weak_ptr<T> newer throws, so this call also must not throw |
44 | { |
45 | } |
46 | |
47 | public: |
48 | |
49 | shared_ptr<T> shared_from_this() |
50 | { |
51 | shared_ptr<T> p( weak_this_ ); |
52 | BOOST_ASSERT( p.get() == this )(static_cast <bool> (p.get() == this) ? void (0) : __assert_fail ("p.get() == this", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); |
53 | return p; |
54 | } |
55 | |
56 | shared_ptr<T const> shared_from_this() const |
57 | { |
58 | shared_ptr<T const> p( weak_this_ ); |
59 | BOOST_ASSERT( p.get() == this )(static_cast <bool> (p.get() == this) ? void (0) : __assert_fail ("p.get() == this", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); |
60 | return p; |
61 | } |
62 | |
63 | weak_ptr<T> weak_from_this() BOOST_SP_NOEXCEPTnoexcept |
64 | { |
65 | return weak_this_; |
66 | } |
67 | |
68 | weak_ptr<T const> weak_from_this() const BOOST_SP_NOEXCEPTnoexcept |
69 | { |
70 | return weak_this_; |
71 | } |
72 | |
73 | public: // actually private, but avoids compiler template friendship issues |
74 | |
75 | // Note: invoked automatically by shared_ptr; do not call |
76 | template<class X, class Y> void _internal_accept_owner( shared_ptr<X> const * ppx, Y * py ) const BOOST_SP_NOEXCEPTnoexcept |
77 | { |
78 | if( weak_this_.expired() ) |
79 | { |
80 | weak_this_ = shared_ptr<T>( *ppx, py ); |
81 | } |
82 | } |
83 | |
84 | private: |
85 | |
86 | mutable weak_ptr<T> weak_this_; |
87 | }; |
88 | |
89 | } // namespace boost |
90 | |
91 | #endif // #ifndef BOOST_SMART_PTR_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED |
1 | #ifndef BOOST_SMART_PTR_WEAK_PTR_HPP_INCLUDED |
2 | #define BOOST_SMART_PTR_WEAK_PTR_HPP_INCLUDED |
3 | |
4 | // |
5 | // weak_ptr.hpp |
6 | // |
7 | // Copyright (c) 2001, 2002, 2003 Peter Dimov |
8 | // |
9 | // Distributed under the Boost Software License, Version 1.0. (See |
10 | // accompanying file LICENSE_1_0.txt or copy at |
11 | // http://www.boost.org/LICENSE_1_0.txt) |
12 | // |
13 | // See http://www.boost.org/libs/smart_ptr/ for documentation. |
14 | // |
15 | |
16 | #include <boost/smart_ptr/detail/requires_cxx11.hpp> |
17 | #include <boost/smart_ptr/detail/shared_count.hpp> |
18 | #include <boost/smart_ptr/shared_ptr.hpp> |
19 | #include <boost/smart_ptr/detail/sp_noexcept.hpp> |
20 | #include <memory> |
21 | #include <cstddef> |
22 | |
23 | namespace boost |
24 | { |
25 | |
26 | template<class T> class weak_ptr |
27 | { |
28 | private: |
29 | |
30 | // Borland 5.5.1 specific workarounds |
31 | typedef weak_ptr<T> this_type; |
32 | |
33 | public: |
34 | |
35 | typedef typename boost::detail::sp_element< T >::type element_type; |
36 | |
37 | BOOST_CONSTEXPRconstexpr weak_ptr() BOOST_SP_NOEXCEPTnoexcept : px(0), pn() |
38 | { |
39 | } |
40 | |
41 | // generated copy constructor, assignment, destructor are fine... |
42 | |
43 | #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) |
44 | |
45 | // ... except in C++0x, move disables the implicit copy |
46 | |
47 | weak_ptr( weak_ptr const & r ) BOOST_SP_NOEXCEPTnoexcept : px( r.px ), pn( r.pn ) |
48 | { |
49 | } |
50 | |
51 | weak_ptr & operator=( weak_ptr const & r ) BOOST_SP_NOEXCEPTnoexcept |
52 | { |
53 | px = r.px; |
54 | pn = r.pn; |
55 | return *this; |
56 | } |
57 | |
58 | #endif |
59 | |
60 | // |
61 | // The "obvious" converting constructor implementation: |
62 | // |
63 | // template<class Y> |
64 | // weak_ptr(weak_ptr<Y> const & r): px(r.px), pn(r.pn) |
65 | // { |
66 | // } |
67 | // |
68 | // has a serious problem. |
69 | // |
70 | // r.px may already have been invalidated. The px(r.px) |
71 | // conversion may require access to *r.px (virtual inheritance). |
72 | // |
73 | // It is not possible to avoid spurious access violations since |
74 | // in multithreaded programs r.px may be invalidated at any point. |
75 | // |
76 | |
77 | template<class Y> |
78 | #if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) |
79 | |
80 | weak_ptr( weak_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() ) |
81 | |
82 | #else |
83 | |
84 | weak_ptr( weak_ptr<Y> const & r ) |
85 | |
86 | #endif |
87 | BOOST_SP_NOEXCEPTnoexcept : px(r.lock().get()), pn(r.pn) |
88 | { |
89 | boost::detail::sp_assert_convertible< Y, T >(); |
90 | } |
91 | |
92 | #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) |
93 | |
94 | template<class Y> |
95 | #if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) |
96 | |
97 | weak_ptr( weak_ptr<Y> && r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() ) |
98 | |
99 | #else |
100 | |
101 | weak_ptr( weak_ptr<Y> && r ) |
102 | |
103 | #endif |
104 | BOOST_SP_NOEXCEPTnoexcept : px( r.lock().get() ), pn( static_cast< boost::detail::weak_count && >( r.pn ) ) |
105 | { |
106 | boost::detail::sp_assert_convertible< Y, T >(); |
107 | r.px = 0; |
108 | } |
109 | |
110 | // for better efficiency in the T == Y case |
111 | weak_ptr( weak_ptr && r ) |
112 | BOOST_SP_NOEXCEPTnoexcept : px( r.px ), pn( static_cast< boost::detail::weak_count && >( r.pn ) ) |
113 | { |
114 | r.px = 0; |
115 | } |
116 | |
117 | // for better efficiency in the T == Y case |
118 | weak_ptr & operator=( weak_ptr && r ) BOOST_SP_NOEXCEPTnoexcept |
119 | { |
120 | this_type( static_cast< weak_ptr && >( r ) ).swap( *this ); |
121 | return *this; |
122 | } |
123 | |
124 | |
125 | #endif |
126 | |
127 | template<class Y> |
128 | #if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) |
129 | |
130 | weak_ptr( shared_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() ) |
131 | |
132 | #else |
133 | |
134 | weak_ptr( shared_ptr<Y> const & r ) |
135 | |
136 | #endif |
137 | BOOST_SP_NOEXCEPTnoexcept : px( r.px ), pn( r.pn ) |
138 | { |
139 | boost::detail::sp_assert_convertible< Y, T >(); |
140 | } |
141 | |
142 | // aliasing |
143 | template<class Y> weak_ptr(shared_ptr<Y> const & r, element_type * p) BOOST_SP_NOEXCEPTnoexcept: px( p ), pn( r.pn ) |
144 | { |
145 | } |
146 | |
147 | template<class Y> weak_ptr(weak_ptr<Y> const & r, element_type * p) BOOST_SP_NOEXCEPTnoexcept: px( p ), pn( r.pn ) |
148 | { |
149 | } |
150 | |
151 | #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) |
152 | |
153 | template<class Y> weak_ptr(weak_ptr<Y> && r, element_type * p) BOOST_SP_NOEXCEPTnoexcept: px( p ), pn( std::move( r.pn ) ) |
154 | { |
155 | } |
156 | |
157 | #endif |
158 | |
159 | #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) |
160 | |
161 | template<class Y> |
162 | weak_ptr & operator=( weak_ptr<Y> const & r ) BOOST_SP_NOEXCEPTnoexcept |
163 | { |
164 | boost::detail::sp_assert_convertible< Y, T >(); |
165 | |
166 | px = r.lock().get(); |
167 | pn = r.pn; |
168 | |
169 | return *this; |
170 | } |
171 | |
172 | #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) |
173 | |
174 | template<class Y> |
175 | weak_ptr & operator=( weak_ptr<Y> && r ) BOOST_SP_NOEXCEPTnoexcept |
176 | { |
177 | this_type( static_cast< weak_ptr<Y> && >( r ) ).swap( *this ); |
178 | return *this; |
179 | } |
180 | |
181 | #endif |
182 | |
183 | template<class Y> |
184 | weak_ptr & operator=( shared_ptr<Y> const & r ) BOOST_SP_NOEXCEPTnoexcept |
185 | { |
186 | boost::detail::sp_assert_convertible< Y, T >(); |
187 | |
188 | px = r.px; |
189 | pn = r.pn; |
190 | |
191 | return *this; |
192 | } |
193 | |
194 | #endif |
195 | |
196 | shared_ptr<T> lock() const BOOST_SP_NOEXCEPTnoexcept |
197 | { |
198 | return shared_ptr<T>( *this, boost::detail::sp_nothrow_tag() ); |
199 | } |
200 | |
201 | long use_count() const BOOST_SP_NOEXCEPTnoexcept |
202 | { |
203 | return pn.use_count(); |
204 | } |
205 | |
206 | bool expired() const BOOST_SP_NOEXCEPTnoexcept |
207 | { |
208 | return pn.use_count() == 0; |
209 | } |
210 | |
211 | bool _empty() const BOOST_SP_NOEXCEPTnoexcept // extension, not in std::weak_ptr |
212 | { |
213 | return pn.empty(); |
214 | } |
215 | |
216 | bool empty() const BOOST_SP_NOEXCEPTnoexcept // extension, not in std::weak_ptr |
217 | { |
218 | return pn.empty(); |
219 | } |
220 | |
221 | void reset() BOOST_SP_NOEXCEPTnoexcept |
222 | { |
223 | this_type().swap(*this); |
224 | } |
225 | |
226 | void swap(this_type & other) BOOST_SP_NOEXCEPTnoexcept |
227 | { |
228 | std::swap(px, other.px); |
229 | pn.swap(other.pn); |
230 | } |
231 | |
232 | template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPTnoexcept |
233 | { |
234 | return pn < rhs.pn; |
235 | } |
236 | |
237 | template<class Y> bool owner_before( shared_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPTnoexcept |
238 | { |
239 | return pn < rhs.pn; |
240 | } |
241 | |
242 | template<class Y> bool owner_equals( weak_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPTnoexcept |
243 | { |
244 | return pn == rhs.pn; |
245 | } |
246 | |
247 | template<class Y> bool owner_equals( shared_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPTnoexcept |
248 | { |
249 | return pn == rhs.pn; |
250 | } |
251 | |
252 | std::size_t owner_hash_value() const BOOST_SP_NOEXCEPTnoexcept |
253 | { |
254 | return pn.hash_value(); |
255 | } |
256 | |
257 | // Tasteless as this may seem, making all members public allows member templates |
258 | // to work in the absence of member template friends. (Matthew Langston) |
259 | |
260 | #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS |
261 | |
262 | private: |
263 | |
264 | template<class Y> friend class weak_ptr; |
265 | template<class Y> friend class shared_ptr; |
266 | |
267 | #endif |
268 | |
269 | element_type * px; // contained pointer |
270 | boost::detail::weak_count pn; // reference counter |
271 | |
272 | }; // weak_ptr |
273 | |
274 | template<class T, class U> inline bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b) BOOST_SP_NOEXCEPTnoexcept |
275 | { |
276 | return a.owner_before( b ); |
277 | } |
278 | |
279 | template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b) BOOST_SP_NOEXCEPTnoexcept |
280 | { |
281 | a.swap(b); |
282 | } |
283 | |
284 | #if defined(__cpp_deduction_guides201703L) |
285 | |
286 | template<class T> weak_ptr( shared_ptr<T> ) -> weak_ptr<T>; |
287 | |
288 | #endif |
289 | |
290 | // hash_value |
291 | |
292 | template< class T > std::size_t hash_value( boost::weak_ptr<T> const & p ) BOOST_SP_NOEXCEPTnoexcept |
293 | { |
294 | return p.owner_hash_value(); |
295 | } |
296 | |
297 | } // namespace boost |
298 | |
299 | // std::hash, std::equal_to |
300 | |
301 | namespace std |
302 | { |
303 | |
304 | #if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) |
305 | |
306 | template<class T> struct hash< ::boost::weak_ptr<T> > |
307 | { |
308 | std::size_t operator()( ::boost::weak_ptr<T> const & p ) const BOOST_SP_NOEXCEPTnoexcept |
309 | { |
310 | return p.owner_hash_value(); |
311 | } |
312 | }; |
313 | |
314 | #endif // #if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) |
315 | |
316 | template<class T> struct equal_to< ::boost::weak_ptr<T> > |
317 | { |
318 | bool operator()( ::boost::weak_ptr<T> const & a, ::boost::weak_ptr<T> const & b ) const BOOST_SP_NOEXCEPTnoexcept |
319 | { |
320 | return a.owner_equals( b ); |
321 | } |
322 | }; |
323 | |
324 | } // namespace std |
325 | |
326 | #endif // #ifndef BOOST_SMART_PTR_WEAK_PTR_HPP_INCLUDED |
1 | #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_ATOMIC_HPP_INCLUDED |
2 | #define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_ATOMIC_HPP_INCLUDED |
3 | |
4 | // MS compatible compilers support #pragma once |
5 | |
6 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) |
7 | # pragma once |
8 | #endif |
9 | |
10 | // detail/sp_counted_base_gcc_atomic.hpp - g++ 4.7+ __atomic intrinsics |
11 | // |
12 | // Copyright 2007, 2020 Peter Dimov |
13 | // Distributed under the Boost Software License, Version 1.0. |
14 | // https://www.boost.org/LICENSE_1_0.txt |
15 | |
16 | #include <boost/smart_ptr/detail/sp_typeinfo_.hpp> |
17 | #include <boost/config.hpp> |
18 | #include <boost/cstdint.hpp> |
19 | |
20 | #if defined(BOOST_SP_REPORT_IMPLEMENTATION) |
21 | |
22 | #include <boost/config/pragma_message.hpp> |
23 | BOOST_PRAGMA_MESSAGE("Using __atomic sp_counted_base")message("Using __atomic sp_counted_base") |
24 | |
25 | #endif |
26 | |
27 | namespace boost |
28 | { |
29 | |
30 | namespace detail |
31 | { |
32 | |
33 | inline void atomic_increment( boost::uint_least32_t * pw ) |
34 | { |
35 | __atomic_fetch_add( pw, 1, __ATOMIC_RELAXED0 ); |
36 | } |
37 | |
38 | inline boost::uint_least32_t atomic_decrement( boost::uint_least32_t * pw ) |
39 | { |
40 | return __atomic_fetch_sub( pw, 1, __ATOMIC_ACQ_REL4 ); |
41 | } |
42 | |
43 | inline boost::uint_least32_t atomic_conditional_increment( boost::uint_least32_t * pw ) |
44 | { |
45 | // long r = *pw; |
46 | // if( r != 0 ) ++*pw; |
47 | // return r; |
48 | |
49 | boost::uint_least32_t r = __atomic_load_n( pw, __ATOMIC_RELAXED0 ); |
50 | |
51 | for( ;; ) |
52 | { |
53 | if( r == 0 ) |
54 | { |
55 | return r; |
56 | } |
57 | |
58 | if( __atomic_compare_exchange_n( pw, &r, r + 1, true, __ATOMIC_RELAXED0, __ATOMIC_RELAXED0 ) ) |
59 | { |
60 | return r; |
61 | } |
62 | } |
63 | } |
64 | |
65 | inline boost::uint_least32_t atomic_load( boost::uint_least32_t const * pw ) |
66 | { |
67 | return __atomic_load_n( pw, __ATOMIC_ACQUIRE2 ); |
68 | } |
69 | |
70 | class BOOST_SYMBOL_VISIBLE__attribute__((__visibility__("default"))) sp_counted_base |
71 | { |
72 | private: |
73 | |
74 | sp_counted_base( sp_counted_base const & ); |
75 | sp_counted_base & operator= ( sp_counted_base const & ); |
76 | |
77 | boost::uint_least32_t use_count_; // #shared |
78 | boost::uint_least32_t weak_count_; // #weak + (#shared != 0) |
79 | |
80 | public: |
81 | |
82 | sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) |
83 | { |
84 | } |
85 | |
86 | virtual ~sp_counted_base() // nothrow |
87 | { |
88 | } |
89 | |
90 | // dispose() is called when use_count_ drops to zero, to release |
91 | // the resources managed by *this. |
92 | |
93 | virtual void dispose() = 0; // nothrow |
94 | |
95 | // destroy() is called when weak_count_ drops to zero. |
96 | |
97 | virtual void destroy() // nothrow |
98 | { |
99 | delete this; |
100 | } |
101 | |
102 | virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0; |
103 | virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0; |
104 | virtual void * get_untyped_deleter() = 0; |
105 | |
106 | void add_ref_copy() |
107 | { |
108 | atomic_increment( &use_count_ ); |
109 | } |
110 | |
111 | bool add_ref_lock() // true on success |
112 | { |
113 | return atomic_conditional_increment( &use_count_ ) != 0; |
114 | } |
115 | |
116 | void release() // nothrow |
117 | { |
118 | if( atomic_decrement( &use_count_ ) == 1 ) |
119 | { |
120 | dispose(); |
121 | weak_release(); |
122 | } |
123 | } |
124 | |
125 | void weak_add_ref() // nothrow |
126 | { |
127 | atomic_increment( &weak_count_ ); |
128 | } |
129 | |
130 | void weak_release() // nothrow |
131 | { |
132 | if( atomic_decrement( &weak_count_ ) == 1 ) |
133 | { |
134 | destroy(); |
135 | } |
136 | } |
137 | |
138 | long use_count() const // nothrow |
139 | { |
140 | return static_cast<long>( atomic_load( &use_count_ ) ); |
141 | } |
142 | }; |
143 | |
144 | } // namespace detail |
145 | |
146 | } // namespace boost |
147 | |
148 | #endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED |