Bug Summary

File:usr/include/boost/smart_ptr/shared_ptr.hpp
Warning:line 785, column 9
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name subnet.cc -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/home/fedora/workspace/kea-dev/clang-static-analyzer/src/lib/dhcpsrv -fcoverage-compilation-dir=/home/fedora/workspace/kea-dev/clang-static-analyzer/src/lib/dhcpsrv -resource-dir /usr/bin/../lib/clang/19 -D HAVE_CONFIG_H -I . -I ../../.. -I ../../../src/lib -I ../../../src/lib -D DHCP_DATA_DIR="/home/fedora/workspace/kea-dev/clang-static-analyzer/kea-bin/var/lib/kea" -D TOP_BUILDDIR="../../.." -D KEA_LFC_EXECUTABLE="/home/fedora/workspace/kea-dev/clang-static-analyzer/kea-bin/sbin/kea-lfc" -D OS_LINUX -I ../../.. -I ../../.. -D PIC -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14/backward -internal-isystem /usr/bin/../lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wwrite-strings -Wno-sign-compare -Wno-missing-field-initializers -std=c++20 -fdeprecated-macro -ferror-limit 19 -stack-protector 2 -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fcxx-exceptions -fexceptions -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/fedora/workspace/kea-dev/clang-static-analyzer/report/2024-12-20-083036-19082-1 -x c++ subnet.cc

