151 lines
5.1 KiB
C++
151 lines
5.1 KiB
C++
/** @file DArena.hpp
|
|
*
|
|
* @author Roland Conybeare, Dec 2025
|
|
**/
|
|
|
|
#pragma once
|
|
|
|
#include "ArenaConfig.hpp"
|
|
|
|
namespace xo {
|
|
namespace mm {
|
|
|
|
/** @class DArena
|
|
*
|
|
* @brief represent arena allocator state
|
|
*
|
|
* Provides minimal RAII functionality around memory mapping.
|
|
* For allocation implementation see @ref IAllocator_DArena
|
|
**/
|
|
struct DArena {
|
|
/*
|
|
* <----------------------------size-------------------------->
|
|
* <------------committed-----------><-------uncommitted------>
|
|
* <--allocated-->
|
|
*
|
|
* XXXXXXXXXXXXXXX___________________..........................
|
|
*
|
|
* [X] allocated: in use
|
|
* [_] committed: physical memory obtained
|
|
* [.] uncommitted: mapped in virtual memory, not backed by memory
|
|
*/
|
|
|
|
/** @defgroup mm-arena-traits arena type traits **/
|
|
///@{
|
|
|
|
/** @brief an amount of memory **/
|
|
using size_type = std::size_t;
|
|
/** @brief allocation pointer; use for allocation results **/
|
|
using value_type = std::byte*;
|
|
/** @brief a contiguous memory range **/
|
|
using range_type = std::pair<value_type, value_type>;
|
|
/** @brief type for allocation header (if enabled) **/
|
|
using header_type = AllocHeader; //std::uint64_t;
|
|
|
|
///@}
|
|
|
|
/** @defgroup mm-arena-ctors arena constructors and destructors **/
|
|
///@{
|
|
|
|
/** create arena per configuration @p cfg. **/
|
|
static DArena map(const ArenaConfig & cfg);
|
|
|
|
/** null ctor **/
|
|
DArena() = default;
|
|
/** ctor from already-mapped (but not committed) address range **/
|
|
DArena(const ArenaConfig & cfg, size_type page_z, value_type lo, value_type hi);
|
|
/** DArena is not copyable **/
|
|
DArena(const DArena & other) = delete;
|
|
/** move ctor **/
|
|
DArena(DArena && other);
|
|
/** dtor releases mapped memory **/
|
|
~DArena();
|
|
|
|
/** move-assignment **/
|
|
DArena & operator=(DArena && other);
|
|
|
|
///@}
|
|
|
|
/** @defgroup mm-arena-methods **/
|
|
///@{
|
|
|
|
size_type reserved() const noexcept { return hi_ - lo_; }
|
|
size_type allocated() const noexcept { return free_ - lo_; }
|
|
size_type committed() const noexcept { return committed_z_; }
|
|
size_type available() const noexcept { return limit_ - free_; }
|
|
|
|
bool contains(const void * addr) const noexcept { return (lo_ <= addr) && (addr < hi_); }
|
|
|
|
/** obtain uncommitted contiguous memory range comprising
|
|
* a whole multiple of @p hugepage_z bytes, of at least size @p req_z,
|
|
* aligned on a @p hugepage_z boundary
|
|
**/
|
|
static range_type map_aligned_range(size_type req_z, size_type hugepage_z);
|
|
|
|
/** true if arena is mapped i.e. has a reserved address range **/
|
|
bool is_mapped() const noexcept { return (lo_ != nullptr) && (hi_ != nullptr); }
|
|
|
|
/** get header from allocated object address **/
|
|
header_type * obj2hdr(void * obj) noexcept;
|
|
|
|
/** discard all allocated memory, return to empty state
|
|
* Promise:
|
|
* - committed memory unchanged
|
|
* - available memory = committed memory
|
|
**/
|
|
void clear() noexcept;
|
|
|
|
///@}
|
|
|
|
/** @defgroup mm-arena-instance-vars **/
|
|
///@{
|
|
|
|
/** arena configuration **/
|
|
ArenaConfig config_;
|
|
|
|
/** size of a VM page (obtained automatically via getpagesize()). Likely 4k **/
|
|
size_type page_z_ = 0;
|
|
|
|
/** arena owns memory in range [@ref lo_, @ref hi_)
|
|
**/
|
|
std::byte * lo_ = nullptr;
|
|
|
|
/** prefix of this size is committed.
|
|
* Remainder mapped but uncommitted.
|
|
**/
|
|
size_type committed_z_ = 0;
|
|
|
|
/** if config_.store_header_flag_:
|
|
* Pointer to header for last allocation.
|
|
**/
|
|
header_type * last_header_ = nullptr;
|
|
|
|
/** free pointer.
|
|
* Memory in range [@ref lo_, @ref free_) current in use
|
|
**/
|
|
std::byte * free_ = nullptr;
|
|
|
|
/** soft limit; end of committed virtual memory
|
|
* Memory in range [@ref lo_, @ref limit_) is committed
|
|
* (backed by physical memory)
|
|
**/
|
|
std::byte * limit_ = nullptr;
|
|
|
|
/** hard limit; end of reserved virtual memory
|
|
* Memory in range [@ref limit_, @ref hi_) is uncommitted
|
|
**/
|
|
std::byte * hi_ = nullptr;
|
|
|
|
/** count runtime errors. Each error updates @ref last_error_ **/
|
|
uint32_t error_count_ = 0;
|
|
|
|
/** capture some error details if/when error **/
|
|
AllocatorError last_error_;
|
|
|
|
///@}
|
|
};
|
|
|
|
} /*namespace mm*/
|
|
} /*namespace xo*/
|
|
|
|
/* end DArena.hpp */
|