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 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
28  
    resource is always valid. Depending on the means of construction, the
30  
    ownership will be either:
29  
    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  
    @ref boost::container::pmr::memory_resource or from a
34  
    @ref boost::container::pmr::polymorphic_allocator. In this case the caller
33  
    @ref boost::container::pmr::polymorphic_allocator. In this case the caller
35  
    is responsible for ensuring that the lifetime of the memory resource
34  
    is responsible for ensuring that the lifetime of the memory resource
36  
    extends until there are no more calls to allocate or deallocate.
35  
    extends 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 @ref make_shared_resource.
39  
    In this case ownership is shared; the lifetime of the memory resource
38  
    In this case ownership is shared; the lifetime of the memory resource
40  
    extends until the last copy of the `storage_ptr` is destroyed.
39  
    extends until the last copy of the `storage_ptr` is destroyed.
41  

40  

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

44  

46  
    @code
45  
    @code
47  
    monotonic_resource mr;                  // Create our memory resource on the stack
46  
    monotonic_resource mr;                  // Create our memory resource on the stack
48  
    storage_ptr sp( &mr );                  // Construct a non-owning pointer to the resource
47  
    storage_ptr sp( &mr );                  // Construct a non-owning pointer to the resource
49  
    @endcode
48  
    @endcode
50  

49  

51  
    This function creates a pointer to a memory resource using shared ownership
50  
    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
51  
    and returns it. The lifetime of the memory resource extends until the last
53  
    copy of the pointer is destroyed:
52  
    copy of the pointer is destroyed:
54  

53  

55  
    @code
54  
    @code
56  
    // Create a counted memory resource and return it
55  
    // Create a counted memory resource and return it
57  
    storage_ptr make_storage()
56  
    storage_ptr make_storage()
58  
    {
57  
    {
59  
        return make_shared_resource< monotonic_resource >();
58  
        return make_shared_resource< monotonic_resource >();
60  
    }
59  
    }
61  
    @endcode
60  
    @endcode
62  

61  

63  
    @par Thread Safety
62  
    @par Thread Safety
64  
    Instances of this type provide the default level of thread safety for all
63  
    Instances of this type provide the default level of thread safety for all
65  
    C++ objects. Specifically, it conforms to
64  
    C++ objects. Specifically, it conforms to
