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 6 : recycled<T>:: 46 : acquire() -> 47 : U* 48 : { 49 : U* p; 50 : { 51 : #if !defined(BOOST_URL_DISABLE_THREADS) 52 : std::lock_guard< 53 12 : std::mutex> lock(m_); 54 : #endif 55 6 : p = head_; 56 6 : if(p) 57 : { 58 : // reuse 59 3 : head_ = head_->next; 60 3 : detail::recycled_remove( 61 : sizeof(U)); 62 3 : ++p->refs; 63 : } 64 : else 65 : { 66 3 : p = new U; 67 : } 68 : } 69 6 : BOOST_ASSERT(p->refs == 1); 70 6 : return p; 71 : } 72 : 73 : template<class T> 74 : void 75 6 : recycled<T>:: 76 : release(U* u) noexcept 77 : { 78 6 : if(--u->refs != 0) 79 0 : return; 80 : { 81 : #if !defined(BOOST_URL_DISABLE_THREADS) 82 : std::lock_guard< 83 6 : std::mutex> lock(m_); 84 : #endif 85 6 : u->next = head_; 86 6 : head_ = u; 87 : } 88 6 : detail::recycled_add( 89 : sizeof(U)); 90 : } 91 : 92 : //------------------------------------------------ 93 : 94 : template<class T> 95 14 : recycled_ptr<T>:: 96 : ~recycled_ptr() 97 : { 98 14 : if(p_) 99 6 : bin_->release(p_); 100 14 : } 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 6 : recycled_ptr<T>:: 113 : recycled_ptr( 114 : recycled<T>& bin, 115 : std::nullptr_t) noexcept 116 6 : : bin_(&bin) 117 : { 118 6 : } 119 : 120 : template<class T> 121 6 : recycled_ptr<T>:: 122 : recycled_ptr() 123 6 : : recycled_ptr(nullptr) 124 : { 125 6 : p_ = bin_->acquire(); 126 6 : } 127 : 128 : template<class T> 129 6 : recycled_ptr<T>:: 130 : recycled_ptr( 131 : std::nullptr_t) noexcept 132 6 : : recycled_ptr([]() -> B& 133 : { 134 : // VFALCO need guaranteed constexpr-init 135 6 : static B r; 136 6 : return r; 137 6 : }(), nullptr) 138 : { 139 6 : } 140 : 141 : template<class T> 142 0 : recycled_ptr<T>:: 143 : recycled_ptr( 144 : recycled_ptr const& other) noexcept 145 0 : : bin_(other.bin_) 146 0 : , p_(other.p_) 147 : { 148 0 : if(p_) 149 0 : ++p_->refs; 150 0 : } 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