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 -
#include <boost/core/detail/static_assert.hpp>
 
13  

12  

14  
#include <boost/container/pmr/polymorphic_allocator.hpp>
13  
#include <boost/container/pmr/polymorphic_allocator.hpp>
15  
#include <boost/json/detail/config.hpp>
14  
#include <boost/json/detail/config.hpp>
16  
#include <boost/json/detail/shared_resource.hpp>
15  
#include <boost/json/detail/shared_resource.hpp>
17  
#include <boost/json/detail/default_resource.hpp>
16  
#include <boost/json/detail/default_resource.hpp>
18  
#include <boost/json/is_deallocate_trivial.hpp>
17  
#include <boost/json/is_deallocate_trivial.hpp>
19  
#include <new>
18  
#include <new>
20  
#include <type_traits>
19  
#include <type_traits>
21  
#include <utility>
20  
#include <utility>
22  

21  

23  
namespace boost {
22  
namespace boost {
24  
namespace json {
23  
namespace json {
25  

24  

26  
/** A smart pointer to a memory resource.
25  
/** A smart pointer to a memory resource.
27  

26  

28 -
    This class is used to hold a pointer to a memory resource. The pointed-to
27 +
    This container is used to hold a pointer to a memory resource. The
29 -
    resource is always valid. Depending on the means of construction, the
28 +
    pointed-to resource is always valid. Depending on the means of
30 -
    ownership will be either:
29 +
    construction, the ownership will be either:
31  

30  

32  
    @li Non-owning, when constructing from a raw pointer to
31  
    @li Non-owning, when constructing from a raw pointer to
33 -
    @ref boost::container::pmr::memory_resource or from a
32 +
    `boost::container::pmr::memory_resource` or from a
34 -
    @ref boost::container::pmr::polymorphic_allocator. In this case the caller
33 +
    `boost::container::pmr::polymorphic_allocator`. In this case the caller is
35 -
    is responsible for ensuring that the lifetime of the memory resource
34 +
    responsible for ensuring that the lifetime of the memory resource extends
36 -
    extends until there are no more calls to allocate or deallocate.
35 +
    until there are no more calls to allocate or deallocate.
37  

36  

38 -
    @li Owning, when constructing using the function @ref make_shared_resource.
37 +
    @li Owning, when constructing using the function
39 -
    In this case ownership is shared; the lifetime of the memory resource
38 +
    @ref make_shared_resource. In this case
40 -
    extends until the last copy of the `storage_ptr` is destroyed.
39 +
    ownership is shared; the lifetime of the memory
 
40 +
    resource extends until the last copy of the
 
41 +
    @ref storage_ptr is destroyed.
41  

42  

42 -
    These statements create a memory resource on the stack and construct
 
43 -
    a pointer from it without taking ownership:
 
44  
    @par Examples
43  
    @par Examples
45  

44  

 
45 +
    These statements create a memory resource on the
 
46 +
    stack and construct a pointer from it without
 
47 +
    taking ownership:
46  
    @code
48  
    @code
47  
    monotonic_resource mr;                  // Create our memory resource on the stack
49  
    monotonic_resource mr;                  // Create our memory resource on the stack
48  
    storage_ptr sp( &mr );                  // Construct a non-owning pointer to the resource
50  
    storage_ptr sp( &mr );                  // Construct a non-owning pointer to the resource
49  
    @endcode
51  
    @endcode
50  

52  

51 -
    This function creates a pointer to a memory resource using shared ownership
53 +
    This function creates a pointer to a memory
52 -
    and returns it. The lifetime of the memory resource extends until the last
54 +
    resource using shared ownership and returns it.
53 -
    copy of the pointer is destroyed:
55 +
    The lifetime of the memory resource extends until
54 -

56 +
    the last copy of the pointer is destroyed:
55  
    @code
57  
    @code
56  
    // Create a counted memory resource and return it
58  
    // Create a counted memory resource and return it
57  
    storage_ptr make_storage()
59  
    storage_ptr make_storage()
58  
    {
60  
    {
59  
        return make_shared_resource< monotonic_resource >();
61  
        return make_shared_resource< monotonic_resource >();
60  
    }
62  
    }
61  
    @endcode
63  
    @endcode
62  

64  

63  
    @par Thread Safety
65  
    @par Thread Safety
64 -
    Instances of this type provide the default level of thread safety for all
66 +

65 -
    C++ objects. Specifically, it conforms to
67 +
    Instances of this type provide the default level of
66 -
    [16.4.6.10 Data race avoidance](http://eel.is/c++draft/res.on.data.races).
68 +
    thread safety for all C++ objects. Specifically, it
 
69 +
    conforms to
 
70 +
    <a href="http://eel.is/c++draft/res.on.data.races">
 
71 +
        16.4.6.10 Data race avoidance</a>.
67  

72  

68  
    @see
73  
    @see
69  
        @ref make_shared_resource,
74  
        @ref make_shared_resource,
70  
        @ref boost::container::pmr::polymorphic_allocator,
75  
        @ref boost::container::pmr::polymorphic_allocator,
71  
        @ref boost::container::pmr::memory_resource.
76  
        @ref boost::container::pmr::memory_resource.
72  

77  

73  
*/
78  
*/
74  
class storage_ptr
79  
class storage_ptr
75  
{
80  
{
76  
#ifndef BOOST_JSON_DOCS
81  
#ifndef BOOST_JSON_DOCS
77  
    // VFALCO doc toolchain shows this when it shouldn't
82  
    // VFALCO doc toolchain shows this when it shouldn't
78  
    friend struct detail::shared_resource;
83  
    friend struct detail::shared_resource;
79  
#endif
84  
#endif
80  
    using shared_resource =
85  
    using shared_resource =
81  
        detail::shared_resource;
86  
        detail::shared_resource;
82  

87  

83  
    using default_resource =
88  
    using default_resource =
84  
        detail::default_resource;
89  
        detail::default_resource;
85  

90  

86  
    std::uintptr_t i_;
91  
    std::uintptr_t i_;
87  

92  

88  
    shared_resource*
93  
    shared_resource*
89  
    get_shared() const noexcept
94  
    get_shared() const noexcept
90  
    {
95  
    {
91  
        return static_cast<shared_resource*>(
96  
        return static_cast<shared_resource*>(
92  
            reinterpret_cast<container::pmr::memory_resource*>(
97  
            reinterpret_cast<container::pmr::memory_resource*>(
93  
                i_ & ~3));
98  
                i_ & ~3));
94  
    }
99  
    }
95  

100  

96  
    void
101  
    void
97  
    addref() const noexcept
102  
    addref() const noexcept
98  
    {
103  
    {
99  
        if(is_shared())
104  
        if(is_shared())
100  
            get_shared()->refs.fetch_add(
105  
            get_shared()->refs.fetch_add(
101  
                1, std::memory_order_relaxed);
106  
                1, std::memory_order_relaxed);
102  
    }
107  
    }
103  

108  

104  
    void
109  
    void
105  
    release() const noexcept
110  
    release() const noexcept
106  
    {
111  
    {
107  
        if(is_shared())
112  
        if(is_shared())
108  
        {
113  
        {
109  
            auto const p = get_shared();
114  
            auto const p = get_shared();
110  
            if(p->refs.fetch_sub(1,
115  
            if(p->refs.fetch_sub(1,
111  
                    std::memory_order_acq_rel) == 1)
116  
                    std::memory_order_acq_rel) == 1)
112  
                delete p;
117  
                delete p;
113  
        }
118  
        }
114  
    }
119  
    }
115  

120  

116  
    template<class T>
121  
    template<class T>
117  
    storage_ptr(
122  
    storage_ptr(
118  
        detail::shared_resource_impl<T>* p) noexcept
123  
        detail::shared_resource_impl<T>* p) noexcept
119  
        : i_(reinterpret_cast<std::uintptr_t>(
124  
        : i_(reinterpret_cast<std::uintptr_t>(
120  
                static_cast<container::pmr::memory_resource*>(p)) + 1 +
125  
                static_cast<container::pmr::memory_resource*>(p)) + 1 +
121  
            (json::is_deallocate_trivial<T>::value ? 2 : 0))
126  
            (json::is_deallocate_trivial<T>::value ? 2 : 0))
122  
    {
127  
    {
123  
        BOOST_ASSERT(p);
128  
        BOOST_ASSERT(p);
124  
    }
129  
    }
125  

130  

126  
public:
131  
public:
127 -
    /** Destructor.
132 +
    /** Destructor
128  

133  

129 -
        If the pointer has shared ownership of the resource, the shared
134 +
        If the pointer has shared ownership of the
130 -
        ownership is released. If this is the last owned copy, the memory
135 +
        resource, the shared ownership is released.
 
136 +
        If this is the last owned copy, the memory
131  
        resource is destroyed.
137  
        resource is destroyed.
132  

138  

133  
        @par Complexity
139  
        @par Complexity
134  
        Constant.
140  
        Constant.
135  

141  

136  
        @par Exception Safety
142  
        @par Exception Safety
137  
        No-throw guarantee.
143  
        No-throw guarantee.
138  
    */
144  
    */
139  
    ~storage_ptr() noexcept
145  
    ~storage_ptr() noexcept
140  
    {
146  
    {
141  
        release();
147  
        release();
142  
    }
148  
    }
143  

149  

144 -
    /** Constructors.
150 +
    /** Constructor
145  

151  

146 -
        @li **(1)** constructs a non-owning pointer that refers to the
152 +
        This constructs a non-owning pointer that refers
147 -
        \<\<default_memory_resource,default memory resource\>\>.
153 +
        to the [default memory resource].
148  

154  

149 -
        @li **(2)** constructs a non-owning pointer that points to the memory
155 +
        @par Complexity
150 -
        resource `r`.
156 +
        Constant.
151  

157  

152 -
        @li **(3)** constructs a non-owning pointer that points to the same
158 +
        @par Exception Safety
153 -
        memory resource as `alloc`, obtained by calling `alloc.resource()`.
159 +
        No-throw guarantee.
154  

160  

155 -
        @li **(4)**, **(5)** construct a pointer to the same memory resource as
161 +
        [default memory resource]: json/allocators/storage_ptr.html#json.allocators.storage_ptr.default_memory_resource
156 -
        `other`, with the same ownership.
162 +
    */
 
163 +
    storage_ptr() noexcept
 
164 +
        : i_(0)
 
165 +
    {
 
166 +
    }
157  

167  

158 -
        After **(4)** and **(5)** if `other` was owning, then the constructed
168 +
    /** Constructor
159 -
        pointer is also owning. In particular, **(4)** transfers ownership to
 
160 -
        the constructed pointer while **(5)** causes it to share ownership with
 
161 -
        `other`. Otherwise, and with other overloads the constructed pointer
 
162 -
        doesn't own its memory resource and the caller is responsible for
 
163 -
        maintaining the lifetime of the pointed-to
 
164 -
        @ref boost::container::pmr::memory_resource.
 
165  

169  

166 -
        After **(4)**, `other` will point to the default memory resource.
170 +
        This constructs a non-owning pointer that points to the memory resource
 
171 +
        `r`. The caller is responsible for maintaining the lifetime of the
 
172 +
        pointed-to `boost::container::pmr::memory_resource`.
167  

173  

168  
        @par Constraints
174  
        @par Constraints
169  
        @code
175  
        @code
170  
        std::is_convertible< T*, boost::container::pmr::memory_resource* >::value == true
176  
        std::is_convertible< T*, boost::container::pmr::memory_resource* >::value == true
171  
        @endcode
177  
        @endcode
172  

178  

173 -
        @pre
179 +
        @par Preconditions
174  
        @code
180  
        @code
175  
        r != nullptr
181  
        r != nullptr
176  
        @endcode
182  
        @endcode
177 -
        @par Complexity
 
178 -
        Constant.
 
179 -

 
180  

183  

181  
        @par Exception Safety
184  
        @par Exception Safety
182  
        No-throw guarantee.
185  
        No-throw guarantee.
183  

186  

184 -
        @{
187 +
        @param r A pointer to the memory resource to use.
185 -
    */
188 +
        This may not be null.
186 -
    storage_ptr() noexcept
 
187 -
        : i_(0)
 
188 -
    {
 
189 -
    }
 
190 -

 
191 -
    /** Overload
 
192 -

 
193 -
        @tparam T The type of memory resource.
 
194 -
        @param r A non-null pointer to the memory resource to use.
 
195  
    */
189  
    */
196  
    template<class T
190  
    template<class T
197  
#ifndef BOOST_JSON_DOCS
191  
#ifndef BOOST_JSON_DOCS
198  
        , class = typename std::enable_if<
192  
        , class = typename std::enable_if<
199  
            std::is_convertible<T*,
193  
            std::is_convertible<T*,
200  
                container::pmr::memory_resource*>::value>::type
194  
                container::pmr::memory_resource*>::value>::type
201  
#endif
195  
#endif
202  
    >
196  
    >
203  
    storage_ptr(T* r) noexcept
197  
    storage_ptr(T* r) noexcept
204  
        : i_(reinterpret_cast<std::uintptr_t>(
198  
        : i_(reinterpret_cast<std::uintptr_t>(
205  
                static_cast<container::pmr::memory_resource *>(r)) +
199  
                static_cast<container::pmr::memory_resource *>(r)) +
206  
            (json::is_deallocate_trivial<T>::value ? 2 : 0))
200  
            (json::is_deallocate_trivial<T>::value ? 2 : 0))
207  
    {
201  
    {
208  
        BOOST_ASSERT(r);
202  
        BOOST_ASSERT(r);
209  
    }
203  
    }
210  

204  

211 -
    /** Overload
205 +
    /** Constructor
212  

206  

213 -
        @tparam V Any type.
207 +
        This constructs a non-owning pointer that points to the same memory
214 -
        @param alloc A @ref boost::container::pmr::polymorphic_allocator to
208 +
        resource as `alloc`, obtained by calling `alloc.resource()`. The caller
 
209 +
        is responsible for maintaining the lifetime of the
 
210 +
        pointed-to `boost::container::pmr::memory_resource`.
 
211 +

 
212 +
        @par Constraints
 
213 +
        @code
 
214 +
        std::is_convertible< T*, boost::container::pmr::memory_resource* >::value == true
 
215 +
        @endcode
 
216 +

 
217 +
        @par Exception Safety
 
218 +
        No-throw guarantee.
 
219 +

 
220 +
        @param alloc A `boost::container::pmr::polymorphic_allocator` to
215  
        construct from.
221  
        construct from.
216  
    */
222  
    */
217 -
    template<class V>
223 +
    template<class T>
218  
    storage_ptr(
224  
    storage_ptr(
219 -
        container::pmr::polymorphic_allocator<V> const& alloc) noexcept
225 +
        container::pmr::polymorphic_allocator<T> const& alloc) noexcept
220  
        : i_(reinterpret_cast<std::uintptr_t>(
226  
        : i_(reinterpret_cast<std::uintptr_t>(
221  
            alloc.resource()))
227  
            alloc.resource()))
222  
    {
228  
    {
223  
    }
229  
    }
224  

230  

225 -
    /** Overload
231 +
    /** Move constructor
226  

232  

227 -
        @param other Another pointer.
233 +
        This function constructs a pointer that
 
234 +
        points to the same memory resource as `other`,
 
235 +
        with the same ownership:
 
236 +

 
237 +
        @li If `other` is non-owning, then `*this`
 
238 +
        will be be non-owning.
 
239 +

 
240 +
        @li If `other` has shared ownership, then
 
241 +
        ownership will be transferred to `*this`.
 
242 +

 
243 +
        After construction, `other` will point
 
244 +
        to the [default memory resource].
 
245 +

 
246 +
        @par Complexity
 
247 +
        Constant.
 
248 +

 
249 +
        @par Exception Safety
 
250 +
        No-throw guarantee.
 
251 +

 
252 +
        @param other The pointer to construct from.
 
253 +

 
254 +
        [default memory resource]: json/allocators/storage_ptr.html#json.allocators.storage_ptr.default_memory_resource
228  
    */
255  
    */
229  
    storage_ptr(
256  
    storage_ptr(
230  
        storage_ptr&& other) noexcept
257  
        storage_ptr&& other) noexcept
231  
        : i_(detail::exchange(other.i_, 0))
258  
        : i_(detail::exchange(other.i_, 0))
232  
    {
259  
    {
233  
    }
260  
    }
234  

261  

235 -
    /** Overload
262 +
    /** Copy constructor
236  

263  

237 -
        @param other
264 +
        This function constructs a pointer that
 
265 +
        points to the same memory resource as `other`,
 
266 +
        with the same ownership:
 
267 +

 
268 +
        @li If `other` is non-owning, then `*this`
 
269 +
        will be be non-owning.
 
270 +

 
271 +
        @li If `other` has shared ownership, then
 
272 +
        `*this` will acquire shared ownership.
 
273 +

 
274 +
        @par Complexity
 
275 +
        Constant.
 
276 +

 
277 +
        @par Exception Safety
 
278 +
        No-throw guarantee.
 
279 +

 
280 +
        @param other The pointer to construct from.
238  
    */
281  
    */
239  
    storage_ptr(
282  
    storage_ptr(
240  
        storage_ptr const& other) noexcept
283  
        storage_ptr const& other) noexcept
241  
        : i_(other.i_)
284  
        : i_(other.i_)
242  
    {
285  
    {
243  
        addref();
286  
        addref();
244 -
    /// @}
 
245 -

 
246 -
    /** Assignment operators.
 
247  
    }
287  
    }
248  

288  

249 -
        This function assigns a pointer that points to the same memory resource
289 +
    /** Move assignment
250 -
        as `other`, with the same ownership:
 
251  

290  

252 -
        @li If `other` is non-owning, then the assigned-to pointer will be be
291 +
        This function assigns a pointer that
253 -
        non-owning.
292 +
        points to the same memory resource as `other`,
 
293 +
        with the same ownership:
254  

294  

255 -
        @li If `other` has shared ownership, then **(1)** transfers ownership
295 +
        @li If `other` is non-owning, then `*this`
256 -
        to the assigned-to pointer, while after **(2)** it shares the ownership
296 +
        will be be non-owning.
257 -
        with `other`.
 
258  

297  

259 -
        If the assigned-to pointer previously had shared ownership, it is
298 +
        @li If `other` has shared ownership, then
260 -
        released before the function returns.
299 +
        ownership will be transferred to `*this`.
261  

300  

262 -
        After **(1)**, `other` will point to the
301 +
        After assignment, `other` will point
263 -
        \<\<default_memory_resource,default memory resource\>\>.
302 +
        to the [default memory resource].
 
303 +
        If `*this` previously had shared ownership,
 
304 +
        it is released before the function returns.
264  

305  

265  
        @par Complexity
306  
        @par Complexity
266  
        Constant.
307  
        Constant.
267  

308  

268  
        @par Exception Safety
309  
        @par Exception Safety
269  
        No-throw guarantee.
310  
        No-throw guarantee.
270  

311  

271 -
        @param other Another pointer.
312 +
        @param other The storage pointer to move.
272  

313  

273 -
        @{
314 +
        [default memory resource]: json/allocators/storage_ptr.html#json.allocators.storage_ptr.default_memory_resource
274  
    */
315  
    */
275  
    storage_ptr&
316  
    storage_ptr&
276  
    operator=(
317  
    operator=(
277  
        storage_ptr&& other) noexcept
318  
        storage_ptr&& other) noexcept
278  
    {
319  
    {
279  
        release();
320  
        release();
280  
        i_ = detail::exchange(other.i_, 0);
321  
        i_ = detail::exchange(other.i_, 0);
281  
        return *this;
322  
        return *this;
282  
    }
323  
    }
283  

324  

 
325 +
    /** Copy assignment.
 
326 +

 
327 +
        This function assigns a pointer that
 
328 +
        points to the same memory resource as `other`,
 
329 +
        with the same ownership:
 
330 +

 
331 +
        @li If `other` is non-owning, then `*this`
 
332 +
        will be be non-owning.
 
333 +

 
334 +
        @li If `other` has shared ownership, then
 
335 +
        `*this` will acquire shared ownership.
 
336 +

 
337 +
        If `*this` previously had shared ownership,
 
338 +
        it is released before the function returns.
 
339 +

 
340 +
        @par Complexity
 
341 +
        Constant.
 
342 +

 
343 +
        @par Exception Safety
 
344 +
        No-throw guarantee.
 
345 +

 
346 +
        @param other The storage pointer to copy.
 
347 +
    */
284  
    storage_ptr&
348  
    storage_ptr&
285  
    operator=(
349  
    operator=(
286  
        storage_ptr const& other) noexcept
350  
        storage_ptr const& other) noexcept
287  
    {
351  
    {
288  
        other.addref();
352  
        other.addref();
289  
        release();
353  
        release();
290  
        i_ = other.i_;
354  
        i_ = other.i_;
291  
        return *this;
355  
        return *this;
292 -
    /// @}
 
293  
    }
356  
    }
294  

357  

295 -
    /** Check if ownership of the memory resource is shared.
358 +
    /** Return `true` if ownership of the memory resource is shared.
296  

359  

297 -
        This function returns true for memory resources created using @ref
360 +
        This function returns true for memory resources
298 -
        make_shared_resource.
361 +
        created using @ref make_shared_resource.
299  
    */
362  
    */
300  
    bool
363  
    bool
301  
    is_shared() const noexcept
364  
    is_shared() const noexcept
302  
    {
365  
    {
303  
        return (i_ & 1) != 0;
366  
        return (i_ & 1) != 0;
304  
    }
367  
    }
305  

368  

306 -
    /** Check if calling `deallocate` on the memory resource has no effect.
369 +
    /** Return `true` if calling `deallocate` on the memory resource has no effect.
307  

370  

308 -
        This function is used to determine if the deallocate function of the
371 +
        This function is used to determine if the deallocate
309 -
        pointed to memory resource is trivial. The value of @ref
372 +
        function of the pointed to memory resource is trivial.
310 -
        is_deallocate_trivial is evaluated and saved when the memory resource
373 +
        The value of @ref is_deallocate_trivial is evaluated
311 -
        is constructed and the type is known, before the type is erased.
374 +
        and saved when the memory resource is constructed
 
375 +
        and the type is known, before the type is erased.
312  
    */
376  
    */
313  
    bool
377  
    bool
314  
    is_deallocate_trivial() const noexcept
378  
    is_deallocate_trivial() const noexcept
315  
    {
379  
    {
316  
        return (i_ & 2) != 0;
380  
        return (i_ & 2) != 0;
317  
    }
381  
    }
318  

382  

319 -
    /** Check if ownership of the memory resource is not shared and deallocate is trivial.
383 +
    /** Return `true` if ownership of the memory resource is not shared and deallocate is trivial.
320  

384  

321 -
        This function is used to determine if calls to deallocate can
385 +
        This function is used to determine if calls to deallocate
322 -
        effectively be skipped. Equivalent to `! is_shared() &&
386 +
        can effectively be skipped.
323 -
        is_deallocate_trivial()`.
387 +

 
388 +
        @par Effects
 
389 +
        Returns `! this->is_shared() && this->is_deallocate_trivial()`
324  
    */
390  
    */
325  
    bool
391  
    bool
326  
    is_not_shared_and_deallocate_is_trivial() const noexcept
392  
    is_not_shared_and_deallocate_is_trivial() const noexcept
327  
    {
393  
    {
328  
        return (i_ & 3) == 2;
394  
        return (i_ & 3) == 2;
329  
    }
395  
    }
330  

396  

331  
    /** Return a pointer to the memory resource.
397  
    /** Return a pointer to the memory resource.
332  

398  

333  
        This function returns a pointer to the
399  
        This function returns a pointer to the
334 -
        referenced @ref boost::container::pmr::memory_resource.
400 +
        referenced `boost::container::pmr::memory_resource`.
335  

401  

336  
        @par Complexity
402  
        @par Complexity
337  
        Constant.
403  
        Constant.
338  

404  

339  
        @par Exception Safety
405  
        @par Exception Safety
340  
        No-throw guarantee.
406  
        No-throw guarantee.
341  
    */
407  
    */
342  
    container::pmr::memory_resource*
408  
    container::pmr::memory_resource*
343  
    get() const noexcept
409  
    get() const noexcept
344  
    {
410  
    {
345  
        if(i_ != 0)
411  
        if(i_ != 0)
346  
            return reinterpret_cast<
412  
            return reinterpret_cast<
347  
                container::pmr::memory_resource*>(i_ & ~3);
413  
                container::pmr::memory_resource*>(i_ & ~3);
348  
        return default_resource::get();
414  
        return default_resource::get();
349  
    }
415  
    }
350  

416  

351  
    /** Return a pointer to the memory resource.
417  
    /** Return a pointer to the memory resource.
352  

418  

353 -
        This function returns a pointer to the referenced @ref
419 +
        This function returns a pointer to the
354 -
        boost::container::pmr::memory_resource.
420 +
        referenced `boost::container::pmr::memory_resource`.
355  

421  

356  
        @par Complexity
422  
        @par Complexity
357  
        Constant.
423  
        Constant.
358  

424  

359  
        @par Exception Safety
425  
        @par Exception Safety
360  
        No-throw guarantee.
426  
        No-throw guarantee.
361  
    */
427  
    */
362  
    container::pmr::memory_resource*
428  
    container::pmr::memory_resource*
363  
    operator->() const noexcept
429  
    operator->() const noexcept
364  
    {
430  
    {
365  
        return get();
431  
        return get();
366  
    }
432  
    }
367  

433  

368  
    /** Return a reference to the memory resource.
434  
    /** Return a reference to the memory resource.
369  

435  

370 -
        This function returns a reference to the pointed-to @ref
436 +
        This function returns a reference to the
371 -
        boost::container::pmr::memory_resource.
437 +
        pointed-to `boost::container::pmr::memory_resource`.
372  

438  

373  
        @par Complexity
439  
        @par Complexity
374  

440  

375  
        Constant.
441  
        Constant.
376  

442  

377  
        @par Exception Safety
443  
        @par Exception Safety
378  

444  

379  
        No-throw guarantee.
445  
        No-throw guarantee.
380  
    */
446  
    */
381  
    container::pmr::memory_resource&
447  
    container::pmr::memory_resource&
382  
    operator*() const noexcept
448  
    operator*() const noexcept
383  
    {
449  
    {
384  
        return *get();
450  
        return *get();
385  
    }
451  
    }
386  

452  

387  
    template<class U, class... Args>
453  
    template<class U, class... Args>
388  
    friend
454  
    friend
389  
    storage_ptr
455  
    storage_ptr
390  
    make_shared_resource(Args&&... args);
456  
    make_shared_resource(Args&&... args);
391  
};
457  
};
392  

458  

393  
#if defined(_MSC_VER)
459  
#if defined(_MSC_VER)
394  
# pragma warning( push )
460  
# pragma warning( push )
395  
# if !defined(__clang__) && _MSC_VER <= 1900
461  
# if !defined(__clang__) && _MSC_VER <= 1900
396  
#  pragma warning( disable : 4702 )
462  
#  pragma warning( disable : 4702 )
397  
# endif
463  
# endif
398  
#endif
464  
#endif
 
465 +
/** Return shared ownership of a new, dynamically allocated memory resource.
399  

466  

400 -
/** Return a pointer that owns a new, dynamically allocated memory resource.
467 +
    This function dynamically allocates a new memory resource
401 -

468 +
    as if by `operator new` that uses shared ownership. The
402 -
    This function dynamically allocates a new memory resource as if by
469 +
    lifetime of the memory resource will be extended until
403 -
    `operator new` that uses shared ownership. The lifetime of the memory
470 +
    the last @ref storage_ptr which points to it is destroyed.
404 -
    resource will be extended until the last @ref storage_ptr which points to
 
405 -
    it is destroyed.
 
406  

471  

407 -
    @par Constraints
472 +
    @par Mandates
408  
    @code
473  
    @code
409  
    std::is_base_of< boost::container::pmr::memory_resource, U >::value == true
474  
    std::is_base_of< boost::container::pmr::memory_resource, U >::value == true
410  
    @endcode
475  
    @endcode
411  

476  

412  
    @par Complexity
477  
    @par Complexity
413  
    Same as `new U( std::forward<Args>(args)... )`.
478  
    Same as `new U( std::forward<Args>(args)... )`.
414  

479  

415  
    @par Exception Safety
480  
    @par Exception Safety
416  
    Strong guarantee.
481  
    Strong guarantee.
417  

482  

418  
    @tparam U The type of memory resource to create.
483  
    @tparam U The type of memory resource to create.
419  

484  

420  
    @param args Parameters forwarded to the constructor of `U`.
485  
    @param args Parameters forwarded to the constructor of `U`.
421  
*/
486  
*/
422  
template<class U, class... Args>
487  
template<class U, class... Args>
423  
storage_ptr
488  
storage_ptr
424  
make_shared_resource(Args&&... args)
489  
make_shared_resource(Args&&... args)
425  
{
490  
{
426  
    // If this generates an error, it means that
491  
    // If this generates an error, it means that
427  
    // `T` is not a memory resource.
492  
    // `T` is not a memory resource.
428 -
    BOOST_CORE_STATIC_ASSERT((
493 +
    BOOST_STATIC_ASSERT(
429 -
        std::is_base_of<container::pmr::memory_resource, U>::value));
494 +
        std::is_base_of<
 
495 +
            container::pmr::memory_resource, U>::value);
430  
    return storage_ptr(new
496  
    return storage_ptr(new
431  
        detail::shared_resource_impl<U>(
497  
        detail::shared_resource_impl<U>(
432  
            std::forward<Args>(args)...));
498  
            std::forward<Args>(args)...));
433  
}
499  
}
434  
#if defined(_MSC_VER)
500  
#if defined(_MSC_VER)
435  
# pragma warning( pop )
501  
# pragma warning( pop )
436  
#endif
502  
#endif
437  

503  

438 -
/// Overload
504 +
/** Return true if two storage pointers point to the same memory resource.
 
505 +

 
506 +
    This function returns `true` if the
 
507 +
    `boost::container::pmr::memory_resource` objects pointed to by `lhs` and
 
508 +
    `rhs` have the same address.
 
509 +
*/
439  
inline
510  
inline
440  
bool
511  
bool
441  
operator==(
512  
operator==(
442  
    storage_ptr const& lhs,
513  
    storage_ptr const& lhs,
443  
    storage_ptr const& rhs) noexcept
514  
    storage_ptr const& rhs) noexcept
444  
{
515  
{
445  
    return lhs.get() == rhs.get();
516  
    return lhs.get() == rhs.get();
446  
}
517  
}
447  

518  

448 -
/// Overload
519 +
/** Return true if two storage pointers point to different memory resources.
 
520 +

 
521 +
    This function returns `true` if the
 
522 +
    `boost::container::pmr::memory_resource` objects pointed to by `lhs` and
 
523 +
    `rhs` have different addresses.
 
524 +
*/
449  
inline
525  
inline
450  
bool
526  
bool
451  
operator!=(
527  
operator!=(
452  
    storage_ptr const& lhs,
528  
    storage_ptr const& lhs,
453  
    storage_ptr const& rhs) noexcept
529  
    storage_ptr const& rhs) noexcept
454  
{
530  
{
455  
    return lhs.get() != rhs.get();
531  
    return lhs.get() != rhs.get();
456  
}
532  
}
457  

533  

458  
} // namespace json
534  
} // namespace json
459  
} // namespace boost
535  
} // namespace boost
460  

536  

461  
#endif
537  
#endif