mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-19 18:45:52 +00:00
Replace qalloc with boost::pmr
This commit is contained in:
@@ -15,6 +15,7 @@ endif ()
|
||||
find_dependency (Boost 1.70
|
||||
COMPONENTS
|
||||
chrono
|
||||
container
|
||||
context
|
||||
coroutine
|
||||
date_time
|
||||
|
||||
@@ -722,7 +722,6 @@ target_sources (rippled PRIVATE
|
||||
src/test/basics/FeeUnits_test.cpp
|
||||
src/test/basics/hardened_hash_test.cpp
|
||||
src/test/basics/mulDiv_test.cpp
|
||||
src/test/basics/qalloc_test.cpp
|
||||
src/test/basics/tagged_integer_test.cpp
|
||||
#[===============================[
|
||||
test sources:
|
||||
|
||||
@@ -47,6 +47,7 @@ endif ()
|
||||
find_package (Boost 1.70 REQUIRED
|
||||
COMPONENTS
|
||||
chrono
|
||||
container
|
||||
context
|
||||
coroutine
|
||||
date_time
|
||||
@@ -69,6 +70,7 @@ target_link_libraries (ripple_boost
|
||||
INTERFACE
|
||||
Boost::boost
|
||||
Boost::chrono
|
||||
Boost::container
|
||||
Boost::coroutine
|
||||
Boost::date_time
|
||||
Boost::filesystem
|
||||
|
||||
@@ -44,6 +44,7 @@ if [[ ${BOOST_BUILD_ALL:-false} == "true" ]]; then
|
||||
BLDARGS+=(--without-python)
|
||||
else
|
||||
BLDARGS+=(--with-chrono)
|
||||
BLDARGS+=(--with-container)
|
||||
BLDARGS+=(--with-context)
|
||||
BLDARGS+=(--with-coroutine)
|
||||
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
|
||||
|
||||
#include <ripple/basics/XRPAmount.h>
|
||||
#include <ripple/basics/qalloc.h>
|
||||
#include <ripple/ledger/RawView.h>
|
||||
#include <ripple/ledger/ReadView.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 <utility>
|
||||
|
||||
@@ -52,25 +55,43 @@ extern open_ledger_t const open_ledger;
|
||||
class OpenView final : public ReadView, public TxsRawView
|
||||
{
|
||||
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;
|
||||
|
||||
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
|
||||
// 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<
|
||||
key_type,
|
||||
std::pair<
|
||||
std::shared_ptr<Serializer const>,
|
||||
std::shared_ptr<Serializer const>>,
|
||||
txData,
|
||||
std::less<key_type>,
|
||||
qalloc_type<
|
||||
std::pair<
|
||||
key_type const,
|
||||
std::pair<
|
||||
std::shared_ptr<Serializer const>,
|
||||
std::shared_ptr<Serializer const>>>,
|
||||
false>>;
|
||||
boost::container::pmr::polymorphic_allocator<
|
||||
std::pair<key_type const, txData>>>;
|
||||
|
||||
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_;
|
||||
Rules rules_;
|
||||
LedgerInfo info_;
|
||||
ReadView const* base_;
|
||||
detail::RawStateTable items_;
|
||||
@@ -98,7 +119,7 @@ public:
|
||||
Since the SLEs are immutable, calls on the
|
||||
RawView interface cannot break invariants.
|
||||
*/
|
||||
OpenView(OpenView const&) = default;
|
||||
OpenView(OpenView const&);
|
||||
|
||||
/** Construct an open ledger view.
|
||||
|
||||
|
||||
@@ -20,9 +20,12 @@
|
||||
#ifndef RIPPLE_LEDGER_RAWSTATETABLE_H_INCLUDED
|
||||
#define RIPPLE_LEDGER_RAWSTATETABLE_H_INCLUDED
|
||||
|
||||
#include <ripple/basics/qalloc.h>
|
||||
#include <ripple/ledger/RawView.h>
|
||||
#include <ripple/ledger/ReadView.h>
|
||||
|
||||
#include <boost/container/pmr/monotonic_buffer_resource.hpp>
|
||||
#include <boost/container/pmr/polymorphic_allocator.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <utility>
|
||||
|
||||
@@ -34,9 +37,24 @@ class RawStateTable
|
||||
{
|
||||
public:
|
||||
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&
|
||||
@@ -89,15 +107,32 @@ private:
|
||||
|
||||
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<
|
||||
key_type,
|
||||
std::pair<Action, std::shared_ptr<SLE>>,
|
||||
sleAction,
|
||||
std::less<key_type>,
|
||||
qalloc_type<
|
||||
std::pair<key_type const, std::pair<Action, std::shared_ptr<SLE>>>,
|
||||
false>>;
|
||||
|
||||
boost::container::pmr::polymorphic_allocator<
|
||||
std::pair<const key_type, sleAction>>>;
|
||||
// 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_;
|
||||
|
||||
XRPAmount dropsDestroyed_{0};
|
||||
};
|
||||
|
||||
|
||||
@@ -60,12 +60,12 @@ public:
|
||||
{
|
||||
value_type result;
|
||||
{
|
||||
SerialIter sit(iter_->second.first->slice());
|
||||
SerialIter sit(iter_->second.txn->slice());
|
||||
result.first = std::make_shared<STTx const>(sit);
|
||||
}
|
||||
if (metadata_)
|
||||
{
|
||||
SerialIter sit(iter_->second.second->slice());
|
||||
SerialIter sit(iter_->second.meta->slice());
|
||||
result.second = std::make_shared<STObject const>(sit, sfMetadata);
|
||||
}
|
||||
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(
|
||||
open_ledger_t,
|
||||
ReadView const* base,
|
||||
Rules const& rules,
|
||||
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_.accepted = false;
|
||||
@@ -89,7 +108,10 @@ OpenView::OpenView(
|
||||
}
|
||||
|
||||
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())
|
||||
, base_(base)
|
||||
, hold_(std::move(hold))
|
||||
@@ -108,7 +130,7 @@ OpenView::apply(TxsRawView& to) const
|
||||
{
|
||||
items_.apply(to);
|
||||
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())
|
||||
return base_->txRead(key);
|
||||
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;
|
||||
if (item.second)
|
||||
if (item.meta)
|
||||
sto = std::make_shared<STObject const>(
|
||||
SerialIter{item.second->slice()}, sfMetadata);
|
||||
SerialIter{item.meta->slice()}, sfMetadata);
|
||||
else
|
||||
sto = nullptr;
|
||||
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& 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)
|
||||
LogicError("rawTxInsert: duplicate TX id" + to_string(key));
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
sle0_ = *iter0_;
|
||||
if (iter1_ != end1)
|
||||
{
|
||||
sle1_ = iter1_->second.second;
|
||||
sle1_ = iter1_->second.sle;
|
||||
skip();
|
||||
}
|
||||
}
|
||||
@@ -129,13 +129,13 @@ private:
|
||||
if (iter1_ == end1_)
|
||||
sle1_ = nullptr;
|
||||
else
|
||||
sle1_ = iter1_->second.second;
|
||||
sle1_ = iter1_->second.sle;
|
||||
}
|
||||
|
||||
void
|
||||
skip()
|
||||
{
|
||||
while (iter1_ != end1_ && iter1_->second.first == Action::erase &&
|
||||
while (iter1_ != end1_ && iter1_->second.action == Action::erase &&
|
||||
sle0_->key() == sle1_->key())
|
||||
{
|
||||
inc1();
|
||||
@@ -157,16 +157,16 @@ RawStateTable::apply(RawView& to) const
|
||||
for (auto const& elem : items_)
|
||||
{
|
||||
auto const& item = elem.second;
|
||||
switch (item.first)
|
||||
switch (item.action)
|
||||
{
|
||||
case Action::erase:
|
||||
to.rawErase(item.second);
|
||||
to.rawErase(item.sle);
|
||||
break;
|
||||
case Action::insert:
|
||||
to.rawInsert(item.second);
|
||||
to.rawInsert(item.sle);
|
||||
break;
|
||||
case Action::replace:
|
||||
to.rawReplace(item.second);
|
||||
to.rawReplace(item.sle);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -180,9 +180,9 @@ RawStateTable::exists(ReadView const& base, Keylet const& k) const
|
||||
if (iter == items_.end())
|
||||
return base.exists(k);
|
||||
auto const& item = iter->second;
|
||||
if (item.first == Action::erase)
|
||||
if (item.action == Action::erase)
|
||||
return false;
|
||||
if (!k.check(*item.second))
|
||||
if (!k.check(*item.sle))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@@ -207,11 +207,11 @@ RawStateTable::succ(
|
||||
if (!next)
|
||||
break;
|
||||
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
|
||||
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
|
||||
if (!next || next > iter->first)
|
||||
@@ -237,7 +237,7 @@ RawStateTable::erase(std::shared_ptr<SLE> const& sle)
|
||||
if (result.second)
|
||||
return;
|
||||
auto& item = result.first->second;
|
||||
switch (item.first)
|
||||
switch (item.action)
|
||||
{
|
||||
case Action::erase:
|
||||
LogicError("RawStateTable::erase: already erased");
|
||||
@@ -246,8 +246,8 @@ RawStateTable::erase(std::shared_ptr<SLE> const& sle)
|
||||
items_.erase(result.first);
|
||||
break;
|
||||
case Action::replace:
|
||||
item.first = Action::erase;
|
||||
item.second = sle;
|
||||
item.action = Action::erase;
|
||||
item.sle = sle;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -262,11 +262,11 @@ RawStateTable::insert(std::shared_ptr<SLE> const& sle)
|
||||
if (result.second)
|
||||
return;
|
||||
auto& item = result.first->second;
|
||||
switch (item.first)
|
||||
switch (item.action)
|
||||
{
|
||||
case Action::erase:
|
||||
item.first = Action::replace;
|
||||
item.second = sle;
|
||||
item.action = Action::replace;
|
||||
item.sle = sle;
|
||||
break;
|
||||
case Action::insert:
|
||||
LogicError("RawStateTable::insert: already inserted");
|
||||
@@ -287,14 +287,14 @@ RawStateTable::replace(std::shared_ptr<SLE> const& sle)
|
||||
if (result.second)
|
||||
return;
|
||||
auto& item = result.first->second;
|
||||
switch (item.first)
|
||||
switch (item.action)
|
||||
{
|
||||
case Action::erase:
|
||||
LogicError("RawStateTable::replace: was erased");
|
||||
break;
|
||||
case Action::insert:
|
||||
case Action::replace:
|
||||
item.second = sle;
|
||||
item.sle = sle;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -306,10 +306,10 @@ RawStateTable::read(ReadView const& base, Keylet const& k) const
|
||||
if (iter == items_.end())
|
||||
return base.read(k);
|
||||
auto const& item = iter->second;
|
||||
if (item.first == Action::erase)
|
||||
if (item.action == Action::erase)
|
||||
return nullptr;
|
||||
// Convert to SLE const
|
||||
std::shared_ptr<SLE const> sle = item.second;
|
||||
std::shared_ptr<SLE const> sle = item.sle;
|
||||
if (!k.check(*sle))
|
||||
return nullptr;
|
||||
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
|
||||
#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 <boost/container/pmr/monotonic_buffer_resource.hpp>
|
||||
#include <boost/intrusive/set.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
@@ -109,8 +112,8 @@ private:
|
||||
using by_when_set = typename boost::intrusive::make_multiset<
|
||||
event,
|
||||
boost::intrusive::constant_time_size<false>>::type;
|
||||
|
||||
qalloc alloc_;
|
||||
// alloc_ is owned by the scheduler
|
||||
boost::container::pmr::monotonic_buffer_resource* alloc_;
|
||||
by_when_set by_when_;
|
||||
|
||||
public:
|
||||
@@ -120,7 +123,8 @@ private:
|
||||
queue_type&
|
||||
operator=(queue_type const&) = delete;
|
||||
|
||||
explicit queue_type(qalloc const& alloc);
|
||||
explicit queue_type(
|
||||
boost::container::pmr::monotonic_buffer_resource* alloc);
|
||||
|
||||
~queue_type();
|
||||
|
||||
@@ -141,7 +145,7 @@ private:
|
||||
erase(iterator iter);
|
||||
};
|
||||
|
||||
qalloc alloc_;
|
||||
boost::container::pmr::monotonic_buffer_resource alloc_{kilobytes(256)};
|
||||
queue_type queue_;
|
||||
|
||||
// Aged containers that rely on this clock take a non-const reference =(
|
||||
@@ -154,10 +158,6 @@ public:
|
||||
|
||||
Scheduler();
|
||||
|
||||
/** Return the allocator. */
|
||||
qalloc const&
|
||||
alloc() const;
|
||||
|
||||
/** Return the clock. (aged_containers want a non-const ref =( */
|
||||
clock_type&
|
||||
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;
|
||||
++iter;
|
||||
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
|
||||
{
|
||||
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));
|
||||
return by_when_.insert(e);
|
||||
}
|
||||
@@ -325,7 +327,7 @@ Scheduler::queue_type::erase(iterator iter) -> typename by_when_set::iterator
|
||||
auto& e = *iter;
|
||||
auto next = by_when_.erase(iter);
|
||||
e.~event();
|
||||
alloc_.dealloc(&e, 1);
|
||||
alloc_->deallocate(&e, sizeof(e));
|
||||
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
|
||||
Scheduler::clock() const -> clock_type&
|
||||
{
|
||||
|
||||
@@ -17,10 +17,12 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/basics/ByteUtilities.h>
|
||||
#include <ripple/beast/unit_test.h>
|
||||
#include <set>
|
||||
#include <test/csf/Scheduler.h>
|
||||
|
||||
#include <set>
|
||||
|
||||
namespace ripple {
|
||||
namespace test {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user