alloc: add base and offset methods
This commit is contained in:
parent
8e46cc8e3c
commit
350dd96b2d
@ -64,6 +64,16 @@ namespace util { namespace alloc {
|
||||
return m_child->deallocate (ptr, bytes, alignment);
|
||||
}
|
||||
|
||||
void*
|
||||
base (void)
|
||||
{
|
||||
return m_child->base ();
|
||||
}
|
||||
|
||||
size_t
|
||||
offset (const void *ptr) const
|
||||
{ return m_child->offset (ptr); }
|
||||
|
||||
void reset (void) { m_child->reset (); }
|
||||
|
||||
// capacity queries
|
||||
@ -74,15 +84,15 @@ namespace util { namespace alloc {
|
||||
private:
|
||||
// Internal base for arbitrary allocator types. Necessary for
|
||||
// type ellision in super-client classes.
|
||||
class base {
|
||||
class interface {
|
||||
public:
|
||||
base () = default;
|
||||
base (const base&) = delete;
|
||||
base (base&&) = delete;
|
||||
base& operator= (const base&) = delete;
|
||||
base& operator= (base&&) = delete;
|
||||
interface () = default;
|
||||
interface (const interface&) = delete;
|
||||
interface (interface&&) = delete;
|
||||
interface& operator= (const interface&) = delete;
|
||||
interface& operator= (interface&&) = delete;
|
||||
|
||||
virtual ~base () { ; }
|
||||
virtual ~interface () { ; }
|
||||
|
||||
// allocation management
|
||||
virtual void*
|
||||
@ -94,6 +104,9 @@ namespace util { namespace alloc {
|
||||
size_t bytes,
|
||||
size_t alignment = DEFAULT_ALIGNMENT) = 0;
|
||||
|
||||
virtual void* base (void) = 0;
|
||||
virtual size_t offset (const void*) const = 0;
|
||||
|
||||
virtual void reset (void) = 0;
|
||||
|
||||
// capacity queries
|
||||
@ -104,11 +117,11 @@ namespace util { namespace alloc {
|
||||
|
||||
|
||||
template <typename T>
|
||||
class child final : public base {
|
||||
class child final : public interface {
|
||||
public:
|
||||
template <typename ...Args>
|
||||
child (Args &&...args):
|
||||
base (),
|
||||
interface (),
|
||||
m_target (std::forward<Args> (args)...)
|
||||
{ ; }
|
||||
|
||||
@ -128,6 +141,18 @@ namespace util { namespace alloc {
|
||||
m_target.deallocate (ptr, bytes, alignment);
|
||||
}
|
||||
|
||||
void *
|
||||
base (void)
|
||||
{
|
||||
return m_target.base ();
|
||||
}
|
||||
|
||||
size_t
|
||||
offset (const void *ptr) const
|
||||
{
|
||||
return m_target.offset (ptr);
|
||||
}
|
||||
|
||||
void reset (void) override
|
||||
{ m_target.reset (); }
|
||||
|
||||
@ -141,11 +166,11 @@ namespace util { namespace alloc {
|
||||
};
|
||||
|
||||
|
||||
dynamic (std::unique_ptr<base> _child):
|
||||
dynamic (std::unique_ptr<interface> _child):
|
||||
m_child (std::move (_child))
|
||||
{ ; }
|
||||
|
||||
std::unique_ptr<base> m_child;
|
||||
std::unique_ptr<interface> m_child;
|
||||
};
|
||||
} }
|
||||
|
||||
|
@ -60,6 +60,25 @@ linear::deallocate (void *ptr, size_t bytes, size_t alignment)
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void*
|
||||
linear::base (void)
|
||||
{
|
||||
return m_begin;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
size_t
|
||||
linear::offset (const void *_ptr) const
|
||||
{
|
||||
auto ptr = reinterpret_cast<const char*> (_ptr);
|
||||
|
||||
CHECK_GE (ptr, m_begin);
|
||||
return ptr - m_begin;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
linear::reset (void)
|
||||
|
@ -33,6 +33,8 @@ namespace util { namespace alloc {
|
||||
|
||||
void* allocate (size_t bytes, size_t alignment = alignof (std::max_align_t));
|
||||
void deallocate (void *ptr, size_t bytes, size_t alignment = alignof (std::max_align_t));
|
||||
void* base (void);
|
||||
size_t offset (const void*) const;
|
||||
|
||||
void reset (void);
|
||||
|
||||
|
@ -29,6 +29,9 @@ namespace util { namespace alloc {
|
||||
void* allocate (size_t bytes, size_t align = alignof (std::max_align_t));
|
||||
void deallocate (void *ptr, size_t bytes, size_t align = alignof (std::max_align_t));
|
||||
|
||||
constexpr void* base (void) { return nullptr; }
|
||||
constexpr size_t offset (const void*) const { return 0; }
|
||||
|
||||
void reset (void) { ; }
|
||||
|
||||
constexpr size_t capacity (void) const { return 0u; }
|
||||
|
@ -94,6 +94,25 @@ stack::deallocate (void *_ptr, size_t bytes, size_t alignment)
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void*
|
||||
stack::base (void)
|
||||
{
|
||||
return m_begin;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
size_t
|
||||
stack::offset (const void *_ptr) const
|
||||
{
|
||||
auto ptr = reinterpret_cast<const char*> (_ptr);
|
||||
|
||||
CHECK_GE (ptr, m_begin);
|
||||
return ptr - m_begin;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
stack::reset (void)
|
||||
|
@ -36,6 +36,8 @@ namespace util { namespace alloc {
|
||||
//[[gnu::alloc_align (2), gnu::alloc_size (1), gnu::returns_nonnull, gnu::warn_unused_result]
|
||||
void *allocate (size_t bytes, size_t alignment = alignof (std::max_align_t));
|
||||
void deallocate (void *ptr, size_t bytes, size_t alignment = alignof (std::max_align_t));
|
||||
void* base (void);
|
||||
size_t offset (const void*) const;
|
||||
|
||||
void reset (void);
|
||||
|
||||
|
@ -12,6 +12,8 @@ main (void)
|
||||
alignas (std::max_align_t) char memory[BUFFER_SIZE];
|
||||
util::alloc::linear store (std::begin (memory), std::end (memory));
|
||||
|
||||
tap.expect_eq (store.base (), std::begin (memory), "base pointers match");
|
||||
tap.expect_eq (store.offset (std::begin (memory)), 0u, "base offset is 0");
|
||||
tap.expect_eq (store.capacity (), BUFFER_SIZE, "bytes capacity matches");
|
||||
|
||||
tap.expect_throw<std::bad_alloc> (
|
||||
|
@ -34,6 +34,8 @@ main (void)
|
||||
|
||||
util::alloc::stack store (memory, memory + BUFFER_AVAILABLE);
|
||||
|
||||
tap.expect_eq (store.base (), std::begin (memory), "base pointers match");
|
||||
tap.expect_eq (store.offset (std::begin (memory)), 0u, "base offset is 0");
|
||||
tap.expect_eq (store.capacity (), BUFFER_AVAILABLE, "bytes capacity matches");
|
||||
|
||||
// larger than total allocations should throw
|
||||
|
Loading…
Reference in New Issue
Block a user