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