Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name subnet.cc -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/home/fedora/workspace/kea-dev/clang-static-analyzer/build/meson-private/tmphs1g5w79 -fcoverage-compilation-dir=/home/fedora/workspace/kea-dev/clang-static-analyzer/build/meson-private/tmphs1g5w79 -resource-dir /usr/bin/../lib/clang/20 -I src/lib/dhcpsrv/libkea-dhcpsrv.so.142.0.0.p -I src/lib/dhcpsrv -I ../../../src/lib/dhcpsrv -I . -I ../../.. -I src -I ../../../src -I src/bin -I ../../../src/bin -I src/lib -I ../../../src/lib -I /usr/include -D _GLIBCXX_ASSERTIONS=1 -D _FILE_OFFSET_BITS=64 -D BOOST_ALL_NO_LIB -D DHCP_DATA_DIR="/usr/local/var/lib/kea" -D KEA_LFC_EXECUTABLE="/usr/local/sbin/kea-lfc" -D LEGAL_LOG_DIR="/usr/local/var/log/kea" -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/backward -internal-isystem /usr/bin/../lib/clang/20/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wwrite-strings -Wno-missing-field-initializers -fdeprecated-macro -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcxx-exceptions -fexceptions -fcolor-diagnostics -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/fedora/workspace/kea-dev/clang-static-analyzer/build/meson-logs/scanbuild/2025-10-17-063701-9203-1 -x c++ ../../../src/lib/dhcpsrv/subnet.cc

