222 lines
3.6 KiB
C++
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
|