xo-alloc2: DX1CollectorIterator infra [WIP]

This commit is contained in:
Roland Conybeare 2025-12-17 20:16:46 -05:00
commit bf27314688
30 changed files with 1041 additions and 176 deletions

View file

@ -5,7 +5,7 @@
#pragma once
#include "alloc/AllocHeader.hpp"
#include "alloc/AllocHeaderConfig.hpp"
#include "alloc/AllocError.hpp"
#include <string>
#include <cstdint>
@ -34,11 +34,6 @@ namespace xo {
* present in arena
**/
bool store_header_flag_ = false;
#ifdef OBSOLETE
/** number of bits to represent allocation size **/
std::uint64_t header_size_bits_ = 32;
std::uint64_t header_size_mask_ = (1ul << header_size_bits_) - 1;
#endif
/** configuration for per-alloc header **/
AllocHeaderConfig header_;
/** true to enable debug logging **/

View file

@ -6,9 +6,11 @@
#pragma once
#include "ArenaConfig.hpp"
#include "alloc/AllocInfo.hpp"
namespace xo {
namespace mm {
struct DArenaIterator; // see DArenaIterator.hpp
/** @class DArena
*
@ -85,6 +87,11 @@ namespace xo {
/** true if arena is mapped i.e. has a reserved address range **/
bool is_mapped() const noexcept { return (lo_ != nullptr) && (hi_ != nullptr); }
/** @ret iterator pointing to the first allocation in this arena **/
DArenaIterator begin() const noexcept;
/** @ret iterator pointing to just after the last allocation in this arena **/
DArenaIterator end() const noexcept;
/** get header from allocated object address **/
header_type * obj2hdr(void * obj) noexcept;
@ -98,7 +105,11 @@ namespace xo {
*
* Note: non-const, may stash error details
**/
AllocInfo alloc_info(value_type mem) noexcept;
AllocInfo alloc_info(value_type mem) const noexcept;
/** capture error information: advance error count + set last_error **/
void capture_error(error err,
size_type target_z = 0) const;
/** discard all allocated memory, return to empty state
* Promise:

View file

@ -0,0 +1,102 @@
/** @file DArenaIterator.hpp
*
* @author Roland Conybeare, Dec 2025
**/
#pragma once
#include "alloc/AllocInfo.hpp"
#include "alloc/AllocHeader.hpp"
#include "cmpresult.hpp"
namespace xo {
namespace mm {
struct DArena;
/** @class DArenaIterator
* @brief Representation for alloc iterator over arena
*
* Map showing an arena allocation:
*
* @pre
*
* <-------------z1--------------->
* < guard >< hz >< req_z >< dz >< guard >
*
* +++++++++0000zzzz@@@@@@@@@@@@@@@@@ppppppp+++++++++
*
* ^ ^ ^
* header mem header
* ^ (next alloc)
* DArenaIterator::pos_
*
* guard [+] guard before+after each allocation, for simple sanitize checks
* header [0] alloc header (non-size bits)
* [z] alloc header (size bits)
* mem [@] app-requested memory, including padding [p]
* dz [p] padding (to uintptr_t alignment. req_z+dz recorded in header)
* free_ DArena::free_ just after guard bytes for last allocation
*
* @endpre
**/
struct DArenaIterator {
DArenaIterator() = default;
DArenaIterator(const DArena * arena,
AllocHeader * pos) : arena_{arena},
pos_{pos} {}
/** Create iterator in invalid state **/
static DArenaIterator invalid() { return DArenaIterator(); }
/** Create iterator pointing to the beginning of @p arena
* Iterator cannot modify memory, but can capture
* an iterator error in @p *arena
**/
static DArenaIterator begin(const DArena * arena);
/** Create iterator pointing to the end of @p arena
* Iterator cannot modify memory, but can capture
* an iterator error in @p *arena
**/
static DArenaIterator end(const DArena * arena);
/** A valid iterator can be compared, at least with itself
* It can be dereferenced if is also non-empty
**/
bool is_valid() const noexcept { return (arena_ != nullptr) && (pos_ != nullptr); }
bool is_invalid() const noexcept { return !is_valid(); }
/** fetch contents at current iterator position **/
AllocInfo deref() const noexcept;
/** compare two iterators. To be comparable,
* iterators must refer to the same arena
**/
cmpresult compare(const DArenaIterator & other) const noexcept;
/** advance iterator to next allocation **/
void next() noexcept;
std::byte * pos_as_byte() const { return (std::byte *)pos_; }
/** *ix synonym for ix.deref() **/
AllocInfo operator*() const noexcept { return this->deref(); }
/** ++ix synonym for ix.next() **/
DArenaIterator & operator++() noexcept { this->next(); return *this; }
/** iterator visits allocations from this arena **/
const DArena * arena_ = nullptr;
/** current iterator position **/
AllocHeader * pos_ = nullptr;
};
inline bool
operator==(const DArenaIterator & x, const DArenaIterator & y) {
return x.compare(y).is_equal();
}
inline bool
operator!=(const DArenaIterator & x, const DArenaIterator & y) {
return !x.compare(y).is_equal();
}
} /*namespace mm*/
} /*namespace xo*/
/* end DArenaIterator.hpp */

View file

@ -0,0 +1,36 @@
/** @file IAllocIterator_DArenaIterator.hpp
*
* @author Roland Conybeare, Dec 2025
**/
#pragma once
#include "alloc/IAllocIterator_Xfer.hpp"
#include "arena/DArenaIterator.hpp"
namespace xo {
namespace mm { struct IAllocIterator_DArenaIterator; }
namespace facet {
template <>
struct FacetImplementation<xo::mm::AAllocIterator,
xo::mm::DArenaIterator> {
using ImplType = xo::mm::IAllocIterator_Xfer<xo::mm::DArenaIterator,
xo::mm::IAllocIterator_DArenaIterator>;
};
}
namespace mm {
/** @class IAllocIterator_DArena
* @brief alloc iteration for the DArena allocator
**/
struct IAllocIterator_DArenaIterator {
static AllocInfo deref(const DArenaIterator &) noexcept;
static cmpresult compare(const DArenaIterator &,
const obj<AAllocIterator> & other) noexcept;
static void next(DArenaIterator &) noexcept;
};
} /*namespace mm*/
} /*namespace xo*/
/* end IAllocIterator_DArenaIterator.cpp */