../../../src/lib/dhcpsrv/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("../../../src/lib/dhcpsrv/subnet.cc"
, 73, oss__.str().c_str()); } while (1)
73 "Invalid id specified for subnet: " << id)do { std::ostringstream oss__; oss__ << "Invalid id specified for subnet: "
<< id; throw BadValue("../../../src/lib/dhcpsrv/subnet.cc"
, 73, oss__.str().c_str()); } while (1)
;
74 }
75 if ((prefix.isV6() && len > 128) || (prefix.isV4() && len > 32)) {
76 isc_throw(BadValue,do { std::ostringstream oss__; oss__ << "Invalid prefix length specified for subnet: "
<< len; throw BadValue("../../../src/lib/dhcpsrv/subnet.cc"
, 77, oss__.str().c_str()); } while (1)
77 "Invalid prefix length specified for subnet: " << len)do { std::ostringstream oss__; oss__ << "Invalid prefix length specified for subnet: "
<< len; throw BadValue("../../../src/lib/dhcpsrv/subnet.cc"
, 77, oss__.str().c_str()); } while (1)
;
78 }
79}
80
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("../../../src/lib/dhcpsrv/subnet.cc"
, 108, oss__.str().c_str()); } while (1)
108 << static_cast<int>(type))do { std::ostringstream oss__; oss__ << "Unsupported pool type: "
<< static_cast<int>(type); throw BadValue("../../../src/lib/dhcpsrv/subnet.cc"
, 108, oss__.str().c_str()); } while (1)
;
109 }
110}
111
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("../../../src/lib/dhcpsrv/subnet.cc"
, 125, oss__.str().c_str()); } while (1)
125 << static_cast<int>(type))do { std::ostringstream oss__; oss__ << "Unsupported pool type: "
<< static_cast<int>(type); throw BadValue("../../../src/lib/dhcpsrv/subnet.cc"
, 125, oss__.str().c_str()); } while (1)
;
126 }
127}
128
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("../../../src/lib/dhcpsrv/subnet.cc"
, 145, oss__.str().c_str()); } while (1)
145 << static_cast<int>(type))do { std::ostringstream oss__; oss__ << "Unsupported pool type: "
<< static_cast<int>(type); throw BadValue("../../../src/lib/dhcpsrv/subnet.cc"
, 145, oss__.str().c_str()); } while (1)
;
146 }
147}
148
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("../../../src/lib/dhcpsrv/subnet.cc"
, 226, oss__.str().c_str()); } while (1)
;
227 }
228
229 try {
230 IOAddress address(prefix.substr(0, pos));
231 int length = boost::lexical_cast<int>(prefix.substr(pos + 1));
232 return (std::make_pair(address, static_cast<int>(length)));
233
234 } catch (...) {
235 isc_throw(BadValue, "unable to parse invalid prefix " << prefix)do { std::ostringstream oss__; oss__ << "unable to parse invalid prefix "
<< prefix; throw BadValue("../../../src/lib/dhcpsrv/subnet.cc"
, 235, oss__.str().c_str()); } while (1)
;
236 }
237}
238
239
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("../../../src/lib/dhcpsrv/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("../../../src/lib/dhcpsrv/subnet.cc", 254, oss__.str
().c_str()); } while (1)
254 << " specified in subnet4")do { std::ostringstream oss__; oss__ << "Non IPv4 prefix "
<< prefix.toText() << " specified in subnet4"; throw
BadValue("../../../src/lib/dhcpsrv/subnet.cc", 254, oss__.str
().c_str()); } while (1)
;
255 }
256 // Timers.
257 setT1(t1);
258 setT2(t2);
259 setValid(valid_lifetime);
260}
261
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>
269 (prefix, length, t1, t2, valid_lifetime, id);
270 subnet->setAllocator(Lease::TYPE_V4,
271 boost::make_shared<IterativeAllocator>
272 (Lease::TYPE_V4, subnet));
273 subnet->setAllocationState(Lease::TYPE_V4,
274 SubnetIterativeAllocationState::create(subnet));
275
276 return (subnet);
277}
278
279ConstSubnet4Ptr
280Subnet4::getNextSubnet(const ConstSubnet4Ptr& first_subnet) const {
281 SharedNetwork4Ptr network;
282 getSharedNetwork(network);
283 if (network) {
284 return (network->getNextSubnet(first_subnet, getID()));
285 }
286
287 return (Subnet4Ptr());
288}
289
290ConstSubnet4Ptr
291Subnet4::getNextSubnet(const ConstSubnet4Ptr& first_subnet,
292 const ClientClasses& client_classes) const {
293 SharedNetwork4Ptr network;
294 getSharedNetwork(network);
295 // We can only get next subnet if shared network has been defined for
296 // the current subnet.
297 if (network) {
298 ConstSubnet4Ptr subnet;
299 do {
300 // Use subnet identifier of this subnet if this is the first
301 // time we're calling getNextSubnet. Otherwise, use the
302 // subnet id of the previously returned subnet.
303 SubnetID subnet_id = subnet ? subnet->getID() : getID();
304 subnet = network->getNextSubnet(first_subnet, subnet_id);
305 // If client classes match the subnet, return it. Otherwise,
306 // try another subnet.
307 if (subnet && subnet->clientSupported(client_classes)) {
308 return (subnet);
309 }
310 } while (subnet);
311 }
312
313 // No subnet found.
314 return (Subnet4Ptr());
315}
316
317
318bool
319Subnet4::clientSupported(const isc::dhcp::ClientClasses& client_classes) const {
320 NetworkPtr network;
321 getSharedNetwork(network);
322 if (network && !network->clientSupported(client_classes)) {
323 return (false);
324 }
325
326 return (Network4::clientSupported(client_classes));
327}
328
329const PoolCollection& Subnet::getPools(Lease::Type type) const {
330 // check if the type is valid (and throw if it isn't)
331 checkType(type);
332
333 switch (type) {
334 case Lease::TYPE_V4:
335 case Lease::TYPE_NA:
336 return (pools_);
337 case Lease::TYPE_TA:
338 return (pools_ta_);
339 case Lease::TYPE_PD:
340 return (pools_pd_);
341 default:
342 isc_throw(BadValue, "Unsupported pool type: "do { std::ostringstream oss__; oss__ << "Unsupported pool type: "
<< static_cast<int>(type); throw BadValue("../../../src/lib/dhcpsrv/subnet.cc"
, 343, oss__.str().c_str()); } while (1)
343 << static_cast<int>(type))do { std::ostringstream oss__; oss__ << "Unsupported pool type: "
<< static_cast<int>(type); throw BadValue("../../../src/lib/dhcpsrv/subnet.cc"
, 343, oss__.str().c_str()); } while (1)
;
344 }
345}
346
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("../../../src/lib/dhcpsrv/subnet.cc"
, 361, oss__.str().c_str()); } while (1)
361 << static_cast<int>(type))do { std::ostringstream oss__; oss__ << "Invalid pool type specified: "
<< static_cast<int>(type); throw BadValue("../../../src/lib/dhcpsrv/subnet.cc"
, 361, oss__.str().c_str()); } while (1)
;
362 }
363}
364
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("../../../src/lib/dhcpsrv/subnet.cc"
, 371, oss__.str().c_str()); } while (1)
371 << Lease::typeToText(type))do { std::ostringstream oss__; oss__ << "no allocator initialized for pool type "
<< Lease::typeToText(type); throw BadValue("../../../src/lib/dhcpsrv/subnet.cc"
, 371, oss__.str().c_str()); } while (1)
;
372 }
373 return (alloc->second);
374}
375
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("../../../src/lib/dhcpsrv/subnet.cc"
, 387, oss__.str().c_str()); } while (1)
387 << Lease::typeToText(type))do { std::ostringstream oss__; oss__ << "no allocation state initialized for pool type "
<< Lease::typeToText(type); throw BadValue("../../../src/lib/dhcpsrv/subnet.cc"
, 387, oss__.str().c_str()); } while (1)
;
388 }
389 return (state->second);
390}
391
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
("../../../src/lib/dhcpsrv/subnet.cc", 489, oss__.str().c_str
()); } while (1)
483 << Lease::typeToText(pool->getType())do { std::ostringstream oss__; oss__ << "a pool of type "
<< Lease::typeToText(pool->getType()) << ", with the following address range: "
<< pool->getFirstAddress() << "-" << pool
->getLastAddress() << " does not match" << " the prefix of a subnet: "
<< prefix_ << "/" << static_cast<int>
(prefix_len_) << " to which it is being added"; throw BadValue
("../../../src/lib/dhcpsrv/subnet.cc", 489, oss__.str().c_str
()); } while (1)
484 << ", with the following address range: "do { std::ostringstream oss__; oss__ << "a pool of type "
<< Lease::typeToText(pool->getType()) << ", with the following address range: "
<< pool->getFirstAddress() << "-" << pool
->getLastAddress() << " does not match" << " the prefix of a subnet: "
<< prefix_ << "/" << static_cast<int>
(prefix_len_) << " to which it is being added"; throw BadValue
("../../../src/lib/dhcpsrv/subnet.cc", 489, oss__.str().c_str
()); } while (1)
485 << pool->getFirstAddress() << "-"do { std::ostringstream oss__; oss__ << "a pool of type "
<< Lease::typeToText(pool->getType()) << ", with the following address range: "
<< pool->getFirstAddress() << "-" << pool
->getLastAddress() << " does not match" << " the prefix of a subnet: "
<< prefix_ << "/" << static_cast<int>
(prefix_len_) << " to which it is being added"; throw BadValue
("../../../src/lib/dhcpsrv/subnet.cc", 489, oss__.str().c_str
()); } while (1)
486 << pool->getLastAddress() << " does not match"do { std::ostringstream oss__; oss__ << "a pool of type "
<< Lease::typeToText(pool->getType()) << ", with the following address range: "
<< pool->getFirstAddress() << "-" << pool
->getLastAddress() << " does not match" << " the prefix of a subnet: "
<< prefix_ << "/" << static_cast<int>
(prefix_len_) << " to which it is being added"; throw BadValue
("../../../src/lib/dhcpsrv/subnet.cc", 489, oss__.str().c_str
()); } while (1)
487 << " the prefix of a subnet: "do { std::ostringstream oss__; oss__ << "a pool of type "
<< Lease::typeToText(pool->getType()) << ", with the following address range: "
<< pool->getFirstAddress() << "-" << pool
->getLastAddress() << " does not match" << " the prefix of a subnet: "
<< prefix_ << "/" << static_cast<int>
(prefix_len_) << " to which it is being added"; throw BadValue
("../../../src/lib/dhcpsrv/subnet.cc", 489, oss__.str().c_str
()); } while (1)
488 << prefix_ << "/" << static_cast<int>(prefix_len_)do { std::ostringstream oss__; oss__ << "a pool of type "
<< Lease::typeToText(pool->getType()) << ", with the following address range: "
<< pool->getFirstAddress() << "-" << pool
->getLastAddress() << " does not match" << " the prefix of a subnet: "
<< prefix_ << "/" << static_cast<int>
(prefix_len_) << " to which it is being added"; throw BadValue
("../../../src/lib/dhcpsrv/subnet.cc", 489, oss__.str().c_str
()); } while (1)
489 << " to which it is being added")do { std::ostringstream oss__; oss__ << "a pool of type "
<< Lease::typeToText(pool->getType()) << ", with the following address range: "
<< pool->getFirstAddress() << "-" << pool
->getLastAddress() << " does not match" << " the prefix of a subnet: "
<< prefix_ << "/" << static_cast<int>
(prefix_len_) << " to which it is being added"; throw BadValue
("../../../src/lib/dhcpsrv/subnet.cc", 489, oss__.str().c_str
()); } while (1)
;
490
491 }
492 }
493
494 bool overlaps = false;
495 if (pool->getType() == Lease::TYPE_V4) {
496 overlaps = poolOverlaps(Lease::TYPE_V4, pool);
497
498 } else {
499 overlaps =
500 poolOverlaps(Lease::TYPE_NA, pool) ||
501 poolOverlaps(Lease::TYPE_PD, pool) ||
502 poolOverlaps(Lease::TYPE_TA, pool);
503 }
504
505 if (overlaps) {
506 isc_throw(BadValue,"a pool of type "do { std::ostringstream oss__; oss__ << "a pool of type "
<< Lease::typeToText(pool->getType()) << ", with the following address range: "
<< pool->getFirstAddress() << "-" << pool
->getLastAddress() << " overlaps with " "an existing pool in the subnet: "
<< prefix_ << "/" << static_cast<int>
(prefix_len_) << " to which it is being added"; throw BadValue
("../../../src/lib/dhcpsrv/subnet.cc", 513, oss__.str().c_str
()); } while (1)
507 << Lease::typeToText(pool->getType())do { std::ostringstream oss__; oss__ << "a pool of type "
<< Lease::typeToText(pool->getType()) << ", with the following address range: "
<< pool->getFirstAddress() << "-" << pool
->getLastAddress() << " overlaps with " "an existing pool in the subnet: "
<< prefix_ << "/" << static_cast<int>
(prefix_len_) << " to which it is being added"; throw BadValue
("../../../src/lib/dhcpsrv/subnet.cc", 513, oss__.str().c_str
()); } while (1)
508 << ", with the following address range: "do { std::ostringstream oss__; oss__ << "a pool of type "
<< Lease::typeToText(pool->getType()) << ", with the following address range: "
<< pool->getFirstAddress() << "-" << pool
->getLastAddress() << " overlaps with " "an existing pool in the subnet: "
<< prefix_ << "/" << static_cast<int>
(prefix_len_) << " to which it is being added"; throw BadValue
("../../../src/lib/dhcpsrv/subnet.cc", 513, oss__.str().c_str
()); } while (1)
509 << pool->getFirstAddress() << "-"do { std::ostringstream oss__; oss__ << "a pool of type "
<< Lease::typeToText(pool->getType()) << ", with the following address range: "
<< pool->getFirstAddress() << "-" << pool
->getLastAddress() << " overlaps with " "an existing pool in the subnet: "
<< prefix_ << "/" << static_cast<int>
(prefix_len_) << " to which it is being added"; throw BadValue
("../../../src/lib/dhcpsrv/subnet.cc", 513, oss__.str().c_str
()); } while (1)
510 << pool->getLastAddress() << " overlaps with "do { std::ostringstream oss__; oss__ << "a pool of type "
<< Lease::typeToText(pool->getType()) << ", with the following address range: "
<< pool->getFirstAddress() << "-" << pool
->getLastAddress() << " overlaps with " "an existing pool in the subnet: "
<< prefix_ << "/" << static_cast<int>
(prefix_len_) << " to which it is being added"; throw BadValue
("../../../src/lib/dhcpsrv/subnet.cc", 513, oss__.str().c_str
()); } while (1)
511 "an existing pool in the subnet: "do { std::ostringstream oss__; oss__ << "a pool of type "
<< Lease::typeToText(pool->getType()) << ", with the following address range: "
<< pool->getFirstAddress() << "-" << pool
->getLastAddress() << " overlaps with " "an existing pool in the subnet: "
<< prefix_ << "/" << static_cast<int>
(prefix_len_) << " to which it is being added"; throw BadValue
("../../../src/lib/dhcpsrv/subnet.cc", 513, oss__.str().c_str
()); } while (1)
512 << prefix_ << "/" << static_cast<int>(prefix_len_)do { std::ostringstream oss__; oss__ << "a pool of type "
<< Lease::typeToText(pool->getType()) << ", with the following address range: "
<< pool->getFirstAddress() << "-" << pool
->getLastAddress() << " overlaps with " "an existing pool in the subnet: "
<< prefix_ << "/" << static_cast<int>
(prefix_len_) << " to which it is being added"; throw BadValue
("../../../src/lib/dhcpsrv/subnet.cc", 513, oss__.str().c_str
()); } while (1)
513 << " to which it is being added")do { std::ostringstream oss__; oss__ << "a pool of type "
<< Lease::typeToText(pool->getType()) << ", with the following address range: "
<< pool->getFirstAddress() << "-" << pool
->getLastAddress() << " overlaps with " "an existing pool in the subnet: "
<< prefix_ << "/" << static_cast<int>
(prefix_len_) << " to which it is being added"; throw BadValue
("../../../src/lib/dhcpsrv/subnet.cc", 513, oss__.str().c_str
()); } while (1)
;
514 }
515
516 PoolCollection& pools_writable = getPoolsWritable(pool->getType());
517
518 // Add the pool to the appropriate pools collection
519 pools_writable.push_back(pool);
520
521 // Sort pools by first address.
522 std::sort(pools_writable.begin(), pools_writable.end(),
523 comparePoolFirstAddress);
524}
525
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
("../../../src/lib/dhcpsrv/subnet.cc", 640, oss__.str().c_str
()); } while (1)
640 << " specified in subnet6")do { std::ostringstream oss__; oss__ << "Non IPv6 prefix "
<< prefix << " specified in subnet6"; throw BadValue
("../../../src/lib/dhcpsrv/subnet.cc", 640, oss__.str().c_str
()); } while (1)
;
641 }
642
643 // Timers.
644 setT1(t1);
645 setT2(t2);
646 setPreferred(preferred_lifetime);
647 setValid(valid_lifetime);
648}
649
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>
1
Calling 'make_shared<isc::dhcp::Subnet6, 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 isc::util::Triplet<unsigned int> &, const unsigned int &>'
19
Returned allocated memory
658 (prefix, length, t1, t2, preferred_lifetime, valid_lifetime, id);
659 // IA_NA
660 subnet->setAllocator(Lease::TYPE_NA,
661 boost::make_shared<IterativeAllocator>
20
Calling 'make_shared<isc::dhcp::IterativeAllocator, isc::dhcp::Lease::Type, boost::shared_ptr<isc::dhcp::Subnet6> &>'
33
Returning; memory was released
662 (Lease::TYPE_NA, subnet));
663 subnet->setAllocationState(Lease::TYPE_NA,
34
Calling 'shared_ptr::operator->'
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("../../../src/lib/dhcpsrv/subnet.cc", 684, oss__
.str().c_str()); } while (1)
683 << "(" << static_cast<int>(type)do { std::ostringstream oss__; oss__ << "Invalid Pool type: "
<< Lease::typeToText(type) << "(" << static_cast
<int>(type) << "), must be TYPE_NA, TYPE_TA or TYPE_PD for Subnet6"
; throw BadValue("../../../src/lib/dhcpsrv/subnet.cc", 684, oss__
.str().c_str()); } while (1)
684 << "), must be TYPE_NA, TYPE_TA or TYPE_PD for Subnet6")do { std::ostringstream oss__; oss__ << "Invalid Pool type: "
<< Lease::typeToText(type) << "(" << static_cast
<int>(type) << "), must be TYPE_NA, TYPE_TA or TYPE_PD for Subnet6"
; throw BadValue("../../../src/lib/dhcpsrv/subnet.cc", 684, oss__
.str().c_str()); } while (1)
;
685 }
686}
687
688ConstSubnet6Ptr
689Subnet6::getNextSubnet(const ConstSubnet6Ptr& first_subnet) const {
690 SharedNetwork6Ptr network;
691 getSharedNetwork(network);
692 if (network) {
693 return (network->getNextSubnet(first_subnet, getID()));
694 }
695
696 return (Subnet6Ptr());
697}
698
699ConstSubnet6Ptr
700Subnet6::getNextSubnet(const ConstSubnet6Ptr& first_subnet,
701 const ClientClasses& client_classes) const {
702 SharedNetwork6Ptr network;
703 getSharedNetwork(network);
704 // We can only get next subnet if shared network has been defined for
705 // the current subnet.
706 if (network) {
707 ConstSubnet6Ptr subnet;
708 do {
709 // Use subnet identifier of this subnet if this is the first
710 // time we're calling getNextSubnet. Otherwise, use the
711 // subnet id of the previously returned subnet.
712 SubnetID subnet_id = subnet ? subnet->getID() : getID();
713 subnet = network->getNextSubnet(first_subnet, subnet_id);
714 // If client classes match the subnet, return it. Otherwise,
715 // try another subnet.
716 if (subnet && subnet->clientSupported(client_classes)) {
717 return (subnet);
718 }
719 } while (subnet);
720 }
721
722 // No subnet found.
723 return (Subnet6Ptr());
724}
725
726bool
727Subnet6::clientSupported(const isc::dhcp::ClientClasses& client_classes) const {
728 NetworkPtr network;
729 getSharedNetwork(network);
730 if (network && !network->clientSupported(client_classes)) {
731 return (false);
732 }
733
734 return (Network6::clientSupported(client_classes));
735}
736
737data::ElementPtr
738Subnet::toElement() const {
739 ElementPtr map = Element::createMap();
740
741 // Add user-context
742 contextToElement(map);
743
744 // Set subnet id
745 SubnetID id = getID();
746 map->set("id", Element::create(static_cast<long long>(id)));
747
748 // Set subnet
749 map->set("subnet", Element::create(toText()));
750
751 return (map);
752}
753
754void
755Subnet4::createAllocators() {
756 auto allocator_type = getAllocatorType();
757 if (allocator_type.empty()) {
758 allocator_type = getDefaultAllocatorType();
759 }
760 if (allocator_type == "random") {
761 setAllocator(Lease::TYPE_V4,
762 boost::make_shared<RandomAllocator>
763 (Lease::TYPE_V4, shared_from_this()));
764 setAllocationState(Lease::TYPE_V4, SubnetAllocationStatePtr());
765
766 for (auto const& pool : pools_) {
767 pool->setAllocationState(PoolRandomAllocationState::create(pool));
768 }
769
770 } else if (allocator_type == "flq") {
771 setAllocator(Lease::TYPE_V4,
772 boost::make_shared<FreeLeaseQueueAllocator>
773 (Lease::TYPE_V4, shared_from_this()));
774 setAllocationState(Lease::TYPE_V4, SubnetAllocationStatePtr());
775
776 for (auto const& pool : pools_) {
777 pool->setAllocationState(PoolFreeLeaseQueueAllocationState::create(pool));
778 }
779
780 } else {
781 setAllocator(Lease::TYPE_V4,
782 boost::make_shared<IterativeAllocator>
783 (Lease::TYPE_V4, shared_from_this()));
784 setAllocationState(Lease::TYPE_V4,
785 SubnetIterativeAllocationState::create(shared_from_this()));
786
787 for (auto const& pool : pools_) {
788 pool->setAllocationState(PoolIterativeAllocationState::create(pool));
789 }
790 }
791}
792
793data::ElementPtr
794Subnet4::toElement() const {
795 // Prepare the map
796 ElementPtr map = Subnet::toElement();
797 ElementPtr network_map = Network4::toElement();
798
799 merge(map, network_map);
800
801 // Set DHCP4o6
802 const Cfg4o6& d4o6 = get4o6();
803 isc::data::merge(map, d4o6.toElement());
804
805 // Set pools
806 auto const& pools = getPools(Lease::TYPE_V4);
807 ElementPtr pool_list = Element::createList();
808 for (auto const& pool : pools) {
809 // Add the formatted pool to the list
810 pool_list->add(pool->toElement());
811 }
812 map->set("pools", pool_list);
813
814 return (map);
815}
816
817std::pair<IOAddress, uint8_t>
818Subnet4::parsePrefix(const std::string& prefix) {
819 std::pair<IOAddress, uint8_t> parsed = Subnet::parsePrefixCommon(prefix);
820 if (!parsed.first.isV4() || parsed.first.isV4Zero() ||
821 (parsed.second > 32) || (parsed.second == 0)) {
822 isc_throw(BadValue, "unable to parse invalid IPv4 prefix " << prefix)do { std::ostringstream oss__; oss__ << "unable to parse invalid IPv4 prefix "
<< prefix; throw BadValue("../../../src/lib/dhcpsrv/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("../../../src/lib/dhcpsrv/subnet.cc", 844, oss__
.str().c_str()); } while (1)
;
845
846 } else {
847 setAllocator(Lease::TYPE_NA,
848 boost::make_shared<IterativeAllocator>
849 (Lease::TYPE_NA, shared_from_this()));
850 setAllocationState(Lease::TYPE_NA, SubnetIterativeAllocationState::create(shared_from_this()));
851 setAllocationState(Lease::TYPE_TA, SubnetIterativeAllocationState::create(shared_from_this()));
852 }
853
854 auto pd_allocator_type = getPdAllocatorType();
855 if (pd_allocator_type.empty()) {
856 pd_allocator_type = getDefaultPdAllocatorType();
857 }
858 // Repeat the same for the delegated prefix allocator.
859 if (pd_allocator_type == "random") {
860 setAllocator(Lease::TYPE_PD,
861 boost::make_shared<RandomAllocator>
862 (Lease::TYPE_PD, shared_from_this()));
863 setAllocationState(Lease::TYPE_PD, SubnetAllocationStatePtr());
864
865 } else if (pd_allocator_type == "flq") {
866 setAllocator(Lease::TYPE_PD,
867 boost::make_shared<FreeLeaseQueueAllocator>
868 (Lease::TYPE_PD, shared_from_this()));
869 setAllocationState(Lease::TYPE_PD, SubnetAllocationStatePtr());
870
871 } else {
872 setAllocator(Lease::TYPE_PD,
873 boost::make_shared<IterativeAllocator>
874 (Lease::TYPE_PD, shared_from_this()));
875 setAllocationState(Lease::TYPE_PD, SubnetIterativeAllocationState::create(shared_from_this()));
876 }
877 // Create allocation states for NA pools.
878 for (auto const& pool : pools_) {
879 if (allocator_type == "random") {
880 pool->setAllocationState(PoolRandomAllocationState::create(pool));
881 } else {
882 pool->setAllocationState(PoolIterativeAllocationState::create(pool));
883 }
884 }
885 // Create allocation states for TA pools.
886 for (auto const& pool : pools_ta_) {
887 if (allocator_type == "random") {
888 pool->setAllocationState(PoolRandomAllocationState::create(pool));
889 } else {
890 pool->setAllocationState(PoolIterativeAllocationState::create(pool));
891 }
892 }
893 // Create allocation states for PD pools.
894 for (auto const& pool : pools_pd_) {
895 if (pd_allocator_type == "random") {
896 pool->setAllocationState(PoolRandomAllocationState::create(pool));
897 } else if (pd_allocator_type == "flq") {
898 pool->setAllocationState(PoolFreeLeaseQueueAllocationState::create(pool));
899 } else {
900 pool->setAllocationState(PoolIterativeAllocationState::create(pool));
901 }
902 }
903}
904
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("../../../src/lib/dhcpsrv/subnet.cc"
, 939, oss__.str().c_str()); } while (1)
;
940 }
941 return (parsed);
942}
943
944} // namespace dhcp
945} // namespace isc

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

