mirror of
https://github.com/vdemydiuk/mtapi.git
synced 2026-08-06 23:47:51 +00:00
Added thirdparty: boost library
This commit is contained in:
+540
@@ -0,0 +1,540 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_STORAGE_PTR_HPP
|
||||
#define BOOST_JSON_STORAGE_PTR_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#include <boost/json/memory_resource.hpp>
|
||||
#include <boost/json/detail/shared_resource.hpp>
|
||||
#include <boost/json/detail/default_resource.hpp>
|
||||
#include <cstddef>
|
||||
#include <new>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace json {
|
||||
|
||||
/** A smart pointer to a @ref memory_resource
|
||||
|
||||
This container is used to hold a pointer to a memory resource. The
|
||||
pointed-to resource is always valid. Depending on the means of
|
||||
construction, the ownership will be either:
|
||||
|
||||
@li Non-owning, when constructing from a raw
|
||||
pointer to @ref memory_resource or from a
|
||||
@ref polymorphic_allocator. In this case the
|
||||
caller is responsible for ensuring that the
|
||||
lifetime of the memory resource extends until
|
||||
there are no more calls to allocate or
|
||||
deallocate.
|
||||
|
||||
@li Owning, when constructing using the function
|
||||
@ref make_shared_resource. In this case
|
||||
ownership is shared; the lifetime of the memory
|
||||
resource extends until the last copy of the
|
||||
@ref storage_ptr is destroyed.
|
||||
|
||||
@par Examples
|
||||
|
||||
These statements create a memory resource on the
|
||||
stack and construct a pointer from it without
|
||||
taking ownership:
|
||||
@code
|
||||
monotonic_resource mr; // Create our memory resource on the stack
|
||||
storage_ptr sp( &mr ); // Construct a non-owning pointer to the resource
|
||||
@endcode
|
||||
|
||||
This function creates a pointer to a memory
|
||||
resource using shared ownership and returns it.
|
||||
The lifetime of the memory resource extends until
|
||||
the last copy of the pointer is destroyed:
|
||||
@code
|
||||
// Create a counted memory resource and return it
|
||||
storage_ptr make_storage()
|
||||
{
|
||||
return make_shared_resource< monotonic_resource >();
|
||||
}
|
||||
@endcode
|
||||
|
||||
@par Thread Safety
|
||||
|
||||
Instances of this type provide the default level of
|
||||
thread safety for all C++ objects. Specifically, it
|
||||
conforms to
|
||||
<a href="http://eel.is/c++draft/res.on.data.races">
|
||||
16.4.6.10 Data race avoidance</a>.
|
||||
|
||||
@see
|
||||
@ref make_shared_resource,
|
||||
@ref memory_resource,
|
||||
@ref polymorphic_allocator
|
||||
*/
|
||||
class storage_ptr
|
||||
{
|
||||
#ifndef BOOST_JSON_DOCS
|
||||
// VFALCO doc toolchain shows this when it shouldn't
|
||||
friend struct detail::shared_resource;
|
||||
#endif
|
||||
using shared_resource =
|
||||
detail::shared_resource;
|
||||
|
||||
using default_resource =
|
||||
detail::default_resource;
|
||||
|
||||
std::uintptr_t i_;
|
||||
|
||||
shared_resource*
|
||||
get_shared() const noexcept
|
||||
{
|
||||
return static_cast<shared_resource*>(
|
||||
reinterpret_cast<memory_resource*>(
|
||||
i_ & ~3));
|
||||
}
|
||||
|
||||
void
|
||||
addref() const noexcept
|
||||
{
|
||||
if(is_shared())
|
||||
get_shared()->refs.fetch_add(
|
||||
1, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void
|
||||
release() const noexcept
|
||||
{
|
||||
if(is_shared())
|
||||
{
|
||||
auto const p = get_shared();
|
||||
if(p->refs.fetch_sub(1,
|
||||
std::memory_order_acq_rel) == 1)
|
||||
delete p;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
storage_ptr(
|
||||
detail::shared_resource_impl<T>* p) noexcept
|
||||
: i_(reinterpret_cast<std::uintptr_t>(
|
||||
static_cast<memory_resource*>(p)) + 1 +
|
||||
(json::is_deallocate_trivial<T>::value ? 2 : 0))
|
||||
{
|
||||
BOOST_ASSERT(p);
|
||||
}
|
||||
|
||||
public:
|
||||
/** Destructor
|
||||
|
||||
If the pointer has shared ownership of the
|
||||
resource, the shared ownership is released.
|
||||
If this is the last owned copy, the memory
|
||||
resource is destroyed.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
~storage_ptr() noexcept
|
||||
{
|
||||
release();
|
||||
}
|
||||
|
||||
/** Constructor
|
||||
|
||||
This constructs a non-owning pointer that refers
|
||||
to the [default memory resource].
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
[default memory resource]: json/allocators/storage_ptr.html#json.allocators.storage_ptr.default_memory_resource
|
||||
*/
|
||||
storage_ptr() noexcept
|
||||
: i_(0)
|
||||
{
|
||||
}
|
||||
|
||||
/** Constructor
|
||||
|
||||
This constructs a non-owning pointer that
|
||||
points to the memory resource `r`.
|
||||
The caller is responsible for maintaining the
|
||||
lifetime of the pointed-to @ref memory_resource.
|
||||
|
||||
@par Constraints
|
||||
@code
|
||||
std::is_convertible< T*, memory_resource* >::value == true
|
||||
@endcode
|
||||
|
||||
@par Preconditions
|
||||
@code
|
||||
r != nullptr
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param r A pointer to the memory resource to use.
|
||||
This may not be null.
|
||||
*/
|
||||
template<class T
|
||||
#ifndef BOOST_JSON_DOCS
|
||||
, class = typename std::enable_if<
|
||||
std::is_convertible<T*,
|
||||
memory_resource*>::value>::type
|
||||
#endif
|
||||
>
|
||||
storage_ptr(T* r) noexcept
|
||||
: i_(reinterpret_cast<std::uintptr_t>(
|
||||
static_cast<memory_resource *>(r)) +
|
||||
(json::is_deallocate_trivial<T>::value ? 2 : 0))
|
||||
{
|
||||
BOOST_ASSERT(r);
|
||||
}
|
||||
|
||||
/** Constructor
|
||||
|
||||
This constructs a non-owning pointer that
|
||||
points to the same memory resource as `alloc`,
|
||||
obtained by calling `alloc.resource()`.
|
||||
The caller is responsible for maintaining the
|
||||
lifetime of the pointed-to @ref memory_resource.
|
||||
|
||||
@par Constraints
|
||||
@code
|
||||
std::is_convertible< T*, memory_resource* >::value == true
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param alloc A @ref polymorphic_allocator to
|
||||
construct from.
|
||||
*/
|
||||
template<class T>
|
||||
storage_ptr(
|
||||
polymorphic_allocator<T> const& alloc) noexcept
|
||||
: i_(reinterpret_cast<std::uintptr_t>(
|
||||
alloc.resource()))
|
||||
{
|
||||
}
|
||||
|
||||
/** Move constructor
|
||||
|
||||
This function constructs a pointer that
|
||||
points to the same memory resource as `other`,
|
||||
with the same ownership:
|
||||
|
||||
@li If `other` is non-owning, then `*this`
|
||||
will be be non-owning.
|
||||
|
||||
@li If `other` has shared ownership, then
|
||||
ownership will be transferred to `*this`.
|
||||
|
||||
After construction, `other` will point
|
||||
to the [default memory resource].
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param other The pointer to construct from.
|
||||
|
||||
[default memory resource]: json/allocators/storage_ptr.html#json.allocators.storage_ptr.default_memory_resource
|
||||
*/
|
||||
storage_ptr(
|
||||
storage_ptr&& other) noexcept
|
||||
: i_(detail::exchange(other.i_, 0))
|
||||
{
|
||||
}
|
||||
|
||||
/** Copy constructor
|
||||
|
||||
This function constructs a pointer that
|
||||
points to the same memory resource as `other`,
|
||||
with the same ownership:
|
||||
|
||||
@li If `other` is non-owning, then `*this`
|
||||
will be be non-owning.
|
||||
|
||||
@li If `other` has shared ownership, then
|
||||
`*this` will acquire shared ownership.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param other The pointer to construct from.
|
||||
*/
|
||||
storage_ptr(
|
||||
storage_ptr const& other) noexcept
|
||||
: i_(other.i_)
|
||||
{
|
||||
addref();
|
||||
}
|
||||
|
||||
/** Move assignment
|
||||
|
||||
This function assigns a pointer that
|
||||
points to the same memory resource as `other`,
|
||||
with the same ownership:
|
||||
|
||||
@li If `other` is non-owning, then `*this`
|
||||
will be be non-owning.
|
||||
|
||||
@li If `other` has shared ownership, then
|
||||
ownership will be transferred to `*this`.
|
||||
|
||||
After assignment, `other` will point
|
||||
to the [default memory resource].
|
||||
If `*this` previously had shared ownership,
|
||||
it is released before the function returns.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param other The storage pointer to move.
|
||||
|
||||
[default memory resource]: json/allocators/storage_ptr.html#json.allocators.storage_ptr.default_memory_resource
|
||||
*/
|
||||
storage_ptr&
|
||||
operator=(
|
||||
storage_ptr&& other) noexcept
|
||||
{
|
||||
release();
|
||||
i_ = detail::exchange(other.i_, 0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Copy assignment.
|
||||
|
||||
This function assigns a pointer that
|
||||
points to the same memory resource as `other`,
|
||||
with the same ownership:
|
||||
|
||||
@li If `other` is non-owning, then `*this`
|
||||
will be be non-owning.
|
||||
|
||||
@li If `other` has shared ownership, then
|
||||
`*this` will acquire shared ownership.
|
||||
|
||||
If `*this` previously had shared ownership,
|
||||
it is released before the function returns.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param other The storage pointer to copy.
|
||||
*/
|
||||
storage_ptr&
|
||||
operator=(
|
||||
storage_ptr const& other) noexcept
|
||||
{
|
||||
other.addref();
|
||||
release();
|
||||
i_ = other.i_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Return `true` if ownership of the memory resource is shared.
|
||||
|
||||
This function returns true for memory resources
|
||||
created using @ref make_shared_resource.
|
||||
*/
|
||||
bool
|
||||
is_shared() const noexcept
|
||||
{
|
||||
return (i_ & 1) != 0;
|
||||
}
|
||||
|
||||
/** Return `true` if calling `deallocate` on the memory resource has no effect.
|
||||
|
||||
This function is used to determine if the deallocate
|
||||
function of the pointed to memory resource is trivial.
|
||||
The value of @ref is_deallocate_trivial is evaluated
|
||||
and saved when the memory resource is constructed
|
||||
and the type is known, before the type is erased.
|
||||
*/
|
||||
bool
|
||||
is_deallocate_trivial() const noexcept
|
||||
{
|
||||
return (i_ & 2) != 0;
|
||||
}
|
||||
|
||||
/** Return `true` if ownership of the memory resource is not shared and deallocate is trivial.
|
||||
|
||||
This function is used to determine if calls to deallocate
|
||||
can effectively be skipped.
|
||||
|
||||
@par Effects
|
||||
Returns `! this->is_shared() && this->is_deallocate_trivial()`
|
||||
*/
|
||||
bool
|
||||
is_not_shared_and_deallocate_is_trivial() const noexcept
|
||||
{
|
||||
return (i_ & 3) == 2;
|
||||
}
|
||||
|
||||
/** Return a pointer to the memory resource.
|
||||
|
||||
This function returns a pointer to the
|
||||
referenced @ref memory_resource.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
memory_resource*
|
||||
get() const noexcept
|
||||
{
|
||||
if(i_ != 0)
|
||||
return reinterpret_cast<
|
||||
memory_resource*>(i_ & ~3);
|
||||
return default_resource::get();
|
||||
}
|
||||
|
||||
/** Return a pointer to the memory resource.
|
||||
|
||||
This function returns a pointer to the
|
||||
referenced @ref memory_resource.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
memory_resource*
|
||||
operator->() const noexcept
|
||||
{
|
||||
return get();
|
||||
}
|
||||
|
||||
/** Return a reference to the memory resource.
|
||||
|
||||
This function returns a reference to the
|
||||
pointed-to @ref memory_resource.
|
||||
|
||||
@par Complexity
|
||||
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
|
||||
No-throw guarantee.
|
||||
*/
|
||||
memory_resource&
|
||||
operator*() const noexcept
|
||||
{
|
||||
return *get();
|
||||
}
|
||||
|
||||
template<class U, class... Args>
|
||||
friend
|
||||
storage_ptr
|
||||
make_shared_resource(Args&&... args);
|
||||
};
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning( push )
|
||||
# if !defined(__clang__) && _MSC_VER <= 1900
|
||||
# pragma warning( disable : 4702 )
|
||||
# endif
|
||||
#endif
|
||||
/** Return shared ownership of a new, dynamically allocated memory resource.
|
||||
|
||||
This function dynamically allocates a new memory resource
|
||||
as if by `operator new` that uses shared ownership. The
|
||||
lifetime of the memory resource will be extended until
|
||||
the last @ref storage_ptr which points to it is destroyed.
|
||||
|
||||
@par Mandates
|
||||
@code
|
||||
std::is_base_of< memory_resource, U >::value == true
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Same as `new U( std::forward<Args>(args)... )`.
|
||||
|
||||
@par Exception Safety
|
||||
Strong guarantee.
|
||||
|
||||
@tparam U The type of memory resource to create.
|
||||
|
||||
@param args Parameters forwarded to the constructor of `U`.
|
||||
*/
|
||||
template<class U, class... Args>
|
||||
storage_ptr
|
||||
make_shared_resource(Args&&... args)
|
||||
{
|
||||
// If this generates an error, it means that
|
||||
// `T` is not a memory resource.
|
||||
BOOST_STATIC_ASSERT(
|
||||
std::is_base_of<
|
||||
memory_resource, U>::value);
|
||||
return storage_ptr(new
|
||||
detail::shared_resource_impl<U>(
|
||||
std::forward<Args>(args)...));
|
||||
}
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning( pop )
|
||||
#endif
|
||||
|
||||
/** Return true if two storage pointers point to the same memory resource.
|
||||
|
||||
This function returns `true` if the @ref memory_resource
|
||||
objects pointed to by `lhs` and `rhs` have the
|
||||
same address.
|
||||
*/
|
||||
inline
|
||||
bool
|
||||
operator==(
|
||||
storage_ptr const& lhs,
|
||||
storage_ptr const& rhs) noexcept
|
||||
{
|
||||
return lhs.get() == rhs.get();
|
||||
}
|
||||
|
||||
/** Return true if two storage pointers point to different memory resources.
|
||||
|
||||
This function returns `true` if the @ref memory_resource
|
||||
objects pointed to by `lhs` and `rhs` have different
|
||||
addresses.
|
||||
*/
|
||||
inline
|
||||
bool
|
||||
operator!=(
|
||||
storage_ptr const& lhs,
|
||||
storage_ptr const& rhs) noexcept
|
||||
{
|
||||
return lhs.get() != rhs.get();
|
||||
}
|
||||
|
||||
} // namespace json
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user