ext-boost/boost/url/grammar/impl/recycled.hpp
2023-05-22 18:45:02 +10:00

222 lines
3.6 KiB
C++

//
// 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 <boost/assert.hpp>
namespace boost {
namespace urls {
namespace grammar {
//------------------------------------------------
template<class T>
recycled<T>::
~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<class T>
auto
recycled<T>::
acquire() ->
U*
{
U* p;
{
#if !defined(BOOST_URL_DISABLE_THREADS)
std::lock_guard<
std::mutex> lock(m_);
#endif
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<class T>
void
recycled<T>::
release(U* u) noexcept
{
if(--u->refs != 0)
return;
{
#if !defined(BOOST_URL_DISABLE_THREADS)
std::lock_guard<
std::mutex> lock(m_);
#endif
u->next = head_;
head_ = u;
}
detail::recycled_add(
sizeof(U));
}
//------------------------------------------------
template<class T>
recycled_ptr<T>::
~recycled_ptr()
{
if(p_)
bin_->release(p_);
}
template<class T>
recycled_ptr<T>::
recycled_ptr(
recycled<T>& bin)
: bin_(&bin)
, p_(bin.acquire())
{
}
template<class T>
recycled_ptr<T>::
recycled_ptr(
recycled<T>& bin,
std::nullptr_t) noexcept
: bin_(&bin)
{
}
template<class T>
recycled_ptr<T>::
recycled_ptr()
: recycled_ptr(nullptr)
{
p_ = bin_->acquire();
}
template<class T>
recycled_ptr<T>::
recycled_ptr(
std::nullptr_t) noexcept
: recycled_ptr([]() -> B&
{
// VFALCO need guaranteed constexpr-init
static B r;
return r;
}(), nullptr)
{
}
template<class T>
recycled_ptr<T>::
recycled_ptr(
recycled_ptr const& other) noexcept
: bin_(other.bin_)
, p_(other.p_)
{
if(p_)
++p_->refs;
}
template<class T>
recycled_ptr<T>::
recycled_ptr(
recycled_ptr&& other) noexcept
: bin_(other.bin_)
, p_(other.p_)
{
other.p_ = nullptr;
}
template<class T>
auto
recycled_ptr<T>::
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<class T>
auto
recycled_ptr<T>::
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<class T>
T&
recycled_ptr<T>::
acquire()
{
if(! p_)
p_ = bin_->acquire();
return p_->t;
}
template<class T>
void
recycled_ptr<T>::
release() noexcept
{
if(p_)
{
bin_->release(p_);
p_ = nullptr;
}
}
} // grammar
} // urls
} // boost
#endif