66  
    [16.4.6.10 Data race avoidance](http://eel.is/c++draft/res.on.data.races).
65  
    [16.4.6.10 Data race avoidance](http://eel.is/c++draft/res.on.data.races).
67  

66  

68  
    @see
67  
    @see
69  
        @ref make_shared_resource,
68  
        @ref make_shared_resource,
70  
        @ref boost::container::pmr::polymorphic_allocator,
69  
        @ref boost::container::pmr::polymorphic_allocator,
71  
        @ref boost::container::pmr::memory_resource.
70  
        @ref boost::container::pmr::memory_resource.
72  

71  

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

81  

83  
    using default_resource =
82  
    using default_resource =
84  
        detail::default_resource;
83  
        detail::default_resource;
85  

84  

86  
    std::uintptr_t i_;
85  
    std::uintptr_t i_;
87  

86  

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

94  

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

102  

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

114  

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

124  

126  
public:
125  
public:
127  
    /** Destructor.
126  
    /** Destructor.
128  

127  

129  
        If the pointer has shared ownership of the resource, the shared
128  
        If the pointer has shared ownership of the resource, the shared
130  
        ownership is released. If this is the last owned copy, the memory
129  
        ownership is released. If this is the last owned copy, the memory
131  
        resource is destroyed.
130  
        resource is destroyed.
132  

131  

133  
        @par Complexity
132  
        @par Complexity
134  
        Constant.
133  
        Constant.
135  

134  

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

142  

144  
    /** Constructors.
143  
    /** Constructors.
145  

144  

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

147  

149  
        @li **(2)** constructs a non-owning pointer that points to the memory
148  
        @li **(2)** constructs a non-owning pointer that points to the memory
150  
        resource `r`.
149  
        resource `r`.
151  

150  

152  
        @li **(3)** constructs a non-owning pointer that points to the same
151  
        @li **(3)** constructs a non-owning pointer that points to the same
153  
        memory resource as `alloc`, obtained by calling `alloc.resource()`.
152  
        memory resource as `alloc`, obtained by calling `alloc.resource()`.
154  

153  

155  
        @li **(4)**, **(5)** construct a pointer to the same memory resource as
154  
        @li **(4)**, **(5)** construct a pointer to the same memory resource as
156  
        `other`, with the same ownership.
155  
        `other`, with the same ownership.
157  

156  

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

164  

166  
        After **(4)**, `other` will point to the default memory resource.
165  
        After **(4)**, `other` will point to the default memory resource.
167  

166  

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

171  

173  
        @pre
172  
        @pre
174  
        @code
173  
        @code
175  
        r != nullptr
174  
        r != nullptr
176  
        @endcode
175  
        @endcode
177  

176  

178  
        @par Complexity
177  
        @par Complexity
179  
        Constant.
178  
        Constant.
180  

179  

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

182  

184  
        @{
183  
        @{
185  
    */
184  
    */
186  
    storage_ptr() noexcept
185  
    storage_ptr() noexcept
187  
        : i_(0)
186  
        : i_(0)
188  
    {
187  
    {
189  
    }
188  
    }
190  

189  

191  
    /** Overload
190  
    /** Overload
192  

191  

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

209  

211  
    /** Overload
210  
    /** Overload
212  

211  

213  
        @tparam V Any type.
212  
        @tparam V Any type.
214  
        @param alloc A @ref boost::container::pmr::polymorphic_allocator to
213  
        @param alloc A @ref boost::container::pmr::polymorphic_allocator to
215  
        construct from.
214  
        construct from.
216  
    */
215  
    */
217  
    template<class V>
216  
    template<class V>
218  
    storage_ptr(
217  
    storage_ptr(
219  
        container::pmr::polymorphic_allocator<V> const& alloc) noexcept
218  
        container::pmr::polymorphic_allocator<V> const& alloc) noexcept
220  
        : i_(reinterpret_cast<std::uintptr_t>(
219  
        : i_(reinterpret_cast<std::uintptr_t>(
221  
            alloc.resource()))
220  
            alloc.resource()))
222  
    {
221  
    {
223  
    }
222  
    }
224  

223  

225  
    /** Overload
224  
    /** Overload
226  

225  

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

233  

235  
    /** Overload
234  
    /** Overload
236  

235  

237  
        @param other
236  
        @param other
238  
    */
237  
    */
239  
    storage_ptr(
238  
    storage_ptr(
240  
        storage_ptr const& other) noexcept
239  
        storage_ptr const& other) noexcept
241  
        : i_(other.i_)
240  
        : i_(other.i_)
242  
    {
241  
    {
243  
        addref();
242  
        addref();
244  
    }
243  
    }
245  
    /// @}
244  
    /// @}
246  

245  

247  
    /** Assignment operators.
246  
    /** Assignment operators.
248  

247  

249  
        This function assigns a pointer that points to the same memory resource
248  
        This function assigns a pointer that points to the same memory resource
250  
        as `other`, with the same ownership:
249  
        as `other`, with the same ownership:
251  

250  

252  
        @li If `other` is non-owning, then the assigned-to pointer will be be
251  
        @li If `other` is non-owning, then the assigned-to pointer will be be
253  
        non-owning.
252  
        non-owning.
254  

253  

255  
        @li If `other` has shared ownership, then **(1)** transfers ownership
254  
        @li If `other` has shared ownership, then **(1)** transfers ownership
256  
        to the assigned-to pointer, while after **(2)** it shares the ownership
255  
        to the assigned-to pointer, while after **(2)** it shares the ownership
257  
        with `other`.
256  
        with `other`.
258  

257  

259  
        If the assigned-to pointer previously had shared ownership, it is
258  
        If the assigned-to pointer previously had shared ownership, it is
260  
        released before the function returns.
259  
        released before the function returns.
261  

260  

262  
        After **(1)**, `other` will point to the
261  
        After **(1)**, `other` will point to the
263  
        \<\<default_memory_resource,default memory resource\>\>.
262  
        \<\<default_memory_resource,default memory resource\>\>.
264  

263  

265  
        @par Complexity
264  
        @par Complexity
266  
        Constant.
265  
        Constant.
267  

266  

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

269  

271  
        @param other Another pointer.
270  
        @param other Another pointer.
272  

271  

273  
        @{
272  
        @{
274  
    */
273  
    */
275  
    storage_ptr&
274  
    storage_ptr&
276  
    operator=(
275  
    operator=(
277  
        storage_ptr&& other) noexcept
276  
        storage_ptr&& other) noexcept
278  
    {
277  
    {
279  
        release();
278  
        release();
280  
        i_ = detail::exchange(other.i_, 0);
279  
        i_ = detail::exchange(other.i_, 0);
281  
        return *this;
280  
        return *this;
282  
    }
281  
    }
283  

282  

284  
    storage_ptr&
283  
    storage_ptr&
285  
    operator=(
284  
    operator=(
286  
        storage_ptr const& other) noexcept
285  
        storage_ptr const& other) noexcept
287  
    {
286  
    {
288  
        other.addref();
287  
        other.addref();
289  
        release();
288  
        release();
290  
        i_ = other.i_;
289  
        i_ = other.i_;
291  
        return *this;
290  
        return *this;
292  
    }
291  
    }
293  
    /// @}
292  
    /// @}
294  

293  

295  
    /** Check if ownership of the memory resource is shared.
294  
    /** Check if ownership of the memory resource is shared.
296  

295  

297  
        This function returns true for memory resources created using @ref
296  
        This function returns true for memory resources created using @ref
298  
        make_shared_resource.
297  
        make_shared_resource.
299  
    */
298  
    */
300  
    bool
299  
    bool
301  
    is_shared() const noexcept
300  
    is_shared() const noexcept
302  
    {
301  
    {
303  
        return (i_ & 1) != 0;
302  
        return (i_ & 1) != 0;
304  
    }
303  
    }
305  

304  

306  
    /** Check if calling `deallocate` on the memory resource has no effect.
305  
    /** Check if calling `deallocate` on the memory resource has no effect.
307  

306  

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

317  

319  
    /** Check if ownership of the memory resource is not shared and deallocate is trivial.
318  
    /** Check if ownership of the memory resource is not shared and deallocate is trivial.
320  

319  

321  
        This function is used to determine if calls to deallocate can
320  
        This function is used to determine if calls to deallocate can
322  
        effectively be skipped. Equivalent to `! is_shared() &&
321  
        effectively be skipped. Equivalent to `! is_shared() &&
323  
        is_deallocate_trivial()`.
322  
        is_deallocate_trivial()`.
324  
    */
323  
    */
325  
    bool
324  
    bool
326  
    is_not_shared_and_deallocate_is_trivial() const noexcept
325  
    is_not_shared_and_deallocate_is_trivial() const noexcept
327  
    {
326  
    {
328  
        return (i_ & 3) == 2;
327  
        return (i_ & 3) == 2;
329  
    }
328  
    }
330  

329  

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

331  

333  
        This function returns a pointer to the
332  
        This function returns a pointer to the
334  
        referenced @ref boost::container::pmr::memory_resource.
333  
        referenced @ref boost::container::pmr::memory_resource.
335  

334  

336  
        @par Complexity
335  
        @par Complexity
337  
        Constant.
336  
        Constant.
338  

337  

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

349  

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

351  

353  
        This function returns a pointer to the referenced @ref
352  
        This function returns a pointer to the referenced @ref
354  
        boost::container::pmr::memory_resource.
353  
        boost::container::pmr::memory_resource.
355  

354  

356  
        @par Complexity
355  
        @par Complexity
357  
        Constant.
356  
        Constant.
358  

357  

359  
        @par Exception Safety
358  
        @par Exception Safety
360  
        No-throw guarantee.
359  
        No-throw guarantee.
361  
    */
360  
    */
362  
    container::pmr::memory_resource*
361  
    container::pmr::memory_resource*
363  
    operator->() const noexcept
362  
    operator->() const noexcept
364  
    {
363  
    {
365  
        return get();
364  
        return get();
366  
    }
365  
    }
367  

366  

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

368  

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

371  

373  
        @par Complexity
372  
        @par Complexity
374  

373  

375  
        Constant.
374  
        Constant.
376  

375  

377  
        @par Exception Safety
376  
        @par Exception Safety
378  

377  

379  
        No-throw guarantee.
378  
        No-throw guarantee.
380  
    */
379  
    */
381  
    container::pmr::memory_resource&
380  
    container::pmr::memory_resource&
382  
    operator*() const noexcept
381  
    operator*() const noexcept
383  
    {
382  
    {
384  
        return *get();
383  
        return *get();
385  
    }
384  
    }
386  

385  

387  
    template<class U, class... Args>
386  
    template<class U, class... Args>
388  
    friend
387  
    friend
389  
    storage_ptr
388  
    storage_ptr
390  
    make_shared_resource(Args&&... args);
389  
    make_shared_resource(Args&&... args);
391  
};
390  
};
392  

