5#include <xrpl/basics/ByteUtilities.h>
6#include <xrpl/beast/type_name.h>
7#include <xrpl/beast/utility/instrumentation.h>
9#include <boost/align.hpp>
10#include <boost/container/static_vector.hpp>
11#include <boost/predef.h>
26template <
typename Type>
31 "SlabAllocator: the requested object must be larger than a pointer.");
33 static_assert(
alignof(Type) == 8 ||
alignof(Type) == 4);
59 while (data + item <=
p +
size)
86 return (pIn >=
p) && (pIn <
p +
size);
121 XRPL_ASSERT(
own(ptr),
"xrpl::SlabAllocator::SlabBlock::deallocate : own input");
165 "xrpl::SlabAllocator::SlabAllocator : valid alignment");
196 auto slab =
slabs_.load();
198 while (slab !=
nullptr)
200 if (
auto ret = slab->allocate())
213 if (buf ==
nullptr) [[unlikely]]
222 madvise(buf,
size, MADV_HUGEPAGE);
235 boost::alignment::aligned_free(buf);
243 while (!
slabs_.compare_exchange_weak(
244 slab->next, slab, std::memory_order_release, std::memory_order_relaxed))
264 "xrpl::SlabAllocator::SlabAllocator::deallocate : non-null "
267 for (
auto slab =
slabs_.load(); slab !=
nullptr; slab = slab->next)
271 slab->deallocate(ptr);
281template <
typename Type>
286 boost::container::static_vector<SlabAllocator<Type>, 64>
allocators_{};
328 for (
auto const& c : cfg)
330 auto& a =
allocators_.emplace_back(c.extra_, c.alloc_, c.align_);
358 if (
auto const size =
sizeof(Type) + extra; size <=
maxSize_)
362 if (a.size() >= size)
382 if (a.deallocate(ptr))
T adjacent_find(T... args)
friend class SlabAllocatorSet
constexpr SlabConfig(std::size_t extra, std::size_t alloc=0, std::size_t align=alignof(Type))
boost::container::static_vector< SlabAllocator< Type >, 64 > allocators_
constexpr SlabAllocatorSet(std::vector< SlabConfig > cfg)
SlabAllocatorSet & operator=(SlabAllocatorSet &&other)=delete
SlabAllocatorSet(SlabAllocatorSet const &other)=delete
SlabAllocatorSet & operator=(SlabAllocatorSet const &other)=delete
bool deallocate(std::uint8_t *ptr) noexcept
Returns the memory block to the allocator.
~SlabAllocatorSet()=default
std::uint8_t * allocate(std::size_t extra) noexcept
Returns a suitably aligned pointer, if one is available.
SlabAllocatorSet(SlabAllocatorSet &&other)=delete
SlabAllocator & operator=(SlabAllocator &&other)=delete
constexpr std::size_t size() const noexcept
Returns the size of the memory block this allocator returns.
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::atomic< SlabBlock * > slabs_
SlabAllocator & operator=(SlabAllocator const &other)=delete
SlabAllocator(SlabAllocator &&other)=delete
std::size_t const itemAlignment_
SlabAllocator(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_
std::size_t const itemSize_
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.
SlabBlock(SlabBlock const &other)=delete
bool own(std::uint8_t const *pIn) const noexcept
Determines whether the given pointer belongs to this allocator.
std::uint8_t const *const p
SlabBlock(SlabBlock *next, std::uint8_t *data, std::size_t size, std::size_t item)
SlabBlock & operator=(SlabBlock &&other)=delete
std::uint8_t * allocate() noexcept
void deallocate(std::uint8_t *ptr) noexcept
Return an item to this allocator's freelist.
SlabBlock(SlabBlock &&other)=delete
SlabBlock & operator=(SlabBlock const &other)=delete