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 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 6 : while(it)
31 : {
32 3 : ++n;
33 3 : auto next = it->next;
34 3 : BOOST_ASSERT(
35 : it->refs == 0);
36 3 : delete it;
37 3 : it = next;
38 : }
39 3 : detail::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 8 : std::mutex> lock(m_);
54 : #endif
55 8 : p = head_;
56 8 : if(p)
57 : {
58 : // reuse
59 5 : head_ = head_->next;
60 5 : detail::recycled_remove(
61 : sizeof(U));
62 5 : ++p->refs;
63 : }
64 : else
65 : {
66 3 : p = new U;
67 : }
68 8 : }
69 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 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 : detail::recycled_add(
89 : sizeof(U));
90 : }
91 :
92 : //------------------------------------------------
93 :
94 : template<class T>
95 18 : recycled_ptr<T>::
96 : ~recycled_ptr()
97 : {
98 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 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 8 : : recycled_ptr([]() -> B&
133 : {
134 : // VFALCO need guaranteed constexpr-init
135 8 : static B r;
136 8 : 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 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
|