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