TLA Line data 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 HIT 5 : recycled<T>::
23 : ~recycled()
24 : {
25 5 : 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 5 : auto it = head_;
30 12 : while(it)
31 : {
32 7 : ++n;
33 7 : auto next = it->next;
34 7 : BOOST_ASSERT(
35 : it->refs == 0);
36 7 : delete it;
37 7 : it = next;
38 : }
39 5 : implementation_defined::recycled_remove(
40 : sizeof(U) * n);
41 5 : }
42 :
43 : template<class T>
44 : auto
45 18 : recycled<T>::
46 : acquire() ->
47 : U*
48 : {
49 : U* p;
50 : {
51 : #if !defined(BOOST_URL_DISABLE_THREADS)
52 : std::lock_guard<
53 18 : std::mutex> lock(m_);
54 : #endif
55 18 : p = head_;
56 18 : if(p)
57 : {
58 : // reuse
59 11 : head_ = head_->next;
60 11 : implementation_defined::recycled_remove(
61 : sizeof(U));
62 11 : ++p->refs;
63 : }
64 : else
65 : {
66 7 : p = new U;
67 : }
68 18 : }
69 18 : BOOST_ASSERT(p->refs == 1);
70 18 : return p;
71 : }
72 :
73 : template<class T>
74 : void
75 24 : recycled<T>::
76 : release(U* u) noexcept
77 : {
78 24 : if(--u->refs != 0)
79 6 : return;
80 : {
81 : #if !defined(BOOST_URL_DISABLE_THREADS)
82 : std::lock_guard<
83 18 : std::mutex> lock(m_);
84 : #endif
85 18 : u->next = head_;
86 18 : head_ = u;
87 18 : }
88 18 : implementation_defined::recycled_add(
89 : sizeof(U));
90 : }
91 :
92 : //------------------------------------------------
93 :
94 : template<class T>
95 52 : recycled_ptr<T>::
96 : ~recycled_ptr()
97 : {
98 52 : if(p_)
99 23 : bin_->release(p_);
100 52 : }
101 :
102 : template<class T>
103 1 : recycled_ptr<T>::
104 : recycled_ptr(
105 : recycled<T>& bin)
106 1 : : bin_(&bin)
107 1 : , p_(bin.acquire())
108 : {
109 1 : }
110 :
111 : template<class T>
112 17 : recycled_ptr<T>::
113 : recycled_ptr(
114 : recycled<T>& bin,
115 : std::nullptr_t) noexcept
116 17 : : bin_(&bin)
117 : {
118 17 : }
119 :
120 : template<class T>
121 17 : recycled_ptr<T>::
122 : recycled_ptr()
123 17 : : recycled_ptr(nullptr)
124 : {
125 17 : p_ = bin_->acquire();
126 17 : }
127 :
128 : template<class T>
129 17 : recycled_ptr<T>::
130 : recycled_ptr(
131 : std::nullptr_t) noexcept
132 34 : : recycled_ptr([]() -> B&
133 : {
134 : // VFALCO need guaranteed constexpr-init
135 17 : static B r;
136 17 : return r;
137 17 : }(), nullptr)
138 : {
139 17 : }
140 :
141 : template<class T>
142 6 : recycled_ptr<T>::
143 : recycled_ptr(
144 : recycled_ptr const& other) noexcept
145 6 : : bin_(other.bin_)
146 6 : , p_(other.p_)
147 : {
148 6 : if(p_)
149 6 : ++p_->refs;
150 6 : }
151 :
152 : template<class T>
153 28 : recycled_ptr<T>::
154 : recycled_ptr(
155 : recycled_ptr&& other) noexcept
156 28 : : bin_(other.bin_)
157 28 : , p_(other.p_)
158 : {
159 28 : other.p_ = nullptr;
160 28 : }
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 1 : recycled_ptr<T>::
181 : operator=(
182 : recycled_ptr const& other) noexcept ->
183 : recycled_ptr&
184 : {
185 1 : if(this == &other)
186 1 : return *this;
187 MIS 0 : BOOST_ASSERT(
188 : bin_ == other.bin_);
189 0 : if(p_)
190 0 : bin_->release(p_);
191 0 : p_ = other.p_;
192 0 : if(p_)
193 0 : ++p_->refs;
194 0 : return *this;
195 : }
196 :
197 : template<class T>
198 : T&
199 : recycled_ptr<T>::
200 : acquire()
201 : {
202 : if(! p_)
203 : p_ = bin_->acquire();
204 : return p_->t;
205 : }
206 :
207 : template<class T>
208 : void
209 HIT 1 : recycled_ptr<T>::
210 : release() noexcept
211 : {
212 1 : if(p_)
213 : {
214 1 : bin_->release(p_);
215 1 : p_ = nullptr;
216 : }
217 1 : }
218 :
219 : } // grammar
220 : } // urls
221 : } // boost
222 :
223 : #endif
|