alloc: add base and offset methods

This commit is contained in:
Danny Robson 2016-06-22 19:51:18 +10:00
parent 8e46cc8e3c
commit 350dd96b2d
8 changed files with 85 additions and 11 deletions

View File

@ -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;
};
} }

View File

@ -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)

View File

@ -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);

View File

@ -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; }

View File

@ -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)

View File

@ -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);

View File

@ -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> (

View File

@ -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