391  

393  
#if defined(_MSC_VER)
392  
#if defined(_MSC_VER)
394  
# pragma warning( push )
393  
# pragma warning( push )
395  
# if !defined(__clang__) && _MSC_VER <= 1900
394  
# if !defined(__clang__) && _MSC_VER <= 1900
396  
#  pragma warning( disable : 4702 )
395  
#  pragma warning( disable : 4702 )
397  
# endif
396  
# endif
398  
#endif
397  
#endif
399  

398  

400  
/** Return a pointer that owns a new, dynamically allocated memory resource.
399  
/** Return a pointer that owns a new, dynamically allocated memory resource.
401  

400  

402  
    This function dynamically allocates a new memory resource as if by
401  
    This function dynamically allocates a new memory resource as if by
403  
    `operator new` that uses shared ownership. The lifetime of the memory
402  
    `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
403  
    resource will be extended until the last @ref storage_ptr which points to
405  
    it is destroyed.
404  
    it is destroyed.
406  

405  

407  
    @par Constraints
406  
    @par Constraints
408  
    @code
407  
    @code
409  
    std::is_base_of< boost::container::pmr::memory_resource, U >::value == true
408  
    std::is_base_of< boost::container::pmr::memory_resource, U >::value == true
410  
    @endcode
409  
    @endcode
411  

410  

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

413  

415  
    @par Exception Safety
414  
    @par Exception Safety
416  
    Strong guarantee.
415  
    Strong guarantee.
417  

416  

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

418  

420  
    @param args Parameters forwarded to the constructor of `U`.
419  
    @param args Parameters forwarded to the constructor of `U`.
421  
*/
420  
*/
422  
template<class U, class... Args>
421  
template<class U, class... Args>
423  
storage_ptr
422  
storage_ptr
424  
make_shared_resource(Args&&... args)
423  
make_shared_resource(Args&&... args)
425  
{
424  
{
426  
    // If this generates an error, it means that
425  
    // If this generates an error, it means that
427  
    // `T` is not a memory resource.
426  
    // `T` is not a memory resource.
428 -
    BOOST_CORE_STATIC_ASSERT((
427 +
    BOOST_STATIC_ASSERT(
429 -
        std::is_base_of<container::pmr::memory_resource, U>::value));
428 +
        std::is_base_of<
 
429 +
            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