TLA 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/core/max_align.hpp>
17 :
18 : #include <memory>
19 :
20 : namespace boost {
21 : namespace json {
22 :
23 : struct alignas(core::max_align_t)
24 : monotonic_resource::block : block_base
25 : {
26 : };
27 :
28 : constexpr
29 : std::size_t
30 HIT 179 : monotonic_resource::
31 : max_size()
32 : {
33 179 : return std::size_t(-1) - sizeof(block);
34 : }
35 :
36 : // lowest power of 2 greater than or equal to n
37 : std::size_t
38 42 : monotonic_resource::
39 : round_pow2(
40 : std::size_t n) noexcept
41 : {
42 42 : if(n & (n - 1))
43 8 : return next_pow2(n);
44 34 : return n;
45 : }
46 :
47 : // lowest power of 2 greater than n
48 : std::size_t
49 56 : monotonic_resource::
50 : next_pow2(
51 : std::size_t n) noexcept
52 : {
53 56 : std::size_t result = min_size_;
54 233 : while(result <= n)
55 : {
56 178 : if(result >= max_size() - result)
57 : {
58 : // overflow
59 1 : result = max_size();
60 1 : break;
61 : }
62 177 : result *= 2;
63 : }
64 56 : return result;
65 : }
66 :
67 : //----------------------------------------------------------
68 :
69 49 : monotonic_resource::
70 49 : ~monotonic_resource()
71 : {
72 49 : release();
73 49 : }
74 :
75 39 : monotonic_resource::
76 : monotonic_resource(
77 : std::size_t initial_size,
78 39 : storage_ptr upstream) noexcept
79 39 : : buffer_{
80 : nullptr, 0, 0, nullptr}
81 78 : , next_size_(round_pow2(initial_size))
82 39 : , upstream_(std::move(upstream))
83 : {
84 39 : }
85 :
86 10 : monotonic_resource::
87 : monotonic_resource(
88 : unsigned char* buffer,
89 : std::size_t size,
90 10 : storage_ptr upstream) noexcept
91 10 : : buffer_{
92 : buffer, size, size, nullptr}
93 20 : , next_size_(next_pow2(size))
94 10 : , upstream_(std::move(upstream))
95 : {
96 10 : }
97 :
98 : void
99 50 : monotonic_resource::
100 : release() noexcept
101 : {
102 50 : auto p = head_;
103 88 : while(p != &buffer_)
104 : {
105 38 : auto next = p->next;
106 38 : upstream_->deallocate(p,
107 38 : sizeof(block) + p->size);
108 38 : p = next;
109 : }
110 50 : buffer_.p = reinterpret_cast<
111 50 : unsigned char*>(buffer_.p) - (
112 50 : buffer_.size - buffer_.avail);
113 50 : buffer_.avail = buffer_.size;
114 50 : head_ = &buffer_;
115 50 : }
116 :
117 : void*
118 129502 : monotonic_resource::
119 : do_allocate(
120 : std::size_t n,
121 : std::size_t align)
122 : {
123 129502 : auto p = std::align(align, n, head_->p, head_->avail);
124 129502 : if(p)
125 : {
126 129464 : head_->p = reinterpret_cast<
127 129464 : unsigned char*>(p) + n;
128 129464 : head_->avail -= n;
129 129464 : return p;
130 : }
131 :
132 38 : if(next_size_ < n)
133 3 : next_size_ = round_pow2(n);
134 38 : auto b = ::new(upstream_->allocate(
135 38 : sizeof(block) + next_size_)) block;
136 38 : b->p = b + 1;
137 38 : b->avail = next_size_;
138 38 : b->size = next_size_;
139 38 : b->next = head_;
140 38 : head_ = b;
141 38 : next_size_ = next_pow2(next_size_);
142 :
143 38 : p = std::align(align, n, head_->p, head_->avail);
144 38 : BOOST_ASSERT(p);
145 38 : head_->p = reinterpret_cast<
146 38 : unsigned char*>(p) + n;
147 38 : head_->avail -= n;
148 38 : return p;
149 : }
150 :
151 : void
152 29 : monotonic_resource::
153 : do_deallocate(
154 : void*,
155 : std::size_t,
156 : std::size_t)
157 : {
158 : // do nothing
159 29 : }
160 :
161 : bool
162 MIS 0 : monotonic_resource::
163 : do_is_equal(
164 : memory_resource const& mr) const noexcept
165 : {
166 0 : return this == &mr;
167 : }
168 :
169 : } // namespace json
170 : } // namespace boost
171 :
172 : #endif
|