1#ifndef BOOST_SMART_PTR_MAKE_SHARED_OBJECT_HPP_INCLUDED
2#define BOOST_SMART_PTR_MAKE_SHARED_OBJECT_HPP_INCLUDED
3
4// make_shared_object.hpp
5//
6// Copyright (c) 2007, 2008, 2012 Peter Dimov
7//
8// Distributed under the Boost Software License, Version 1.0.
9// See accompanying file LICENSE_1_0.txt or copy at
10// http://www.boost.org/LICENSE_1_0.txt
11//
12// See http://www.boost.org/libs/smart_ptr/ for documentation.
13
14#include <boost/smart_ptr/detail/requires_cxx11.hpp>
15#include <boost/config.hpp>
16#include <boost/move/core.hpp>
17#include <boost/move/utility_core.hpp>
18#include <boost/smart_ptr/shared_ptr.hpp>
19#include <boost/smart_ptr/detail/sp_forward.hpp>
20#include <boost/smart_ptr/detail/sp_noexcept.hpp>
21#include <boost/type_traits/type_with_alignment.hpp>
22#include <boost/type_traits/alignment_of.hpp>
23#include <cstddef>
24#include <new>
25
26namespace boost
27{
28
29namespace detail
30{
31
32template< std::size_t N, std::size_t A > struct sp_aligned_storage
33{
34 union type
35 {
36 char data_[ N ];
37 typename boost::type_with_alignment< A >::type align_;
38 };
39};
40
41template< class T > class sp_ms_deleter
42{
43private:
44
45 typedef typename sp_aligned_storage< sizeof( T ), ::boost::alignment_of< T >::value >::type storage_type;
46
47 bool initialized_;
48 storage_type storage_;
49
50private:
51
52 void destroy() BOOST_SP_NOEXCEPTnoexcept
53 {
54 if( initialized_ )
55 {
56#if defined( __GNUC__4 )
57
58 // fixes incorrect aliasing warning
59 T * p = reinterpret_cast< T* >( storage_.data_ );
60 p->~T();
61
62#else
63
64 reinterpret_cast< T* >( storage_.data_ )->~T();
65
66#endif
67
68 initialized_ = false;
69 }
70 }
71
72public:
73
74 sp_ms_deleter() BOOST_SP_NOEXCEPTnoexcept : initialized_( false )
75 {
76 }
77
78 template<class A> explicit sp_ms_deleter( A const & ) BOOST_SP_NOEXCEPTnoexcept : initialized_( false )
79 {
80 }
81
82 // optimization: do not copy storage_
83 sp_ms_deleter( sp_ms_deleter const & ) BOOST_SP_NOEXCEPTnoexcept : initialized_( false )
84 {
85 }
86
87 ~sp_ms_deleter() BOOST_SP_NOEXCEPTnoexcept
88 {
89 destroy();
90 }
91
92 void operator()( T * ) BOOST_SP_NOEXCEPTnoexcept
93 {
94 destroy();
95 }
96
97 static void operator_fn( T* ) BOOST_SP_NOEXCEPTnoexcept // operator() can't be static
98 {
99 }
100
101 void * address() BOOST_SP_NOEXCEPTnoexcept
102 {
103 return storage_.data_;
104 }
105
106 void set_initialized() BOOST_SP_NOEXCEPTnoexcept
107 {
108 initialized_ = true;
109 }
110};
111
112template< class T, class A > class sp_as_deleter
113{
114private:
115
116 typedef typename sp_aligned_storage< sizeof( T ), ::boost::alignment_of< T >::value >::type storage_type;
117
118 storage_type storage_;
119 A a_;
120 bool initialized_;
121
122private:
123
124 void destroy() BOOST_SP_NOEXCEPTnoexcept
125 {
126 if( initialized_ )
127 {
128 T * p = reinterpret_cast< T* >( storage_.data_ );
129
130#if !defined( BOOST_NO_CXX11_ALLOCATOR )
131
132 std::allocator_traits<A>::destroy( a_, p );
133
134#else
135
136 p->~T();
137
138#endif
139
140 initialized_ = false;
141 }
142 }
143
144public:
145
146 sp_as_deleter( A const & a ) BOOST_SP_NOEXCEPTnoexcept : a_( a ), initialized_( false )
147 {
148 }
149
150 // optimization: do not copy storage_
151 sp_as_deleter( sp_as_deleter const & r ) BOOST_SP_NOEXCEPTnoexcept : a_( r.a_), initialized_( false )
152 {
153 }
154
155 ~sp_as_deleter() BOOST_SP_NOEXCEPTnoexcept
156 {
157 destroy();
158 }
159
160 void operator()( T * ) BOOST_SP_NOEXCEPTnoexcept
161 {
162 destroy();
163 }
164
165 static void operator_fn( T* ) BOOST_SP_NOEXCEPTnoexcept // operator() can't be static
166 {
167 }
168
169 void * address() BOOST_SP_NOEXCEPTnoexcept
170 {
171 return storage_.data_;
172 }
173
174 void set_initialized() BOOST_SP_NOEXCEPTnoexcept
175 {
176 initialized_ = true;
177 }
178};
179
180template< class T > struct sp_if_not_array
181{
182 typedef boost::shared_ptr< T > type;
183};
184
185#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
186
187template< class T > struct sp_if_not_array< T[] >
188{
189};
190
191#if !defined( BOOST_BORLANDC ) || !BOOST_WORKAROUND( BOOST_BORLANDC, < 0x600 )((1 + 0 == 0) && (BOOST_BORLANDC != 0) && (1 %
(( (BOOST_BORLANDC < 0x600) ) + 1)))
192
193template< class T, std::size_t N > struct sp_if_not_array< T[N] >
194{
195};
196
197#endif
198
199#endif
200
201} // namespace detail
202
203#if !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
204# define BOOST_SP_MSD( T ) boost::detail::sp_inplace_tag< boost::detail::sp_ms_deleter< T > >()
205#else
206# define BOOST_SP_MSD( T ) boost::detail::sp_ms_deleter< T >()
207#endif
208
209// _noinit versions
210
211template< class T > typename boost::detail::sp_if_not_array< T >::type make_shared_noinit()
212{
213 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
214
215 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
216
217 void * pv = pd->address();
218
219 ::new( pv ) T;
220 pd->set_initialized();
221
222 T * pt2 = static_cast< T* >( pv );
223
224 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
225 return boost::shared_ptr< T >( pt, pt2 );
226}
227
228template< class T, class A > typename boost::detail::sp_if_not_array< T >::type allocate_shared_noinit( A const & a )
229{
230 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
231
232 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
233
234 void * pv = pd->address();
235
236 ::new( pv ) T;
237 pd->set_initialized();
238
239 T * pt2 = static_cast< T* >( pv );
240
241 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
242 return boost::shared_ptr< T >( pt, pt2 );
243}
244
245#if !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
246
247// Variadic templates, rvalue reference
248
249template< class T, class... Args > typename boost::detail::sp_if_not_array< T >::type make_shared( Args && ... args )
250{
251 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
2
Calling constructor for 'shared_ptr<isc::dhcp::Subnet6>'
6
Returning from constructor for 'shared_ptr<isc::dhcp::Subnet6>'
252
253 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
254
255 void * pv = pd->address();
256
257 ::new( pv ) T( boost::detail::sp_forward<Args>( args )... );
21
Calling implicit destructor for 'weak_ptr<isc::dhcp::Subnet>'
22
Calling '~weak_count'
31
Returning from '~weak_count'
32
Returning from destructor for 'weak_ptr<isc::dhcp::Subnet>'
258 pd->set_initialized();
259
260 T * pt2 = static_cast< T* >( pv );
261
262 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
7
Calling 'sp_enable_shared_from_this<isc::dhcp::Subnet6, isc::dhcp::Subnet6, isc::dhcp::Subnet6>'
18
Returning from 'sp_enable_shared_from_this<isc::dhcp::Subnet6, isc::dhcp::Subnet6, isc::dhcp::Subnet6>'
263 return boost::shared_ptr< T >( pt, pt2 );
264}
265
266template< class T, class A, class... Args > typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, Args && ... args )
267{
268#if !defined( BOOST_NO_CXX11_ALLOCATOR )
269
270 typedef typename std::allocator_traits<A>::template rebind_alloc<T> A2;
271 A2 a2( a );
272
273 typedef boost::detail::sp_as_deleter< T, A2 > D;
274
275 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_inplace_tag<D>(), a2 );
276
277#else
278
279 typedef boost::detail::sp_ms_deleter< T > D;
280
281 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_inplace_tag<D>(), a );
282
283#endif
284
285 D * pd = static_cast< D* >( pt._internal_get_untyped_deleter() );
286 void * pv = pd->address();
287
288#if !defined( BOOST_NO_CXX11_ALLOCATOR )
289
290 std::allocator_traits<A2>::construct( a2, static_cast< T* >( pv ), boost::detail::sp_forward<Args>( args )... );
291
292#else
293
294 ::new( pv ) T( boost::detail::sp_forward<Args>( args )... );
295
296#endif
297
298 pd->set_initialized();
299
300 T * pt2 = static_cast< T* >( pv );
301
302 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
303 return boost::shared_ptr< T >( pt, pt2 );
304}
305
306#else // !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
307
308// Common zero-argument versions
309
310template< class T > typename boost::detail::sp_if_not_array< T >::type make_shared()
311{
312 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
313
314 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
315
316 void * pv = pd->address();
317
318 ::new( pv ) T();
319 pd->set_initialized();
320
321 T * pt2 = static_cast< T* >( pv );
322
323 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
324 return boost::shared_ptr< T >( pt, pt2 );
325}
326
327template< class T, class A > typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a )
328{
329 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
330
331 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
332
333 void * pv = pd->address();
334
335 ::new( pv ) T();
336 pd->set_initialized();
337
338 T * pt2 = static_cast< T* >( pv );
339
340 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
341 return boost::shared_ptr< T >( pt, pt2 );
342}
343
344// C++03 version
345
346template< class T, class A1 >
347typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1)A1 && a1 )
348{
349 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
350
351 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
352
353 void * pv = pd->address();
354
355 ::new( pv ) T(
356 boost::forward<A1>( a1 )
357 );
358
359 pd->set_initialized();
360
361 T * pt2 = static_cast< T* >( pv );
362
363 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
364 return boost::shared_ptr< T >( pt, pt2 );
365}
366
367template< class T, class A, class A1 >
368typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1)A1 && a1 )
369{
370 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
371
372 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
373
374 void * pv = pd->address();
375
376 ::new( pv ) T(
377 boost::forward<A1>( a1 )
378 );
379
380 pd->set_initialized();
381
382 T * pt2 = static_cast< T* >( pv );
383
384 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
385 return boost::shared_ptr< T >( pt, pt2 );
386}
387
388template< class T, class A1, class A2 >
389typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2 )
390{
391 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
392
393 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
394
395 void * pv = pd->address();
396
397 ::new( pv ) T(
398 boost::forward<A1>( a1 ),
399 boost::forward<A2>( a2 )
400 );
401
402 pd->set_initialized();
403
404 T * pt2 = static_cast< T* >( pv );
405
406 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
407 return boost::shared_ptr< T >( pt, pt2 );
408}
409
410template< class T, class A, class A1, class A2 >
411typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2 )
412{
413 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
414
415 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
416
417 void * pv = pd->address();
418
419 ::new( pv ) T(
420 boost::forward<A1>( a1 ),
421 boost::forward<A2>( a2 )
422 );
423
424 pd->set_initialized();
425
426 T * pt2 = static_cast< T* >( pv );
427
428 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
429 return boost::shared_ptr< T >( pt, pt2 );
430}
431
432template< class T, class A1, class A2, class A3 >
433typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2, BOOST_FWD_REF(A3)A3 && a3 )
434{
435 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
436
437 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
438
439 void * pv = pd->address();
440
441 ::new( pv ) T(
442 boost::forward<A1>( a1 ),
443 boost::forward<A2>( a2 ),
444 boost::forward<A3>( a3 )
445 );
446
447 pd->set_initialized();
448
449 T * pt2 = static_cast< T* >( pv );
450
451 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
452 return boost::shared_ptr< T >( pt, pt2 );
453}
454
455template< class T, class A, class A1, class A2, class A3 >
456typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2, BOOST_FWD_REF(A3)A3 && a3 )
457{
458 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
459
460 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
461
462 void * pv = pd->address();
463
464 ::new( pv ) T(
465 boost::forward<A1>( a1 ),
466 boost::forward<A2>( a2 ),
467 boost::forward<A3>( a3 )
468 );
469
470 pd->set_initialized();
471
472 T * pt2 = static_cast< T* >( pv );
473
474 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
475 return boost::shared_ptr< T >( pt, pt2 );
476}
477
478template< class T, class A1, class A2, class A3, class A4 >
479typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2, BOOST_FWD_REF(A3)A3 && a3, BOOST_FWD_REF(A4)A4 && a4 )
480{
481 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
482
483 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
484
485 void * pv = pd->address();
486
487 ::new( pv ) T(
488 boost::forward<A1>( a1 ),
489 boost::forward<A2>( a2 ),
490 boost::forward<A3>( a3 ),
491 boost::forward<A4>( a4 )
492 );
493
494 pd->set_initialized();
495
496 T * pt2 = static_cast< T* >( pv );
497
498 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
499 return boost::shared_ptr< T >( pt, pt2 );
500}
501
502template< class T, class A, class A1, class A2, class A3, class A4 >
503typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2, BOOST_FWD_REF(A3)A3 && a3, BOOST_FWD_REF(A4)A4 && a4 )
504{
505 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
506
507 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
508
509 void * pv = pd->address();
510
511 ::new( pv ) T(
512 boost::forward<A1>( a1 ),
513 boost::forward<A2>( a2 ),
514 boost::forward<A3>( a3 ),
515 boost::forward<A4>( a4 )
516 );
517
518 pd->set_initialized();
519
520 T * pt2 = static_cast< T* >( pv );
521
522 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
523 return boost::shared_ptr< T >( pt, pt2 );
524}
525
526template< class T, class A1, class A2, class A3, class A4, class A5 >
527typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2, BOOST_FWD_REF(A3)A3 && a3, BOOST_FWD_REF(A4)A4 && a4, BOOST_FWD_REF(A5)A5 && a5 )
528{
529 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
530
531 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
532
533 void * pv = pd->address();
534
535 ::new( pv ) T(
536 boost::forward<A1>( a1 ),
537 boost::forward<A2>( a2 ),
538 boost::forward<A3>( a3 ),
539 boost::forward<A4>( a4 ),
540 boost::forward<A5>( a5 )
541 );
542
543 pd->set_initialized();
544
545 T * pt2 = static_cast< T* >( pv );
546
547 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
548 return boost::shared_ptr< T >( pt, pt2 );
549}
550
551template< class T, class A, class A1, class A2, class A3, class A4, class A5 >
552typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2, BOOST_FWD_REF(A3)A3 && a3, BOOST_FWD_REF(A4)A4 && a4, BOOST_FWD_REF(A5)A5 && a5 )
553{
554 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
555
556 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
557
558 void * pv = pd->address();
559
560 ::new( pv ) T(
561 boost::forward<A1>( a1 ),
562 boost::forward<A2>( a2 ),
563 boost::forward<A3>( a3 ),
564 boost::forward<A4>( a4 ),
565 boost::forward<A5>( a5 )
566 );
567
568 pd->set_initialized();
569
570 T * pt2 = static_cast< T* >( pv );
571
572 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
573 return boost::shared_ptr< T >( pt, pt2 );
574}
575
576template< class T, class A1, class A2, class A3, class A4, class A5, class A6 >
577typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2, BOOST_FWD_REF(A3)A3 && a3, BOOST_FWD_REF(A4)A4 && a4, BOOST_FWD_REF(A5)A5 && a5, BOOST_FWD_REF(A6)A6 && a6 )
578{
579 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
580
581 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
582
583 void * pv = pd->address();
584
585 ::new( pv ) T(
586 boost::forward<A1>( a1 ),
587 boost::forward<A2>( a2 ),
588 boost::forward<A3>( a3 ),
589 boost::forward<A4>( a4 ),
590 boost::forward<A5>( a5 ),
591 boost::forward<A6>( a6 )
592 );
593
594 pd->set_initialized();
595
596 T * pt2 = static_cast< T* >( pv );
597
598 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
599 return boost::shared_ptr< T >( pt, pt2 );
600}
601
602template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6 >
603typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2, BOOST_FWD_REF(A3)A3 && a3, BOOST_FWD_REF(A4)A4 && a4, BOOST_FWD_REF(A5)A5 && a5, BOOST_FWD_REF(A6)A6 && a6 )
604{
605 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
606
607 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
608
609 void * pv = pd->address();
610
611 ::new( pv ) T(
612 boost::forward<A1>( a1 ),
613 boost::forward<A2>( a2 ),
614 boost::forward<A3>( a3 ),
615 boost::forward<A4>( a4 ),
616 boost::forward<A5>( a5 ),
617 boost::forward<A6>( a6 )
618 );
619
620 pd->set_initialized();
621
622 T * pt2 = static_cast< T* >( pv );
623
624 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
625 return boost::shared_ptr< T >( pt, pt2 );
626}
627
628template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 >
629typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2, BOOST_FWD_REF(A3)A3 && a3, BOOST_FWD_REF(A4)A4 && a4, BOOST_FWD_REF(A5)A5 && a5, BOOST_FWD_REF(A6)A6 && a6, BOOST_FWD_REF(A7)A7 && a7 )
630{
631 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
632
633 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
634
635 void * pv = pd->address();
636
637 ::new( pv ) T(
638 boost::forward<A1>( a1 ),
639 boost::forward<A2>( a2 ),
640 boost::forward<A3>( a3 ),
641 boost::forward<A4>( a4 ),
642 boost::forward<A5>( a5 ),
643 boost::forward<A6>( a6 ),
644 boost::forward<A7>( a7 )
645 );
646
647 pd->set_initialized();
648
649 T * pt2 = static_cast< T* >( pv );
650
651 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
652 return boost::shared_ptr< T >( pt, pt2 );
653}
654
655template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7 >
656typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2, BOOST_FWD_REF(A3)A3 && a3, BOOST_FWD_REF(A4)A4 && a4, BOOST_FWD_REF(A5)A5 && a5, BOOST_FWD_REF(A6)A6 && a6, BOOST_FWD_REF(A7)A7 && a7 )
657{
658 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
659
660 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
661
662 void * pv = pd->address();
663
664 ::new( pv ) T(
665 boost::forward<A1>( a1 ),
666 boost::forward<A2>( a2 ),
667 boost::forward<A3>( a3 ),
668 boost::forward<A4>( a4 ),
669 boost::forward<A5>( a5 ),
670 boost::forward<A6>( a6 ),
671 boost::forward<A7>( a7 )
672 );
673
674 pd->set_initialized();
675
676 T * pt2 = static_cast< T* >( pv );
677
678 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
679 return boost::shared_ptr< T >( pt, pt2 );
680}
681
682template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 >
683typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2, BOOST_FWD_REF(A3)A3 && a3, BOOST_FWD_REF(A4)A4 && a4, BOOST_FWD_REF(A5)A5 && a5, BOOST_FWD_REF(A6)A6 && a6, BOOST_FWD_REF(A7)A7 && a7, BOOST_FWD_REF(A8)A8 && a8 )
684{
685 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
686
687 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
688
689 void * pv = pd->address();
690
691 ::new( pv ) T(
692 boost::forward<A1>( a1 ),
693 boost::forward<A2>( a2 ),
694 boost::forward<A3>( a3 ),
695 boost::forward<A4>( a4 ),
696 boost::forward<A5>( a5 ),
697 boost::forward<A6>( a6 ),
698 boost::forward<A7>( a7 ),
699 boost::forward<A8>( a8 )
700 );
701
702 pd->set_initialized();
703
704 T * pt2 = static_cast< T* >( pv );
705
706 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
707 return boost::shared_ptr< T >( pt, pt2 );
708}
709
710template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 >
711typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2, BOOST_FWD_REF(A3)A3 && a3, BOOST_FWD_REF(A4)A4 && a4, BOOST_FWD_REF(A5)A5 && a5, BOOST_FWD_REF(A6)A6 && a6, BOOST_FWD_REF(A7)A7 && a7, BOOST_FWD_REF(A8)A8 && a8 )
712{
713 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
714
715 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
716
717 void * pv = pd->address();
718
719 ::new( pv ) T(
720 boost::forward<A1>( a1 ),
721 boost::forward<A2>( a2 ),
722 boost::forward<A3>( a3 ),
723 boost::forward<A4>( a4 ),
724 boost::forward<A5>( a5 ),
725 boost::forward<A6>( a6 ),
726 boost::forward<A7>( a7 ),
727 boost::forward<A8>( a8 )
728 );
729
730 pd->set_initialized();
731
732 T * pt2 = static_cast< T* >( pv );
733
734 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
735 return boost::shared_ptr< T >( pt, pt2 );
736}
737
738template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 >
739typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2, BOOST_FWD_REF(A3)A3 && a3, BOOST_FWD_REF(A4)A4 && a4, BOOST_FWD_REF(A5)A5 && a5, BOOST_FWD_REF(A6)A6 && a6, BOOST_FWD_REF(A7)A7 && a7, BOOST_FWD_REF(A8)A8 && a8, BOOST_FWD_REF(A9)A9 && a9 )
740{
741 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
742
743 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
744
745 void * pv = pd->address();
746
747 ::new( pv ) T(
748 boost::forward<A1>( a1 ),
749 boost::forward<A2>( a2 ),
750 boost::forward<A3>( a3 ),
751 boost::forward<A4>( a4 ),
752 boost::forward<A5>( a5 ),
753 boost::forward<A6>( a6 ),
754 boost::forward<A7>( a7 ),
755 boost::forward<A8>( a8 ),
756 boost::forward<A9>( a9 )
757 );
758
759 pd->set_initialized();
760
761 T * pt2 = static_cast< T* >( pv );
762
763 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
764 return boost::shared_ptr< T >( pt, pt2 );
765}
766
767template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 >
768typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1)A1 && a1, BOOST_FWD_REF(A2)A2 && a2, BOOST_FWD_REF(A3)A3 && a3, BOOST_FWD_REF(A4)A4 && a4, BOOST_FWD_REF(A5)A5 && a5, BOOST_FWD_REF(A6)A6 && a6, BOOST_FWD_REF(A7)A7 && a7, BOOST_FWD_REF(A8)A8 && a8, BOOST_FWD_REF(A9)A9 && a9 )
769{
770 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
771
772 boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
773
774 void * pv = pd->address();
775
776 ::new( pv ) T(
777 boost::forward<A1>( a1 ),
778 boost::forward<A2>( a2 ),
779 boost::forward<A3>( a3 ),
780 boost::forward<A4>( a4 ),
781 boost::forward<A5>( a5 ),
782 boost::forward<A6>( a6 ),
783 boost::forward<A7>( a7 ),
784 boost::forward<A8>( a8 ),
785 boost::forward<A9>( a9 )
786 );
787
788 pd->set_initialized();
789
790 T * pt2 = static_cast< T* >( pv );
791
792 boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
793 return boost::shared_ptr< T >( pt, pt2 );
794}
795
796#endif // !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
797
798#undef BOOST_SP_MSD
799
800} // namespace boost
801
802#endif // #ifndef BOOST_SMART_PTR_MAKE_SHARED_OBJECT_HPP_INCLUDED

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

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

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

