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("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("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("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("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("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("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("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("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("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("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("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("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("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("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("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("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("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("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("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("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("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("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("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 ("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 ("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 ("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 ("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 ("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 ("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 ("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 ("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 ("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 ("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 ("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 ("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 ("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 ("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 ("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 ("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 ("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 ("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("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("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("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("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("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("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 != 0 ) | |||
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_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 |