libs/url/include/boost/url/grammar/impl/recycled.hpp

100.0% Lines (58/58) 92.6% Functions (25/27) 78.3% Branches (18/23)
libs/url/include/boost/url/grammar/impl/recycled.hpp
Line Branch Hits Source Code
1 //
2 // Copyright (c) 2022 Vinnie Falco (vinnie.falco@gmail.com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/boostorg/url
8 //
9
10 #ifndef BOOST_URL_GRAMMAR_IMPL_RECYCLED_PTR_HPP
11 #define BOOST_URL_GRAMMAR_IMPL_RECYCLED_PTR_HPP
12
13 #include <boost/assert.hpp>
14
15 namespace boost {
16 namespace urls {
17 namespace grammar {
18
19 //------------------------------------------------
20
21 template<class T>
22 3 recycled<T>::
23 ~recycled()
24 {
25 3 std::size_t n = 0;
26 // VFALCO we should probably deallocate
27 // in reverse order of allocation but
28 // that requires a doubly-linked list.
29 3 auto it = head_;
30
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 while(it)
31 {
32 3 ++n;
33 3 auto next = it->next;
34
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 BOOST_ASSERT(
35 it->refs == 0);
36
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 delete it;
37 3 it = next;
38 }
39 3 implementation_defined::recycled_remove(
40 sizeof(U) * n);
41 3 }
42
43 template<class T>
44 auto
45 8 recycled<T>::
46 acquire() ->
47 U*
48 {
49 U* p;
50 {
51 #if !defined(BOOST_URL_DISABLE_THREADS)
52 std::lock_guard<
53
1/1
✓ Branch 1 taken 8 times.
8 std::mutex> lock(m_);
54 #endif
55 8 p = head_;
56
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
8 if(p)
57 {
58 // reuse
59 5 head_ = head_->next;
60 5 implementation_defined::recycled_remove(
61 sizeof(U));
62 5 ++p->refs;
63 }
64 else
65 {
66
1/1
✓ Branch 1 taken 3 times.
3 p = new U;
67 }
68 8 }
69
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 BOOST_ASSERT(p->refs == 1);
70 8 return p;
71 }
72
73 template<class T>
74 void
75 10 recycled<T>::
76 release(U* u) noexcept
77 {
78
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 8 times.
10 if(--u->refs != 0)
79 2 return;
80 {
81 #if !defined(BOOST_URL_DISABLE_THREADS)
82 std::lock_guard<
83 8 std::mutex> lock(m_);
84 #endif
85 8 u->next = head_;
86 8 head_ = u;
87 8 }
88 8 implementation_defined::recycled_add(
89 sizeof(U));
90 }
91
92 //------------------------------------------------
93
94 template<class T>
95 18 recycled_ptr<T>::
96 ~recycled_ptr()
97 {
98
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 8 times.
18 if(p_)
99 10 bin_->release(p_);
100 18 }
101
102 template<class T>
103 recycled_ptr<T>::
104 recycled_ptr(
105 recycled<T>& bin)
106 : bin_(&bin)
107 , p_(bin.acquire())
108 {
109 }
110
111 template<class T>
112 8 recycled_ptr<T>::
113 recycled_ptr(
114 recycled<T>& bin,
115 std::nullptr_t) noexcept
116 8 : bin_(&bin)
117 {
118 8 }
119
120 template<class T>
121 8 recycled_ptr<T>::
122 recycled_ptr()
123 8 : recycled_ptr(nullptr)
124 {
125
1/1
✓ Branch 1 taken 8 times.
8 p_ = bin_->acquire();
126 8 }
127
128 template<class T>
129 8 recycled_ptr<T>::
130 recycled_ptr(
131 std::nullptr_t) noexcept
132 12 : recycled_ptr([]() -> B&
133 {
134 // VFALCO need guaranteed constexpr-init
135
3/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 3 times.
✓ Branch 3 taken 1 time.
✗ Branch 4 not taken.
4 static B r;
136 4 return r;
137 8 }(), nullptr)
138 {
139 8 }
140
141 template<class T>
142 2 recycled_ptr<T>::
143 recycled_ptr(
144 recycled_ptr const& other) noexcept
145 2 : bin_(other.bin_)
146 2 , p_(other.p_)
147 {
148
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if(p_)
149 2 ++p_->refs;
150 2 }
151
152 template<class T>
153 8 recycled_ptr<T>::
154 recycled_ptr(
155 recycled_ptr&& other) noexcept
156 8 : bin_(other.bin_)
157 8 , p_(other.p_)
158 {
159 8 other.p_ = nullptr;
160 8 }
161
162 template<class T>
163 auto
164 recycled_ptr<T>::
165 operator=(
166 recycled_ptr&& other) noexcept ->
167 recycled_ptr&
168 {
169 BOOST_ASSERT(
170 bin_ == other.bin_);
171 if(p_)
172 bin_->release(p_);
173 p_ = other.p_;
174 other.p_ = nullptr;
175 return *this;
176 }
177
178 template<class T>
179 auto
180 recycled_ptr<T>::
181 operator=(
182 recycled_ptr const& other) noexcept ->
183 recycled_ptr&
184 {
185 BOOST_ASSERT(
186 bin_ == other.bin_);
187 if(p_)
188 bin_->release(p_);
189 p_ = other.p_;
190 if(p_)
191 ++p_->refs;
192 return *this;
193 }
194
195 template<class T>
196 T&
197 recycled_ptr<T>::
198 acquire()
199 {
200 if(! p_)
201 p_ = bin_->acquire();
202 return p_->t;
203 }
204
205 template<class T>
206 void
207 recycled_ptr<T>::
208 release() noexcept
209 {
210 if(p_)
211 {
212 bin_->release(p_);
213 p_ = nullptr;
214 }
215 }
216
217 } // grammar
218 } // urls
219 } // boost
220
221 #endif
222