Line data Source code
1 : //
2 : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 : // Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
4 : //
5 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 : //
8 : // Official repository: https://github.com/boostorg/json
9 : //
10 :
11 : #ifndef BOOST_JSON_IMPL_MONOTONIC_RESOURCE_IPP
12 : #define BOOST_JSON_IMPL_MONOTONIC_RESOURCE_IPP
13 :
14 : #include <boost/json/monotonic_resource.hpp>
15 : #include <boost/json/detail/except.hpp>
16 : #include <boost/align/align.hpp>
17 : #include <boost/core/max_align.hpp>
18 :
19 : #include <memory>
20 :
21 : namespace boost {
22 : namespace json {
23 :
24 : struct alignas(core::max_align_t)
25 : monotonic_resource::block : block_base
26 : {
27 : };
28 :
29 : constexpr
30 : std::size_t
31 164 : monotonic_resource::
32 : max_size()
33 : {
34 164 : return std::size_t(-1) - sizeof(block);
35 : }
36 :
37 : // lowest power of 2 greater than or equal to n
38 : std::size_t
39 39 : monotonic_resource::
40 : round_pow2(
41 : std::size_t n) noexcept
42 : {
43 39 : if(n & (n - 1))
44 7 : return next_pow2(n);
45 32 : return n;
46 : }
47 :
48 : // lowest power of 2 greater than n
49 : std::size_t
50 51 : monotonic_resource::
51 : next_pow2(
52 : std::size_t n) noexcept
53 : {
54 51 : std::size_t result = min_size_;
55 213 : while(result <= n)
56 : {
57 163 : if(result >= max_size() - result)
58 : {
59 : // overflow
60 1 : result = max_size();
61 1 : break;
62 : }
63 162 : result *= 2;
64 : }
65 51 : return result;
66 : }
67 :
68 : //----------------------------------------------------------
69 :
70 47 : monotonic_resource::
71 47 : ~monotonic_resource()
72 : {
73 47 : release();
74 47 : }
75 :
76 37 : monotonic_resource::
77 : monotonic_resource(
78 : std::size_t initial_size,
79 37 : storage_ptr upstream) noexcept
80 37 : : buffer_{
81 : nullptr, 0, 0, nullptr}
82 74 : , next_size_(round_pow2(initial_size))
83 37 : , upstream_(std::move(upstream))
84 : {
85 37 : }
86 :
87 10 : monotonic_resource::
88 : monotonic_resource(
89 : unsigned char* buffer,
90 : std::size_t size,
91 10 : storage_ptr upstream) noexcept
92 10 : : buffer_{
93 : buffer, size, size, nullptr}
94 20 : , next_size_(next_pow2(size))
95 10 : , upstream_(std::move(upstream))
96 : {
97 10 : }
98 :
99 : void
100 48 : monotonic_resource::
101 : release() noexcept
102 : {
103 48 : auto p = head_;
104 82 : while(p != &buffer_)
105 : {
106 34 : auto next = p->next;
107 34 : upstream_->deallocate(p, p->size);
108 34 : p = next;
109 : }
110 48 : buffer_.p = reinterpret_cast<
111 48 : unsigned char*>(buffer_.p) - (
112 48 : buffer_.size - buffer_.avail);
113 48 : buffer_.avail = buffer_.size;
114 48 : head_ = &buffer_;
115 48 : }
116 :
117 : void*
118 129498 : monotonic_resource::
119 : do_allocate(
120 : std::size_t n,
121 : std::size_t align)
122 : {
123 129498 : auto p = alignment::align(
124 129498 : align, n, head_->p, head_->avail);
125 129498 : if(p)
126 : {
127 129464 : head_->p = reinterpret_cast<
128 129464 : unsigned char*>(p) + n;
129 129464 : head_->avail -= n;
130 129464 : return p;
131 : }
132 :
133 34 : if(next_size_ < n)
134 2 : next_size_ = round_pow2(n);
135 34 : auto b = ::new(upstream_->allocate(
136 34 : sizeof(block) + next_size_)) block;
137 34 : b->p = b + 1;
138 34 : b->avail = next_size_;
139 34 : b->size = next_size_;
140 34 : b->next = head_;
141 34 : head_ = b;
142 34 : next_size_ = next_pow2(next_size_);
143 :
144 34 : p = alignment::align(
145 34 : align, n, head_->p, head_->avail);
146 34 : BOOST_ASSERT(p);
147 34 : head_->p = reinterpret_cast<
148 34 : unsigned char*>(p) + n;
149 34 : head_->avail -= n;
150 34 : return p;
151 : }
152 :
153 : void
154 29 : monotonic_resource::
155 : do_deallocate(
156 : void*,
157 : std::size_t,
158 : std::size_t)
159 : {
160 : // do nothing
161 29 : }
162 :
163 : bool
164 0 : monotonic_resource::
165 : do_is_equal(
166 : memory_resource const& mr) const noexcept
167 : {
168 0 : return this == &mr;
169 : }
170 :
171 : } // namespace json
172 : } // namespace boost
173 :
174 : #endif
|