alloc: return views rather than raw pointers
This commit is contained in:
parent
df3a556867
commit
2620e2ed33
@ -38,8 +38,8 @@ namespace util::alloc {
|
||||
U*
|
||||
acquire (Args&&... args)
|
||||
{
|
||||
U *data = reinterpret_cast<U*> (
|
||||
m_store.allocate (sizeof (U), alignof (U))
|
||||
U *data = util::cast::alignment<U*> (
|
||||
m_store.allocate (sizeof (U), alignof (U)).data ()
|
||||
);
|
||||
|
||||
try {
|
||||
|
@ -17,6 +17,8 @@
|
||||
#ifndef CRUFT_UTIL_ALLOC_RAW_AFFIX_HPP
|
||||
#define CRUFT_UTIL_ALLOC_RAW_AFFIX_HPP
|
||||
|
||||
#include "../../view.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace util::alloc::raw {
|
||||
@ -29,11 +31,13 @@ namespace util::alloc::raw {
|
||||
/// useful for sentinels, reference counts, etc.
|
||||
template <class ParentT, class PrefixT, class SuffixT>
|
||||
class affix {
|
||||
void* allocate (size_t bytes);
|
||||
void* allocate (size_t bytes, size_t align);
|
||||
util::view<std::byte*> allocate (size_t bytes);
|
||||
util::view<std::byte*> allocate (size_t bytes, size_t align);
|
||||
|
||||
void deallocate (void *ptr, size_t bytes);
|
||||
void deallocate (void *ptr, size_t bytes, size_t align);
|
||||
void deallocate (util::view<std::byte*> ptr) { return deallocate (ptr.data (), ptr.size ()); }
|
||||
void deallocate (util::view<std::byte*> ptr, size_t alignment) { return deallocate (ptr.data (), ptr.size (), alignment); }
|
||||
void deallocate (void *ptr, size_t bytes);
|
||||
void deallocate (void *ptr, size_t bytes, size_t align);
|
||||
|
||||
std::byte* begin (void);
|
||||
const std::byte* begin (void) const;
|
||||
|
@ -18,6 +18,7 @@
|
||||
#define CRUFT_UTIL_ALLOC_RAW_ALIGNED_DIRECT_HPP
|
||||
|
||||
#include "../../../debug.hpp"
|
||||
#include "../../../view.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
|
@ -70,7 +70,7 @@ namespace util::alloc::raw::aligned {
|
||||
allocate (std::size_t size)
|
||||
{
|
||||
auto ptr= reinterpret_cast<std::byte*> (
|
||||
m_successor.allocate (size)
|
||||
m_successor.allocate (size).data ()
|
||||
);
|
||||
return ptr + m_offset;
|
||||
}
|
||||
|
@ -98,8 +98,8 @@ namespace util::alloc::raw {
|
||||
virtual ~interface () { ; }
|
||||
|
||||
// allocation management
|
||||
virtual void* allocate (size_t bytes) = 0;
|
||||
virtual void* allocate (size_t bytes, size_t alignment) = 0;
|
||||
virtual util::view<std::byte*> allocate (size_t bytes) = 0;
|
||||
virtual util::view<std::byte*> allocate (size_t bytes, size_t alignment) = 0;
|
||||
|
||||
virtual void deallocate (void *ptr, size_t bytes) = 0;
|
||||
virtual void deallocate (void *ptr, size_t bytes, size_t alignment) = 0;
|
||||
@ -132,7 +132,7 @@ namespace util::alloc::raw {
|
||||
{ ; }
|
||||
|
||||
// allocation management
|
||||
void*
|
||||
util::view<std::byte*>
|
||||
allocate (size_t bytes) override
|
||||
{ return m_target.allocate (bytes); }
|
||||
|
||||
@ -140,7 +140,7 @@ namespace util::alloc::raw {
|
||||
// we can't totally eliminate this call given the point is to
|
||||
// expose the common API area, but we will throw if the operation
|
||||
// is unsupported in the child.
|
||||
void*
|
||||
util::view<std::byte*>
|
||||
allocate (size_t bytes, size_t alignment) override
|
||||
{
|
||||
if constexpr (has_aligned_allocate_v<ChildT>) {
|
||||
|
@ -17,6 +17,8 @@
|
||||
#ifndef CRUFT_UTIL_ALLOC_RAW_FALLBACK_HPP
|
||||
#define CRUFT_UTIL_ALLOC_RAW_FALLBACK_HPP
|
||||
|
||||
#include "../../view.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <tuple>
|
||||
|
||||
@ -30,9 +32,11 @@ namespace util::alloc::raw {
|
||||
m_children (_children...)
|
||||
{ ; }
|
||||
|
||||
void* allocate (size_t bytes);
|
||||
void* allocate (size_t bytes, size_t align);
|
||||
util::view<std::byte*> allocate (size_t bytes);
|
||||
util::view<std::byte*> allocate (size_t bytes, size_t align);
|
||||
|
||||
void deallocate (util::view<std::byte*> ptr) { return deallocate (ptr.data (), ptr.size ()); }
|
||||
void deallocate (util::view<std::byte*> ptr, size_t alignment) { return deallocate (ptr.data (), ptr.size (), alignment); }
|
||||
void deallocate (void *ptr, size_t bytes);
|
||||
void deallocate (void *ptr, size_t bytes, size_t align);
|
||||
|
||||
|
@ -31,7 +31,7 @@ linear::linear (util::view<std::byte*> _data):
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void*
|
||||
util::view<std::byte*>
|
||||
linear::allocate (size_t bytes)
|
||||
{
|
||||
if (m_cursor + bytes > m_end)
|
||||
@ -39,12 +39,12 @@ linear::allocate (size_t bytes)
|
||||
|
||||
auto ptr = m_cursor;
|
||||
m_cursor += bytes;
|
||||
return ptr;
|
||||
return { ptr, bytes };
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void*
|
||||
util::view<std::byte*>
|
||||
linear::allocate (size_t bytes, size_t alignment)
|
||||
{
|
||||
auto ptr = align (m_cursor, alignment);
|
||||
@ -53,7 +53,7 @@ linear::allocate (size_t bytes, size_t alignment)
|
||||
|
||||
m_cursor = ptr + bytes;
|
||||
|
||||
return ptr;
|
||||
return { ptr, bytes };
|
||||
}
|
||||
|
||||
|
||||
|
@ -34,11 +34,13 @@ namespace util::alloc::raw {
|
||||
|
||||
linear (util::view<std::byte*> _data);
|
||||
|
||||
void* allocate (size_t bytes);
|
||||
void* allocate (size_t bytes, size_t alignment);
|
||||
util::view<std::byte*> allocate (size_t bytes);
|
||||
util::view<std::byte*> allocate (size_t bytes, size_t alignment);
|
||||
|
||||
void deallocate (void *ptr, size_t bytes);
|
||||
void deallocate (void *ptr, size_t bytes, size_t alignment);
|
||||
void deallocate (util::view<std::byte*> ptr) { return deallocate (ptr.data (), ptr.size ()); }
|
||||
void deallocate (util::view<std::byte*> ptr, size_t alignment) { return deallocate (ptr.data (), ptr.size (), alignment); }
|
||||
void deallocate (void *ptr, size_t bytes);
|
||||
void deallocate (void *ptr, size_t bytes, size_t alignment);
|
||||
|
||||
std::byte* data (void);
|
||||
std::byte* begin (void);
|
||||
|
@ -24,7 +24,7 @@ using util::alloc::raw::malloc;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void*
|
||||
util::view<std::byte*>
|
||||
malloc::allocate (size_t bytes)
|
||||
{
|
||||
return allocate (bytes, alignof (std::max_align_t));
|
||||
@ -32,14 +32,14 @@ malloc::allocate (size_t bytes)
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void*
|
||||
util::view<std::byte*>
|
||||
malloc::allocate (size_t bytes, size_t align)
|
||||
{
|
||||
// C malloc guarantees maximal alignment
|
||||
CHECK_LE (align, alignof (std::max_align_t));
|
||||
(void)align;
|
||||
|
||||
return ::malloc (bytes);
|
||||
return util::view<std::byte*> (reinterpret_cast<std::byte*> (::malloc (bytes)), bytes);
|
||||
}
|
||||
|
||||
|
||||
|
@ -17,17 +17,21 @@
|
||||
#ifndef CRUFT_UTIL_ALLOC_RAW_MALLOC_HPP
|
||||
#define CRUFT_UTIL_ALLOC_RAW_MALLOC_HPP
|
||||
|
||||
#include "../../view.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
|
||||
namespace util::alloc::raw {
|
||||
class malloc {
|
||||
public:
|
||||
void* allocate (size_t bytes);
|
||||
void* allocate (size_t bytes, size_t align);
|
||||
util::view<std::byte*> allocate (size_t bytes);
|
||||
util::view<std::byte*> allocate (size_t bytes, size_t align);
|
||||
|
||||
void deallocate (void *ptr, size_t bytes);
|
||||
void deallocate (void *ptr, size_t bytes, size_t align);
|
||||
void deallocate (util::view<std::byte*> ptr) { return deallocate (ptr.data (), ptr.size ()); }
|
||||
void deallocate (util::view<std::byte*> ptr, size_t alignment) { return deallocate (ptr.data (), ptr.size (), alignment); }
|
||||
void deallocate (void *ptr, size_t bytes);
|
||||
void deallocate (void *ptr, size_t bytes, size_t align);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ using util::alloc::raw::null;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void*
|
||||
util::view<std::byte*>
|
||||
null::allocate (size_t bytes)
|
||||
{
|
||||
return allocate (bytes, alignof (std::max_align_t));
|
||||
@ -33,7 +33,7 @@ null::allocate (size_t bytes)
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void*
|
||||
util::view<std::byte*>
|
||||
null::allocate (size_t bytes, size_t align)
|
||||
{
|
||||
(void)bytes;
|
||||
|
@ -32,8 +32,11 @@ namespace util::alloc::raw {
|
||||
null (const null&) = delete;
|
||||
null& operator= (const null&) = delete;
|
||||
|
||||
void* allocate (size_t bytes);
|
||||
void* allocate (size_t bytes, size_t align);
|
||||
util::view<std::byte*> allocate (size_t bytes);
|
||||
util::view<std::byte*> allocate (size_t bytes, size_t align);
|
||||
|
||||
void deallocate (util::view<std::byte*> ptr) { return deallocate (ptr.data (), ptr.size ()); }
|
||||
void deallocate (util::view<std::byte*> ptr, size_t alignment) { return deallocate (ptr.data (), ptr.size (), alignment); }
|
||||
void deallocate (void *ptr, size_t bytes);
|
||||
void deallocate (void *ptr, size_t bytes, size_t align);
|
||||
|
||||
|
@ -47,7 +47,7 @@ constexpr auto MIN_ALIGNMENT = sizeof (record::offset_t);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void*
|
||||
util::view<std::byte*>
|
||||
stack::allocate (size_t bytes)
|
||||
{
|
||||
return allocate (bytes, alignof (std::max_align_t));
|
||||
@ -55,7 +55,7 @@ stack::allocate (size_t bytes)
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void*
|
||||
util::view<std::byte*>
|
||||
stack::allocate (size_t bytes, size_t alignment)
|
||||
{
|
||||
// reserve space at the front of the allocation to record the total
|
||||
@ -78,7 +78,7 @@ stack::allocate (size_t bytes, size_t alignment)
|
||||
*record.as_offset = util::cast::lossless <uint32_t> (ptr - m_cursor);
|
||||
|
||||
m_cursor = ptr + bytes;
|
||||
return ptr;
|
||||
return { ptr, bytes };
|
||||
}
|
||||
|
||||
|
||||
|
@ -34,9 +34,11 @@ namespace util::alloc::raw {
|
||||
|
||||
stack (util::view<std::byte*> _data);
|
||||
|
||||
void *allocate (size_t bytes, size_t alignment);
|
||||
void *allocate (size_t bytes);
|
||||
util::view<std::byte*> allocate (size_t bytes, size_t alignment);
|
||||
util::view<std::byte*> allocate (size_t bytes);
|
||||
|
||||
void deallocate (util::view<std::byte*> ptr) { return deallocate (ptr.data (), ptr.size ()); }
|
||||
void deallocate (util::view<std::byte*> ptr, size_t alignment) { return deallocate (ptr.data (), ptr.size (), alignment); }
|
||||
void deallocate (void *ptr, size_t bytes);
|
||||
void deallocate (void *ptr, size_t bytes, size_t alignment);
|
||||
|
||||
|
@ -29,10 +29,10 @@ main (int, char**)
|
||||
// alignment to produce a likely system alignment. eg, 3 + 5 == 8 which is
|
||||
// a power-of-2.
|
||||
uintptr_t result[4] = {
|
||||
reinterpret_cast<uintptr_t>(alloc.allocate (9)), // just over a power of two
|
||||
reinterpret_cast<uintptr_t>(alloc.allocate (1)), // a single byte
|
||||
reinterpret_cast<uintptr_t>(alloc.allocate (64)), // a cache line
|
||||
reinterpret_cast<uintptr_t>(alloc.allocate (250)) // multiple cache lines, but not a power of two
|
||||
reinterpret_cast<uintptr_t>(alloc.allocate (9).data ()), // just over a power of two
|
||||
reinterpret_cast<uintptr_t>(alloc.allocate (1).data ()), // a single byte
|
||||
reinterpret_cast<uintptr_t>(alloc.allocate (64).data ()), // a cache line
|
||||
reinterpret_cast<uintptr_t>(alloc.allocate (250).data ()) // multiple cache lines, but not a power of two
|
||||
};
|
||||
|
||||
tap.expect (
|
||||
|
@ -11,7 +11,7 @@ n_allocations (util::alloc::raw::stack &store,
|
||||
{
|
||||
for (unsigned i = 0; i < count; ++i) {
|
||||
auto ptr = store.allocate (bytes, alignment);
|
||||
store.deallocate (ptr, bytes, alignment);
|
||||
store.deallocate (ptr, alignment);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user