mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-20 11:05:54 +00:00
Replace qalloc with boost::pmr
This commit is contained in:
@@ -15,6 +15,7 @@ endif ()
|
|||||||
find_dependency (Boost 1.70
|
find_dependency (Boost 1.70
|
||||||
COMPONENTS
|
COMPONENTS
|
||||||
chrono
|
chrono
|
||||||
|
container
|
||||||
context
|
context
|
||||||
coroutine
|
coroutine
|
||||||
date_time
|
date_time
|
||||||
|
|||||||
@@ -722,7 +722,6 @@ target_sources (rippled PRIVATE
|
|||||||
src/test/basics/FeeUnits_test.cpp
|
src/test/basics/FeeUnits_test.cpp
|
||||||
src/test/basics/hardened_hash_test.cpp
|
src/test/basics/hardened_hash_test.cpp
|
||||||
src/test/basics/mulDiv_test.cpp
|
src/test/basics/mulDiv_test.cpp
|
||||||
src/test/basics/qalloc_test.cpp
|
|
||||||
src/test/basics/tagged_integer_test.cpp
|
src/test/basics/tagged_integer_test.cpp
|
||||||
#[===============================[
|
#[===============================[
|
||||||
test sources:
|
test sources:
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ endif ()
|
|||||||
find_package (Boost 1.70 REQUIRED
|
find_package (Boost 1.70 REQUIRED
|
||||||
COMPONENTS
|
COMPONENTS
|
||||||
chrono
|
chrono
|
||||||
|
container
|
||||||
context
|
context
|
||||||
coroutine
|
coroutine
|
||||||
date_time
|
date_time
|
||||||
@@ -69,6 +70,7 @@ target_link_libraries (ripple_boost
|
|||||||
INTERFACE
|
INTERFACE
|
||||||
Boost::boost
|
Boost::boost
|
||||||
Boost::chrono
|
Boost::chrono
|
||||||
|
Boost::container
|
||||||
Boost::coroutine
|
Boost::coroutine
|
||||||
Boost::date_time
|
Boost::date_time
|
||||||
Boost::filesystem
|
Boost::filesystem
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ if [[ ${BOOST_BUILD_ALL:-false} == "true" ]]; then
|
|||||||
BLDARGS+=(--without-python)
|
BLDARGS+=(--without-python)
|
||||||
else
|
else
|
||||||
BLDARGS+=(--with-chrono)
|
BLDARGS+=(--with-chrono)
|
||||||
|
BLDARGS+=(--with-container)
|
||||||
BLDARGS+=(--with-context)
|
BLDARGS+=(--with-context)
|
||||||
BLDARGS+=(--with-coroutine)
|
BLDARGS+=(--with-coroutine)
|
||||||
BLDARGS+=(--with-date_time)
|
BLDARGS+=(--with-date_time)
|
||||||
|
|||||||
@@ -1,372 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of rippled: https://github.com/ripple/rippled
|
|
||||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef RIPPLE_BASICS_QALLOC_H_INCLUDED
|
|
||||||
#define RIPPLE_BASICS_QALLOC_H_INCLUDED
|
|
||||||
|
|
||||||
#include <ripple/basics/ByteUtilities.h>
|
|
||||||
#include <ripple/basics/contract.h>
|
|
||||||
#include <boost/intrusive/list.hpp>
|
|
||||||
#include <cstddef>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <limits>
|
|
||||||
#include <memory>
|
|
||||||
#include <new>
|
|
||||||
#include <sstream>
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
namespace ripple {
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template <class = void>
|
|
||||||
class qalloc_impl
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
class block
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
std::size_t count_ = 0;
|
|
||||||
std::size_t bytes_;
|
|
||||||
std::size_t remain_;
|
|
||||||
std::uint8_t* free_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
block* next;
|
|
||||||
|
|
||||||
block(block const&) = delete;
|
|
||||||
block&
|
|
||||||
operator=(block const&) = delete;
|
|
||||||
|
|
||||||
explicit block(std::size_t bytes);
|
|
||||||
|
|
||||||
void*
|
|
||||||
allocate(std::size_t bytes, std::size_t align);
|
|
||||||
|
|
||||||
bool
|
|
||||||
deallocate();
|
|
||||||
};
|
|
||||||
|
|
||||||
block* used_ = nullptr;
|
|
||||||
block* free_ = nullptr;
|
|
||||||
|
|
||||||
public:
|
|
||||||
static constexpr auto block_size = kilobytes(256);
|
|
||||||
|
|
||||||
qalloc_impl() = default;
|
|
||||||
qalloc_impl(qalloc_impl const&) = delete;
|
|
||||||
qalloc_impl&
|
|
||||||
operator=(qalloc_impl const&) = delete;
|
|
||||||
|
|
||||||
~qalloc_impl();
|
|
||||||
|
|
||||||
void*
|
|
||||||
allocate(std::size_t bytes, std::size_t align);
|
|
||||||
|
|
||||||
void
|
|
||||||
deallocate(void* p);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
template <class T, bool ShareOnCopy = true>
|
|
||||||
class qalloc_type
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
template <class, bool>
|
|
||||||
friend class qalloc_type;
|
|
||||||
|
|
||||||
std::shared_ptr<detail::qalloc_impl<>> impl_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
using value_type = T;
|
|
||||||
using pointer = T*;
|
|
||||||
using const_pointer = T const*;
|
|
||||||
using reference = typename std::add_lvalue_reference<T>::type;
|
|
||||||
using const_reference = typename std::add_lvalue_reference<T const>::type;
|
|
||||||
using propagate_on_container_move_assignment = std::true_type;
|
|
||||||
|
|
||||||
template <class U>
|
|
||||||
struct rebind
|
|
||||||
{
|
|
||||||
explicit rebind() = default;
|
|
||||||
|
|
||||||
using other = qalloc_type<U, ShareOnCopy>;
|
|
||||||
};
|
|
||||||
|
|
||||||
qalloc_type(qalloc_type const&) = default;
|
|
||||||
qalloc_type(qalloc_type&& other) noexcept = default;
|
|
||||||
qalloc_type&
|
|
||||||
operator=(qalloc_type const&) = default;
|
|
||||||
qalloc_type&
|
|
||||||
operator=(qalloc_type&&) noexcept = default;
|
|
||||||
|
|
||||||
qalloc_type();
|
|
||||||
|
|
||||||
template <class U>
|
|
||||||
qalloc_type(qalloc_type<U, ShareOnCopy> const& u);
|
|
||||||
|
|
||||||
template <class U>
|
|
||||||
U*
|
|
||||||
alloc(std::size_t n);
|
|
||||||
|
|
||||||
template <class U>
|
|
||||||
void
|
|
||||||
dealloc(U* p, std::size_t n);
|
|
||||||
|
|
||||||
T*
|
|
||||||
allocate(std::size_t n);
|
|
||||||
|
|
||||||
void
|
|
||||||
deallocate(T* p, std::size_t n);
|
|
||||||
|
|
||||||
template <class U>
|
|
||||||
bool
|
|
||||||
operator==(qalloc_type<U, ShareOnCopy> const& u);
|
|
||||||
|
|
||||||
template <class U>
|
|
||||||
bool
|
|
||||||
operator!=(qalloc_type<U, ShareOnCopy> const& u);
|
|
||||||
|
|
||||||
qalloc_type
|
|
||||||
select_on_container_copy_construction() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
qalloc_type select_on_copy(std::true_type) const;
|
|
||||||
|
|
||||||
qalloc_type select_on_copy(std::false_type) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Allocator optimized for delete in temporal order.
|
|
||||||
|
|
||||||
This allocator is optimized for the case where objects
|
|
||||||
are deleted in approximately the same order that they
|
|
||||||
were created.
|
|
||||||
|
|
||||||
Thread Safety:
|
|
||||||
|
|
||||||
May not be called concurrently.
|
|
||||||
*/
|
|
||||||
using qalloc = qalloc_type<int, true>;
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template <class _>
|
|
||||||
qalloc_impl<_>::block::block(std::size_t bytes)
|
|
||||||
: bytes_(bytes - sizeof(*this))
|
|
||||||
, remain_(bytes_)
|
|
||||||
, free_(reinterpret_cast<std::uint8_t*>(this + 1))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class _>
|
|
||||||
void*
|
|
||||||
qalloc_impl<_>::block::allocate(std::size_t bytes, std::size_t align)
|
|
||||||
{
|
|
||||||
align = std::max(align, std::alignment_of<block*>::value);
|
|
||||||
auto pad = [](void const* p, std::size_t a) {
|
|
||||||
auto const i = reinterpret_cast<std::uintptr_t>(p);
|
|
||||||
return (a - (i % a)) % a;
|
|
||||||
};
|
|
||||||
|
|
||||||
auto const n0 = pad(free_ + sizeof(block*), align);
|
|
||||||
auto const n1 = n0 + sizeof(block*) + bytes;
|
|
||||||
if (remain_ < n1)
|
|
||||||
return nullptr;
|
|
||||||
auto p = reinterpret_cast<block**>(free_ + n0 + sizeof(block*));
|
|
||||||
assert(pad(p - 1, std::alignment_of<block*>::value) == 0);
|
|
||||||
p[-1] = this;
|
|
||||||
++count_;
|
|
||||||
free_ += n1;
|
|
||||||
remain_ -= n1;
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class _>
|
|
||||||
bool
|
|
||||||
qalloc_impl<_>::block::deallocate()
|
|
||||||
{
|
|
||||||
--count_;
|
|
||||||
if (count_ > 0)
|
|
||||||
return false;
|
|
||||||
remain_ = bytes_;
|
|
||||||
free_ = reinterpret_cast<std::uint8_t*>(this + 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class _>
|
|
||||||
qalloc_impl<_>::~qalloc_impl()
|
|
||||||
{
|
|
||||||
if (used_)
|
|
||||||
{
|
|
||||||
used_->~block();
|
|
||||||
std::free(used_);
|
|
||||||
}
|
|
||||||
while (free_)
|
|
||||||
{
|
|
||||||
auto const next = free_->next;
|
|
||||||
free_->~block();
|
|
||||||
std::free(free_);
|
|
||||||
free_ = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class _>
|
|
||||||
void*
|
|
||||||
qalloc_impl<_>::allocate(std::size_t bytes, std::size_t align)
|
|
||||||
{
|
|
||||||
if (used_)
|
|
||||||
{
|
|
||||||
auto const p = used_->allocate(bytes, align);
|
|
||||||
if (p)
|
|
||||||
return p;
|
|
||||||
used_ = nullptr;
|
|
||||||
}
|
|
||||||
if (free_)
|
|
||||||
{
|
|
||||||
auto const p = free_->allocate(bytes, align);
|
|
||||||
if (p)
|
|
||||||
{
|
|
||||||
used_ = free_;
|
|
||||||
free_ = free_->next;
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::size_t const adj_align =
|
|
||||||
std::max(align, std::alignment_of<block*>::value);
|
|
||||||
std::size_t const min_alloc = // align up
|
|
||||||
((sizeof(block) + sizeof(block*) + bytes) + (adj_align - 1)) &
|
|
||||||
~(adj_align - 1);
|
|
||||||
auto const n = std::max<std::size_t>(block_size, min_alloc);
|
|
||||||
block* const b = new (std::malloc(n)) block(n);
|
|
||||||
if (!b)
|
|
||||||
Throw<std::bad_alloc>();
|
|
||||||
used_ = b;
|
|
||||||
// VFALCO This has to succeed
|
|
||||||
return used_->allocate(bytes, align);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class _>
|
|
||||||
void
|
|
||||||
qalloc_impl<_>::deallocate(void* p)
|
|
||||||
{
|
|
||||||
auto const b = reinterpret_cast<block**>(p)[-1];
|
|
||||||
if (b->deallocate())
|
|
||||||
{
|
|
||||||
if (used_ == b)
|
|
||||||
used_ = nullptr;
|
|
||||||
b->next = free_;
|
|
||||||
free_ = b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template <class T, bool ShareOnCopy>
|
|
||||||
qalloc_type<T, ShareOnCopy>::qalloc_type()
|
|
||||||
: impl_(std::make_shared<detail::qalloc_impl<>>())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T, bool ShareOnCopy>
|
|
||||||
template <class U>
|
|
||||||
qalloc_type<T, ShareOnCopy>::qalloc_type(qalloc_type<U, ShareOnCopy> const& u)
|
|
||||||
: impl_(u.impl_)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T, bool ShareOnCopy>
|
|
||||||
template <class U>
|
|
||||||
U*
|
|
||||||
qalloc_type<T, ShareOnCopy>::alloc(std::size_t n)
|
|
||||||
{
|
|
||||||
if (n > std::numeric_limits<std::size_t>::max() / sizeof(U))
|
|
||||||
Throw<std::bad_alloc>();
|
|
||||||
auto const bytes = n * sizeof(U);
|
|
||||||
return static_cast<U*>(impl_->allocate(bytes, std::alignment_of<U>::value));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T, bool ShareOnCopy>
|
|
||||||
template <class U>
|
|
||||||
inline void
|
|
||||||
qalloc_type<T, ShareOnCopy>::dealloc(U* p, std::size_t n)
|
|
||||||
{
|
|
||||||
impl_->deallocate(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T, bool ShareOnCopy>
|
|
||||||
T*
|
|
||||||
qalloc_type<T, ShareOnCopy>::allocate(std::size_t n)
|
|
||||||
{
|
|
||||||
return alloc<T>(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T, bool ShareOnCopy>
|
|
||||||
inline void
|
|
||||||
qalloc_type<T, ShareOnCopy>::deallocate(T* p, std::size_t n)
|
|
||||||
{
|
|
||||||
dealloc(p, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T, bool ShareOnCopy>
|
|
||||||
template <class U>
|
|
||||||
inline bool
|
|
||||||
qalloc_type<T, ShareOnCopy>::operator==(qalloc_type<U, ShareOnCopy> const& u)
|
|
||||||
{
|
|
||||||
return impl_.get() == u.impl_.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T, bool ShareOnCopy>
|
|
||||||
template <class U>
|
|
||||||
inline bool
|
|
||||||
qalloc_type<T, ShareOnCopy>::operator!=(qalloc_type<U, ShareOnCopy> const& u)
|
|
||||||
{
|
|
||||||
return !(*this == u);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T, bool ShareOnCopy>
|
|
||||||
auto
|
|
||||||
qalloc_type<T, ShareOnCopy>::select_on_container_copy_construction() const
|
|
||||||
-> qalloc_type
|
|
||||||
{
|
|
||||||
return select_on_copy(std::integral_constant<bool, ShareOnCopy>{});
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T, bool ShareOnCopy>
|
|
||||||
auto qalloc_type<T, ShareOnCopy>::select_on_copy(std::true_type) const
|
|
||||||
-> qalloc_type
|
|
||||||
{
|
|
||||||
return *this; // shared arena
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T, bool ShareOnCopy>
|
|
||||||
auto qalloc_type<T, ShareOnCopy>::select_on_copy(std::false_type) const
|
|
||||||
-> qalloc_type
|
|
||||||
{
|
|
||||||
return {}; // new arena
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ripple
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -21,10 +21,13 @@
|
|||||||
#define RIPPLE_LEDGER_OPENVIEW_H_INCLUDED
|
#define RIPPLE_LEDGER_OPENVIEW_H_INCLUDED
|
||||||
|
|
||||||
#include <ripple/basics/XRPAmount.h>
|
#include <ripple/basics/XRPAmount.h>
|
||||||
#include <ripple/basics/qalloc.h>
|
|
||||||
#include <ripple/ledger/RawView.h>
|
#include <ripple/ledger/RawView.h>
|
||||||
#include <ripple/ledger/ReadView.h>
|
#include <ripple/ledger/ReadView.h>
|
||||||
#include <ripple/ledger/detail/RawStateTable.h>
|
#include <ripple/ledger/detail/RawStateTable.h>
|
||||||
|
|
||||||
|
#include <boost/container/pmr/monotonic_buffer_resource.hpp>
|
||||||
|
#include <boost/container/pmr/polymorphic_allocator.hpp>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
@@ -52,25 +55,43 @@ extern open_ledger_t const open_ledger;
|
|||||||
class OpenView final : public ReadView, public TxsRawView
|
class OpenView final : public ReadView, public TxsRawView
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
// Initial size for the monotonic_buffer_resource used for allocations
|
||||||
|
// The size was chosen from the old `qalloc` code (which this replaces).
|
||||||
|
// It is unclear how the size initially chosen in qalloc.
|
||||||
|
static constexpr size_t initialBufferSize = kilobytes(256);
|
||||||
|
|
||||||
class txs_iter_impl;
|
class txs_iter_impl;
|
||||||
|
|
||||||
|
struct txData
|
||||||
|
{
|
||||||
|
std::shared_ptr<Serializer const> txn;
|
||||||
|
std::shared_ptr<Serializer const> meta;
|
||||||
|
|
||||||
|
// Constructor needed for emplacement in std::map
|
||||||
|
txData(
|
||||||
|
std::shared_ptr<Serializer const> const& txn_,
|
||||||
|
std::shared_ptr<Serializer const> const& meta_)
|
||||||
|
: txn(txn_), meta(meta_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// List of tx, key order
|
// List of tx, key order
|
||||||
|
// Use the boost pmr functionality instead of the c++-17 standard pmr
|
||||||
|
// functions b/c clang does not support pmr yet (as-of 9/2020)
|
||||||
using txs_map = std::map<
|
using txs_map = std::map<
|
||||||
key_type,
|
key_type,
|
||||||
std::pair<
|
txData,
|
||||||
std::shared_ptr<Serializer const>,
|
|
||||||
std::shared_ptr<Serializer const>>,
|
|
||||||
std::less<key_type>,
|
std::less<key_type>,
|
||||||
qalloc_type<
|
boost::container::pmr::polymorphic_allocator<
|
||||||
std::pair<
|
std::pair<key_type const, txData>>>;
|
||||||
key_type const,
|
|
||||||
std::pair<
|
|
||||||
std::shared_ptr<Serializer const>,
|
|
||||||
std::shared_ptr<Serializer const>>>,
|
|
||||||
false>>;
|
|
||||||
|
|
||||||
Rules rules_;
|
// monotonic_resource_ must outlive `items_`. Make a pointer so it may be
|
||||||
|
// easily moved.
|
||||||
|
std::unique_ptr<boost::container::pmr::monotonic_buffer_resource>
|
||||||
|
monotonic_resource_;
|
||||||
txs_map txs_;
|
txs_map txs_;
|
||||||
|
Rules rules_;
|
||||||
LedgerInfo info_;
|
LedgerInfo info_;
|
||||||
ReadView const* base_;
|
ReadView const* base_;
|
||||||
detail::RawStateTable items_;
|
detail::RawStateTable items_;
|
||||||
@@ -98,7 +119,7 @@ public:
|
|||||||
Since the SLEs are immutable, calls on the
|
Since the SLEs are immutable, calls on the
|
||||||
RawView interface cannot break invariants.
|
RawView interface cannot break invariants.
|
||||||
*/
|
*/
|
||||||
OpenView(OpenView const&) = default;
|
OpenView(OpenView const&);
|
||||||
|
|
||||||
/** Construct an open ledger view.
|
/** Construct an open ledger view.
|
||||||
|
|
||||||
|
|||||||
@@ -20,9 +20,12 @@
|
|||||||
#ifndef RIPPLE_LEDGER_RAWSTATETABLE_H_INCLUDED
|
#ifndef RIPPLE_LEDGER_RAWSTATETABLE_H_INCLUDED
|
||||||
#define RIPPLE_LEDGER_RAWSTATETABLE_H_INCLUDED
|
#define RIPPLE_LEDGER_RAWSTATETABLE_H_INCLUDED
|
||||||
|
|
||||||
#include <ripple/basics/qalloc.h>
|
|
||||||
#include <ripple/ledger/RawView.h>
|
#include <ripple/ledger/RawView.h>
|
||||||
#include <ripple/ledger/ReadView.h>
|
#include <ripple/ledger/ReadView.h>
|
||||||
|
|
||||||
|
#include <boost/container/pmr/monotonic_buffer_resource.hpp>
|
||||||
|
#include <boost/container/pmr/polymorphic_allocator.hpp>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
@@ -34,9 +37,24 @@ class RawStateTable
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using key_type = ReadView::key_type;
|
using key_type = ReadView::key_type;
|
||||||
|
// Initial size for the monotonic_buffer_resource used for allocations
|
||||||
|
// The size was chosen from the old `qalloc` code (which this replaces).
|
||||||
|
// It is unclear how the size initially chosen in qalloc.
|
||||||
|
static constexpr size_t initialBufferSize = kilobytes(256);
|
||||||
|
|
||||||
|
RawStateTable()
|
||||||
|
: monotonic_resource_{std::make_unique<
|
||||||
|
boost::container::pmr::monotonic_buffer_resource>(
|
||||||
|
initialBufferSize)}
|
||||||
|
, items_{monotonic_resource_.get()} {};
|
||||||
|
|
||||||
|
RawStateTable(RawStateTable const& rhs)
|
||||||
|
: monotonic_resource_{std::make_unique<
|
||||||
|
boost::container::pmr::monotonic_buffer_resource>(
|
||||||
|
initialBufferSize)}
|
||||||
|
, items_{rhs.items_, monotonic_resource_.get()}
|
||||||
|
, dropsDestroyed_{rhs.dropsDestroyed_} {};
|
||||||
|
|
||||||
RawStateTable() = default;
|
|
||||||
RawStateTable(RawStateTable const&) = default;
|
|
||||||
RawStateTable(RawStateTable&&) = default;
|
RawStateTable(RawStateTable&&) = default;
|
||||||
|
|
||||||
RawStateTable&
|
RawStateTable&
|
||||||
@@ -89,15 +107,32 @@ private:
|
|||||||
|
|
||||||
class sles_iter_impl;
|
class sles_iter_impl;
|
||||||
|
|
||||||
|
struct sleAction
|
||||||
|
{
|
||||||
|
Action action;
|
||||||
|
std::shared_ptr<SLE> sle;
|
||||||
|
|
||||||
|
// Constructor needed for emplacement in std::map
|
||||||
|
sleAction(Action action_, std::shared_ptr<SLE> const& sle_)
|
||||||
|
: action(action_), sle(sle_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Use the boost pmr functionality instead of the c++-17 standard pmr
|
||||||
|
// functions b/c clang does not support pmr yet (as-of 9/2020)
|
||||||
using items_t = std::map<
|
using items_t = std::map<
|
||||||
key_type,
|
key_type,
|
||||||
std::pair<Action, std::shared_ptr<SLE>>,
|
sleAction,
|
||||||
std::less<key_type>,
|
std::less<key_type>,
|
||||||
qalloc_type<
|
boost::container::pmr::polymorphic_allocator<
|
||||||
std::pair<key_type const, std::pair<Action, std::shared_ptr<SLE>>>,
|
std::pair<const key_type, sleAction>>>;
|
||||||
false>>;
|
// monotonic_resource_ must outlive `items_`. Make a pointer so it may be
|
||||||
|
// easily moved.
|
||||||
|
std::unique_ptr<boost::container::pmr::monotonic_buffer_resource>
|
||||||
|
monotonic_resource_;
|
||||||
items_t items_;
|
items_t items_;
|
||||||
|
|
||||||
XRPAmount dropsDestroyed_{0};
|
XRPAmount dropsDestroyed_{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -60,12 +60,12 @@ public:
|
|||||||
{
|
{
|
||||||
value_type result;
|
value_type result;
|
||||||
{
|
{
|
||||||
SerialIter sit(iter_->second.first->slice());
|
SerialIter sit(iter_->second.txn->slice());
|
||||||
result.first = std::make_shared<STTx const>(sit);
|
result.first = std::make_shared<STTx const>(sit);
|
||||||
}
|
}
|
||||||
if (metadata_)
|
if (metadata_)
|
||||||
{
|
{
|
||||||
SerialIter sit(iter_->second.second->slice());
|
SerialIter sit(iter_->second.meta->slice());
|
||||||
result.second = std::make_shared<STObject const>(sit, sfMetadata);
|
result.second = std::make_shared<STObject const>(sit, sfMetadata);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@@ -74,12 +74,31 @@ public:
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
OpenView::OpenView(OpenView const& rhs)
|
||||||
|
: ReadView(rhs)
|
||||||
|
, TxsRawView(rhs)
|
||||||
|
, monotonic_resource_{std::make_unique<
|
||||||
|
boost::container::pmr::monotonic_buffer_resource>(initialBufferSize)}
|
||||||
|
, txs_{rhs.txs_, monotonic_resource_.get()}
|
||||||
|
, rules_{rhs.rules_}
|
||||||
|
, info_{rhs.info_}
|
||||||
|
, base_{rhs.base_}
|
||||||
|
, items_{rhs.items_}
|
||||||
|
, hold_{rhs.hold_}
|
||||||
|
, open_{rhs.open_} {};
|
||||||
|
|
||||||
OpenView::OpenView(
|
OpenView::OpenView(
|
||||||
open_ledger_t,
|
open_ledger_t,
|
||||||
ReadView const* base,
|
ReadView const* base,
|
||||||
Rules const& rules,
|
Rules const& rules,
|
||||||
std::shared_ptr<void const> hold)
|
std::shared_ptr<void const> hold)
|
||||||
: rules_(rules), info_(base->info()), base_(base), hold_(std::move(hold))
|
: monotonic_resource_{std::make_unique<
|
||||||
|
boost::container::pmr::monotonic_buffer_resource>(initialBufferSize)}
|
||||||
|
, txs_{monotonic_resource_.get()}
|
||||||
|
, rules_(rules)
|
||||||
|
, info_(base->info())
|
||||||
|
, base_(base)
|
||||||
|
, hold_(std::move(hold))
|
||||||
{
|
{
|
||||||
info_.validated = false;
|
info_.validated = false;
|
||||||
info_.accepted = false;
|
info_.accepted = false;
|
||||||
@@ -89,7 +108,10 @@ OpenView::OpenView(
|
|||||||
}
|
}
|
||||||
|
|
||||||
OpenView::OpenView(ReadView const* base, std::shared_ptr<void const> hold)
|
OpenView::OpenView(ReadView const* base, std::shared_ptr<void const> hold)
|
||||||
: rules_(base->rules())
|
: monotonic_resource_{std::make_unique<
|
||||||
|
boost::container::pmr::monotonic_buffer_resource>(initialBufferSize)}
|
||||||
|
, txs_{monotonic_resource_.get()}
|
||||||
|
, rules_(base->rules())
|
||||||
, info_(base->info())
|
, info_(base->info())
|
||||||
, base_(base)
|
, base_(base)
|
||||||
, hold_(std::move(hold))
|
, hold_(std::move(hold))
|
||||||
@@ -108,7 +130,7 @@ OpenView::apply(TxsRawView& to) const
|
|||||||
{
|
{
|
||||||
items_.apply(to);
|
items_.apply(to);
|
||||||
for (auto const& item : txs_)
|
for (auto const& item : txs_)
|
||||||
to.rawTxInsert(item.first, item.second.first, item.second.second);
|
to.rawTxInsert(item.first, item.second.txn, item.second.meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---
|
//---
|
||||||
@@ -194,11 +216,11 @@ OpenView::txRead(key_type const& key) const -> tx_type
|
|||||||
if (iter == txs_.end())
|
if (iter == txs_.end())
|
||||||
return base_->txRead(key);
|
return base_->txRead(key);
|
||||||
auto const& item = iter->second;
|
auto const& item = iter->second;
|
||||||
auto stx = std::make_shared<STTx const>(SerialIter{item.first->slice()});
|
auto stx = std::make_shared<STTx const>(SerialIter{item.txn->slice()});
|
||||||
decltype(tx_type::second) sto;
|
decltype(tx_type::second) sto;
|
||||||
if (item.second)
|
if (item.meta)
|
||||||
sto = std::make_shared<STObject const>(
|
sto = std::make_shared<STObject const>(
|
||||||
SerialIter{item.second->slice()}, sfMetadata);
|
SerialIter{item.meta->slice()}, sfMetadata);
|
||||||
else
|
else
|
||||||
sto = nullptr;
|
sto = nullptr;
|
||||||
return {std::move(stx), std::move(sto)};
|
return {std::move(stx), std::move(sto)};
|
||||||
@@ -240,7 +262,10 @@ OpenView::rawTxInsert(
|
|||||||
std::shared_ptr<Serializer const> const& txn,
|
std::shared_ptr<Serializer const> const& txn,
|
||||||
std::shared_ptr<Serializer const> const& metaData)
|
std::shared_ptr<Serializer const> const& metaData)
|
||||||
{
|
{
|
||||||
auto const result = txs_.emplace(key, std::make_pair(txn, metaData));
|
auto const result = txs_.emplace(
|
||||||
|
std::piecewise_construct,
|
||||||
|
std::forward_as_tuple(key),
|
||||||
|
std::forward_as_tuple(txn, metaData));
|
||||||
if (!result.second)
|
if (!result.second)
|
||||||
LogicError("rawTxInsert: duplicate TX id" + to_string(key));
|
LogicError("rawTxInsert: duplicate TX id" + to_string(key));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public:
|
|||||||
sle0_ = *iter0_;
|
sle0_ = *iter0_;
|
||||||
if (iter1_ != end1)
|
if (iter1_ != end1)
|
||||||
{
|
{
|
||||||
sle1_ = iter1_->second.second;
|
sle1_ = iter1_->second.sle;
|
||||||
skip();
|
skip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -129,13 +129,13 @@ private:
|
|||||||
if (iter1_ == end1_)
|
if (iter1_ == end1_)
|
||||||
sle1_ = nullptr;
|
sle1_ = nullptr;
|
||||||
else
|
else
|
||||||
sle1_ = iter1_->second.second;
|
sle1_ = iter1_->second.sle;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
skip()
|
skip()
|
||||||
{
|
{
|
||||||
while (iter1_ != end1_ && iter1_->second.first == Action::erase &&
|
while (iter1_ != end1_ && iter1_->second.action == Action::erase &&
|
||||||
sle0_->key() == sle1_->key())
|
sle0_->key() == sle1_->key())
|
||||||
{
|
{
|
||||||
inc1();
|
inc1();
|
||||||
@@ -157,16 +157,16 @@ RawStateTable::apply(RawView& to) const
|
|||||||
for (auto const& elem : items_)
|
for (auto const& elem : items_)
|
||||||
{
|
{
|
||||||
auto const& item = elem.second;
|
auto const& item = elem.second;
|
||||||
switch (item.first)
|
switch (item.action)
|
||||||
{
|
{
|
||||||
case Action::erase:
|
case Action::erase:
|
||||||
to.rawErase(item.second);
|
to.rawErase(item.sle);
|
||||||
break;
|
break;
|
||||||
case Action::insert:
|
case Action::insert:
|
||||||
to.rawInsert(item.second);
|
to.rawInsert(item.sle);
|
||||||
break;
|
break;
|
||||||
case Action::replace:
|
case Action::replace:
|
||||||
to.rawReplace(item.second);
|
to.rawReplace(item.sle);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -180,9 +180,9 @@ RawStateTable::exists(ReadView const& base, Keylet const& k) const
|
|||||||
if (iter == items_.end())
|
if (iter == items_.end())
|
||||||
return base.exists(k);
|
return base.exists(k);
|
||||||
auto const& item = iter->second;
|
auto const& item = iter->second;
|
||||||
if (item.first == Action::erase)
|
if (item.action == Action::erase)
|
||||||
return false;
|
return false;
|
||||||
if (!k.check(*item.second))
|
if (!k.check(*item.sle))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -207,11 +207,11 @@ RawStateTable::succ(
|
|||||||
if (!next)
|
if (!next)
|
||||||
break;
|
break;
|
||||||
iter = items_.find(*next);
|
iter = items_.find(*next);
|
||||||
} while (iter != items_.end() && iter->second.first == Action::erase);
|
} while (iter != items_.end() && iter->second.action == Action::erase);
|
||||||
// Find non-deleted successor in our list
|
// Find non-deleted successor in our list
|
||||||
for (iter = items_.upper_bound(key); iter != items_.end(); ++iter)
|
for (iter = items_.upper_bound(key); iter != items_.end(); ++iter)
|
||||||
{
|
{
|
||||||
if (iter->second.first != Action::erase)
|
if (iter->second.action != Action::erase)
|
||||||
{
|
{
|
||||||
// Found both, return the lower key
|
// Found both, return the lower key
|
||||||
if (!next || next > iter->first)
|
if (!next || next > iter->first)
|
||||||
@@ -237,7 +237,7 @@ RawStateTable::erase(std::shared_ptr<SLE> const& sle)
|
|||||||
if (result.second)
|
if (result.second)
|
||||||
return;
|
return;
|
||||||
auto& item = result.first->second;
|
auto& item = result.first->second;
|
||||||
switch (item.first)
|
switch (item.action)
|
||||||
{
|
{
|
||||||
case Action::erase:
|
case Action::erase:
|
||||||
LogicError("RawStateTable::erase: already erased");
|
LogicError("RawStateTable::erase: already erased");
|
||||||
@@ -246,8 +246,8 @@ RawStateTable::erase(std::shared_ptr<SLE> const& sle)
|
|||||||
items_.erase(result.first);
|
items_.erase(result.first);
|
||||||
break;
|
break;
|
||||||
case Action::replace:
|
case Action::replace:
|
||||||
item.first = Action::erase;
|
item.action = Action::erase;
|
||||||
item.second = sle;
|
item.sle = sle;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -262,11 +262,11 @@ RawStateTable::insert(std::shared_ptr<SLE> const& sle)
|
|||||||
if (result.second)
|
if (result.second)
|
||||||
return;
|
return;
|
||||||
auto& item = result.first->second;
|
auto& item = result.first->second;
|
||||||
switch (item.first)
|
switch (item.action)
|
||||||
{
|
{
|
||||||
case Action::erase:
|
case Action::erase:
|
||||||
item.first = Action::replace;
|
item.action = Action::replace;
|
||||||
item.second = sle;
|
item.sle = sle;
|
||||||
break;
|
break;
|
||||||
case Action::insert:
|
case Action::insert:
|
||||||
LogicError("RawStateTable::insert: already inserted");
|
LogicError("RawStateTable::insert: already inserted");
|
||||||
@@ -287,14 +287,14 @@ RawStateTable::replace(std::shared_ptr<SLE> const& sle)
|
|||||||
if (result.second)
|
if (result.second)
|
||||||
return;
|
return;
|
||||||
auto& item = result.first->second;
|
auto& item = result.first->second;
|
||||||
switch (item.first)
|
switch (item.action)
|
||||||
{
|
{
|
||||||
case Action::erase:
|
case Action::erase:
|
||||||
LogicError("RawStateTable::replace: was erased");
|
LogicError("RawStateTable::replace: was erased");
|
||||||
break;
|
break;
|
||||||
case Action::insert:
|
case Action::insert:
|
||||||
case Action::replace:
|
case Action::replace:
|
||||||
item.second = sle;
|
item.sle = sle;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -306,10 +306,10 @@ RawStateTable::read(ReadView const& base, Keylet const& k) const
|
|||||||
if (iter == items_.end())
|
if (iter == items_.end())
|
||||||
return base.read(k);
|
return base.read(k);
|
||||||
auto const& item = iter->second;
|
auto const& item = iter->second;
|
||||||
if (item.first == Action::erase)
|
if (item.action == Action::erase)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
// Convert to SLE const
|
// Convert to SLE const
|
||||||
std::shared_ptr<SLE const> sle = item.second;
|
std::shared_ptr<SLE const> sle = item.sle;
|
||||||
if (!k.check(*sle))
|
if (!k.check(*sle))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return sle;
|
return sle;
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of rippled: https://github.com/ripple/rippled
|
|
||||||
Copyright (c) 2018 Ripple Labs Inc.
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#include <ripple/basics/qalloc.h>
|
|
||||||
#include <ripple/beast/unit_test.h>
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
namespace ripple {
|
|
||||||
|
|
||||||
struct qalloc_test : beast::unit_test::suite
|
|
||||||
{
|
|
||||||
void
|
|
||||||
testBasicProperties()
|
|
||||||
{
|
|
||||||
BEAST_EXPECT(std::is_default_constructible<qalloc>{});
|
|
||||||
BEAST_EXPECT(std::is_copy_constructible<qalloc>{});
|
|
||||||
BEAST_EXPECT(std::is_copy_assignable<qalloc>{});
|
|
||||||
BEAST_EXPECT(std::is_nothrow_move_constructible<qalloc>{});
|
|
||||||
BEAST_EXPECT(std::is_nothrow_move_assignable<qalloc>{});
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
run() override
|
|
||||||
{
|
|
||||||
testBasicProperties();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
BEAST_DEFINE_TESTSUITE(qalloc, ripple_basics, ripple);
|
|
||||||
|
|
||||||
} // namespace ripple
|
|
||||||
@@ -20,9 +20,12 @@
|
|||||||
#ifndef RIPPLE_TEST_CSF_SCHEDULER_H_INCLUDED
|
#ifndef RIPPLE_TEST_CSF_SCHEDULER_H_INCLUDED
|
||||||
#define RIPPLE_TEST_CSF_SCHEDULER_H_INCLUDED
|
#define RIPPLE_TEST_CSF_SCHEDULER_H_INCLUDED
|
||||||
|
|
||||||
#include <ripple/basics/qalloc.h>
|
#include <ripple/basics/ByteUtilities.h>
|
||||||
#include <ripple/beast/clock/manual_clock.h>
|
#include <ripple/beast/clock/manual_clock.h>
|
||||||
|
|
||||||
|
#include <boost/container/pmr/monotonic_buffer_resource.hpp>
|
||||||
#include <boost/intrusive/set.hpp>
|
#include <boost/intrusive/set.hpp>
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
@@ -109,8 +112,8 @@ private:
|
|||||||
using by_when_set = typename boost::intrusive::make_multiset<
|
using by_when_set = typename boost::intrusive::make_multiset<
|
||||||
event,
|
event,
|
||||||
boost::intrusive::constant_time_size<false>>::type;
|
boost::intrusive::constant_time_size<false>>::type;
|
||||||
|
// alloc_ is owned by the scheduler
|
||||||
qalloc alloc_;
|
boost::container::pmr::monotonic_buffer_resource* alloc_;
|
||||||
by_when_set by_when_;
|
by_when_set by_when_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -120,7 +123,8 @@ private:
|
|||||||
queue_type&
|
queue_type&
|
||||||
operator=(queue_type const&) = delete;
|
operator=(queue_type const&) = delete;
|
||||||
|
|
||||||
explicit queue_type(qalloc const& alloc);
|
explicit queue_type(
|
||||||
|
boost::container::pmr::monotonic_buffer_resource* alloc);
|
||||||
|
|
||||||
~queue_type();
|
~queue_type();
|
||||||
|
|
||||||
@@ -141,7 +145,7 @@ private:
|
|||||||
erase(iterator iter);
|
erase(iterator iter);
|
||||||
};
|
};
|
||||||
|
|
||||||
qalloc alloc_;
|
boost::container::pmr::monotonic_buffer_resource alloc_{kilobytes(256)};
|
||||||
queue_type queue_;
|
queue_type queue_;
|
||||||
|
|
||||||
// Aged containers that rely on this clock take a non-const reference =(
|
// Aged containers that rely on this clock take a non-const reference =(
|
||||||
@@ -154,10 +158,6 @@ public:
|
|||||||
|
|
||||||
Scheduler();
|
Scheduler();
|
||||||
|
|
||||||
/** Return the allocator. */
|
|
||||||
qalloc const&
|
|
||||||
alloc() const;
|
|
||||||
|
|
||||||
/** Return the clock. (aged_containers want a non-const ref =( */
|
/** Return the clock. (aged_containers want a non-const ref =( */
|
||||||
clock_type&
|
clock_type&
|
||||||
clock() const;
|
clock() const;
|
||||||
@@ -275,7 +275,9 @@ public:
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
inline Scheduler::queue_type::queue_type(qalloc const& alloc) : alloc_(alloc)
|
inline Scheduler::queue_type::queue_type(
|
||||||
|
boost::container::pmr::monotonic_buffer_resource* alloc)
|
||||||
|
: alloc_(alloc)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,7 +288,7 @@ inline Scheduler::queue_type::~queue_type()
|
|||||||
auto e = &*iter;
|
auto e = &*iter;
|
||||||
++iter;
|
++iter;
|
||||||
e->~event();
|
e->~event();
|
||||||
alloc_.dealloc(e, 1);
|
alloc_->deallocate(e, sizeof(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,7 +316,7 @@ Scheduler::queue_type::emplace(time_point when, Handler&& h) ->
|
|||||||
typename by_when_set::iterator
|
typename by_when_set::iterator
|
||||||
{
|
{
|
||||||
using event_type = event_impl<std::decay_t<Handler>>;
|
using event_type = event_impl<std::decay_t<Handler>>;
|
||||||
auto const p = alloc_.alloc<event_type>(1);
|
auto const p = alloc_->allocate(sizeof(event_type));
|
||||||
auto& e = *new (p) event_type(when, std::forward<Handler>(h));
|
auto& e = *new (p) event_type(when, std::forward<Handler>(h));
|
||||||
return by_when_.insert(e);
|
return by_when_.insert(e);
|
||||||
}
|
}
|
||||||
@@ -325,7 +327,7 @@ Scheduler::queue_type::erase(iterator iter) -> typename by_when_set::iterator
|
|||||||
auto& e = *iter;
|
auto& e = *iter;
|
||||||
auto next = by_when_.erase(iter);
|
auto next = by_when_.erase(iter);
|
||||||
e.~event();
|
e.~event();
|
||||||
alloc_.dealloc(&e, 1);
|
alloc_->deallocate(&e, sizeof(e));
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -349,16 +351,10 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
inline Scheduler::Scheduler() : queue_(alloc_)
|
inline Scheduler::Scheduler() : queue_(&alloc_)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
inline qalloc const&
|
|
||||||
Scheduler::alloc() const
|
|
||||||
{
|
|
||||||
return alloc_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline auto
|
inline auto
|
||||||
Scheduler::clock() const -> clock_type&
|
Scheduler::clock() const -> clock_type&
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,10 +17,12 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
|
#include <ripple/basics/ByteUtilities.h>
|
||||||
#include <ripple/beast/unit_test.h>
|
#include <ripple/beast/unit_test.h>
|
||||||
#include <set>
|
|
||||||
#include <test/csf/Scheduler.h>
|
#include <test/csf/Scheduler.h>
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
namespace test {
|
namespace test {
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user