Documentation for fennec::allocation

This commit is contained in:
Medusa Slockbower 2025-05-30 23:33:15 -04:00
parent 67c8ad9a0d
commit 29f21d84d8
2 changed files with 88 additions and 15 deletions

View File

@ -30,11 +30,25 @@
#ifndef FENNEC_CONTAINERS_DYNARRAY_H #ifndef FENNEC_CONTAINERS_DYNARRAY_H
#define FENNEC_CONTAINERS_DYNARRAY_H #define FENNEC_CONTAINERS_DYNARRAY_H
#include <fennec/memory/allocator.h>
namespace fennec namespace fennec
{ {
template<class T, class Alloc>
class dynarray
{
public:
using element_t = T;
using alloc_t = Alloc;
dynarray() : _alloc(), _size(0) {}
dynarray()
private:
allocation<element_t, alloc_t> _alloc;
size_t _size;
};
} }

View File

@ -158,22 +158,59 @@ public:
/// ///
/// \brief Container to hold an allocation /// \brief Container to hold an allocation
/// \tparam T The data type of the allocation /// \tparam T The data type of the allocation
///
/// \details This simply acts as a proxy for allocating memory. It does not call any constructors or
/// initialize any values as if they were the provided data type. Any operations present work
/// only on individual bytes.
template<typename T, class AllocT> template<typename T, class AllocT>
class allocation class allocation
{ {
public: public:
// TODO: Document /// \brief alias for the allocator type
using alloc_t = typename allocator_traits<AllocT>::template rebind<T>; using alloc_t = typename allocator_traits<AllocT>::template rebind<T>;
using element_t = T;
/// \brief alias for the data type
using value_t = T;
/// \brief size type definition for ptr_traits
using size_t = size_t; using size_t = size_t;
/// \brief diff type definition for ptr_traits
using diff_t = ptrdiff_t; using diff_t = ptrdiff_t;
allocation() : _data(nullptr), _capacity(0) {} ///
allocation(size_t n) : _data(_alloc.al), _capacity(n) {} /// \brief Default Constructor, initializes internal data to `null` and the capacity to `0`
~allocation() { if (_data) _alloc.deallocate(_data); } constexpr allocation() noexcept : _data(nullptr), _capacity(0) {}
void allocate(size_t n) ///
/// \brief Sized Constructor, initializes the allocation with a block of size `n * sizeof(T)` bytes
/// \param n The number of elements of type `T` to allocate for
constexpr allocation(size_t n) noexcept : _data(_alloc.al), _capacity(n) {}
///
/// \brief Allocator Constructor
/// \param alloc The allocation object to copy.
///
/// \details This constructor should be used when the type `AllocT` needs internal data.
constexpr allocation(const alloc_t& alloc) noexcept : _alloc(alloc), _data(nullptr), _capacity(0) {}
///
/// \brief Sized Allocator Constructor
/// \param n The number of elements of type `T` to allocate for
/// \param alloc The allocation object to copy.
///
/// \details This constructor should be used when the type `AllocT` needs internal data.
constexpr allocation(size_t n, const alloc_t& alloc) noexcept : _alloc(alloc), _data(nullptr), _capacity(0) {}
///
/// \brief Default Destructor, releases the memory block if still present
constexpr ~allocation() noexcept { if (_data) _alloc.deallocate(_data); }
///
/// \brief Allocate a block of memory for the allocation.
/// If there is already an allocated block of memory, the previous allocation is released.
/// \param n The number of elements of type `T` to allocate for
constexpr void allocate(size_t n) noexcept
{ {
if (_data) if (_data)
_alloc.deallocate(_data); _alloc.deallocate(_data);
@ -181,7 +218,9 @@ public:
_data = alloc_t::allocate(_capacity = n); _data = alloc_t::allocate(_capacity = n);
} }
void release() ///
/// \brief Release the block of memory.
constexpr void release() noexcept
{ {
if (_data) if (_data)
_alloc.deallocate(_data); _alloc.deallocate(_data);
@ -189,22 +228,42 @@ public:
_capacity = 0; _capacity = 0;
} }
void reallocate(size_t n) ///
/// \brief Reallocate the block with a new size.
/// Contents are copied to the new allocation.
constexpr void reallocate(size_t n) noexcept
{ {
if (_data == nullptr) if (_data == nullptr)
return _alloc.allocate(_capacity = n); return _alloc.allocate(_capacity = n);
element_t* old = _data; value_t* old = _data;
_data = alloc_t::allocate(n); _data = alloc_t::allocate(n);
fennec::memcpy(_data, old, min(_capacity, n) * sizeof(T)); fennec::memcpy(_data, old, min(_capacity, n) * sizeof(T));
_alloc.deallocate(old); _alloc.deallocate(old);
_capacity = n; _capacity = n;
} }
///
/// \brief Clear the block of memory, setting all bytes to 0.
constexpr void clear() noexcept
{
fennec::memset(_data, 0, _capacity * sizeof(T));
}
///
/// \brief Getter for the byte size of the allocation.
/// \returns the size of the allocation in bytes
constexpr size_t size() const { return _capacity * sizeof(T); }
///
/// \brief Getter for the number of elements `n` of type `T` that the allocation can hold.
/// \return the size of the allocation in elements
constexpr size_t capacity() const { return _capacity; }
private: private:
alloc_t _alloc; alloc_t _alloc; // Allocator object
element_t* _data; value_t* _data; // Handle for the memory block
size_t _capacity; size_t _capacity; // Capacity of the memory block in elements.
}; };
} }