subnet.cc

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
30using namespace isc::asiolink;
31using namespace isc::data;
32using namespace isc::dhcp;
33using namespace isc::util;
34
35using namespace std;
36
37namespace {
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.
43bool
44prefixLessThanFirstAddress(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.
57bool
58comparePoolFirstAddress(const PoolPtr& pool1,
59 const PoolPtr& pool2) {
60 return (pool1->getFirstAddress() < pool2->getFirstAddress());
61}
62
63}
64
65namespace isc {
66namespace dhcp {
67
68Subnet::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
81bool
82Subnet::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
89std::string
90Subnet::toText() const {
91 std::stringstream tmp;
92 tmp << prefix_ << "/" << static_cast<unsigned int>(prefix_len_);
93 return (tmp.str());
94}
95
96uint128_t
97Subnet::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
112uint128_t
113Subnet::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
129uint128_t
130Subnet::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
149uint128_t
150Subnet::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
167uint128_t
168Subnet::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
190uint128_t
191Subnet::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
220std::pair<IOAddress, uint8_t>
221Subnet::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
240void 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
246Subnet4::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
262Subnet4Ptr
263Subnet4::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>
1
Calling 'make_shared<isc::dhcp::Subnet4, const isc::asiolink::IOAddress &, unsigned char &, const isc::util::Triplet<unsigned int> &, const isc::util::Triplet<unsigned int> &, const isc::util::Triplet<unsigned int> &, const unsigned int &>'
7
Returned allocated memory
269 (prefix, length, t1, t2, valid_lifetime, id);
270 subnet->setAllocator(Lease::TYPE_V4,
271 boost::make_shared<IterativeAllocator>
8
Calling 'make_shared<isc::dhcp::IterativeAllocator, isc::dhcp::Lease::Type, boost::shared_ptr<isc::dhcp::Subnet4> &>'
21
Returning; memory was released
272 (Lease::TYPE_V4, subnet));
273 subnet->setAllocationState(Lease::TYPE_V4,
22
Calling 'shared_ptr::operator->'
274 SubnetIterativeAllocationState::create(subnet));
275
276 return (subnet);
277}
278
279ConstSubnet4Ptr
280Subnet4::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
290ConstSubnet4Ptr
291Subnet4::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
318bool
319Subnet4::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
329const 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
347PoolCollection& 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
365AllocatorPtr
366Subnet::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
376void
377Subnet::setAllocator(Lease::Type type, const AllocatorPtr& allocator) {
378 allocators_[type] = allocator;
379}
380
381SubnetAllocationStatePtr
382Subnet::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
392void
393Subnet::setAllocationState(Lease::Type type, const SubnetAllocationStatePtr& allocation_state) {
394 allocation_states_[type] = allocation_state;
395}
396
397const 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
436void
437Subnet::initAllocatorsAfterConfigure() {
438 for (auto const& allocator : allocators_) {
439 allocator.second->initAfterConfigure();
440 }
441}
442
443const 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
471void
472Subnet::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
526void
527Subnet::delPools(Lease::Type type) {
528 getPoolsWritable(type).clear();
529}
530
531bool
532Subnet::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
549bool
550Subnet::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
572bool
573Subnet::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
631Subnet6::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
650Subnet6Ptr
651Subnet6::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
680void 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
688ConstSubnet6Ptr
689Subnet6::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
699ConstSubnet6Ptr
700Subnet6::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
726bool
727Subnet6::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
737data::ElementPtr
738Subnet::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
754void
755Subnet4::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
793data::ElementPtr
794Subnet4::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
817std::pair<IOAddress, uint8_t>
818Subnet4::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
827void
828Subnet6::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
905data::ElementPtr
906Subnet6::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
934std::pair<IOAddress, uint8_t>
935Subnet6::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

/usr/include/boost/smart_ptr/make_shared_object.hpp

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
26namespace boost
27{
28
29namespace detail
30{
31
32template< 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
41template< class T > class sp_ms_deleter
42{
43private:
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
50private:
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
72public:
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
112template< class T, class A > class sp_as_deleter
113{
114private:
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
122private:
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
144public:
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
180template< 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
187template< 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
193template< 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
211template< 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
228template< 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
249template< 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 ) );
2
Calling constructor for 'shared_ptr<isc::dhcp::Subnet4>'
6
Returning from constructor for 'shared_ptr<isc::dhcp::Subnet4>'
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 )... );
9
Calling implicit destructor for 'weak_ptr<isc::dhcp::Subnet>'
10
Calling '~weak_count'
19
Returning from '~weak_count'
20
Returning from destructor for 'weak_ptr<isc::dhcp::Subnet>'
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
266template< 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
310template< 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
327template< 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
346template< class T, class A1 >
347typename 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
367template< class T, class A, class A1 >
368typename 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
388template< class T, class A1, class A2 >
389typename 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
410template< class T, class A, class A1, class A2 >
411typename 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
432template< class T, class A1, class A2, class A3 >
433typename 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
455template< class T, class A, class A1, class A2, class A3 >
456typename 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
478template< class T, class A1, class A2, class A3, class A4 >
479typename 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
502template< class T, class A, class A1, class A2, class A3, class A4 >
503typename 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
526template< class T, class A1, class A2, class A3, class A4, class A5 >
527typename 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
551template< class T, class A, class A1, class A2, class A3, class A4, class A5 >
552typename 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
576template< class T, class A1, class A2, class A3, class A4, class A5, class A6 >
577typename 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
602template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6 >
603typename 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
628template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 >
629typename 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
655template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7 >
656typename 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
682template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 >
683typename 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
710template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 >
711typename 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
738template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 >
739typename 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
767template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 >
768typename 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

/usr/include/boost/smart_ptr/shared_ptr.hpp

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
52namespace boost
53{
54
55template<class T> class shared_ptr;
56template<class T> class weak_ptr;
57template<class T> class enable_shared_from_this;
58class enable_shared_from_raw;
59
60namespace movelib
61{
62
63 template< class T, class D > class unique_ptr;
64
65} // namespace movelib
66
67namespace detail
68{
69
70// sp_element, element_type
71
72template< class T > struct sp_element
73{
74 typedef T type;
75};
76
77#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
78
79template< 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
86template< 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
97template< class T > struct sp_dereference
98{
99 typedef T & type;
100};
101
102template<> struct sp_dereference< void >
103{
104 typedef void type;
105};
106
107#if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
108
109template<> struct sp_dereference< void const >
110{
111 typedef void type;
112};
113
114template<> struct sp_dereference< void volatile >
115{
116 typedef void type;
117};
118
119template<> 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
128template< 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
135template< 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
146template< class T > struct sp_member_access
147{
148 typedef T * type;
149};
150
151#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
152
153template< 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
160template< 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
171template< class T > struct sp_array_access
172{
173 typedef void type;
174};
175
176#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
177
178template< 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
185template< 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
196template< class T > struct sp_extent
197{
198 enum _vt { value = 0 };
199};
200
201#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
202
203template< 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
212template< 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
220template< 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
226struct sp_any_pointer
227{
228 template<class T> sp_any_pointer( T* ) {}
229};
230
231inline void sp_enable_shared_from_this( sp_any_pointer, sp_any_pointer, sp_any_pointer )
232{
233}
234
235#else // _MANAGED
236
237inline 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
247template< class T, class R > struct sp_enable_if_auto_ptr
248{
249};
250
251template< 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
260template< 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
278template< 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
286template< 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
292template< 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
302template< 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
309template< 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
314template< 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
321struct 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
336template<class T> class shared_ptr
337{
338private:
339
340 // Borland 5.5.1 specific workaround
341 typedef shared_ptr<T> this_type;
342
343public:
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 ) )
3
Calling constructor for 'shared_count'
5
Returning from constructor for 'shared_count'
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__))
;
23
'?' condition is true
785 return px;
24
Use of memory after it is freed
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
875private:
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
888template<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
893template<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
902template<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
911template<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
916template<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
921template<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
926template<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
933template<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
938template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b) BOOST_SP_NOEXCEPTnoexcept
939{
940 a.swap(b);
941}
942
943template<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
953template<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
963template<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
973template<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
985template<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
995template<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
1005template<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
1015template<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
1029template<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
1040template<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
1053using std::basic_ostream;
1054template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p)
1055# else
1056template<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
1071namespace detail
1072{
1073
1074template<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
1079template<class D, class T> D * basic_get_local_deleter( D *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPTnoexcept;
1080template<class D, class T> D const * basic_get_local_deleter( D const *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPTnoexcept;
1081
1082class esft2_deleter_wrapper
1083{
1084private:
1085
1086 shared_ptr<void const volatile> deleter_;
1087
1088public:
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
1113template<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
1137template<class T> inline bool atomic_is_lock_free( shared_ptr<T> const * /*p*/ ) BOOST_SP_NOEXCEPTnoexcept
1138{
1139 return false;
1140}
1141
1142template<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
1148template<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
1153template<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
1159template<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
1164template<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
1175template<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
1180template<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
1205template<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
1214template< class T > struct hash;
1215
1216template< 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
1227namespace std
1228{
1229
1230template<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
1244namespace boost
1245{
1246
1247namespace detail
1248{
1249
1250template<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
1255template<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
1264template<class T> shared_ptr( weak_ptr<T> ) -> shared_ptr<T>;
1265template<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

/usr/include/boost/smart_ptr/detail/shared_count.hpp

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
49namespace boost
50{
51
52namespace movelib
53{
54
55template< class T, class D > class unique_ptr;
56
57} // namespace movelib
58
59namespace detail
60{
61
62#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
63
64int const shared_count_id = 0x2C35F101;
65int const weak_count_id = 0x298C38A4;
66
67#endif
68
69struct sp_nothrow_tag {};
70
71template< class D > struct sp_inplace_tag
72{
73};
74
75template< class T > class sp_reference_wrapper
76{
77public:
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
88private:
89
90 T * t_;
91};
92
93template< class D > struct sp_convert_reference
94{
95 typedef D type;
96};
97
98template< class D > struct sp_convert_reference< D& >
99{
100 typedef sp_reference_wrapper< D > type;
101};
102
103template<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
111class weak_count;
112
113class shared_count
114{
115private:
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
125public:
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 );
4
Memory is allocated
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
533class weak_count
534{
535private:
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
545public:
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_
10.1
Field 'pi_' is not equal to null
10.1
Field 'pi_' is not equal to null
10.1
Field 'pi_' is not equal to null
10.1
Field 'pi_' is not equal to null
10.1
Field 'pi_' is not equal to null
10.1
Field 'pi_' is not equal to null
!= 0) pi_->weak_release();
11
Taking true branch
12
Calling 'sp_counted_base::weak_release'
18
Returning; memory was released
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
663inline 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
674inline 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
685inline bool shared_count::operator==( weak_count const & r ) const BOOST_SP_NOEXCEPTnoexcept
686{
687 return pi_ == r.pi_;
688}
689
690inline 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

/usr/include/boost/smart_ptr/weak_ptr.hpp

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
23namespace boost
24{
25
26template<class T> class weak_ptr
27{
28private:
29
30 // Borland 5.5.1 specific workarounds
31 typedef weak_ptr<T> this_type;
32
33public:
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
262private:
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
274template<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
279template<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
286template<class T> weak_ptr( shared_ptr<T> ) -> weak_ptr<T>;
287
288#endif
289
290// hash_value
291
292template< 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
301namespace std
302{
303
304#if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
305
306template<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
316template<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

/usr/include/boost/smart_ptr/detail/sp_counted_base_gcc_atomic.hpp

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>
23BOOST_PRAGMA_MESSAGE("Using __atomic sp_counted_base")message("Using __atomic sp_counted_base")
24
25#endif
26
27namespace boost
28{
29
30namespace detail
31{
32
33inline void atomic_increment( boost::uint_least32_t * pw )
34{
35 __atomic_fetch_add( pw, 1, __ATOMIC_RELAXED0 );
36}
37
38inline boost::uint_least32_t atomic_decrement( boost::uint_least32_t * pw )
39{
40 return __atomic_fetch_sub( pw, 1, __ATOMIC_ACQ_REL4 );
41}
42
43inline 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
65inline boost::uint_least32_t atomic_load( boost::uint_least32_t const * pw )
66{
67 return __atomic_load_n( pw, __ATOMIC_ACQUIRE2 );
68}
69
70class BOOST_SYMBOL_VISIBLE__attribute__((__visibility__("default"))) sp_counted_base
71{
72private:
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
80public:
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;
16
Memory is released
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 )
13
Assuming the condition is true
14
Taking true branch
133 {
134 destroy();
15
Calling 'sp_counted_base::destroy'
17
Returning; memory was released
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