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*
89  
    get_shared() const noexcept
89  
    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*>(
93  
                i_ & ~3));
93  
                i_ & ~3));
94  
    }
94  
    }
95  

95  

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

103  

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

115  

116  
    template<class T>
116  
    template<class T>
117  
    storage_ptr(
117  
    storage_ptr(
118  
        detail::shared_resource_impl<T>* p) noexcept
118  
        detail::shared_resource_impl<T>* p) noexcept
119  
        : i_(reinterpret_cast<std::uintptr_t>(
119  
        : i_(reinterpret_cast<std::uintptr_t>(
120  
                static_cast<container::pmr::memory_resource*>(p)) + 1 +
120  
                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  
    {
123  
        BOOST_ASSERT(p);
123  
        BOOST_ASSERT(p);
124  
    }
124  
    }
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  
    */
139  
    ~storage_ptr() noexcept
139  
    ~storage_ptr() noexcept
140  
    {
140  
    {
141  
        release();
141  
        release();
142  
    }
142  
    }
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  
    */
186  
    storage_ptr() noexcept
186  
    storage_ptr() noexcept
187  
        : i_(0)
187  
        : i_(0)
188  
    {
188  
    {
189  
    }
189  
    }
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  
    >
203  
    storage_ptr(T* r) noexcept
203  
    storage_ptr(T* r) noexcept
204  
        : i_(reinterpret_cast<std::uintptr_t>(
204  
        : i_(reinterpret_cast<std::uintptr_t>(
205  
                static_cast<container::pmr::memory_resource *>(r)) +
205  
                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  
    {
208  
        BOOST_ASSERT(r);
208  
        BOOST_ASSERT(r);
209  
    }
209  
    }
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>
218  
    storage_ptr(
218  
    storage_ptr(
219  
        container::pmr::polymorphic_allocator<V> const& alloc) noexcept
219  
        container::pmr::polymorphic_allocator<V> const& alloc) noexcept
220  
        : i_(reinterpret_cast<std::uintptr_t>(
220  
        : i_(reinterpret_cast<std::uintptr_t>(
221  
            alloc.resource()))
221  
            alloc.resource()))
222  
    {
222  
    {
223  
    }
223  
    }
224  

224  

225  
    /** Overload
225  
    /** Overload
226  

226  

227  
        @param other Another pointer.
227  
        @param other Another pointer.
228  
    */
228  
    */
229  
    storage_ptr(
229  
    storage_ptr(
230  
        storage_ptr&& other) noexcept
230  
        storage_ptr&& other) noexcept
231  
        : i_(detail::exchange(other.i_, 0))
231  
        : i_(detail::exchange(other.i_, 0))
232  
    {
232  
    {
233  
    }
233  
    }
234  

234  

235  
    /** Overload
235  
    /** Overload
236  

236  

237  
        @param other
237  
        @param other
238  
    */
238  
    */
239  
    storage_ptr(
239  
    storage_ptr(
240  
        storage_ptr const& other) noexcept
240  
        storage_ptr const& other) noexcept
241  
        : i_(other.i_)
241  
        : i_(other.i_)
242  
    {
242  
    {
243  
        addref();
243  
        addref();
244  
    }
244  
    }
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&
276  
    operator=(
276  
    operator=(
277  
        storage_ptr&& other) noexcept
277  
        storage_ptr&& other) noexcept
278  
    {
278  
    {
279  
        release();
279  
        release();
280  
        i_ = detail::exchange(other.i_, 0);
280  
        i_ = detail::exchange(other.i_, 0);
281  
        return *this;
281  
        return *this;
282  
    }
282  
    }
283  

283  

284  
    storage_ptr&
284  
    storage_ptr&
285  
    operator=(
285  
    operator=(
286  
        storage_ptr const& other) noexcept
286  
        storage_ptr const& other) noexcept
287  
    {
287  
    {
288  
        other.addref();
288  
        other.addref();
289  
        release();
289  
        release();
290  
        i_ = other.i_;
290  
        i_ = other.i_;
291  
        return *this;
291  
        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
301  
    is_shared() const noexcept
301  
    is_shared() const noexcept
302  
    {
302  
    {
303  
        return (i_ & 1) != 0;
303  
        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
314  
    is_deallocate_trivial() const noexcept
314  
    is_deallocate_trivial() const noexcept
315  
    {
315  
    {
316  
        return (i_ & 2) != 0;
316  
        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
326  
    is_not_shared_and_deallocate_is_trivial() const noexcept
326  
    is_not_shared_and_deallocate_is_trivial() const noexcept
327  
    {
327  
    {
328  
        return (i_ & 3) == 2;
328  
        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*
343  
    get() const noexcept
343  
    get() const noexcept
344  
    {
344  
    {
345  
        if(i_ != 0)
345  
        if(i_ != 0)
346  
            return reinterpret_cast<
346  
            return reinterpret_cast<
347  
                container::pmr::memory_resource*>(i_ & ~3);
347  
                container::pmr::memory_resource*>(i_ & ~3);
348  
        return default_resource::get();
348  
        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*
363  
    operator->() const noexcept
363  
    operator->() const noexcept
364  
    {
364  
    {
365  
        return get();
365  
        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&
382  
    operator*() const noexcept
382  
    operator*() const noexcept
383  
    {
383  
    {
384  
        return *get();
384  
        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
424  
make_shared_resource(Args&&... args)
424  
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));
430  
    return storage_ptr(new
430  
    return storage_ptr(new
431  
        detail::shared_resource_impl<U>(
431  
        detail::shared_resource_impl<U>(
432  
            std::forward<Args>(args)...));
432  
            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
441  
operator==(
441  
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  
{
445  
    return lhs.get() == rhs.get();
445  
    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