libcarla/include/system/boost/json/impl/monotonic_resource.ipp
2024-10-18 13:19:59 +08:00

172 lines
3.3 KiB
C++

//
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@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_IMPL_MONOTONIC_RESOURCE_IPP
#define BOOST_JSON_IMPL_MONOTONIC_RESOURCE_IPP
#include <boost/json/monotonic_resource.hpp>
#include <boost/json/detail/align.hpp>
#include <boost/json/detail/except.hpp>
#include <memory>
BOOST_JSON_NS_BEGIN
struct alignas(detail::max_align_t)
monotonic_resource::block : block_base
{
};
constexpr
std::size_t
monotonic_resource::
max_size()
{
return std::size_t(-1) - sizeof(block);
}
// lowest power of 2 greater than or equal to n
std::size_t
monotonic_resource::
round_pow2(
std::size_t n) noexcept
{
if(n & (n - 1))
return next_pow2(n);
return n;
}
// lowest power of 2 greater than n
std::size_t
monotonic_resource::
next_pow2(
std::size_t n) noexcept
{
std::size_t result = min_size_;
while(result <= n)
{
if(result >= max_size() - result)
{
// overflow
result = max_size();
break;
}
result *= 2;
}
return result;
}
//----------------------------------------------------------
monotonic_resource::
~monotonic_resource()
{
release();
}
monotonic_resource::
monotonic_resource(
std::size_t initial_size,
storage_ptr upstream) noexcept
: buffer_{
nullptr, 0, 0, nullptr}
, next_size_(round_pow2(initial_size))
, upstream_(std::move(upstream))
{
}
monotonic_resource::
monotonic_resource(
unsigned char* buffer,
std::size_t size,
storage_ptr upstream) noexcept
: buffer_{
buffer, size, size, nullptr}
, next_size_(next_pow2(size))
, upstream_(std::move(upstream))
{
}
void
monotonic_resource::
release() noexcept
{
auto p = head_;
while(p != &buffer_)
{
auto next = p->next;
upstream_->deallocate(p, p->size);
p = next;
}
buffer_.p = reinterpret_cast<
unsigned char*>(buffer_.p) - (
buffer_.size - buffer_.avail);
buffer_.avail = buffer_.size;
head_ = &buffer_;
}
void*
monotonic_resource::
do_allocate(
std::size_t n,
std::size_t align)
{
auto p = detail::align(
align, n, head_->p, head_->avail);
if(p)
{
head_->p = reinterpret_cast<
unsigned char*>(p) + n;
head_->avail -= n;
return p;
}
if(next_size_ < n)
next_size_ = round_pow2(n);
auto b = ::new(upstream_->allocate(
sizeof(block) + next_size_)) block;
b->p = b + 1;
b->avail = next_size_;
b->size = next_size_;
b->next = head_;
head_ = b;
next_size_ = next_pow2(next_size_);
p = detail::align(
align, n, head_->p, head_->avail);
BOOST_ASSERT(p);
head_->p = reinterpret_cast<
unsigned char*>(p) + n;
head_->avail -= n;
return p;
}
void
monotonic_resource::
do_deallocate(
void*,
std::size_t,
std::size_t)
{
// do nothing
}
bool
monotonic_resource::
do_is_equal(
memory_resource const& mr) const noexcept
{
return this == &mr;
}
BOOST_JSON_NS_END
#endif