Bug Summary

File:usr/include/boost/smart_ptr/shared_ptr.hpp
Warning:line 787, 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 -fcoverage-compilation-dir=/home/fedora/workspace/kea-dev/clang-static-analyzer/src/lib/dhcpsrv -resource-dir /usr/lib64/clang/16 -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" -I /usr/include/mysql -I /usr/include/mysql/mysql -D _GNU_SOURCE -I /usr/include/libxml2 -I /usr/include -I /usr/include/pgsql/server -D OS_LINUX -I ../../.. -I ../../.. -D PIC -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13/backward -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../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 -fdebug-compilation-dir=/home/fedora/workspace/kea-dev/clang-static-analyzer/src/lib/dhcpsrv -ferror-limit 19 -stack-protector 2 -fgnuc-version=4.2.1 -fno-implicit-modules -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-05-17-164749-18469-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
279Subnet4Ptr
280Subnet4::getNextSubnet(const Subnet4Ptr& 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
290Subnet4Ptr
291Subnet4::getNextSubnet(const Subnet4Ptr& 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 Subnet4Ptr 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
688Subnet6Ptr
689Subnet6::getNextSubnet(const Subnet6Ptr& 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
699Subnet6Ptr
700Subnet6::getNextSubnet(const Subnet6Ptr& 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 Subnet6Ptr 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/config.hpp>
15#include <boost/move/core.hpp>
16#include <boost/move/utility_core.hpp>
17#include <boost/smart_ptr/shared_ptr.hpp>
18#include <boost/smart_ptr/detail/sp_forward.hpp>
19#include <boost/smart_ptr/detail/sp_noexcept.hpp>
20#include <boost/type_traits/type_with_alignment.hpp>
21#include <boost/type_traits/alignment_of.hpp>
22#include <cstddef>
23#include <new>
24
25namespace boost
26{
27
28namespace detail
29{
30
31template< std::size_t N, std::size_t A > struct sp_aligned_storage
32{
33 union type
34 {
35 char data_[ N ];
36 typename boost::type_with_alignment< A >::type align_;
37 };
38};
39
40template< class T > class sp_ms_deleter
41{
42private:
43
44 typedef typename sp_aligned_storage< sizeof( T ), ::boost::alignment_of< T >::value >::type storage_type;
45
46 bool initialized_;
47 storage_type storage_;
48
49private:
50
51 void destroy() BOOST_SP_NOEXCEPTnoexcept
52 {
53 if( initialized_ )
54 {
55#if defined( __GNUC__4 )
56
57 // fixes incorrect aliasing warning
58 T * p = reinterpret_cast< T* >( storage_.data_ );
59 p->~T();
60
61#else
62
63 reinterpret_cast< T* >( storage_.data_ )->~T();
64
65#endif
66
67 initialized_ = false;
68 }
69 }
70
71public:
72
73 sp_ms_deleter() BOOST_SP_NOEXCEPTnoexcept : initialized_( false )
74 {
75 }
76
77 template<class A> explicit sp_ms_deleter( A const & ) BOOST_SP_NOEXCEPTnoexcept : initialized_( false )
78 {
79 }
80
81 // optimization: do not copy storage_
82 sp_ms_deleter( sp_ms_deleter const & ) BOOST_SP_NOEXCEPTnoexcept : initialized_( false )
83 {
84 }
85
86 ~sp_ms_deleter() BOOST_SP_NOEXCEPTnoexcept
87 {
88 destroy();
89 }
90
91 void operator()( T * ) BOOST_SP_NOEXCEPTnoexcept
92 {
93 destroy();
94 }
95
96 static void operator_fn( T* ) BOOST_SP_NOEXCEPTnoexcept // operator() can't be static
97 {
98 }
99
100 void * address() BOOST_SP_NOEXCEPTnoexcept
101 {
102 return storage_.data_;
103 }
104
105 void set_initialized() BOOST_SP_NOEXCEPTnoexcept
106 {
107 initialized_ = true;
108 }
109};
110
111template< class T, class A > class sp_as_deleter
112{
113private:
114
115 typedef typename sp_aligned_storage< sizeof( T ), ::boost::alignment_of< T >::value >::type storage_type;
116
117 storage_type storage_;
118 A a_;
119 bool initialized_;
120
121private:
122
123 void destroy() BOOST_SP_NOEXCEPTnoexcept
124 {
125 if( initialized_ )
126 {
127 T * p = reinterpret_cast< T* >( storage_.data_ );
128
129#if !defined( BOOST_NO_CXX11_ALLOCATOR )
130
131 std::allocator_traits<A>::destroy( a_, p );
132
133#else
134
135 p->~T();
136
137#endif
138
139 initialized_ = false;
140 }
141 }
142
143public:
144
145 sp_as_deleter( A const & a ) BOOST_SP_NOEXCEPTnoexcept : a_( a ), initialized_( false )
146 {
147 }
148
149 // optimization: do not copy storage_
150 sp_as_deleter( sp_as_deleter const & r ) BOOST_SP_NOEXCEPTnoexcept : a_( r.a_), initialized_( false )
151 {
152 }
153
154 ~sp_as_deleter() BOOST_SP_NOEXCEPTnoexcept
155 {
156 destroy();
157 }
158
159 void operator()( T * ) BOOST_SP_NOEXCEPTnoexcept
160 {
161 destroy();
162 }
163
164 static void operator_fn( T* ) BOOST_SP_NOEXCEPTnoexcept // operator() can't be static
165 {
166 }
167
168 void * address() BOOST_SP_NOEXCEPTnoexcept
169 {
170 return storage_.data_;
171 }
172
173 void set_initialized() BOOST_SP_NOEXCEPTnoexcept
174 {
175 initialized_ = true;
176 }
177};
178
179template< class T > struct sp_if_not_array
180{
181 typedef boost::shared_ptr< T > type;
182};
183
184#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
185
186template< class T > struct sp_if_not_array< T[] >
187{
188};
189
190#if !defined( BOOST_BORLANDC ) || !BOOST_WORKAROUND( BOOST_BORLANDC, < 0x600 )((1 + 0 == 0) && (BOOST_BORLANDC != 0) && (1 %
(( (BOOST_BORLANDC < 0x600) ) + 1)))
191
192template< class T, std::size_t N > struct sp_if_not_array< T[N] >
193{
194};
195
196#endif
197
198#endif
199
200} // namespace detail
201
202#if !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
203# define BOOST_SP_MSD( T ) boost::detail::sp_inplace_tag< boost::detail::sp_ms_deleter< T > >()
204#else
205# define BOOST_SP_MSD( T ) boost::detail::sp_ms_deleter< T >()
206#endif
207
208// _noinit versions
209
210template< class T > typename boost::detail::sp_if_not_array< T >::type make_shared_noinit()
211{
212 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
213
214 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
215
216 void * pv = pd->address();
217
218 ::new( pv ) T;
219 pd->set_initialized();
220
221 T * pt2 = static_cast< T* >( pv );
222
223 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
224 return boost::shared_ptr< T >( pt, pt2 );
225}
226
227template< class T, class A > typename boost::detail::sp_if_not_array< T >::type allocate_shared_noinit( A const & a )
228{
229 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
230
231 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
232
233 void * pv = pd->address();
234
235 ::new( pv ) T;
236 pd->set_initialized();
237
238 T * pt2 = static_cast< T* >( pv );
239
240 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
241 return boost::shared_ptr< T >( pt, pt2 );
242}
243
244#if !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
245
246// Variadic templates, rvalue reference
247
248template< class T, class... Args > typename boost::detail::sp_if_not_array< T >::type make_shared( Args && ... args )
249{
250 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>'
251
252 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
253
254 void * pv = pd->address();
255
256 ::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>'
257 pd->set_initialized();
258
259 T * pt2 = static_cast< T* >( pv );
260
261 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
262 return boost::shared_ptr< T >( pt, pt2 );
263}
264
265template< class T, class A, class... Args > typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, Args && ... args )
266{
267#if !defined( BOOST_NO_CXX11_ALLOCATOR )
268
269 typedef typename std::allocator_traits<A>::template rebind_alloc<T> A2;
270 A2 a2( a );
271
272 typedef boost::detail::sp_as_deleter< T, A2 > D;
273
274 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_inplace_tag<D>(), a2 );
275
276#else
277
278 typedef boost::detail::sp_ms_deleter< T > D;
279
280 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_inplace_tag<D>(), a );
281
282#endif
283
284 D * pd = static_cast< D* >( pt._internal_get_untyped_deleter() );
285 void * pv = pd->address();
286
287#if !defined( BOOST_NO_CXX11_ALLOCATOR )
288
289 std::allocator_traits<A2>::construct( a2, static_cast< T* >( pv ), boost::detail::sp_forward<Args>( args )... );
290
291#else
292
293 ::new( pv ) T( boost::detail::sp_forward<Args>( args )... );
294
295#endif
296
297 pd->set_initialized();
298
299 T * pt2 = static_cast< T* >( pv );
300
301 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
302 return boost::shared_ptr< T >( pt, pt2 );
303}
304
305#else // !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
306
307// Common zero-argument versions
308
309template< class T > typename boost::detail::sp_if_not_array< T >::type make_shared()
310{
311 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
312
313 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
314
315 void * pv = pd->address();
316
317 ::new( pv ) T();
318 pd->set_initialized();
319
320 T * pt2 = static_cast< T* >( pv );
321
322 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
323 return boost::shared_ptr< T >( pt, pt2 );
324}
325
326template< class T, class A > typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a )
327{
328 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
329
330 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
331
332 void * pv = pd->address();
333
334 ::new( pv ) T();
335 pd->set_initialized();
336
337 T * pt2 = static_cast< T* >( pv );
338
339 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
340 return boost::shared_ptr< T >( pt, pt2 );
341}
342
343// C++03 version
344
345template< class T, class A1 >
346typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1)A1 && a1 )
347{
348 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
349
350 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
351
352 void * pv = pd->address();
353
354 ::new( pv ) T(
355 boost::forward<A1>( a1 )
356 );
357
358 pd->set_initialized();
359
360 T * pt2 = static_cast< T* >( pv );
361
362 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
363 return boost::shared_ptr< T >( pt, pt2 );
364}
365
366template< class T, class A, class A1 >
367typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1)A1 && a1 )
368{
369 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
370
371 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
372
373 void * pv = pd->address();
374
375 ::new( pv ) T(
376 boost::forward<A1>( a1 )
377 );
378
379 pd->set_initialized();
380
381 T * pt2 = static_cast< T* >( pv );
382
383 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
384 return boost::shared_ptr< T >( pt, pt2 );
385}
386
387template< class T, class A1, class A2 >
388typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2 )
389{
390 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
391
392 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
393
394 void * pv = pd->address();
395
396 ::new( pv ) T(
397 boost::forward<A1>( a1 ),
398 boost::forward<A2>( a2 )
399 );
400
401 pd->set_initialized();
402
403 T * pt2 = static_cast< T* >( pv );
404
405 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
406 return boost::shared_ptr< T >( pt, pt2 );
407}
408
409template< class T, class A, class A1, class A2 >
410typename 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 )
411{
412 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
413
414 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
415
416 void * pv = pd->address();
417
418 ::new( pv ) T(
419 boost::forward<A1>( a1 ),
420 boost::forward<A2>( a2 )
421 );
422
423 pd->set_initialized();
424
425 T * pt2 = static_cast< T* >( pv );
426
427 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
428 return boost::shared_ptr< T >( pt, pt2 );
429}
430
431template< class T, class A1, class A2, class A3 >
432typename 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 )
433{
434 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
435
436 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
437
438 void * pv = pd->address();
439
440 ::new( pv ) T(
441 boost::forward<A1>( a1 ),
442 boost::forward<A2>( a2 ),
443 boost::forward<A3>( a3 )
444 );
445
446 pd->set_initialized();
447
448 T * pt2 = static_cast< T* >( pv );
449
450 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
451 return boost::shared_ptr< T >( pt, pt2 );
452}
453
454template< class T, class A, class A1, class A2, class A3 >
455typename 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 )
456{
457 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
458
459 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
460
461 void * pv = pd->address();
462
463 ::new( pv ) T(
464 boost::forward<A1>( a1 ),
465 boost::forward<A2>( a2 ),
466 boost::forward<A3>( a3 )
467 );
468
469 pd->set_initialized();
470
471 T * pt2 = static_cast< T* >( pv );
472
473 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
474 return boost::shared_ptr< T >( pt, pt2 );
475}
476
477template< class T, class A1, class A2, class A3, class A4 >
478typename 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 )
479{
480 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
481
482 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
483
484 void * pv = pd->address();
485
486 ::new( pv ) T(
487 boost::forward<A1>( a1 ),
488 boost::forward<A2>( a2 ),
489 boost::forward<A3>( a3 ),
490 boost::forward<A4>( a4 )
491 );
492
493 pd->set_initialized();
494
495 T * pt2 = static_cast< T* >( pv );
496
497 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
498 return boost::shared_ptr< T >( pt, pt2 );
499}
500
501template< class T, class A, class A1, class A2, class A3, class A4 >
502typename 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 )
503{
504 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
505
506 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
507
508 void * pv = pd->address();
509
510 ::new( pv ) T(
511 boost::forward<A1>( a1 ),
512 boost::forward<A2>( a2 ),
513 boost::forward<A3>( a3 ),
514 boost::forward<A4>( a4 )
515 );
516
517 pd->set_initialized();
518
519 T * pt2 = static_cast< T* >( pv );
520
521 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
522 return boost::shared_ptr< T >( pt, pt2 );
523}
524
525template< class T, class A1, class A2, class A3, class A4, class A5 >
526typename 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 )
527{
528 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
529
530 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
531
532 void * pv = pd->address();
533
534 ::new( pv ) T(
535 boost::forward<A1>( a1 ),
536 boost::forward<A2>( a2 ),
537 boost::forward<A3>( a3 ),
538 boost::forward<A4>( a4 ),
539 boost::forward<A5>( a5 )
540 );
541
542 pd->set_initialized();
543
544 T * pt2 = static_cast< T* >( pv );
545
546 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
547 return boost::shared_ptr< T >( pt, pt2 );
548}
549
550template< class T, class A, class A1, class A2, class A3, class A4, class A5 >
551typename 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 )
552{
553 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
554
555 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
556
557 void * pv = pd->address();
558
559 ::new( pv ) T(
560 boost::forward<A1>( a1 ),
561 boost::forward<A2>( a2 ),
562 boost::forward<A3>( a3 ),
563 boost::forward<A4>( a4 ),
564 boost::forward<A5>( a5 )
565 );
566
567 pd->set_initialized();
568
569 T * pt2 = static_cast< T* >( pv );
570
571 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
572 return boost::shared_ptr< T >( pt, pt2 );
573}
574
575template< class T, class A1, class A2, class A3, class A4, class A5, class A6 >
576typename 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 )
577{
578 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
579
580 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
581
582 void * pv = pd->address();
583
584 ::new( pv ) T(
585 boost::forward<A1>( a1 ),
586 boost::forward<A2>( a2 ),
587 boost::forward<A3>( a3 ),
588 boost::forward<A4>( a4 ),
589 boost::forward<A5>( a5 ),
590 boost::forward<A6>( a6 )
591 );
592
593 pd->set_initialized();
594
595 T * pt2 = static_cast< T* >( pv );
596
597 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
598 return boost::shared_ptr< T >( pt, pt2 );
599}
600
601template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6 >
602typename 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 )
603{
604 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
605
606 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
607
608 void * pv = pd->address();
609
610 ::new( pv ) T(
611 boost::forward<A1>( a1 ),
612 boost::forward<A2>( a2 ),
613 boost::forward<A3>( a3 ),
614 boost::forward<A4>( a4 ),
615 boost::forward<A5>( a5 ),
616 boost::forward<A6>( a6 )
617 );
618
619 pd->set_initialized();
620
621 T * pt2 = static_cast< T* >( pv );
622
623 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
624 return boost::shared_ptr< T >( pt, pt2 );
625}
626
627template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 >
628typename 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 )
629{
630 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
631
632 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
633
634 void * pv = pd->address();
635
636 ::new( pv ) T(
637 boost::forward<A1>( a1 ),
638 boost::forward<A2>( a2 ),
639 boost::forward<A3>( a3 ),
640 boost::forward<A4>( a4 ),
641 boost::forward<A5>( a5 ),
642 boost::forward<A6>( a6 ),
643 boost::forward<A7>( a7 )
644 );
645
646 pd->set_initialized();
647
648 T * pt2 = static_cast< T* >( pv );
649
650 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
651 return boost::shared_ptr< T >( pt, pt2 );
652}
653
654template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7 >
655typename 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 )
656{
657 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
658
659 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
660
661 void * pv = pd->address();
662
663 ::new( pv ) T(
664 boost::forward<A1>( a1 ),
665 boost::forward<A2>( a2 ),
666 boost::forward<A3>( a3 ),
667 boost::forward<A4>( a4 ),
668 boost::forward<A5>( a5 ),
669 boost::forward<A6>( a6 ),
670 boost::forward<A7>( a7 )
671 );
672
673 pd->set_initialized();
674
675 T * pt2 = static_cast< T* >( pv );
676
677 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
678 return boost::shared_ptr< T >( pt, pt2 );
679}
680
681template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 >
682typename 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 )
683{
684 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
685
686 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
687
688 void * pv = pd->address();
689
690 ::new( pv ) T(
691 boost::forward<A1>( a1 ),
692 boost::forward<A2>( a2 ),
693 boost::forward<A3>( a3 ),
694 boost::forward<A4>( a4 ),
695 boost::forward<A5>( a5 ),
696 boost::forward<A6>( a6 ),
697 boost::forward<A7>( a7 ),
698 boost::forward<A8>( a8 )
699 );
700
701 pd->set_initialized();
702
703 T * pt2 = static_cast< T* >( pv );
704
705 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
706 return boost::shared_ptr< T >( pt, pt2 );
707}
708
709template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 >
710typename 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 )
711{
712 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
713
714 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
715
716 void * pv = pd->address();
717
718 ::new( pv ) T(
719 boost::forward<A1>( a1 ),
720 boost::forward<A2>( a2 ),
721 boost::forward<A3>( a3 ),
722 boost::forward<A4>( a4 ),
723 boost::forward<A5>( a5 ),
724 boost::forward<A6>( a6 ),
725 boost::forward<A7>( a7 ),
726 boost::forward<A8>( a8 )
727 );
728
729 pd->set_initialized();
730
731 T * pt2 = static_cast< T* >( pv );
732
733 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
734 return boost::shared_ptr< T >( pt, pt2 );
735}
736
737template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 >
738typename 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 )
739{
740 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
741
742 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
743
744 void * pv = pd->address();
745
746 ::new( pv ) T(
747 boost::forward<A1>( a1 ),
748 boost::forward<A2>( a2 ),
749 boost::forward<A3>( a3 ),
750 boost::forward<A4>( a4 ),
751 boost::forward<A5>( a5 ),
752 boost::forward<A6>( a6 ),
753 boost::forward<A7>( a7 ),
754 boost::forward<A8>( a8 ),
755 boost::forward<A9>( a9 )
756 );
757
758 pd->set_initialized();
759
760 T * pt2 = static_cast< T* >( pv );
761
762 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
763 return boost::shared_ptr< T >( pt, pt2 );
764}
765
766template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 >
767typename 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 )
768{
769 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
770
771 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
772
773 void * pv = pd->address();
774
775 ::new( pv ) T(
776 boost::forward<A1>( a1 ),
777 boost::forward<A2>( a2 ),
778 boost::forward<A3>( a3 ),
779 boost::forward<A4>( a4 ),
780 boost::forward<A5>( a5 ),
781 boost::forward<A6>( a6 ),
782 boost::forward<A7>( a7 ),
783 boost::forward<A8>( a8 ),
784 boost::forward<A9>( a9 )
785 );
786
787 pd->set_initialized();
788
789 T * pt2 = static_cast< T* >( pv );
790
791 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
792 return boost::shared_ptr< T >( pt, pt2 );
793}
794
795#endif // !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
796
797#undef BOOST_SP_MSD
798
799} // namespace boost
800
801#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/shared_count.hpp>
18#include <boost/smart_ptr/detail/sp_convertible.hpp>
19#include <boost/smart_ptr/detail/sp_nullptr_t.hpp>
20#include <boost/smart_ptr/detail/sp_disable_deprecated.hpp>
21#include <boost/smart_ptr/detail/sp_noexcept.hpp>
22#include <boost/checked_delete.hpp>
23#include <boost/throw_exception.hpp>
24#include <boost/assert.hpp>
25#include <boost/config.hpp>
26#include <boost/config/workaround.hpp>
27
28#if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
29#include <boost/smart_ptr/detail/spinlock_pool.hpp>
30#endif
31
32#include <algorithm> // for std::swap
33#include <functional> // for std::less
34#include <typeinfo> // for std::bad_cast
35#include <cstddef> // for std::size_t
36#include <memory> // for std::auto_ptr
37
38#if !defined(BOOST_NO_IOSTREAM)
39#if !defined(BOOST_NO_IOSFWD)
40#include <iosfwd> // for std::basic_ostream
41#else
42#include <ostream>
43#endif
44#endif
45
46#if defined( BOOST_SP_DISABLE_DEPRECATED )
47#pragma GCC diagnostic push
48#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
49#endif
50
51namespace boost
52{
53
54template<class T> class shared_ptr;
55template<class T> class weak_ptr;
56template<class T> class enable_shared_from_this;
57class enable_shared_from_raw;
58
59namespace movelib
60{
61
62 template< class T, class D > class unique_ptr;
63
64} // namespace movelib
65
66namespace detail
67{
68
69// sp_element, element_type
70
71template< class T > struct sp_element
72{
73 typedef T type;
74};
75
76#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
77
78template< class T > struct sp_element< T[] >
79{
80 typedef T type;
81};
82
83#if !defined( BOOST_BORLANDC ) || !BOOST_WORKAROUND( BOOST_BORLANDC, < 0x600 )((1 + 0 == 0) && (BOOST_BORLANDC != 0) && (1 %
(( (BOOST_BORLANDC < 0x600) ) + 1)))
84
85template< class T, std::size_t N > struct sp_element< T[N] >
86{
87 typedef T type;
88};
89
90#endif
91
92#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
93
94// sp_dereference, return type of operator*
95
96template< class T > struct sp_dereference
97{
98 typedef T & type;
99};
100
101template<> struct sp_dereference< void >
102{
103 typedef void type;
104};
105
106#if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
107
108template<> struct sp_dereference< void const >
109{
110 typedef void type;
111};
112
113template<> struct sp_dereference< void volatile >
114{
115 typedef void type;
116};
117
118template<> struct sp_dereference< void const volatile >
119{
120 typedef void type;
121};
122
123#endif // !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
124
125#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
126
127template< class T > struct sp_dereference< T[] >
128{
129 typedef void type;
130};
131
132#if !defined( BOOST_BORLANDC ) || !BOOST_WORKAROUND( BOOST_BORLANDC, < 0x600 )((1 + 0 == 0) && (BOOST_BORLANDC != 0) && (1 %
(( (BOOST_BORLANDC < 0x600) ) + 1)))
133
134template< class T, std::size_t N > struct sp_dereference< T[N] >
135{
136 typedef void type;
137};
138
139#endif
140
141#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
142
143// sp_member_access, return type of operator->
144
145template< class T > struct sp_member_access
146{
147 typedef T * type;
148};
149
150#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
151
152template< class T > struct sp_member_access< T[] >
153{
154 typedef void type;
155};
156
157#if !defined( BOOST_BORLANDC ) || !BOOST_WORKAROUND( BOOST_BORLANDC, < 0x600 )((1 + 0 == 0) && (BOOST_BORLANDC != 0) && (1 %
(( (BOOST_BORLANDC < 0x600) ) + 1)))
158
159template< class T, std::size_t N > struct sp_member_access< T[N] >
160{
161 typedef void type;
162};
163
164#endif
165
166#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
167
168// sp_array_access, return type of operator[]
169
170template< class T > struct sp_array_access
171{
172 typedef void type;
173};
174
175#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
176
177template< class T > struct sp_array_access< T[] >
178{
179 typedef T & type;
180};
181
182#if !defined( BOOST_BORLANDC ) || !BOOST_WORKAROUND( BOOST_BORLANDC, < 0x600 )((1 + 0 == 0) && (BOOST_BORLANDC != 0) && (1 %
(( (BOOST_BORLANDC < 0x600) ) + 1)))
183
184template< class T, std::size_t N > struct sp_array_access< T[N] >
185{
186 typedef T & type;
187};
188
189#endif
190
191#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
192
193// sp_extent, for operator[] index check
194
195template< class T > struct sp_extent
196{
197 enum _vt { value = 0 };
198};
199
200#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
201
202template< class T, std::size_t N > struct sp_extent< T[N] >
203{
204 enum _vt { value = N };
205};
206
207#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
208
209// enable_shared_from_this support
210
211template< 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 )
212{
213 if( pe != 0 )
214 {
215 pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );
216 }
217}
218
219template< 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 );
220
221#ifdef _MANAGED
222
223// Avoid C4793, ... causes native code generation
224
225struct sp_any_pointer
226{
227 template<class T> sp_any_pointer( T* ) {}
228};
229
230inline void sp_enable_shared_from_this( sp_any_pointer, sp_any_pointer, sp_any_pointer )
231{
232}
233
234#else // _MANAGED
235
236inline void sp_enable_shared_from_this( ... )
237{
238}
239
240#endif // _MANAGED
241
242#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR )
243
244// rvalue auto_ptr support based on a technique by Dave Abrahams
245
246template< class T, class R > struct sp_enable_if_auto_ptr
247{
248};
249
250template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R >
251{
252 typedef R type;
253};
254
255#endif
256
257// sp_assert_convertible
258
259template< class Y, class T > inline void sp_assert_convertible() BOOST_SP_NOEXCEPTnoexcept
260{
261#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
262
263 // static_assert( sp_convertible< Y, T >::value );
264 typedef char tmp[ sp_convertible< Y, T >::value? 1: -1 ];
265 (void)sizeof( tmp );
266
267#else
268
269 T* p = static_cast< Y* >( 0 );
270 (void)p;
271
272#endif
273}
274
275// pointer constructor helper
276
277template< class T, class Y > inline void sp_pointer_construct( boost::shared_ptr< T > * ppx, Y * p, boost::detail::shared_count & pn )
278{
279 boost::detail::shared_count( p ).swap( pn );
280 boost::detail::sp_enable_shared_from_this( ppx, p, p );
281}
282
283#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
284
285template< class T, class Y > inline void sp_pointer_construct( boost::shared_ptr< T[] > * /*ppx*/, Y * p, boost::detail::shared_count & pn )
286{
287 sp_assert_convertible< Y[], T[] >();
288 boost::detail::shared_count( p, boost::checked_array_deleter< T >() ).swap( pn );
289}
290
291template< 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 )
292{
293 sp_assert_convertible< Y[N], T[N] >();
294 boost::detail::shared_count( p, boost::checked_array_deleter< T >() ).swap( pn );
295}
296
297#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
298
299// deleter constructor helper
300
301template< class T, class Y > inline void sp_deleter_construct( boost::shared_ptr< T > * ppx, Y * p )
302{
303 boost::detail::sp_enable_shared_from_this( ppx, p, p );
304}
305
306#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
307
308template< class T, class Y > inline void sp_deleter_construct( boost::shared_ptr< T[] > * /*ppx*/, Y * /*p*/ )
309{
310 sp_assert_convertible< Y[], T[] >();
311}
312
313template< class T, std::size_t N, class Y > inline void sp_deleter_construct( boost::shared_ptr< T[N] > * /*ppx*/, Y * /*p*/ )
314{
315 sp_assert_convertible< Y[N], T[N] >();
316}
317
318#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
319
320struct sp_internal_constructor_tag
321{
322};
323
324} // namespace detail
325
326
327//
328// shared_ptr
329//
330// An enhanced relative of scoped_ptr with reference counted copy semantics.
331// The object pointed to is deleted when the last shared_ptr pointing to it
332// is destroyed or reset.
333//
334
335template<class T> class shared_ptr
336{
337private:
338
339 // Borland 5.5.1 specific workaround
340 typedef shared_ptr<T> this_type;
341
342public:
343
344 typedef typename boost::detail::sp_element< T >::type element_type;
345
346 BOOST_CONSTEXPRconstexpr shared_ptr() BOOST_SP_NOEXCEPTnoexcept : px( 0 ), pn()
347 {
348 }
349
350#if !defined( BOOST_NO_CXX11_NULLPTR )
351
352 BOOST_CONSTEXPRconstexpr shared_ptr( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPTnoexcept : px( 0 ), pn()
353 {
354 }
355
356#endif
357
358 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_ )
359 {
360 }
361
362#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
363
364 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_ ) )
365 {
366 }
367
368#endif
369
370 template<class Y>
371 explicit shared_ptr( Y * p ): px( p ), pn() // Y must be complete
372 {
373 boost::detail::sp_pointer_construct( this, p, pn );
374 }
375
376 //
377 // Requirements: D's copy/move constructors must not throw
378 //
379 // shared_ptr will release p by calling d(p)
380 //
381
382#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
383
384 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'
385 {
386 boost::detail::sp_deleter_construct( this, p );
387 }
388
389#else
390
391 template<class Y, class D> shared_ptr( Y * p, D d ): px( p ), pn( p, d )
392 {
393 boost::detail::sp_deleter_construct( this, p );
394 }
395
396#endif
397
398#if !defined( BOOST_NO_CXX11_NULLPTR )
399
400#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
401
402 template<class D> shared_ptr( boost::detail::sp_nullptr_t p, D d ): px( p ), pn( p, static_cast< D&& >( d ) )
403 {
404 }
405
406#else
407
408 template<class D> shared_ptr( boost::detail::sp_nullptr_t p, D d ): px( p ), pn( p, d )
409 {
410 }
411
412#endif
413
414#endif
415
416 // As above, but with allocator. A's copy constructor shall not throw.
417
418#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
419
420 template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, static_cast< D&& >( d ), a )
421 {
422 boost::detail::sp_deleter_construct( this, p );
423 }
424
425#else
426
427 template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a )
428 {
429 boost::detail::sp_deleter_construct( this, p );
430 }
431
432#endif
433
434#if !defined( BOOST_NO_CXX11_NULLPTR )
435
436#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
437
438 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 )
439 {
440 }
441
442#else
443
444 template<class D, class A> shared_ptr( boost::detail::sp_nullptr_t p, D d, A a ): px( p ), pn( p, d, a )
445 {
446 }
447
448#endif
449
450#endif
451
452// generated copy constructor, destructor are fine...
453
454#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
455
456// ... except in C++0x, move disables the implicit copy
457
458 shared_ptr( shared_ptr const & r ) BOOST_SP_NOEXCEPTnoexcept : px( r.px ), pn( r.pn )
459 {
460 }
461
462#endif
463
464 template<class Y>
465 explicit shared_ptr( weak_ptr<Y> const & r ): pn( r.pn ) // may throw
466 {
467 boost::detail::sp_assert_convertible< Y, T >();
468
469 // it is now safe to copy r.px, as pn(r.pn) did not throw
470 px = r.px;
471 }
472
473 template<class Y>
474 shared_ptr( weak_ptr<Y> const & r, boost::detail::sp_nothrow_tag )
475 BOOST_SP_NOEXCEPTnoexcept : px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() )
476 {
477 if( !pn.empty() )
478 {
479 px = r.px;
480 }
481 }
482
483 template<class Y>
484#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
485
486 shared_ptr( shared_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
487
488#else
489
490 shared_ptr( shared_ptr<Y> const & r )
491
492#endif
493 BOOST_SP_NOEXCEPTnoexcept : px( r.px ), pn( r.pn )
494 {
495 boost::detail::sp_assert_convertible< Y, T >();
496 }
497
498 // aliasing
499 template< class Y >
500 shared_ptr( shared_ptr<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPTnoexcept : px( p ), pn( r.pn )
501 {
502 }
503
504#ifndef BOOST_NO_AUTO_PTR
505
506 template<class Y>
507 explicit shared_ptr( std::auto_ptr<Y> & r ): px(r.get()), pn()
508 {
509 boost::detail::sp_assert_convertible< Y, T >();
510
511 Y * tmp = r.get();
512 pn = boost::detail::shared_count( r );
513
514 boost::detail::sp_deleter_construct( this, tmp );
515 }
516
517#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
518
519 template<class Y>
520 shared_ptr( std::auto_ptr<Y> && r ): px(r.get()), pn()
521 {
522 boost::detail::sp_assert_convertible< Y, T >();
523
524 Y * tmp = r.get();
525 pn = boost::detail::shared_count( r );
526
527 boost::detail::sp_deleter_construct( this, tmp );
528 }
529
530#elif !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
531
532 template<class Ap>
533 explicit shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr<Ap, int>::type = 0 ): px( r.get() ), pn()
534 {
535 typedef typename Ap::element_type Y;
536
537 boost::detail::sp_assert_convertible< Y, T >();
538
539 Y * tmp = r.get();
540 pn = boost::detail::shared_count( r );
541
542 boost::detail::sp_deleter_construct( this, tmp );
543 }
544
545#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
546
547#endif // BOOST_NO_AUTO_PTR
548
549#if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
550
551 template< class Y, class D >
552 shared_ptr( std::unique_ptr< Y, D > && r ): px( r.get() ), pn()
553 {
554 boost::detail::sp_assert_convertible< Y, T >();
555
556 typename std::unique_ptr< Y, D >::pointer tmp = r.get();
557
558 if( tmp != 0 )
559 {
560 pn = boost::detail::shared_count( r );
561 boost::detail::sp_deleter_construct( this, tmp );
562 }
563 }
564
565#endif
566
567 template< class Y, class D >
568 shared_ptr( boost::movelib::unique_ptr< Y, D > r ): px( r.get() ), pn()
569 {
570 boost::detail::sp_assert_convertible< Y, T >();
571
572 typename boost::movelib::unique_ptr< Y, D >::pointer tmp = r.get();
573
574 if( tmp != 0 )
575 {
576 pn = boost::detail::shared_count( r );
577 boost::detail::sp_deleter_construct( this, tmp );
578 }
579 }
580
581 // assignment
582
583 shared_ptr & operator=( shared_ptr const & r ) BOOST_SP_NOEXCEPTnoexcept
584 {
585 this_type(r).swap(*this);
586 return *this;
587 }
588
589#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1400)
590
591 template<class Y>
592 shared_ptr & operator=(shared_ptr<Y> const & r) BOOST_SP_NOEXCEPTnoexcept
593 {
594 this_type(r).swap(*this);
595 return *this;
596 }
597
598#endif
599
600#ifndef BOOST_NO_AUTO_PTR
601
602 template<class Y>
603 shared_ptr & operator=( std::auto_ptr<Y> & r )
604 {
605 this_type( r ).swap( *this );
606 return *this;
607 }
608
609#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
610
611 template<class Y>
612 shared_ptr & operator=( std::auto_ptr<Y> && r )
613 {
614 this_type( static_cast< std::auto_ptr<Y> && >( r ) ).swap( *this );
615 return *this;
616 }
617
618#elif !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
619
620 template<class Ap>
621 typename boost::detail::sp_enable_if_auto_ptr< Ap, shared_ptr & >::type operator=( Ap r )
622 {
623 this_type( r ).swap( *this );
624 return *this;
625 }
626
627#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
628
629#endif // BOOST_NO_AUTO_PTR
630
631#if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
632
633 template<class Y, class D>
634 shared_ptr & operator=( std::unique_ptr<Y, D> && r )
635 {
636 this_type( static_cast< std::unique_ptr<Y, D> && >( r ) ).swap(*this);
637 return *this;
638 }
639
640#endif
641
642 template<class Y, class D>
643 shared_ptr & operator=( boost::movelib::unique_ptr<Y, D> r )
644 {
645 // this_type( static_cast< unique_ptr<Y, D> && >( r ) ).swap( *this );
646
647 boost::detail::sp_assert_convertible< Y, T >();
648
649 typename boost::movelib::unique_ptr< Y, D >::pointer p = r.get();
650
651 shared_ptr tmp;
652
653 if( p != 0 )
654 {
655 tmp.px = p;
656 tmp.pn = boost::detail::shared_count( r );
657
658 boost::detail::sp_deleter_construct( &tmp, p );
659 }
660
661 tmp.swap( *this );
662
663 return *this;
664 }
665
666// Move support
667
668#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
669
670 shared_ptr( shared_ptr && r ) BOOST_SP_NOEXCEPTnoexcept : px( r.px ), pn()
671 {
672 pn.swap( r.pn );
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()
687 {
688 boost::detail::sp_assert_convertible< Y, T >();
689
690 pn.swap( r.pn );
691 r.px = 0;
692 }
693
694 shared_ptr & operator=( shared_ptr && r ) BOOST_SP_NOEXCEPTnoexcept
695 {
696 this_type( static_cast< shared_ptr && >( r ) ).swap( *this );
697 return *this;
698 }
699
700 template<class Y>
701 shared_ptr & operator=( shared_ptr<Y> && r ) BOOST_SP_NOEXCEPTnoexcept
702 {
703 this_type( static_cast< shared_ptr<Y> && >( r ) ).swap( *this );
704 return *this;
705 }
706
707 // aliasing move
708 template<class Y>
709 shared_ptr( shared_ptr<Y> && r, element_type * p ) BOOST_SP_NOEXCEPTnoexcept : px( p ), pn()
710 {
711 pn.swap( r.pn );
712 r.px = 0;
713 }
714
715#endif
716
717#if !defined( BOOST_NO_CXX11_NULLPTR )
718
719 shared_ptr & operator=( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPTnoexcept
720 {
721 this_type().swap(*this);
722 return *this;
723 }
724
725#endif
726
727 void reset() BOOST_SP_NOEXCEPTnoexcept
728 {
729 this_type().swap(*this);
730 }
731
732 template<class Y> void reset( Y * p ) // Y must be complete
733 {
734 BOOST_ASSERT( p == 0 || p != px )(static_cast <bool> (p == 0 || p != px) ? void (0) : __assert_fail
("p == 0 || p != px", "/usr/include/boost/smart_ptr/shared_ptr.hpp"
, 734, __extension__ __PRETTY_FUNCTION__))
; // catch self-reset errors
735 this_type( p ).swap( *this );
736 }
737
738#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
739
740 template<class Y, class D> void reset( Y * p, D d )
741 {
742 this_type( p, static_cast< D&& >( d ) ).swap( *this );
743 }
744
745 template<class Y, class D, class A> void reset( Y * p, D d, A a )
746 {
747 this_type( p, static_cast< D&& >( d ), a ).swap( *this );
748 }
749
750#else
751
752 template<class Y, class D> void reset( Y * p, D d )
753 {
754 this_type( p, d ).swap( *this );
755 }
756
757 template<class Y, class D, class A> void reset( Y * p, D d, A a )
758 {
759 this_type( p, d, a ).swap( *this );
760 }
761
762#endif
763
764 template<class Y> void reset( shared_ptr<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPTnoexcept
765 {
766 this_type( r, p ).swap( *this );
767 }
768
769#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
770
771 template<class Y> void reset( shared_ptr<Y> && r, element_type * p ) BOOST_SP_NOEXCEPTnoexcept
772 {
773 this_type( static_cast< shared_ptr<Y> && >( r ), p ).swap( *this );
774 }
775
776#endif
777
778 typename boost::detail::sp_dereference< T >::type operator* () const BOOST_SP_NOEXCEPT_WITH_ASSERTnoexcept
779 {
780 BOOST_ASSERT( px != 0 )(static_cast <bool> (px != 0) ? void (0) : __assert_fail
("px != 0", "/usr/include/boost/smart_ptr/shared_ptr.hpp", 780
, __extension__ __PRETTY_FUNCTION__))
;
781 return *px;
782 }
783
784 typename boost::detail::sp_member_access< T >::type operator-> () const BOOST_SP_NOEXCEPT_WITH_ASSERTnoexcept
785 {
786 BOOST_ASSERT( px != 0 )(static_cast <bool> (px != 0) ? void (0) : __assert_fail
("px != 0", "/usr/include/boost/smart_ptr/shared_ptr.hpp", 786
, __extension__ __PRETTY_FUNCTION__))
;
23
'?' condition is true
787 return px;
24
Use of memory after it is freed
788 }
789
790 typename boost::detail::sp_array_access< T >::type operator[] ( std::ptrdiff_t i ) const BOOST_SP_NOEXCEPT_WITH_ASSERTnoexcept
791 {
792 BOOST_ASSERT( px != 0 )(static_cast <bool> (px != 0) ? void (0) : __assert_fail
("px != 0", "/usr/include/boost/smart_ptr/shared_ptr.hpp", 792
, __extension__ __PRETTY_FUNCTION__))
;
793 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 )"
, "/usr/include/boost/smart_ptr/shared_ptr.hpp", 793, __extension__
__PRETTY_FUNCTION__))
;
794
795 return static_cast< typename boost::detail::sp_array_access< T >::type >( px[ i ] );
796 }
797
798 element_type * get() const BOOST_SP_NOEXCEPTnoexcept
799 {
800 return px;
801 }
802
803// implicit conversion to "bool"
804#include <boost/smart_ptr/detail/operator_bool.hpp>
805
806 bool unique() const BOOST_SP_NOEXCEPTnoexcept
807 {
808 return pn.unique();
809 }
810
811 long use_count() const BOOST_SP_NOEXCEPTnoexcept
812 {
813 return pn.use_count();
814 }
815
816 void swap( shared_ptr & other ) BOOST_SP_NOEXCEPTnoexcept
817 {
818 std::swap(px, other.px);
819 pn.swap(other.pn);
820 }
821
822 template<class Y> bool owner_before( shared_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPTnoexcept
823 {
824 return pn < rhs.pn;
825 }
826
827 template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPTnoexcept
828 {
829 return pn < rhs.pn;
830 }
831
832 template<class Y> bool owner_equals( shared_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPTnoexcept
833 {
834 return pn == rhs.pn;
835 }
836
837 template<class Y> bool owner_equals( weak_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPTnoexcept
838 {
839 return pn == rhs.pn;
840 }
841
842 std::size_t owner_hash_value() const BOOST_SP_NOEXCEPTnoexcept
843 {
844 return pn.hash_value();
845 }
846
847 void * _internal_get_deleter( boost::detail::sp_typeinfo_ const & ti ) const BOOST_SP_NOEXCEPTnoexcept
848 {
849 return pn.get_deleter( ti );
850 }
851
852 void * _internal_get_local_deleter( boost::detail::sp_typeinfo_ const & ti ) const BOOST_SP_NOEXCEPTnoexcept
853 {
854 return pn.get_local_deleter( ti );
855 }
856
857 void * _internal_get_untyped_deleter() const BOOST_SP_NOEXCEPTnoexcept
858 {
859 return pn.get_untyped_deleter();
860 }
861
862 bool _internal_equiv( shared_ptr const & r ) const BOOST_SP_NOEXCEPTnoexcept
863 {
864 return px == r.px && pn == r.pn;
865 }
866
867 boost::detail::shared_count _internal_count() const BOOST_SP_NOEXCEPTnoexcept
868 {
869 return pn;
870 }
871
872// Tasteless as this may seem, making all members public allows member templates
873// to work in the absence of member template friends. (Matthew Langston)
874
875#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
876
877private:
878
879 template<class Y> friend class shared_ptr;
880 template<class Y> friend class weak_ptr;
881
882
883#endif
884
885 element_type * px; // contained pointer
886 boost::detail::shared_count pn; // reference counter
887
888}; // shared_ptr
889
890template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_SP_NOEXCEPTnoexcept
891{
892 return a.get() == b.get();
893}
894
895template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_SP_NOEXCEPTnoexcept
896{
897 return a.get() != b.get();
898}
899
900#if __GNUC__4 == 2 && __GNUC_MINOR__2 <= 96
901
902// Resolve the ambiguity between our op!= and the one in rel_ops
903
904template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b) BOOST_SP_NOEXCEPTnoexcept
905{
906 return a.get() != b.get();
907}
908
909#endif
910
911#if !defined( BOOST_NO_CXX11_NULLPTR )
912
913template<class T> inline bool operator==( shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPTnoexcept
914{
915 return p.get() == 0;
916}
917
918template<class T> inline bool operator==( boost::detail::sp_nullptr_t, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPTnoexcept
919{
920 return p.get() == 0;
921}
922
923template<class T> inline bool operator!=( shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPTnoexcept
924{
925 return p.get() != 0;
926}
927
928template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPTnoexcept
929{
930 return p.get() != 0;
931}
932
933#endif
934
935template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_SP_NOEXCEPTnoexcept
936{
937 return a.owner_before( b );
938}
939
940template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b) BOOST_SP_NOEXCEPTnoexcept
941{
942 a.swap(b);
943}
944
945template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> const & r ) BOOST_SP_NOEXCEPTnoexcept
946{
947 (void) static_cast< T* >( static_cast< U* >( 0 ) );
948
949 typedef typename shared_ptr<T>::element_type E;
950
951 E * p = static_cast< E* >( r.get() );
952 return shared_ptr<T>( r, p );
953}
954
955template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> const & r ) BOOST_SP_NOEXCEPTnoexcept
956{
957 (void) const_cast< T* >( static_cast< U* >( 0 ) );
958
959 typedef typename shared_ptr<T>::element_type E;
960
961 E * p = const_cast< E* >( r.get() );
962 return shared_ptr<T>( r, p );
963}
964
965template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> const & r ) BOOST_SP_NOEXCEPTnoexcept
966{
967 (void) dynamic_cast< T* >( static_cast< U* >( 0 ) );
968
969 typedef typename shared_ptr<T>::element_type E;
970
971 E * p = dynamic_cast< E* >( r.get() );
972 return p? shared_ptr<T>( r, p ): shared_ptr<T>();
973}
974
975template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U> const & r ) BOOST_SP_NOEXCEPTnoexcept
976{
977 (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
978
979 typedef typename shared_ptr<T>::element_type E;
980
981 E * p = reinterpret_cast< E* >( r.get() );
982 return shared_ptr<T>( r, p );
983}
984
985#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
986
987template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> && r ) BOOST_SP_NOEXCEPTnoexcept
988{
989 (void) static_cast< T* >( static_cast< U* >( 0 ) );
990
991 typedef typename shared_ptr<T>::element_type E;
992
993 E * p = static_cast< E* >( r.get() );
994 return shared_ptr<T>( std::move(r), p );
995}
996
997template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> && r ) BOOST_SP_NOEXCEPTnoexcept
998{
999 (void) const_cast< T* >( static_cast< U* >( 0 ) );
1000
1001 typedef typename shared_ptr<T>::element_type E;
1002
1003 E * p = const_cast< E* >( r.get() );
1004 return shared_ptr<T>( std::move(r), p );
1005}
1006
1007template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> && r ) BOOST_SP_NOEXCEPTnoexcept
1008{
1009 (void) dynamic_cast< T* >( static_cast< U* >( 0 ) );
1010
1011 typedef typename shared_ptr<T>::element_type E;
1012
1013 E * p = dynamic_cast< E* >( r.get() );
1014 return p? shared_ptr<T>( std::move(r), p ): shared_ptr<T>();
1015}
1016
1017template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U> && r ) BOOST_SP_NOEXCEPTnoexcept
1018{
1019 (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
1020
1021 typedef typename shared_ptr<T>::element_type E;
1022
1023 E * p = reinterpret_cast< E* >( r.get() );
1024 return shared_ptr<T>( std::move(r), p );
1025}
1026
1027#endif // !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
1028
1029// get_pointer() enables boost::mem_fn to recognize shared_ptr
1030
1031template<class T> inline typename shared_ptr<T>::element_type * get_pointer(shared_ptr<T> const & p) BOOST_SP_NOEXCEPTnoexcept
1032{
1033 return p.get();
1034}
1035
1036// operator<<
1037
1038#if !defined(BOOST_NO_IOSTREAM)
1039
1040#if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__4) && (__GNUC__4 < 3) )
1041
1042template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p)
1043{
1044 os << p.get();
1045 return os;
1046}
1047
1048#else
1049
1050// in STLport's no-iostreams mode no iostream symbols can be used
1051#ifndef _STLP_NO_IOSTREAMS
1052
1053# 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)))
1054// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
1055using std::basic_ostream;
1056template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p)
1057# else
1058template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p)
1059# endif
1060{
1061 os << p.get();
1062 return os;
1063}
1064
1065#endif // _STLP_NO_IOSTREAMS
1066
1067#endif // __GNUC__ < 3
1068
1069#endif // !defined(BOOST_NO_IOSTREAM)
1070
1071// get_deleter
1072
1073namespace detail
1074{
1075
1076template<class D, class T> D * basic_get_deleter( shared_ptr<T> const & p ) BOOST_SP_NOEXCEPTnoexcept
1077{
1078 return static_cast<D *>( p._internal_get_deleter(BOOST_SP_TYPEID_(D)typeid(D)) );
1079}
1080
1081template<class D, class T> D * basic_get_local_deleter( D *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPTnoexcept;
1082template<class D, class T> D const * basic_get_local_deleter( D const *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPTnoexcept;
1083
1084class esft2_deleter_wrapper
1085{
1086private:
1087
1088 shared_ptr<void const volatile> deleter_;
1089
1090public:
1091
1092 esft2_deleter_wrapper() BOOST_SP_NOEXCEPTnoexcept
1093 {
1094 }
1095
1096 template< class T > void set_deleter( shared_ptr<T> const & deleter ) BOOST_SP_NOEXCEPTnoexcept
1097 {
1098 deleter_ = deleter;
1099 }
1100
1101 template<typename D> D* get_deleter() const BOOST_SP_NOEXCEPTnoexcept
1102 {
1103 return boost::detail::basic_get_deleter<D>( deleter_ );
1104 }
1105
1106 template< class T> void operator()( T* ) BOOST_SP_NOEXCEPT_WITH_ASSERTnoexcept
1107 {
1108 BOOST_ASSERT( deleter_.use_count() <= 1 )(static_cast <bool> (deleter_.use_count() <= 1) ? void
(0) : __assert_fail ("deleter_.use_count() <= 1", "/usr/include/boost/smart_ptr/shared_ptr.hpp"
, 1108, __extension__ __PRETTY_FUNCTION__))
;
1109 deleter_.reset();
1110 }
1111};
1112
1113} // namespace detail
1114
1115template<class D, class T> D * get_deleter( shared_ptr<T> const & p ) BOOST_SP_NOEXCEPTnoexcept
1116{
1117 D * d = boost::detail::basic_get_deleter<D>( p );
1118
1119 if( d == 0 )
1120 {
1121 d = boost::detail::basic_get_local_deleter( d, p );
1122 }
1123
1124 if( d == 0 )
1125 {
1126 boost::detail::esft2_deleter_wrapper *del_wrapper = boost::detail::basic_get_deleter<boost::detail::esft2_deleter_wrapper>(p);
1127// The following get_deleter method call is fully qualified because
1128// older versions of gcc (2.95, 3.2.3) fail to compile it when written del_wrapper->get_deleter<D>()
1129 if(del_wrapper) d = del_wrapper->::boost::detail::esft2_deleter_wrapper::get_deleter<D>();
1130 }
1131
1132 return d;
1133}
1134
1135// atomic access
1136
1137#if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
1138
1139template<class T> inline bool atomic_is_lock_free( shared_ptr<T> const * /*p*/ ) BOOST_SP_NOEXCEPTnoexcept
1140{
1141 return false;
1142}
1143
1144template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p ) BOOST_SP_NOEXCEPTnoexcept
1145{
1146 boost::detail::spinlock_pool<2>::scoped_lock lock( p );
1147 return *p;
1148}
1149
1150template<class T, class M> inline shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, /*memory_order mo*/ M ) BOOST_SP_NOEXCEPTnoexcept
1151{
1152 return atomic_load( p );
1153}
1154
1155template<class T> void atomic_store( shared_ptr<T> * p, shared_ptr<T> r ) BOOST_SP_NOEXCEPTnoexcept
1156{
1157 boost::detail::spinlock_pool<2>::scoped_lock lock( p );
1158 p->swap( r );
1159}
1160
1161template<class T, class M> inline void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, /*memory_order mo*/ M ) BOOST_SP_NOEXCEPTnoexcept
1162{
1163 atomic_store( p, r ); // std::move( r )
1164}
1165
1166template<class T> shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r ) BOOST_SP_NOEXCEPTnoexcept
1167{
1168 boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
1169
1170 sp.lock();
1171 p->swap( r );
1172 sp.unlock();
1173
1174 return r; // return std::move( r )
1175}
1176
1177template<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
1178{
1179 return atomic_exchange( p, r ); // std::move( r )
1180}
1181
1182template<class T> bool atomic_compare_exchange( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w ) BOOST_SP_NOEXCEPTnoexcept
1183{
1184 boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
1185
1186 sp.lock();
1187
1188 if( p->_internal_equiv( *v ) )
1189 {
1190 p->swap( w );
1191
1192 sp.unlock();
1193
1194 return true;
1195 }
1196 else
1197 {
1198 shared_ptr<T> tmp( *p );
1199
1200 sp.unlock();
1201
1202 tmp.swap( *v );
1203 return false;
1204 }
1205}
1206
1207template<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
1208{
1209 return atomic_compare_exchange( p, v, w ); // std::move( w )
1210}
1211
1212#endif // !defined(BOOST_SP_NO_ATOMIC_ACCESS)
1213
1214// hash_value
1215
1216template< class T > struct hash;
1217
1218template< class T > std::size_t hash_value( boost::shared_ptr<T> const & p ) BOOST_SP_NOEXCEPTnoexcept
1219{
1220 return boost::hash< typename boost::shared_ptr<T>::element_type* >()( p.get() );
1221}
1222
1223} // namespace boost
1224
1225// std::hash
1226
1227#if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
1228
1229namespace std
1230{
1231
1232template<class T> struct hash< ::boost::shared_ptr<T> >
1233{
1234 std::size_t operator()( ::boost::shared_ptr<T> const & p ) const BOOST_SP_NOEXCEPTnoexcept
1235 {
1236 return std::hash< typename ::boost::shared_ptr<T>::element_type* >()( p.get() );
1237 }
1238};
1239
1240} // namespace std
1241
1242#endif // #if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
1243
1244#include <boost/smart_ptr/detail/local_sp_deleter.hpp>
1245
1246namespace boost
1247{
1248
1249namespace detail
1250{
1251
1252template<class D, class T> D * basic_get_local_deleter( D *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPTnoexcept
1253{
1254 return static_cast<D *>( p._internal_get_local_deleter( BOOST_SP_TYPEID_(local_sp_deleter<D>)typeid(local_sp_deleter<D>) ) );
1255}
1256
1257template<class D, class T> D const * basic_get_local_deleter( D const *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPTnoexcept
1258{
1259 return static_cast<D *>( p._internal_get_local_deleter( BOOST_SP_TYPEID_(local_sp_deleter<D>)typeid(local_sp_deleter<D>) ) );
1260}
1261
1262} // namespace detail
1263
1264#if defined(__cpp_deduction_guides201703L)
1265
1266template<class T> shared_ptr( weak_ptr<T> ) -> shared_ptr<T>;
1267template<class T, class D> shared_ptr( std::unique_ptr<T, D> ) -> shared_ptr<T>;
1268
1269#endif
1270
1271} // namespace boost
1272
1273#if defined( BOOST_SP_DISABLE_DEPRECATED )
1274#pragma GCC diagnostic pop
1275#endif
1276
1277#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/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/shared_count.hpp>
17#include <boost/smart_ptr/shared_ptr.hpp>
18#include <boost/smart_ptr/detail/sp_noexcept.hpp>
19#include <memory>
20#include <cstddef>
21
22namespace boost
23{
24
25template<class T> class weak_ptr
26{
27private:
28
29 // Borland 5.5.1 specific workarounds
30 typedef weak_ptr<T> this_type;
31
32public:
33
34 typedef typename boost::detail::sp_element< T >::type element_type;
35
36 BOOST_CONSTEXPRconstexpr weak_ptr() BOOST_SP_NOEXCEPTnoexcept : px(0), pn()
37 {
38 }
39
40// generated copy constructor, assignment, destructor are fine...
41
42#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
43
44// ... except in C++0x, move disables the implicit copy
45
46 weak_ptr( weak_ptr const & r ) BOOST_SP_NOEXCEPTnoexcept : px( r.px ), pn( r.pn )
47 {
48 }
49
50 weak_ptr & operator=( weak_ptr const & r ) BOOST_SP_NOEXCEPTnoexcept
51 {
52 px = r.px;
53 pn = r.pn;
54 return *this;
55 }
56
57#endif
58
59//
60// The "obvious" converting constructor implementation:
61//
62// template<class Y>
63// weak_ptr(weak_ptr<Y> const & r): px(r.px), pn(r.pn)
64// {
65// }
66//
67// has a serious problem.
68//
69// r.px may already have been invalidated. The px(r.px)
70// conversion may require access to *r.px (virtual inheritance).
71//
72// It is not possible to avoid spurious access violations since
73// in multithreaded programs r.px may be invalidated at any point.
74//
75
76 template<class Y>
77#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
78
79 weak_ptr( weak_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
80
81#else
82
83 weak_ptr( weak_ptr<Y> const & r )
84
85#endif
86 BOOST_SP_NOEXCEPTnoexcept : px(r.lock().get()), pn(r.pn)
87 {
88 boost::detail::sp_assert_convertible< Y, T >();
89 }
90
91#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
92
93 template<class Y>
94#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
95
96 weak_ptr( weak_ptr<Y> && r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
97
98#else
99
100 weak_ptr( weak_ptr<Y> && r )
101
102#endif
103 BOOST_SP_NOEXCEPTnoexcept : px( r.lock().get() ), pn( static_cast< boost::detail::weak_count && >( r.pn ) )
104 {
105 boost::detail::sp_assert_convertible< Y, T >();
106 r.px = 0;
107 }
108
109 // for better efficiency in the T == Y case
110 weak_ptr( weak_ptr && r )
111 BOOST_SP_NOEXCEPTnoexcept : px( r.px ), pn( static_cast< boost::detail::weak_count && >( r.pn ) )
112 {
113 r.px = 0;
114 }
115
116 // for better efficiency in the T == Y case
117 weak_ptr & operator=( weak_ptr && r ) BOOST_SP_NOEXCEPTnoexcept
118 {
119 this_type( static_cast< weak_ptr && >( r ) ).swap( *this );
120 return *this;
121 }
122
123
124#endif
125
126 template<class Y>
127#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
128
129 weak_ptr( shared_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
130
131#else
132
133 weak_ptr( shared_ptr<Y> const & r )
134
135#endif
136 BOOST_SP_NOEXCEPTnoexcept : px( r.px ), pn( r.pn )
137 {
138 boost::detail::sp_assert_convertible< Y, T >();
139 }
140
141 // aliasing
142 template<class Y> weak_ptr(shared_ptr<Y> const & r, element_type * p) BOOST_SP_NOEXCEPTnoexcept: px( p ), pn( r.pn )
143 {
144 }
145
146 template<class Y> weak_ptr(weak_ptr<Y> const & r, element_type * p) BOOST_SP_NOEXCEPTnoexcept: px( p ), pn( r.pn )
147 {
148 }
149
150#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
151
152 template<class Y> weak_ptr(weak_ptr<Y> && r, element_type * p) BOOST_SP_NOEXCEPTnoexcept: px( p ), pn( std::move( r.pn ) )
153 {
154 }
155
156#endif
157
158#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300)
159
160 template<class Y>
161 weak_ptr & operator=( weak_ptr<Y> const & r ) BOOST_SP_NOEXCEPTnoexcept
162 {
163 boost::detail::sp_assert_convertible< Y, T >();
164
165 px = r.lock().get();
166 pn = r.pn;
167
168 return *this;
169 }
170
171#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
172
173 template<class Y>
174 weak_ptr & operator=( weak_ptr<Y> && r ) BOOST_SP_NOEXCEPTnoexcept
175 {
176 this_type( static_cast< weak_ptr<Y> && >( r ) ).swap( *this );
177 return *this;
178 }
179
180#endif
181
182 template<class Y>
183 weak_ptr & operator=( shared_ptr<Y> const & r ) BOOST_SP_NOEXCEPTnoexcept
184 {
185 boost::detail::sp_assert_convertible< Y, T >();
186
187 px = r.px;
188 pn = r.pn;
189
190 return *this;
191 }
192
193#endif
194
195 shared_ptr<T> lock() const BOOST_SP_NOEXCEPTnoexcept
196 {
197 return shared_ptr<T>( *this, boost::detail::sp_nothrow_tag() );
198 }
199
200 long use_count() const BOOST_SP_NOEXCEPTnoexcept
201 {
202 return pn.use_count();
203 }
204
205 bool expired() const BOOST_SP_NOEXCEPTnoexcept
206 {
207 return pn.use_count() == 0;
208 }
209
210 bool _empty() const BOOST_SP_NOEXCEPTnoexcept // extension, not in std::weak_ptr
211 {
212 return pn.empty();
213 }
214
215 bool empty() const BOOST_SP_NOEXCEPTnoexcept // extension, not in std::weak_ptr
216 {
217 return pn.empty();
218 }
219
220 void reset() BOOST_SP_NOEXCEPTnoexcept
221 {
222 this_type().swap(*this);
223 }
224
225 void swap(this_type & other) BOOST_SP_NOEXCEPTnoexcept
226 {
227 std::swap(px, other.px);
228 pn.swap(other.pn);
229 }
230
231 template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPTnoexcept
232 {
233 return pn < rhs.pn;
234 }
235
236 template<class Y> bool owner_before( shared_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPTnoexcept
237 {
238 return pn < rhs.pn;
239 }
240
241 template<class Y> bool owner_equals( weak_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPTnoexcept
242 {
243 return pn == rhs.pn;
244 }
245
246 template<class Y> bool owner_equals( shared_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPTnoexcept
247 {
248 return pn == rhs.pn;
249 }
250
251 std::size_t owner_hash_value() const BOOST_SP_NOEXCEPTnoexcept
252 {
253 return pn.hash_value();
254 }
255
256// Tasteless as this may seem, making all members public allows member templates
257// to work in the absence of member template friends. (Matthew Langston)
258
259#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
260
261private:
262
263 template<class Y> friend class weak_ptr;
264 template<class Y> friend class shared_ptr;
265
266#endif
267
268 element_type * px; // contained pointer
269 boost::detail::weak_count pn; // reference counter
270
271}; // weak_ptr
272
273template<class T, class U> inline bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b) BOOST_SP_NOEXCEPTnoexcept
274{
275 return a.owner_before( b );
276}
277
278template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b) BOOST_SP_NOEXCEPTnoexcept
279{
280 a.swap(b);
281}
282
283#if defined(__cpp_deduction_guides201703L)
284
285template<class T> weak_ptr( shared_ptr<T> ) -> weak_ptr<T>;
286
287#endif
288
289// hash_value
290
291template< class T > std::size_t hash_value( boost::weak_ptr<T> const & p ) BOOST_SP_NOEXCEPTnoexcept
292{
293 return p.owner_hash_value();
294}
295
296} // namespace boost
297
298// std::hash, std::equal_to
299
300namespace std
301{
302
303#if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
304
305template<class T> struct hash< ::boost::weak_ptr<T> >
306{
307 std::size_t operator()( ::boost::weak_ptr<T> const & p ) const BOOST_SP_NOEXCEPTnoexcept
308 {
309 return p.owner_hash_value();
310 }
311};
312
313#endif // #if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
314
315template<class T> struct equal_to< ::boost::weak_ptr<T> >
316{
317 bool operator()( ::boost::weak_ptr<T> const & a, ::boost::weak_ptr<T> const & b ) const BOOST_SP_NOEXCEPTnoexcept
318 {
319 return a.owner_equals( b );
320 }
321};
322
323} // namespace std
324
325#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 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