100.00% Lines (68/68)
100.00% Functions (20/20)
| TLA | Baseline | Branch | ||||||
|---|---|---|---|---|---|---|---|---|
| Line | Hits | Code | Line | Hits | Code | |||
| 1 | // | 1 | // | |||||
| 2 | // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) | 2 | // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) | |||||
| 3 | // | 3 | // | |||||
| 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |||||
| 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |||||
| 6 | // | 6 | // | |||||
| 7 | // Official repository: https://github.com/boostorg/json | 7 | // Official repository: https://github.com/boostorg/json | |||||
| 8 | // | 8 | // | |||||
| 9 | 9 | |||||||
| 10 | #ifndef BOOST_JSON_STORAGE_PTR_HPP | 10 | #ifndef BOOST_JSON_STORAGE_PTR_HPP | |||||
| 11 | #define BOOST_JSON_STORAGE_PTR_HPP | 11 | #define BOOST_JSON_STORAGE_PTR_HPP | |||||
| 12 | 12 | |||||||
| 13 | #include <boost/core/detail/static_assert.hpp> | 13 | #include <boost/core/detail/static_assert.hpp> | |||||
| 14 | #include <boost/container/pmr/polymorphic_allocator.hpp> | 14 | #include <boost/container/pmr/polymorphic_allocator.hpp> | |||||
| 15 | #include <boost/json/detail/config.hpp> | 15 | #include <boost/json/detail/config.hpp> | |||||
| 16 | #include <boost/json/detail/shared_resource.hpp> | 16 | #include <boost/json/detail/shared_resource.hpp> | |||||
| 17 | #include <boost/json/detail/default_resource.hpp> | 17 | #include <boost/json/detail/default_resource.hpp> | |||||
| 18 | #include <boost/json/is_deallocate_trivial.hpp> | 18 | #include <boost/json/is_deallocate_trivial.hpp> | |||||
| 19 | #include <new> | 19 | #include <new> | |||||
| 20 | #include <type_traits> | 20 | #include <type_traits> | |||||
| 21 | #include <utility> | 21 | #include <utility> | |||||
| 22 | 22 | |||||||
| 23 | namespace boost { | 23 | namespace boost { | |||||
| 24 | namespace json { | 24 | namespace json { | |||||
| 25 | 25 | |||||||
| 26 | /** A smart pointer to a memory resource. | 26 | /** A smart pointer to a memory resource. | |||||
| 27 | 27 | |||||||
| 28 | This class is used to hold a pointer to a memory resource. The pointed-to | 28 | This class is used to hold a pointer to a memory resource. The pointed-to | |||||
| 29 | resource is always valid. Depending on the means of construction, the | 29 | resource is always valid. Depending on the means of construction, the | |||||
| 30 | ownership will be either: | 30 | ownership will be either: | |||||
| 31 | 31 | |||||||
| 32 | @li Non-owning, when constructing from a raw pointer to | 32 | @li Non-owning, when constructing from a raw pointer to | |||||
| 33 | @ref boost::container::pmr::memory_resource or from a | 33 | @ref boost::container::pmr::memory_resource or from a | |||||
| 34 | @ref boost::container::pmr::polymorphic_allocator. In this case the caller | 34 | @ref boost::container::pmr::polymorphic_allocator. In this case the caller | |||||
| 35 | is responsible for ensuring that the lifetime of the memory resource | 35 | is responsible for ensuring that the lifetime of the memory resource | |||||
| 36 | extends until there are no more calls to allocate or deallocate. | 36 | extends until there are no more calls to allocate or deallocate. | |||||
| 37 | 37 | |||||||
| 38 | @li Owning, when constructing using the function @ref make_shared_resource. | 38 | @li Owning, when constructing using the function @ref make_shared_resource. | |||||
| 39 | In this case ownership is shared; the lifetime of the memory resource | 39 | In this case ownership is shared; the lifetime of the memory resource | |||||
| 40 | extends until the last copy of the `storage_ptr` is destroyed. | 40 | extends until the last copy of the `storage_ptr` is destroyed. | |||||
| 41 | 41 | |||||||
| 42 | @par Examples | 42 | @par Examples | |||||
| 43 | These statements create a memory resource on the stack and construct | 43 | These statements create a memory resource on the stack and construct | |||||
| 44 | a pointer from it without taking ownership: | 44 | a pointer from it without taking ownership: | |||||
| 45 | 45 | |||||||
| 46 | @code | 46 | @code | |||||
| 47 | monotonic_resource mr; // Create our memory resource on the stack | 47 | monotonic_resource mr; // Create our memory resource on the stack | |||||
| 48 | storage_ptr sp( &mr ); // Construct a non-owning pointer to the resource | 48 | storage_ptr sp( &mr ); // Construct a non-owning pointer to the resource | |||||
| 49 | @endcode | 49 | @endcode | |||||
| 50 | 50 | |||||||
| 51 | This function creates a pointer to a memory resource using shared ownership | 51 | This function creates a pointer to a memory resource using shared ownership | |||||
| 52 | and returns it. The lifetime of the memory resource extends until the last | 52 | and returns it. The lifetime of the memory resource extends until the last | |||||
| 53 | copy of the pointer is destroyed: | 53 | copy of the pointer is destroyed: | |||||
| 54 | 54 | |||||||
| 55 | @code | 55 | @code | |||||
| 56 | // Create a counted memory resource and return it | 56 | // Create a counted memory resource and return it | |||||
| 57 | storage_ptr make_storage() | 57 | storage_ptr make_storage() | |||||
| 58 | { | 58 | { | |||||
| 59 | return make_shared_resource< monotonic_resource >(); | 59 | return make_shared_resource< monotonic_resource >(); | |||||
| 60 | } | 60 | } | |||||
| 61 | @endcode | 61 | @endcode | |||||
| 62 | 62 | |||||||
| 63 | @par Thread Safety | 63 | @par Thread Safety | |||||
| 64 | Instances of this type provide the default level of thread safety for all | 64 | Instances of this type provide the default level of thread safety for all | |||||
| 65 | C++ objects. Specifically, it conforms to | 65 | C++ objects. Specifically, it conforms to | |||||
| 66 | [16.4.6.10 Data race avoidance](http://eel.is/c++draft/res.on.data.races). | 66 | [16.4.6.10 Data race avoidance](http://eel.is/c++draft/res.on.data.races). | |||||
| 67 | 67 | |||||||
| 68 | @see | 68 | @see | |||||
| 69 | @ref make_shared_resource, | 69 | @ref make_shared_resource, | |||||
| 70 | @ref boost::container::pmr::polymorphic_allocator, | 70 | @ref boost::container::pmr::polymorphic_allocator, | |||||
| 71 | @ref boost::container::pmr::memory_resource. | 71 | @ref boost::container::pmr::memory_resource. | |||||
| 72 | 72 | |||||||
| 73 | */ | 73 | */ | |||||
| 74 | class storage_ptr | 74 | class storage_ptr | |||||
| 75 | { | 75 | { | |||||
| 76 | #ifndef BOOST_JSON_DOCS | 76 | #ifndef BOOST_JSON_DOCS | |||||
| 77 | // VFALCO doc toolchain shows this when it shouldn't | 77 | // VFALCO doc toolchain shows this when it shouldn't | |||||
| 78 | friend struct detail::shared_resource; | 78 | friend struct detail::shared_resource; | |||||
| 79 | #endif | 79 | #endif | |||||
| 80 | using shared_resource = | 80 | using shared_resource = | |||||
| 81 | detail::shared_resource; | 81 | detail::shared_resource; | |||||
| 82 | 82 | |||||||
| 83 | using default_resource = | 83 | using default_resource = | |||||
| 84 | detail::default_resource; | 84 | detail::default_resource; | |||||
| 85 | 85 | |||||||
| 86 | std::uintptr_t i_; | 86 | std::uintptr_t i_; | |||||
| 87 | 87 | |||||||
| 88 | shared_resource* | 88 | shared_resource* | |||||
| HITCBC | 89 | 302 | get_shared() const noexcept | 89 | 302 | get_shared() const noexcept | ||
| 90 | { | 90 | { | |||||
| 91 | return static_cast<shared_resource*>( | 91 | return static_cast<shared_resource*>( | |||||
| 92 | reinterpret_cast<container::pmr::memory_resource*>( | 92 | reinterpret_cast<container::pmr::memory_resource*>( | |||||
| HITCBC | 93 | 302 | i_ & ~3)); | 93 | 302 | i_ & ~3)); | ||
| 94 | } | 94 | } | |||||
| 95 | 95 | |||||||
| 96 | void | 96 | void | |||||
| HITCBC | 97 | 6352730 | addref() const noexcept | 97 | 6352730 | addref() const noexcept | ||
| 98 | { | 98 | { | |||||
| HITCBC | 99 | 6352730 | if(is_shared()) | 99 | 6352730 | if(is_shared()) | ||
| HITCBC | 100 | 141 | get_shared()->refs.fetch_add( | 100 | 141 | get_shared()->refs.fetch_add( | ||
| 101 | 1, std::memory_order_relaxed); | 101 | 1, std::memory_order_relaxed); | |||||
| HITCBC | 102 | 6352730 | } | 102 | 6352730 | } | ||
| 103 | 103 | |||||||
| 104 | void | 104 | void | |||||
| HITCBC | 105 | 43990763 | release() const noexcept | 105 | 43990763 | release() const noexcept | ||
| 106 | { | 106 | { | |||||
| HITCBC | 107 | 43990763 | if(is_shared()) | 107 | 43990763 | if(is_shared()) | ||
| 108 | { | 108 | { | |||||
| HITCBC | 109 | 161 | auto const p = get_shared(); | 109 | 161 | auto const p = get_shared(); | ||
| HITCBC | 110 | 161 | if(p->refs.fetch_sub(1, | 110 | 161 | if(p->refs.fetch_sub(1, | ||
| HITCBC | 111 | 161 | std::memory_order_acq_rel) == 1) | 111 | 161 | std::memory_order_acq_rel) == 1) | ||
| HITCBC | 112 | 20 | delete p; | 112 | 20 | delete p; | ||
| 113 | } | 113 | } | |||||
| HITCBC | 114 | 43990763 | } | 114 | 43990763 | } | ||
| 115 | 115 | |||||||
| 116 | template<class T> | 116 | template<class T> | |||||
| HITCBC | 117 | 20 | storage_ptr( | 117 | 20 | storage_ptr( | ||
| 118 | detail::shared_resource_impl<T>* p) noexcept | 118 | detail::shared_resource_impl<T>* p) noexcept | |||||
| HITCBC | 119 | 20 | : i_(reinterpret_cast<std::uintptr_t>( | 119 | 20 | : i_(reinterpret_cast<std::uintptr_t>( | ||
| HITCBC | 120 | 20 | static_cast<container::pmr::memory_resource*>(p)) + 1 + | 120 | 20 | static_cast<container::pmr::memory_resource*>(p)) + 1 + | ||
| 121 | (json::is_deallocate_trivial<T>::value ? 2 : 0)) | 121 | (json::is_deallocate_trivial<T>::value ? 2 : 0)) | |||||
| 122 | { | 122 | { | |||||
| HITCBC | 123 | 20 | BOOST_ASSERT(p); | 123 | 20 | BOOST_ASSERT(p); | ||
| HITCBC | 124 | 20 | } | 124 | 20 | } | ||
| 125 | 125 | |||||||
| 126 | public: | 126 | public: | |||||
| 127 | /** Destructor. | 127 | /** Destructor. | |||||
| 128 | 128 | |||||||
| 129 | If the pointer has shared ownership of the resource, the shared | 129 | If the pointer has shared ownership of the resource, the shared | |||||
| 130 | ownership is released. If this is the last owned copy, the memory | 130 | ownership is released. If this is the last owned copy, the memory | |||||
| 131 | resource is destroyed. | 131 | resource is destroyed. | |||||
| 132 | 132 | |||||||
| 133 | @par Complexity | 133 | @par Complexity | |||||
| 134 | Constant. | 134 | Constant. | |||||
| 135 | 135 | |||||||
| 136 | @par Exception Safety | 136 | @par Exception Safety | |||||
| 137 | No-throw guarantee. | 137 | No-throw guarantee. | |||||
| 138 | */ | 138 | */ | |||||
| HITCBC | 139 | 41914113 | ~storage_ptr() noexcept | 139 | 41914113 | ~storage_ptr() noexcept | ||
| 140 | { | 140 | { | |||||
| HITCBC | 141 | 41914113 | release(); | 141 | 41914113 | release(); | ||
| HITCBC | 142 | 41914113 | } | 142 | 41914113 | } | ||
| 143 | 143 | |||||||
| 144 | /** Constructors. | 144 | /** Constructors. | |||||
| 145 | 145 | |||||||
| 146 | @li **(1)** constructs a non-owning pointer that refers to the | 146 | @li **(1)** constructs a non-owning pointer that refers to the | |||||
| 147 | \<\<default_memory_resource,default memory resource\>\>. | 147 | \<\<default_memory_resource,default memory resource\>\>. | |||||
| 148 | 148 | |||||||
| 149 | @li **(2)** constructs a non-owning pointer that points to the memory | 149 | @li **(2)** constructs a non-owning pointer that points to the memory | |||||
| 150 | resource `r`. | 150 | resource `r`. | |||||
| 151 | 151 | |||||||
| 152 | @li **(3)** constructs a non-owning pointer that points to the same | 152 | @li **(3)** constructs a non-owning pointer that points to the same | |||||
| 153 | memory resource as `alloc`, obtained by calling `alloc.resource()`. | 153 | memory resource as `alloc`, obtained by calling `alloc.resource()`. | |||||
| 154 | 154 | |||||||
| 155 | @li **(4)**, **(5)** construct a pointer to the same memory resource as | 155 | @li **(4)**, **(5)** construct a pointer to the same memory resource as | |||||
| 156 | `other`, with the same ownership. | 156 | `other`, with the same ownership. | |||||
| 157 | 157 | |||||||
| 158 | After **(4)** and **(5)** if `other` was owning, then the constructed | 158 | After **(4)** and **(5)** if `other` was owning, then the constructed | |||||
| 159 | pointer is also owning. In particular, **(4)** transfers ownership to | 159 | pointer is also owning. In particular, **(4)** transfers ownership to | |||||
| 160 | the constructed pointer while **(5)** causes it to share ownership with | 160 | the constructed pointer while **(5)** causes it to share ownership with | |||||
| 161 | `other`. Otherwise, and with other overloads the constructed pointer | 161 | `other`. Otherwise, and with other overloads the constructed pointer | |||||
| 162 | doesn't own its memory resource and the caller is responsible for | 162 | doesn't own its memory resource and the caller is responsible for | |||||
| 163 | maintaining the lifetime of the pointed-to | 163 | maintaining the lifetime of the pointed-to | |||||
| 164 | @ref boost::container::pmr::memory_resource. | 164 | @ref boost::container::pmr::memory_resource. | |||||
| 165 | 165 | |||||||
| 166 | After **(4)**, `other` will point to the default memory resource. | 166 | After **(4)**, `other` will point to the default memory resource. | |||||
| 167 | 167 | |||||||
| 168 | @par Constraints | 168 | @par Constraints | |||||
| 169 | @code | 169 | @code | |||||
| 170 | std::is_convertible< T*, boost::container::pmr::memory_resource* >::value == true | 170 | std::is_convertible< T*, boost::container::pmr::memory_resource* >::value == true | |||||
| 171 | @endcode | 171 | @endcode | |||||
| 172 | 172 | |||||||
| 173 | @pre | 173 | @pre | |||||
| 174 | @code | 174 | @code | |||||
| 175 | r != nullptr | 175 | r != nullptr | |||||
| 176 | @endcode | 176 | @endcode | |||||
| 177 | 177 | |||||||
| 178 | @par Complexity | 178 | @par Complexity | |||||
| 179 | Constant. | 179 | Constant. | |||||
| 180 | 180 | |||||||
| 181 | @par Exception Safety | 181 | @par Exception Safety | |||||
| 182 | No-throw guarantee. | 182 | No-throw guarantee. | |||||
| 183 | 183 | |||||||
| 184 | @{ | 184 | @{ | |||||
| 185 | */ | 185 | */ | |||||
| HITCBC | 186 | 14653478 | storage_ptr() noexcept | 186 | 14653478 | storage_ptr() noexcept | ||
| HITCBC | 187 | 14653478 | : i_(0) | 187 | 14653478 | : i_(0) | ||
| 188 | { | 188 | { | |||||
| HITCBC | 189 | 14653478 | } | 189 | 14653478 | } | ||
| 190 | 190 | |||||||
| 191 | /** Overload | 191 | /** Overload | |||||
| 192 | 192 | |||||||
| 193 | @tparam T The type of memory resource. | 193 | @tparam T The type of memory resource. | |||||
| 194 | @param r A non-null pointer to the memory resource to use. | 194 | @param r A non-null pointer to the memory resource to use. | |||||
| 195 | */ | 195 | */ | |||||
| 196 | template<class T | 196 | template<class T | |||||
| 197 | #ifndef BOOST_JSON_DOCS | 197 | #ifndef BOOST_JSON_DOCS | |||||
| 198 | , class = typename std::enable_if< | 198 | , class = typename std::enable_if< | |||||
| 199 | std::is_convertible<T*, | 199 | std::is_convertible<T*, | |||||
| 200 | container::pmr::memory_resource*>::value>::type | 200 | container::pmr::memory_resource*>::value>::type | |||||
| 201 | #endif | 201 | #endif | |||||
| 202 | > | 202 | > | |||||
| HITCBC | 203 | 57222 | storage_ptr(T* r) noexcept | 203 | 57222 | storage_ptr(T* r) noexcept | ||
| HITCBC | 204 | 57222 | : i_(reinterpret_cast<std::uintptr_t>( | 204 | 57222 | : i_(reinterpret_cast<std::uintptr_t>( | ||
| HITCBC | 205 | 18 | static_cast<container::pmr::memory_resource *>(r)) + | 205 | 18 | static_cast<container::pmr::memory_resource *>(r)) + | ||
| 206 | (json::is_deallocate_trivial<T>::value ? 2 : 0)) | 206 | (json::is_deallocate_trivial<T>::value ? 2 : 0)) | |||||
| 207 | { | 207 | { | |||||
| HITCBC | 208 | 57222 | BOOST_ASSERT(r); | 208 | 57222 | BOOST_ASSERT(r); | ||
| HITCBC | 209 | 57222 | } | 209 | 57222 | } | ||
| 210 | 210 | |||||||
| 211 | /** Overload | 211 | /** Overload | |||||
| 212 | 212 | |||||||
| 213 | @tparam V Any type. | 213 | @tparam V Any type. | |||||
| 214 | @param alloc A @ref boost::container::pmr::polymorphic_allocator to | 214 | @param alloc A @ref boost::container::pmr::polymorphic_allocator to | |||||
| 215 | construct from. | 215 | construct from. | |||||
| 216 | */ | 216 | */ | |||||
| 217 | template<class V> | 217 | template<class V> | |||||
| HITCBC | 218 | 10 | storage_ptr( | 218 | 10 | storage_ptr( | ||
| 219 | container::pmr::polymorphic_allocator<V> const& alloc) noexcept | 219 | container::pmr::polymorphic_allocator<V> const& alloc) noexcept | |||||
| HITCBC | 220 | 10 | : i_(reinterpret_cast<std::uintptr_t>( | 220 | 10 | : i_(reinterpret_cast<std::uintptr_t>( | ||
| HITCBC | 221 | 10 | alloc.resource())) | 221 | 10 | alloc.resource())) | ||
| 222 | { | 222 | { | |||||
| HITCBC | 223 | 10 | } | 223 | 10 | } | ||
| 224 | 224 | |||||||
| 225 | /** Overload | 225 | /** Overload | |||||
| 226 | 226 | |||||||
| 227 | @param other Another pointer. | 227 | @param other Another pointer. | |||||
| 228 | */ | 228 | */ | |||||
| HITCBC | 229 | 22965882 | storage_ptr( | 229 | 22965882 | storage_ptr( | ||
| 230 | storage_ptr&& other) noexcept | 230 | storage_ptr&& other) noexcept | |||||
| HITCBC | 231 | 22965882 | : i_(detail::exchange(other.i_, 0)) | 231 | 22965882 | : i_(detail::exchange(other.i_, 0)) | ||
| 232 | { | 232 | { | |||||
| HITCBC | 233 | 22965882 | } | 233 | 22965882 | } | ||
| 234 | 234 | |||||||
| 235 | /** Overload | 235 | /** Overload | |||||
| 236 | 236 | |||||||
| 237 | @param other | 237 | @param other | |||||
| 238 | */ | 238 | */ | |||||
| HITCBC | 239 | 6352729 | storage_ptr( | 239 | 6352729 | storage_ptr( | ||
| 240 | storage_ptr const& other) noexcept | 240 | storage_ptr const& other) noexcept | |||||
| HITCBC | 241 | 6352729 | : i_(other.i_) | 241 | 6352729 | : i_(other.i_) | ||
| 242 | { | 242 | { | |||||
| HITCBC | 243 | 6352729 | addref(); | 243 | 6352729 | addref(); | ||
| HITCBC | 244 | 6352729 | } | 244 | 6352729 | } | ||
| 245 | /// @} | 245 | /// @} | |||||
| 246 | 246 | |||||||
| 247 | /** Assignment operators. | 247 | /** Assignment operators. | |||||
| 248 | 248 | |||||||
| 249 | This function assigns a pointer that points to the same memory resource | 249 | This function assigns a pointer that points to the same memory resource | |||||
| 250 | as `other`, with the same ownership: | 250 | as `other`, with the same ownership: | |||||
| 251 | 251 | |||||||
| 252 | @li If `other` is non-owning, then the assigned-to pointer will be be | 252 | @li If `other` is non-owning, then the assigned-to pointer will be be | |||||
| 253 | non-owning. | 253 | non-owning. | |||||
| 254 | 254 | |||||||
| 255 | @li If `other` has shared ownership, then **(1)** transfers ownership | 255 | @li If `other` has shared ownership, then **(1)** transfers ownership | |||||
| 256 | to the assigned-to pointer, while after **(2)** it shares the ownership | 256 | to the assigned-to pointer, while after **(2)** it shares the ownership | |||||
| 257 | with `other`. | 257 | with `other`. | |||||
| 258 | 258 | |||||||
| 259 | If the assigned-to pointer previously had shared ownership, it is | 259 | If the assigned-to pointer previously had shared ownership, it is | |||||
| 260 | released before the function returns. | 260 | released before the function returns. | |||||
| 261 | 261 | |||||||
| 262 | After **(1)**, `other` will point to the | 262 | After **(1)**, `other` will point to the | |||||
| 263 | \<\<default_memory_resource,default memory resource\>\>. | 263 | \<\<default_memory_resource,default memory resource\>\>. | |||||
| 264 | 264 | |||||||
| 265 | @par Complexity | 265 | @par Complexity | |||||
| 266 | Constant. | 266 | Constant. | |||||
| 267 | 267 | |||||||
| 268 | @par Exception Safety | 268 | @par Exception Safety | |||||
| 269 | No-throw guarantee. | 269 | No-throw guarantee. | |||||
| 270 | 270 | |||||||
| 271 | @param other Another pointer. | 271 | @param other Another pointer. | |||||
| 272 | 272 | |||||||
| 273 | @{ | 273 | @{ | |||||
| 274 | */ | 274 | */ | |||||
| 275 | storage_ptr& | 275 | storage_ptr& | |||||
| HITCBC | 276 | 2076649 | operator=( | 276 | 2076649 | operator=( | ||
| 277 | storage_ptr&& other) noexcept | 277 | storage_ptr&& other) noexcept | |||||
| 278 | { | 278 | { | |||||
| HITCBC | 279 | 2076649 | release(); | 279 | 2076649 | release(); | ||
| HITCBC | 280 | 2076649 | i_ = detail::exchange(other.i_, 0); | 280 | 2076649 | i_ = detail::exchange(other.i_, 0); | ||
| HITCBC | 281 | 2076649 | return *this; | 281 | 2076649 | return *this; | ||
| 282 | } | 282 | } | |||||
| 283 | 283 | |||||||
| 284 | storage_ptr& | 284 | storage_ptr& | |||||
| HITCBC | 285 | 1 | operator=( | 285 | 1 | operator=( | ||
| 286 | storage_ptr const& other) noexcept | 286 | storage_ptr const& other) noexcept | |||||
| 287 | { | 287 | { | |||||
| HITCBC | 288 | 1 | other.addref(); | 288 | 1 | other.addref(); | ||
| HITCBC | 289 | 1 | release(); | 289 | 1 | release(); | ||
| HITCBC | 290 | 1 | i_ = other.i_; | 290 | 1 | i_ = other.i_; | ||
| HITCBC | 291 | 1 | return *this; | 291 | 1 | return *this; | ||
| 292 | } | 292 | } | |||||
| 293 | /// @} | 293 | /// @} | |||||
| 294 | 294 | |||||||
| 295 | /** Check if ownership of the memory resource is shared. | 295 | /** Check if ownership of the memory resource is shared. | |||||
| 296 | 296 | |||||||
| 297 | This function returns true for memory resources created using @ref | 297 | This function returns true for memory resources created using @ref | |||||
| 298 | make_shared_resource. | 298 | make_shared_resource. | |||||
| 299 | */ | 299 | */ | |||||
| 300 | bool | 300 | bool | |||||
| HITCBC | 301 | 50343494 | is_shared() const noexcept | 301 | 50343494 | is_shared() const noexcept | ||
| 302 | { | 302 | { | |||||
| HITCBC | 303 | 50343494 | return (i_ & 1) != 0; | 303 | 50343494 | return (i_ & 1) != 0; | ||
| 304 | } | 304 | } | |||||
| 305 | 305 | |||||||
| 306 | /** Check if calling `deallocate` on the memory resource has no effect. | 306 | /** Check if calling `deallocate` on the memory resource has no effect. | |||||
| 307 | 307 | |||||||
| 308 | This function is used to determine if the deallocate function of the | 308 | This function is used to determine if the deallocate function of the | |||||
| 309 | pointed to memory resource is trivial. The value of @ref | 309 | pointed to memory resource is trivial. The value of @ref | |||||
| 310 | is_deallocate_trivial is evaluated and saved when the memory resource | 310 | is_deallocate_trivial is evaluated and saved when the memory resource | |||||
| 311 | is constructed and the type is known, before the type is erased. | 311 | is constructed and the type is known, before the type is erased. | |||||
| 312 | */ | 312 | */ | |||||
| 313 | bool | 313 | bool | |||||
| HITCBC | 314 | 1 | is_deallocate_trivial() const noexcept | 314 | 1 | is_deallocate_trivial() const noexcept | ||
| 315 | { | 315 | { | |||||
| HITCBC | 316 | 1 | return (i_ & 2) != 0; | 316 | 1 | return (i_ & 2) != 0; | ||
| 317 | } | 317 | } | |||||
| 318 | 318 | |||||||
| 319 | /** Check if ownership of the memory resource is not shared and deallocate is trivial. | 319 | /** Check if ownership of the memory resource is not shared and deallocate is trivial. | |||||
| 320 | 320 | |||||||
| 321 | This function is used to determine if calls to deallocate can | 321 | This function is used to determine if calls to deallocate can | |||||
| 322 | effectively be skipped. Equivalent to `! is_shared() && | 322 | effectively be skipped. Equivalent to `! is_shared() && | |||||
| 323 | is_deallocate_trivial()`. | 323 | is_deallocate_trivial()`. | |||||
| 324 | */ | 324 | */ | |||||
| 325 | bool | 325 | bool | |||||
| HITCBC | 326 | 4323577 | is_not_shared_and_deallocate_is_trivial() const noexcept | 326 | 4323577 | is_not_shared_and_deallocate_is_trivial() const noexcept | ||
| 327 | { | 327 | { | |||||
| HITCBC | 328 | 4323577 | return (i_ & 3) == 2; | 328 | 4323577 | return (i_ & 3) == 2; | ||
| 329 | } | 329 | } | |||||
| 330 | 330 | |||||||
| 331 | /** Return a pointer to the memory resource. | 331 | /** Return a pointer to the memory resource. | |||||
| 332 | 332 | |||||||
| 333 | This function returns a pointer to the | 333 | This function returns a pointer to the | |||||
| 334 | referenced @ref boost::container::pmr::memory_resource. | 334 | referenced @ref boost::container::pmr::memory_resource. | |||||
| 335 | 335 | |||||||
| 336 | @par Complexity | 336 | @par Complexity | |||||
| 337 | Constant. | 337 | Constant. | |||||
| 338 | 338 | |||||||
| 339 | @par Exception Safety | 339 | @par Exception Safety | |||||
| 340 | No-throw guarantee. | 340 | No-throw guarantee. | |||||
| 341 | */ | 341 | */ | |||||
| 342 | container::pmr::memory_resource* | 342 | container::pmr::memory_resource* | |||||
| HITCBC | 343 | 653431 | get() const noexcept | 343 | 653431 | get() const noexcept | ||
| 344 | { | 344 | { | |||||
| HITCBC | 345 | 653431 | if(i_ != 0) | 345 | 653431 | if(i_ != 0) | ||
| 346 | return reinterpret_cast< | 346 | return reinterpret_cast< | |||||
| HITCBC | 347 | 122583 | container::pmr::memory_resource*>(i_ & ~3); | 347 | 122583 | container::pmr::memory_resource*>(i_ & ~3); | ||
| HITCBC | 348 | 530848 | return default_resource::get(); | 348 | 530848 | return default_resource::get(); | ||
| 349 | } | 349 | } | |||||
| 350 | 350 | |||||||
| 351 | /** Return a pointer to the memory resource. | 351 | /** Return a pointer to the memory resource. | |||||
| 352 | 352 | |||||||
| 353 | This function returns a pointer to the referenced @ref | 353 | This function returns a pointer to the referenced @ref | |||||
| 354 | boost::container::pmr::memory_resource. | 354 | boost::container::pmr::memory_resource. | |||||
| 355 | 355 | |||||||
| 356 | @par Complexity | 356 | @par Complexity | |||||
| 357 | Constant. | 357 | Constant. | |||||
| 358 | 358 | |||||||
| 359 | @par Exception Safety | 359 | @par Exception Safety | |||||
| 360 | No-throw guarantee. | 360 | No-throw guarantee. | |||||
| 361 | */ | 361 | */ | |||||
| 362 | container::pmr::memory_resource* | 362 | container::pmr::memory_resource* | |||||
| HITCBC | 363 | 649785 | operator->() const noexcept | 363 | 649785 | operator->() const noexcept | ||
| 364 | { | 364 | { | |||||
| HITCBC | 365 | 649785 | return get(); | 365 | 649785 | return get(); | ||
| 366 | } | 366 | } | |||||
| 367 | 367 | |||||||
| 368 | /** Return a reference to the memory resource. | 368 | /** Return a reference to the memory resource. | |||||
| 369 | 369 | |||||||
| 370 | This function returns a reference to the pointed-to @ref | 370 | This function returns a reference to the pointed-to @ref | |||||
| 371 | boost::container::pmr::memory_resource. | 371 | boost::container::pmr::memory_resource. | |||||
| 372 | 372 | |||||||
| 373 | @par Complexity | 373 | @par Complexity | |||||
| 374 | 374 | |||||||
| 375 | Constant. | 375 | Constant. | |||||
| 376 | 376 | |||||||
| 377 | @par Exception Safety | 377 | @par Exception Safety | |||||
| 378 | 378 | |||||||
| 379 | No-throw guarantee. | 379 | No-throw guarantee. | |||||
| 380 | */ | 380 | */ | |||||
| 381 | container::pmr::memory_resource& | 381 | container::pmr::memory_resource& | |||||
| HITCBC | 382 | 3614 | operator*() const noexcept | 382 | 3614 | operator*() const noexcept | ||
| 383 | { | 383 | { | |||||
| HITCBC | 384 | 3614 | return *get(); | 384 | 3614 | return *get(); | ||
| 385 | } | 385 | } | |||||
| 386 | 386 | |||||||
| 387 | template<class U, class... Args> | 387 | template<class U, class... Args> | |||||
| 388 | friend | 388 | friend | |||||
| 389 | storage_ptr | 389 | storage_ptr | |||||
| 390 | make_shared_resource(Args&&... args); | 390 | make_shared_resource(Args&&... args); | |||||
| 391 | }; | 391 | }; | |||||
| 392 | 392 | |||||||
| 393 | #if defined(_MSC_VER) | 393 | #if defined(_MSC_VER) | |||||
| 394 | # pragma warning( push ) | 394 | # pragma warning( push ) | |||||
| 395 | # if !defined(__clang__) && _MSC_VER <= 1900 | 395 | # if !defined(__clang__) && _MSC_VER <= 1900 | |||||
| 396 | # pragma warning( disable : 4702 ) | 396 | # pragma warning( disable : 4702 ) | |||||
| 397 | # endif | 397 | # endif | |||||
| 398 | #endif | 398 | #endif | |||||
| 399 | 399 | |||||||
| 400 | /** Return a pointer that owns a new, dynamically allocated memory resource. | 400 | /** Return a pointer that owns a new, dynamically allocated memory resource. | |||||
| 401 | 401 | |||||||
| 402 | This function dynamically allocates a new memory resource as if by | 402 | This function dynamically allocates a new memory resource as if by | |||||
| 403 | `operator new` that uses shared ownership. The lifetime of the memory | 403 | `operator new` that uses shared ownership. The lifetime of the memory | |||||
| 404 | resource will be extended until the last @ref storage_ptr which points to | 404 | resource will be extended until the last @ref storage_ptr which points to | |||||
| 405 | it is destroyed. | 405 | it is destroyed. | |||||
| 406 | 406 | |||||||
| 407 | @par Constraints | 407 | @par Constraints | |||||
| 408 | @code | 408 | @code | |||||
| 409 | std::is_base_of< boost::container::pmr::memory_resource, U >::value == true | 409 | std::is_base_of< boost::container::pmr::memory_resource, U >::value == true | |||||
| 410 | @endcode | 410 | @endcode | |||||
| 411 | 411 | |||||||
| 412 | @par Complexity | 412 | @par Complexity | |||||
| 413 | Same as `new U( std::forward<Args>(args)... )`. | 413 | Same as `new U( std::forward<Args>(args)... )`. | |||||
| 414 | 414 | |||||||
| 415 | @par Exception Safety | 415 | @par Exception Safety | |||||
| 416 | Strong guarantee. | 416 | Strong guarantee. | |||||
| 417 | 417 | |||||||
| 418 | @tparam U The type of memory resource to create. | 418 | @tparam U The type of memory resource to create. | |||||
| 419 | 419 | |||||||
| 420 | @param args Parameters forwarded to the constructor of `U`. | 420 | @param args Parameters forwarded to the constructor of `U`. | |||||
| 421 | */ | 421 | */ | |||||
| 422 | template<class U, class... Args> | 422 | template<class U, class... Args> | |||||
| 423 | storage_ptr | 423 | storage_ptr | |||||
| HITCBC | 424 | 21 | make_shared_resource(Args&&... args) | 424 | 21 | make_shared_resource(Args&&... args) | ||
| 425 | { | 425 | { | |||||
| 426 | // If this generates an error, it means that | 426 | // If this generates an error, it means that | |||||
| 427 | // `T` is not a memory resource. | 427 | // `T` is not a memory resource. | |||||
| 428 | BOOST_CORE_STATIC_ASSERT(( | 428 | BOOST_CORE_STATIC_ASSERT(( | |||||
| 429 | std::is_base_of<container::pmr::memory_resource, U>::value)); | 429 | std::is_base_of<container::pmr::memory_resource, U>::value)); | |||||
| HITCBC | 430 | 23 | return storage_ptr(new | 430 | 23 | return storage_ptr(new | ||
| 431 | detail::shared_resource_impl<U>( | 431 | detail::shared_resource_impl<U>( | |||||
| HITCBC | 432 | 22 | std::forward<Args>(args)...)); | 432 | 22 | std::forward<Args>(args)...)); | ||
| 433 | } | 433 | } | |||||
| 434 | #if defined(_MSC_VER) | 434 | #if defined(_MSC_VER) | |||||
| 435 | # pragma warning( pop ) | 435 | # pragma warning( pop ) | |||||
| 436 | #endif | 436 | #endif | |||||
| 437 | 437 | |||||||
| 438 | /// Overload | 438 | /// Overload | |||||
| 439 | inline | 439 | inline | |||||
| 440 | bool | 440 | bool | |||||
| HITCBC | 441 | 5 | operator==( | 441 | 5 | operator==( | ||
| 442 | storage_ptr const& lhs, | 442 | storage_ptr const& lhs, | |||||
| 443 | storage_ptr const& rhs) noexcept | 443 | storage_ptr const& rhs) noexcept | |||||
| 444 | { | 444 | { | |||||
| HITCBC | 445 | 5 | return lhs.get() == rhs.get(); | 445 | 5 | return lhs.get() == rhs.get(); | ||
| 446 | } | 446 | } | |||||
| 447 | 447 | |||||||
| 448 | /// Overload | 448 | /// Overload | |||||
| 449 | inline | 449 | inline | |||||
| 450 | bool | 450 | bool | |||||
| 451 | operator!=( | 451 | operator!=( | |||||
| 452 | storage_ptr const& lhs, | 452 | storage_ptr const& lhs, | |||||
| 453 | storage_ptr const& rhs) noexcept | 453 | storage_ptr const& rhs) noexcept | |||||
| 454 | { | 454 | { | |||||
| 455 | return lhs.get() != rhs.get(); | 455 | return lhs.get() != rhs.get(); | |||||
| 456 | } | 456 | } | |||||
| 457 | 457 | |||||||
| 458 | } // namespace json | 458 | } // namespace json | |||||
| 459 | } // namespace boost | 459 | } // namespace boost | |||||
| 460 | 460 | |||||||
| 461 | #endif | 461 | #endif | |||||