1#ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED
2#define BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED
3
4// MS compatible compilers support #pragma once
5
6#if defined(_MSC_VER) && (_MSC_VER >= 1020)
7# pragma once
8#endif
9
10//
11// detail/shared_count.hpp
12//
13// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
14// Copyright 2004-2005 Peter Dimov
15//
16// Distributed under the Boost Software License, Version 1.0. (See
17// accompanying file LICENSE_1_0.txt or copy at
18// http://www.boost.org/LICENSE_1_0.txt)
19//
20
21#if defined(__BORLANDC__) && !defined(__clang__1)
22# pragma warn -8027 // Functions containing try are not expanded inline
23#endif
24
25#include <boost/smart_ptr/bad_weak_ptr.hpp>
26#include <boost/smart_ptr/detail/sp_counted_base.hpp>
27#include <boost/smart_ptr/detail/sp_counted_impl.hpp>
28#include <boost/smart_ptr/detail/sp_disable_deprecated.hpp>
29#include <boost/smart_ptr/detail/sp_noexcept.hpp>
30#include <boost/core/checked_delete.hpp>
31#include <boost/throw_exception.hpp>
32#include <boost/core/addressof.hpp>
33#include <boost/config.hpp>
34#include <boost/config/workaround.hpp>
35#include <boost/cstdint.hpp>
36#include <memory> // std::auto_ptr
37#include <functional> // std::less
38#include <cstddef> // std::size_t
39
40#ifdef BOOST_NO_EXCEPTIONS
41# include <new> // std::bad_alloc
42#endif
43
44#if defined( BOOST_SP_DISABLE_DEPRECATED )
45#pragma GCC diagnostic push
46#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
47#endif
48
49namespace boost
50{
51
52namespace movelib
53{
54
55template< class T, class D > class unique_ptr;
56
57} // namespace movelib
58
59namespace detail
60{
61
62#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
63
64int const shared_count_id = 0x2C35F101;
65int const weak_count_id = 0x298C38A4;
66
67#endif
68
69struct sp_nothrow_tag {};
70
71template< class D > struct sp_inplace_tag
72{
73};
74
75template< class T > class sp_reference_wrapper
76{
77public:
78
79 explicit sp_reference_wrapper( T & t): t_( boost::addressof( t ) )
80 {
81 }
82
83 template< class Y > void operator()( Y * p ) const
84 {
85 (*t_)( p );
86 }
87
88private:
89
90 T * t_;
91};
92
93template< class D > struct sp_convert_reference
94{
95 typedef D type;
96};
97
98template< class D > struct sp_convert_reference< D& >
99{
100 typedef sp_reference_wrapper< D > type;
101};
102
103template<class T> std::size_t sp_hash_pointer( T* p ) BOOST_NOEXCEPTnoexcept
104{
105 boost::uintptr_t v = reinterpret_cast<boost::uintptr_t>( p );
106
107 // match boost::hash<T*>
108 return static_cast<std::size_t>( v + ( v >> 3 ) );
109}
110
111class weak_count;
112
113class shared_count
114{
115private:
116
117 sp_counted_base * pi_;
118
119#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
120 int id_;
121#endif
122
123 friend class weak_count;
124
125public:
126
127 BOOST_CONSTEXPRconstexpr shared_count() BOOST_SP_NOEXCEPTnoexcept: pi_(0)
128#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
129 , id_(shared_count_id)
130#endif
131 {
132 }
133
134 BOOST_CONSTEXPRconstexpr explicit shared_count( sp_counted_base * pi ) BOOST_SP_NOEXCEPTnoexcept: pi_( pi )
135#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
136 , id_(shared_count_id)
137#endif
138 {
139 }
140
141 template<class Y> explicit shared_count( Y * p ): pi_( 0 )
142#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
143 , id_(shared_count_id)
144#endif
145 {
146#ifndef BOOST_NO_EXCEPTIONS
147
148 try
149 {
150 pi_ = new sp_counted_impl_p<Y>( p );
151 }
152 catch(...)
153 {
154 boost::checked_delete( p );
155 throw;
156 }
157
158#else
159
160 pi_ = new sp_counted_impl_p<Y>( p );
161
162 if( pi_ == 0 )
163 {
164 boost::checked_delete( p );
165 boost::throw_exception( std::bad_alloc() );
166 }
167
168#endif
169 }
170
171#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1200 )((1 + 0 == 0) && (BOOST_MSVC != 0) && (1 % ((
(BOOST_MSVC <= 1200) ) + 1)))
172 template<class Y, class D> shared_count( Y * p, D d ): pi_(0)
173#else
174 template<class P, class D> shared_count( P p, D d ): pi_(0)
175#endif
176#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
177 , id_(shared_count_id)
178#endif
179 {
180#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1200 )((1 + 0 == 0) && (BOOST_MSVC != 0) && (1 % ((
(BOOST_MSVC <= 1200) ) + 1)))
181 typedef Y* P;
182#endif
183#ifndef BOOST_NO_EXCEPTIONS
184
185 try
186 {
187 pi_ = new sp_counted_impl_pd<P, D>(p, d);
188 }
189 catch(...)
190 {
191 d(p); // delete p
192 throw;
193 }
194
195#else
196
197 pi_ = new sp_counted_impl_pd<P, D>(p, d);
198
199 if(pi_ == 0)
200 {
201 d(p); // delete p
202 boost::throw_exception(std::bad_alloc());
203 }
204
205#endif
206 }
207
208#if !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
209
210 template< class P, class D > shared_count( P p, sp_inplace_tag<D> ): pi_( 0 )
211#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
212 , id_(shared_count_id)
213#endif
214 {
215#ifndef BOOST_NO_EXCEPTIONS
216
217 try
218 {
219 pi_ = new sp_counted_impl_pd< P, D >( p );
4
Memory is allocated
220 }
221 catch( ... )
222 {
223 D::operator_fn( p ); // delete p
224 throw;
225 }
226
227#else
228
229 pi_ = new sp_counted_impl_pd< P, D >( p );
230
231 if( pi_ == 0 )
232 {
233 D::operator_fn( p ); // delete p
234 boost::throw_exception( std::bad_alloc() );
235 }
236
237#endif // #ifndef BOOST_NO_EXCEPTIONS
238 }
239
240#endif // !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
241
242 template<class P, class D, class A> shared_count( P p, D d, A a ): pi_( 0 )
243#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
244 , id_(shared_count_id)
245#endif
246 {
247 typedef sp_counted_impl_pda<P, D, A> impl_type;
248
249#if !defined( BOOST_NO_CXX11_ALLOCATOR )
250
251 typedef typename std::allocator_traits<A>::template rebind_alloc< impl_type > A2;
252
253#else
254
255 typedef typename A::template rebind< impl_type >::other A2;
256
257#endif
258
259 A2 a2( a );
260
261#ifndef BOOST_NO_EXCEPTIONS
262
263 try
264 {
265 pi_ = a2.allocate( 1 );
266 ::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
267 }
268 catch(...)
269 {
270 d( p );
271
272 if( pi_ != 0 )
273 {
274 a2.deallocate( static_cast< impl_type* >( pi_ ), 1 );
275 }
276
277 throw;
278 }
279
280#else
281
282 pi_ = a2.allocate( 1 );
283
284 if( pi_ != 0 )
285 {
286 ::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
287 }
288 else
289 {
290 d( p );
291 boost::throw_exception( std::bad_alloc() );
292 }
293
294#endif
295 }
296
297#if !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
298
299 template< class P, class D, class A > shared_count( P p, sp_inplace_tag< D >, A a ): pi_( 0 )
300#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
301 , id_(shared_count_id)
302#endif
303 {
304 typedef sp_counted_impl_pda< P, D, A > impl_type;
305
306#if !defined( BOOST_NO_CXX11_ALLOCATOR )
307
308 typedef typename std::allocator_traits<A>::template rebind_alloc< impl_type > A2;
309
310#else
311
312 typedef typename A::template rebind< impl_type >::other A2;
313
314#endif
315
316 A2 a2( a );
317
318#ifndef BOOST_NO_EXCEPTIONS
319
320 try
321 {
322 pi_ = a2.allocate( 1 );
323 ::new( static_cast< void* >( pi_ ) ) impl_type( p, a );
324 }
325 catch(...)
326 {
327 D::operator_fn( p );
328
329 if( pi_ != 0 )
330 {
331 a2.deallocate( static_cast< impl_type* >( pi_ ), 1 );
332 }
333
334 throw;
335 }
336
337#else
338
339 pi_ = a2.allocate( 1 );
340
341 if( pi_ != 0 )
342 {
343 ::new( static_cast< void* >( pi_ ) ) impl_type( p, a );
344 }
345 else
346 {
347 D::operator_fn( p );
348 boost::throw_exception( std::bad_alloc() );
349 }
350
351#endif // #ifndef BOOST_NO_EXCEPTIONS
352 }
353
354#endif // !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
355
356#ifndef BOOST_NO_AUTO_PTR
357
358 // auto_ptr<Y> is special cased to provide the strong guarantee
359
360 template<class Y>
361 explicit shared_count( std::auto_ptr<Y> & r ): pi_( new sp_counted_impl_p<Y>( r.get() ) )
362#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
363 , id_(shared_count_id)
364#endif
365 {
366#ifdef BOOST_NO_EXCEPTIONS
367
368 if( pi_ == 0 )
369 {
370 boost::throw_exception(std::bad_alloc());
371 }
372
373#endif
374
375 r.release();
376 }
377
378#endif
379
380#if !defined( BOOST_NO_CXX11_SMART_PTR )
381
382 template<class Y, class D>
383 explicit shared_count( std::unique_ptr<Y, D> & r ): pi_( 0 )
384#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
385 , id_(shared_count_id)
386#endif
387 {
388 typedef typename sp_convert_reference<D>::type D2;
389
390 D2 d2( static_cast<D&&>( r.get_deleter() ) );
391 pi_ = new sp_counted_impl_pd< typename std::unique_ptr<Y, D>::pointer, D2 >( r.get(), d2 );
392
393#ifdef BOOST_NO_EXCEPTIONS
394
395 if( pi_ == 0 )
396 {
397 boost::throw_exception( std::bad_alloc() );
398 }
399
400#endif
401
402 r.release();
403 }
404
405#endif
406
407 template<class Y, class D>
408 explicit shared_count( boost::movelib::unique_ptr<Y, D> & r ): pi_( 0 )
409#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
410 , id_(shared_count_id)
411#endif
412 {
413 typedef typename sp_convert_reference<D>::type D2;
414
415 D2 d2( r.get_deleter() );
416 pi_ = new sp_counted_impl_pd< typename boost::movelib::unique_ptr<Y, D>::pointer, D2 >( r.get(), d2 );
417
418#ifdef BOOST_NO_EXCEPTIONS
419
420 if( pi_ == 0 )
421 {
422 boost::throw_exception( std::bad_alloc() );
423 }
424
425#endif
426
427 r.release();
428 }
429
430 ~shared_count() /*BOOST_SP_NOEXCEPT*/
431 {
432 if( pi_ != 0 ) pi_->release();
433#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
434 id_ = 0;
435#endif
436 }
437
438 shared_count(shared_count const & r) BOOST_SP_NOEXCEPTnoexcept: pi_(r.pi_)
439#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
440 , id_(shared_count_id)
441#endif
442 {
443 if( pi_ != 0 ) pi_->add_ref_copy();
444 }
445
446#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
447
448 shared_count(shared_count && r) BOOST_SP_NOEXCEPTnoexcept: pi_(r.pi_)
449#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
450 , id_(shared_count_id)
451#endif
452 {
453 r.pi_ = 0;
454 }
455
456#endif
457
458 explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0
459 shared_count( weak_count const & r, sp_nothrow_tag ) BOOST_SP_NOEXCEPTnoexcept; // constructs an empty *this when r.use_count() == 0
460
461 shared_count & operator= (shared_count const & r) BOOST_SP_NOEXCEPTnoexcept
462 {
463 sp_counted_base * tmp = r.pi_;
464
465 if( tmp != pi_ )
466 {
467 if( tmp != 0 ) tmp->add_ref_copy();
468 if( pi_ != 0 ) pi_->release();
469 pi_ = tmp;
470 }
471
472 return *this;
473 }
474
475 void swap(shared_count & r) BOOST_SP_NOEXCEPTnoexcept
476 {
477 sp_counted_base * tmp = r.pi_;
478 r.pi_ = pi_;
479 pi_ = tmp;
480 }
481
482 long use_count() const BOOST_SP_NOEXCEPTnoexcept
483 {
484 return pi_ != 0? pi_->use_count(): 0;
485 }
486
487 bool unique() const BOOST_SP_NOEXCEPTnoexcept
488 {
489 return use_count() == 1;
490 }
491
492 bool empty() const BOOST_SP_NOEXCEPTnoexcept
493 {
494 return pi_ == 0;
495 }
496
497 bool operator==( shared_count const & r ) const BOOST_SP_NOEXCEPTnoexcept
498 {
499 return pi_ == r.pi_;
500 }
501
502 bool operator==( weak_count const & r ) const BOOST_SP_NOEXCEPTnoexcept;
503
504 bool operator<( shared_count const & r ) const BOOST_SP_NOEXCEPTnoexcept
505 {
506 return std::less<sp_counted_base *>()( pi_, r.pi_ );
507 }
508
509 bool operator<( weak_count const & r ) const BOOST_SP_NOEXCEPTnoexcept;
510
511 void * get_deleter( sp_typeinfo_ const & ti ) const BOOST_SP_NOEXCEPTnoexcept
512 {
513 return pi_? pi_->get_deleter( ti ): 0;
514 }
515
516 void * get_local_deleter( sp_typeinfo_ const & ti ) const BOOST_SP_NOEXCEPTnoexcept
517 {
518 return pi_? pi_->get_local_deleter( ti ): 0;
519 }
520
521 void * get_untyped_deleter() const BOOST_SP_NOEXCEPTnoexcept
522 {
523 return pi_? pi_->get_untyped_deleter(): 0;
524 }
525
526 std::size_t hash_value() const BOOST_SP_NOEXCEPTnoexcept
527 {
528 return sp_hash_pointer( pi_ );
529 }
530};
531
532
533class weak_count
534{
535private:
536
537 sp_counted_base * pi_;
538
539#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
540 int id_;
541#endif
542
543 friend class shared_count;
544
545public:
546
547 BOOST_CONSTEXPRconstexpr weak_count() BOOST_SP_NOEXCEPTnoexcept: pi_(0)
548#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
549 , id_(weak_count_id)
550#endif
551 {
552 }
553
554 weak_count(shared_count const & r) BOOST_SP_NOEXCEPTnoexcept: pi_(r.pi_)
555#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
556 , id_(weak_count_id)
557#endif
558 {
559 if(pi_ != 0) pi_->weak_add_ref();
560 }
561
562 weak_count(weak_count const & r) BOOST_SP_NOEXCEPTnoexcept: pi_(r.pi_)
563#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
564 , id_(weak_count_id)
565#endif
566 {
567 if(pi_ != 0) pi_->weak_add_ref();
568 }
569
570// Move support
571
572#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
573
574 weak_count(weak_count && r) BOOST_SP_NOEXCEPTnoexcept: pi_(r.pi_)
575#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
576 , id_(weak_count_id)
577#endif
578 {
579 r.pi_ = 0;
580 }
581
582#endif
583
584 ~weak_count() /*BOOST_SP_NOEXCEPT*/
585 {
586 if(pi_
22.1
Field 'pi_' is not equal to null
22.1
Field 'pi_' is not equal to null
22.1
Field 'pi_' is not equal to null
22.1
Field 'pi_' is not equal to null
22.1
Field 'pi_' is not equal to null
22.1
Field 'pi_' is not equal to null
22.1
Field 'pi_' is not equal to null
!= 0) pi_->weak_release();
23
Taking true branch
24
Calling 'sp_counted_base::weak_release'
30
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_ )
13
Assuming 'tmp' is equal to field 'pi_'
14
Taking false branch
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/enable_shared_from_this.hpp

1#ifndef BOOST_SMART_PTR_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
2#define BOOST_SMART_PTR_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
3
4//
5// enable_shared_from_this.hpp
6//
7// Copyright 2002, 2009 Peter Dimov
8//
9// Distributed under the Boost Software License, Version 1.0.
10// See accompanying file LICENSE_1_0.txt or copy at
11// http://www.boost.org/LICENSE_1_0.txt
12//
13// See http://www.boost.org/libs/smart_ptr/ for documentation.
14//
15
16#include <boost/smart_ptr/detail/requires_cxx11.hpp>
17#include <boost/smart_ptr/weak_ptr.hpp>
18#include <boost/smart_ptr/shared_ptr.hpp>
19#include <boost/smart_ptr/detail/sp_noexcept.hpp>
20#include <boost/assert.hpp>
21#include <boost/config.hpp>
22
23namespace boost
24{
25
26template<class T> class enable_shared_from_this
27{
28protected:
29
30 BOOST_CONSTEXPRconstexpr enable_shared_from_this() BOOST_SP_NOEXCEPTnoexcept
31 {
32 }
33
34 BOOST_CONSTEXPRconstexpr enable_shared_from_this(enable_shared_from_this const &) BOOST_SP_NOEXCEPTnoexcept
35 {
36 }
37
38 enable_shared_from_this & operator=(enable_shared_from_this const &) BOOST_SP_NOEXCEPTnoexcept
39 {
40 return *this;
41 }
42
43 ~enable_shared_from_this() BOOST_SP_NOEXCEPTnoexcept // ~weak_ptr<T> newer throws, so this call also must not throw
44 {
45 }
46
47public:
48
49 shared_ptr<T> shared_from_this()
50 {
51 shared_ptr<T> p( weak_this_ );
52 BOOST_ASSERT( p.get() == this )(static_cast <bool> (p.get() == this) ? void (0) : __assert_fail
("p.get() == this", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__))
;
53 return p;
54 }
55
56 shared_ptr<T const> shared_from_this() const
57 {
58 shared_ptr<T const> p( weak_this_ );
59 BOOST_ASSERT( p.get() == this )(static_cast <bool> (p.get() == this) ? void (0) : __assert_fail
("p.get() == this", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__))
;
60 return p;
61 }
62
63 weak_ptr<T> weak_from_this() BOOST_SP_NOEXCEPTnoexcept
64 {
65 return weak_this_;
66 }
67
68 weak_ptr<T const> weak_from_this() const BOOST_SP_NOEXCEPTnoexcept
69 {
70 return weak_this_;
71 }
72
73public: // actually private, but avoids compiler template friendship issues
74
75 // Note: invoked automatically by shared_ptr; do not call
76 template<class X, class Y> void _internal_accept_owner( shared_ptr<X> const * ppx, Y * py ) const BOOST_SP_NOEXCEPTnoexcept
77 {
78 if( weak_this_.expired() )
10
Taking true branch
79 {
80 weak_this_ = shared_ptr<T>( *ppx, py );
11
Calling 'weak_ptr::operator='
16
Returning from 'weak_ptr::operator='
81 }
82 }
83
84private:
85
86 mutable weak_ptr<T> weak_this_;
87};
88
89} // namespace boost
90
91#endif // #ifndef BOOST_SMART_PTR_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED

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

1#ifndef BOOST_SMART_PTR_WEAK_PTR_HPP_INCLUDED
2#define BOOST_SMART_PTR_WEAK_PTR_HPP_INCLUDED
3
4//
5// weak_ptr.hpp
6//
7// Copyright (c) 2001, 2002, 2003 Peter Dimov
8//
9// Distributed under the Boost Software License, Version 1.0. (See
10// accompanying file LICENSE_1_0.txt or copy at
11// http://www.boost.org/LICENSE_1_0.txt)
12//
13// See http://www.boost.org/libs/smart_ptr/ for documentation.
14//
15
16#include <boost/smart_ptr/detail/requires_cxx11.hpp>
17#include <boost/smart_ptr/detail/shared_count.hpp>
18#include <boost/smart_ptr/shared_ptr.hpp>
19#include <boost/smart_ptr/detail/sp_noexcept.hpp>
20#include <memory>
21#include <cstddef>
22
23namespace boost
24{
25
26template<class T> class weak_ptr
27{
28private:
29
30 // Borland 5.5.1 specific workarounds
31 typedef weak_ptr<T> this_type;
32
33public:
34
35 typedef typename boost::detail::sp_element< T >::type element_type;
36
37 BOOST_CONSTEXPRconstexpr weak_ptr() BOOST_SP_NOEXCEPTnoexcept : px(0), pn()
38 {
39 }
40
41// generated copy constructor, assignment, destructor are fine...
42
43#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
44
45// ... except in C++0x, move disables the implicit copy
46
47 weak_ptr( weak_ptr const & r ) BOOST_SP_NOEXCEPTnoexcept : px( r.px ), pn( r.pn )
48 {
49 }
50
51 weak_ptr & operator=( weak_ptr const & r ) BOOST_SP_NOEXCEPTnoexcept
52 {
53 px = r.px;
54 pn = r.pn;
55 return *this;
56 }
57
58#endif
59
60//
61// The "obvious" converting constructor implementation:
62//
63// template<class Y>
64// weak_ptr(weak_ptr<Y> const & r): px(r.px), pn(r.pn)
65// {
66// }
67//
68// has a serious problem.
69//
70// r.px may already have been invalidated. The px(r.px)
71// conversion may require access to *r.px (virtual inheritance).
72//
73// It is not possible to avoid spurious access violations since
74// in multithreaded programs r.px may be invalidated at any point.
75//
76
77 template<class Y>
78#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
79
80 weak_ptr( weak_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
81
82#else
83
84 weak_ptr( weak_ptr<Y> const & r )
85
86#endif
87 BOOST_SP_NOEXCEPTnoexcept : px(r.lock().get()), pn(r.pn)
88 {
89 boost::detail::sp_assert_convertible< Y, T >();
90 }
91
92#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
93
94 template<class Y>
95#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
96
97 weak_ptr( weak_ptr<Y> && r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
98
99#else
100
101 weak_ptr( weak_ptr<Y> && r )
102
103#endif
104 BOOST_SP_NOEXCEPTnoexcept : px( r.lock().get() ), pn( static_cast< boost::detail::weak_count && >( r.pn ) )
105 {
106 boost::detail::sp_assert_convertible< Y, T >();
107 r.px = 0;
108 }
109
110 // for better efficiency in the T == Y case
111 weak_ptr( weak_ptr && r )
112 BOOST_SP_NOEXCEPTnoexcept : px( r.px ), pn( static_cast< boost::detail::weak_count && >( r.pn ) )
113 {
114 r.px = 0;
115 }
116
117 // for better efficiency in the T == Y case
118 weak_ptr & operator=( weak_ptr && r ) BOOST_SP_NOEXCEPTnoexcept
119 {
120 this_type( static_cast< weak_ptr && >( r ) ).swap( *this );
121 return *this;
122 }
123
124
125#endif
126
127 template<class Y>
128#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
129
130 weak_ptr( shared_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
131
132#else
133
134 weak_ptr( shared_ptr<Y> const & r )
135
136#endif
137 BOOST_SP_NOEXCEPTnoexcept : px( r.px ), pn( r.pn )
138 {
139 boost::detail::sp_assert_convertible< Y, T >();
140 }
141
142 // aliasing
143 template<class Y> weak_ptr(shared_ptr<Y> const & r, element_type * p) BOOST_SP_NOEXCEPTnoexcept: px( p ), pn( r.pn )
144 {
145 }
146
147 template<class Y> weak_ptr(weak_ptr<Y> const & r, element_type * p) BOOST_SP_NOEXCEPTnoexcept: px( p ), pn( r.pn )
148 {
149 }
150
151#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
152
153 template<class Y> weak_ptr(weak_ptr<Y> && r, element_type * p) BOOST_SP_NOEXCEPTnoexcept: px( p ), pn( std::move( r.pn ) )
154 {
155 }
156
157#endif
158
159#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300)
160
161 template<class Y>
162 weak_ptr & operator=( weak_ptr<Y> const & r ) BOOST_SP_NOEXCEPTnoexcept
163 {
164 boost::detail::sp_assert_convertible< Y, T >();
165
166 px = r.lock().get();
167 pn = r.pn;
168
169 return *this;
170 }
171
172#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
173
174 template<class Y>
175 weak_ptr & operator=( weak_ptr<Y> && r ) BOOST_SP_NOEXCEPTnoexcept
176 {
177 this_type( static_cast< weak_ptr<Y> && >( r ) ).swap( *this );
178 return *this;
179 }
180
181#endif
182
183 template<class Y>
184 weak_ptr & operator=( shared_ptr<Y> const & r ) BOOST_SP_NOEXCEPTnoexcept
185 {
186 boost::detail::sp_assert_convertible< Y, T >();
187
188 px = r.px;
189 pn = r.pn;
12
Calling 'weak_count::operator='
15
Returning from 'weak_count::operator='
190
191 return *this;
192 }
193
194#endif
195
196 shared_ptr<T> lock() const BOOST_SP_NOEXCEPTnoexcept
197 {
198 return shared_ptr<T>( *this, boost::detail::sp_nothrow_tag() );
199 }
200
201 long use_count() const BOOST_SP_NOEXCEPTnoexcept
202 {
203 return pn.use_count();
204 }
205
206 bool expired() const BOOST_SP_NOEXCEPTnoexcept
207 {
208 return pn.use_count() == 0;
209 }
210
211 bool _empty() const BOOST_SP_NOEXCEPTnoexcept // extension, not in std::weak_ptr
212 {
213 return pn.empty();
214 }
215
216 bool empty() const BOOST_SP_NOEXCEPTnoexcept // extension, not in std::weak_ptr
217 {
218 return pn.empty();
219 }
220
221 void reset() BOOST_SP_NOEXCEPTnoexcept
222 {
223 this_type().swap(*this);
224 }
225
226 void swap(this_type & other) BOOST_SP_NOEXCEPTnoexcept
227 {
228 std::swap(px, other.px);
229 pn.swap(other.pn);
230 }
231
232 template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPTnoexcept
233 {
234 return pn < rhs.pn;
235 }
236
237 template<class Y> bool owner_before( shared_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPTnoexcept
238 {
239 return pn < rhs.pn;
240 }
241
242 template<class Y> bool owner_equals( weak_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPTnoexcept
243 {
244 return pn == rhs.pn;
245 }
246
247 template<class Y> bool owner_equals( shared_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPTnoexcept
248 {
249 return pn == rhs.pn;
250 }
251
252 std::size_t owner_hash_value() const BOOST_SP_NOEXCEPTnoexcept
253 {
254 return pn.hash_value();
255 }
256
257// Tasteless as this may seem, making all members public allows member templates
258// to work in the absence of member template friends. (Matthew Langston)
259
260#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
261
262private:
263
264 template<class Y> friend class weak_ptr;
265 template<class Y> friend class shared_ptr;
266
267#endif
268
269 element_type * px; // contained pointer
270 boost::detail::weak_count pn; // reference counter
271
272}; // weak_ptr
273
274template<class T, class U> inline bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b) BOOST_SP_NOEXCEPTnoexcept
275{
276 return a.owner_before( b );
277}
278
279template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b) BOOST_SP_NOEXCEPTnoexcept
280{
281 a.swap(b);
282}
283
284#if defined(__cpp_deduction_guides201703L)
285
286template<class T> weak_ptr( shared_ptr<T> ) -> weak_ptr<T>;
287
288#endif
289
290// hash_value
291
292template< class T > std::size_t hash_value( boost::weak_ptr<T> const & p ) BOOST_SP_NOEXCEPTnoexcept
293{
294 return p.owner_hash_value();
295}
296
297} // namespace boost
298
299// std::hash, std::equal_to
300
301namespace std
302{
303
304#if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
305
306template<class T> struct hash< ::boost::weak_ptr<T> >
307{
308 std::size_t operator()( ::boost::weak_ptr<T> const & p ) const BOOST_SP_NOEXCEPTnoexcept
309 {
310 return p.owner_hash_value();
311 }
312};
313
314#endif // #if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
315
316template<class T> struct equal_to< ::boost::weak_ptr<T> >
317{
318 bool operator()( ::boost::weak_ptr<T> const & a, ::boost::weak_ptr<T> const & b ) const BOOST_SP_NOEXCEPTnoexcept
319 {
320 return a.owner_equals( b );
321 }
322};
323
324} // namespace std
325
326#endif // #ifndef BOOST_SMART_PTR_WEAK_PTR_HPP_INCLUDED

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

1#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_ATOMIC_HPP_INCLUDED
2#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_ATOMIC_HPP_INCLUDED
3
4// MS compatible compilers support #pragma once
5
6#if defined(_MSC_VER) && (_MSC_VER >= 1020)
7# pragma once
8#endif
9
10// detail/sp_counted_base_gcc_atomic.hpp - g++ 4.7+ __atomic intrinsics
11//
12// Copyright 2007, 2020 Peter Dimov
13// Distributed under the Boost Software License, Version 1.0.
14// https://www.boost.org/LICENSE_1_0.txt
15
16#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
17#include <boost/config.hpp>
18#include <boost/cstdint.hpp>
19
20#if defined(BOOST_SP_REPORT_IMPLEMENTATION)
21
22#include <boost/config/pragma_message.hpp>
23BOOST_PRAGMA_MESSAGE("Using __atomic sp_counted_base")message("Using __atomic sp_counted_base")
24
25#endif
26
27namespace boost
28{
29
30namespace detail
31{
32
33inline void atomic_increment( boost::uint_least32_t * pw )
34{
35 __atomic_fetch_add( pw, 1, __ATOMIC_RELAXED0 );
36}
37
38inline boost::uint_least32_t atomic_decrement( boost::uint_least32_t * pw )
39{
40 return __atomic_fetch_sub( pw, 1, __ATOMIC_ACQ_REL4 );
41}
42
43inline boost::uint_least32_t atomic_conditional_increment( boost::uint_least32_t * pw )
44{
45 // long r = *pw;
46 // if( r != 0 ) ++*pw;
47 // return r;
48
49 boost::uint_least32_t r = __atomic_load_n( pw, __ATOMIC_RELAXED0 );
50
51 for( ;; )
52 {
53 if( r == 0 )
54 {
55 return r;
56 }
57
58 if( __atomic_compare_exchange_n( pw, &r, r + 1, true, __ATOMIC_RELAXED0, __ATOMIC_RELAXED0 ) )
59 {
60 return r;
61 }
62 }
63}
64
65inline boost::uint_least32_t atomic_load( boost::uint_least32_t const * pw )
66{
67 return __atomic_load_n( pw, __ATOMIC_ACQUIRE2 );
68}
69
70class BOOST_SYMBOL_VISIBLE__attribute__((__visibility__("default"))) sp_counted_base
71{
72private:
73
74 sp_counted_base( sp_counted_base const & );
75 sp_counted_base & operator= ( sp_counted_base const & );
76
77 boost::uint_least32_t use_count_; // #shared
78 boost::uint_least32_t weak_count_; // #weak + (#shared != 0)
79
80public:
81
82 sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
83 {
84 }
85
86 virtual ~sp_counted_base() // nothrow
87 {
88 }
89
90 // dispose() is called when use_count_ drops to zero, to release
91 // the resources managed by *this.
92
93 virtual void dispose() = 0; // nothrow
94
95 // destroy() is called when weak_count_ drops to zero.
96
97 virtual void destroy() // nothrow
98 {
99 delete this;
28
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 )
25
Assuming the condition is true
26
Taking true branch
133 {
134 destroy();
27
Calling 'sp_counted_base::destroy'
29
Returning; memory was released
135 }
136 }
137
138 long use_count() const // nothrow
139 {
140 return static_cast<long>( atomic_load( &use_count_ ) );
141 }
142};
143
144} // namespace detail
145
146} // namespace boost
147
148#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED