// // Copyright (c) 2022 Vinnie Falco (vinnie.falco@gmail.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Official repository: https://github.com/boostorg/url // #ifndef BOOST_URL_GRAMMAR_IMPL_RECYCLED_PTR_HPP #define BOOST_URL_GRAMMAR_IMPL_RECYCLED_PTR_HPP #include namespace boost { namespace urls { namespace grammar { //------------------------------------------------ template recycled:: ~recycled() { std::size_t n = 0; // VFALCO we should probably deallocate // in reverse order of allocation but // that requires a doubly-linked list. auto it = head_; while(it) { ++n; auto next = it->next; BOOST_ASSERT( it->refs == 0); delete it; it = next; } detail::recycled_remove( sizeof(U) * n); } template auto recycled:: acquire() -> U* { U* p; { std::lock_guard< std::mutex> lock(m_); p = head_; if(p) { // reuse head_ = head_->next; detail::recycled_remove( sizeof(U)); ++p->refs; } else { p = new U; } } BOOST_ASSERT(p->refs == 1); return p; } template void recycled:: release(U* u) noexcept { if(--u->refs != 0) return; m_.lock(); u->next = head_; head_ = u; m_.unlock(); detail::recycled_add( sizeof(U)); } //------------------------------------------------ template recycled_ptr:: ~recycled_ptr() { if(p_) bin_->release(p_); } template recycled_ptr:: recycled_ptr( recycled& bin) : bin_(&bin) , p_(bin.acquire()) { } template recycled_ptr:: recycled_ptr( recycled& bin, std::nullptr_t) noexcept : bin_(&bin) { } template recycled_ptr:: recycled_ptr() : recycled_ptr(nullptr) { p_ = bin_->acquire(); } template recycled_ptr:: recycled_ptr( std::nullptr_t) noexcept : recycled_ptr([]() -> B& { // VFALCO need guaranteed constexpr-init static B r; return r; }(), nullptr) { } template recycled_ptr:: recycled_ptr( recycled_ptr const& other) noexcept : bin_(other.bin_) , p_(other.p_) { if(p_) ++p_->refs; } template recycled_ptr:: recycled_ptr( recycled_ptr&& other) noexcept : bin_(other.bin_) , p_(other.p_) { other.p_ = nullptr; } template auto recycled_ptr:: operator=( recycled_ptr&& other) noexcept -> recycled_ptr& { BOOST_ASSERT( bin_ == other.bin_); if(p_) bin_->release(p_); p_ = other.p_; other.p_ = nullptr; return *this; } template auto recycled_ptr:: operator=( recycled_ptr const& other) noexcept -> recycled_ptr& { BOOST_ASSERT( bin_ == other.bin_); if(p_) bin_->release(p_); p_ = other.p_; if(p_) ++p_->refs; return *this; } template T& recycled_ptr:: acquire() { if(! p_) p_ = bin_->acquire(); return p_->t; } template void recycled_ptr:: release() noexcept { if(p_) { bin_->release(p_); p_ = nullptr; } } } // grammar } // urls } // boost #endif