impl/monotonic_resource.ipp

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