3#ifndef XRPL_BASICS_SLABALLOCATOR_H_INCLUDED
4#define XRPL_BASICS_SLABALLOCATOR_H_INCLUDED
6#include <xrpl/basics/ByteUtilities.h>
7#include <xrpl/beast/type_name.h>
8#include <xrpl/beast/utility/instrumentation.h>
10#include <boost/align.hpp>
11#include <boost/container/static_vector.hpp>
12#include <boost/predef.h>
27template <
typename Type>
32 "SlabAllocator: the requested object must be larger than a pointer.");
34 static_assert(
alignof(Type) == 8 ||
alignof(Type) == 4);
64 while (data + item <=
p_ +
size_)
131 "ripple::SlabAllocator::SlabBlock::deallocate : own input");
176 "ripple::SlabAllocator::SlabAllocator : valid alignment");
209 auto slab =
slabs_.load();
211 while (slab !=
nullptr)
213 if (
auto ret = slab->allocate())
229 if (!buf) [[unlikely]]
239 madvise(buf,
size, MADV_HUGEPAGE);
244 auto slabData =
reinterpret_cast<void*
>(
250 if (!boost::alignment::align(
253 boost::alignment::aligned_free(buf);
264 while (!
slabs_.compare_exchange_weak(
288 "ripple::SlabAllocator::SlabAllocator::deallocate : non-null "
291 for (
auto slab =
slabs_.load(); slab !=
nullptr; slab = slab->next_)
295 slab->deallocate(ptr);
305template <
typename Type>
310 boost::container::static_vector<SlabAllocator<Type>, 64>
allocators_;
354 "SlabAllocatorSet<" + beast::type_name<Type>() +
355 ">: duplicate slab size");
358 for (
auto const& c : cfg)
360 auto& a =
allocators_.emplace_back(c.extra, c.alloc, c.align);
390 if (
auto const size =
sizeof(Type) + extra; size <=
maxSize_)
394 if (a.size() >= size)
414 if (a.deallocate(ptr))
T adjacent_find(T... args)
constexpr SlabConfig(std::size_t extra_, std::size_t alloc_=0, std::size_t align_=alignof(Type))
A collection of slab allocators of various sizes for a given type.
constexpr SlabAllocatorSet(std::vector< SlabConfig > cfg)
SlabAllocatorSet & operator=(SlabAllocatorSet &&other)=delete
SlabAllocatorSet(SlabAllocatorSet &&other)=delete
boost::container::static_vector< SlabAllocator< Type >, 64 > allocators_
std::uint8_t * allocate(std::size_t extra) noexcept
Returns a suitably aligned pointer, if one is available.
bool deallocate(std::uint8_t *ptr) noexcept
Returns the memory block to the allocator.
SlabAllocatorSet(SlabAllocatorSet const &other)=delete
SlabAllocatorSet & operator=(SlabAllocatorSet const &other)=delete
constexpr SlabAllocator(std::size_t extra, std::size_t alloc=0, std::size_t align=0)
Constructs a slab allocator able to allocate objects of a fixed size.
std::size_t const itemSize_
std::size_t const itemAlignment_
constexpr std::size_t size() const noexcept
Returns the size of the memory block this allocator returns.
std::atomic< SlabBlock * > slabs_
SlabAllocator & operator=(SlabAllocator const &other)=delete
bool deallocate(std::uint8_t *ptr) noexcept
Returns the memory block to the allocator.
std::uint8_t * allocate() noexcept
Returns a suitably aligned pointer, if one is available.
std::size_t const slabSize_
SlabAllocator(SlabAllocator &&other)=delete
SlabAllocator(SlabAllocator const &other)=delete
SlabAllocator & operator=(SlabAllocator &&other)=delete
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
constexpr auto megabytes(T value) noexcept
A block of memory that is owned by a slab allocator.
bool own(std::uint8_t const *p) const noexcept
Determines whether the given pointer belongs to this allocator.
void deallocate(std::uint8_t *ptr) noexcept
Return an item to this allocator's freelist.
SlabBlock & operator=(SlabBlock const &other)=delete
SlabBlock(SlabBlock &&other)=delete
std::uint8_t const *const p_
SlabBlock(SlabBlock *next, std::uint8_t *data, std::size_t size, std::size_t item)
SlabBlock(SlabBlock const &other)=delete
std::uint8_t * allocate() noexcept
SlabBlock & operator=(SlabBlock &&other)=delete