File indexing completed on 2025-01-18 09:39:01
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_JSON_IMPL_MONOTONIC_RESOURCE_IPP
0012 #define BOOST_JSON_IMPL_MONOTONIC_RESOURCE_IPP
0013
0014 #include <boost/json/monotonic_resource.hpp>
0015 #include <boost/json/detail/except.hpp>
0016 #include <boost/align/align.hpp>
0017 #include <boost/core/max_align.hpp>
0018
0019 #include <memory>
0020
0021 namespace boost {
0022 namespace json {
0023
0024 struct alignas(core::max_align_t)
0025 monotonic_resource::block : block_base
0026 {
0027 };
0028
0029 constexpr
0030 std::size_t
0031 monotonic_resource::
0032 max_size()
0033 {
0034 return std::size_t(-1) - sizeof(block);
0035 }
0036
0037
0038 std::size_t
0039 monotonic_resource::
0040 round_pow2(
0041 std::size_t n) noexcept
0042 {
0043 if(n & (n - 1))
0044 return next_pow2(n);
0045 return n;
0046 }
0047
0048
0049 std::size_t
0050 monotonic_resource::
0051 next_pow2(
0052 std::size_t n) noexcept
0053 {
0054 std::size_t result = min_size_;
0055 while(result <= n)
0056 {
0057 if(result >= max_size() - result)
0058 {
0059
0060 result = max_size();
0061 break;
0062 }
0063 result *= 2;
0064 }
0065 return result;
0066 }
0067
0068
0069
0070 monotonic_resource::
0071 ~monotonic_resource()
0072 {
0073 release();
0074 }
0075
0076 monotonic_resource::
0077 monotonic_resource(
0078 std::size_t initial_size,
0079 storage_ptr upstream) noexcept
0080 : buffer_{
0081 nullptr, 0, 0, nullptr}
0082 , next_size_(round_pow2(initial_size))
0083 , upstream_(std::move(upstream))
0084 {
0085 }
0086
0087 monotonic_resource::
0088 monotonic_resource(
0089 unsigned char* buffer,
0090 std::size_t size,
0091 storage_ptr upstream) noexcept
0092 : buffer_{
0093 buffer, size, size, nullptr}
0094 , next_size_(next_pow2(size))
0095 , upstream_(std::move(upstream))
0096 {
0097 }
0098
0099 void
0100 monotonic_resource::
0101 release() noexcept
0102 {
0103 auto p = head_;
0104 while(p != &buffer_)
0105 {
0106 auto next = p->next;
0107 upstream_->deallocate(p, p->size);
0108 p = next;
0109 }
0110 buffer_.p = reinterpret_cast<
0111 unsigned char*>(buffer_.p) - (
0112 buffer_.size - buffer_.avail);
0113 buffer_.avail = buffer_.size;
0114 head_ = &buffer_;
0115 }
0116
0117 void*
0118 monotonic_resource::
0119 do_allocate(
0120 std::size_t n,
0121 std::size_t align)
0122 {
0123 auto p = alignment::align(
0124 align, n, head_->p, head_->avail);
0125 if(p)
0126 {
0127 head_->p = reinterpret_cast<
0128 unsigned char*>(p) + n;
0129 head_->avail -= n;
0130 return p;
0131 }
0132
0133 if(next_size_ < n)
0134 next_size_ = round_pow2(n);
0135 auto b = ::new(upstream_->allocate(
0136 sizeof(block) + next_size_)) block;
0137 b->p = b + 1;
0138 b->avail = next_size_;
0139 b->size = next_size_;
0140 b->next = head_;
0141 head_ = b;
0142 next_size_ = next_pow2(next_size_);
0143
0144 p = alignment::align(
0145 align, n, head_->p, head_->avail);
0146 BOOST_ASSERT(p);
0147 head_->p = reinterpret_cast<
0148 unsigned char*>(p) + n;
0149 head_->avail -= n;
0150 return p;
0151 }
0152
0153 void
0154 monotonic_resource::
0155 do_deallocate(
0156 void*,
0157 std::size_t,
0158 std::size_t)
0159 {
0160
0161 }
0162
0163 bool
0164 monotonic_resource::
0165 do_is_equal(
0166 memory_resource const& mr) const noexcept
0167 {
0168 return this == &mr;
0169 }
0170
0171 }
0172 }
0173
0174 #endif