jam 0.0.1
A compacting generational garbage collector for C++26
Loading...
Searching...
No Matches
Word heap

Concepts

concept  jam::visitor
 A visitor for jam's compressed, alignment-preserving heap.
concept  jam::traceable
 T supports tracing after it is complete.Ordinary trace return types are unrestricted; collection uses their effects. A void claim_and_trace(heap::visitor &) const noexcept member takes priority for allocation tracing and may be virtual. Its override must claim the exact complete object before declaring fields or following targets.

Classes

class  jam::heap_scope
 Bind an existing heap, restoring the previous binding on scope exit.The heap must outlive the scope. Scopes nest on one thread and may re-enter a heap. They neither own the heap nor synchronize access to it. More...
struct  jam::leaf< T >
 A value with no outgoing managed references.Specializing tracer<T> by deriving from leaf<T> explicitly suppresses traversal. Heap storage requirements are separate from this reference-free promise. More...
struct  jam::tracer< T >
 Per-value tracing customization; values without a hook or manifest are leaves.An allocation-only claim_and_trace hook does not describe embedded fields. Scalars and ordinary records without a trace member or manifest contain no managed edges by convention. Records containing managed pointers must enumerate them in a manifest, trace member or tracer specialization. Trivial copyability does not enumerate fields. More...
struct  jam::tracer< T >
 Forward a value hook or a cooperative allocation hook.Visit each live ptr by reference from the supplied value. Nested values share the enclosing allocation's pointer mask. Static trace(visit, ptr<T>) owns allocation claiming and may walk directly between records. More...
class  jam::ptr< T >
 A typed heap offset, with no root registration or ownership. More...
class  jam::weak_ptr< T >
 A four-byte weak heap field; tracing updates its slot without retaining its target.Construct from a ptr or root. Collection clears the field when its target is unclaimed; minor collection leaves old targets alone. Use lock() to retain a target across collection. There is no control block or external registration: stack copies expire at collection just like ptr, even if the target survives. The field must be listed in its owner's manifest or trace hook. More...
struct  jam::tracer< ptr< T > >
 Tag a reference slot and enqueue its target. More...
struct  jam::tracer< weak_ptr< T > >
 Declare a weak field for forwarding without following its target. More...
struct  jam::tracer< std::tuple< Ts... > >
 Visit each tuple element in the enclosing allocation. More...
struct  jam::tracer< std::array< T, N > >
 Visit each array element in the enclosing allocation. More...
struct  jam::tracer< std::variant< Ts... > >
 Visit only the active variant alternative in the enclosing allocation. More...
struct  jam::generation_options
 Sizing policy for one generation. Sizes are platform pages. More...
struct  jam::heap_options
 Two generations and one shared worker pool. More...
class  jam::heap
 A circular, double-mapped arena with bounded parallel compaction.Compressed four-byte offsets address two generations of up to 16 GiB each. The high bit selects young; the remaining bits count eight-byte cells. Record alignment up to 64 bytes is retained by dilation and padding between independent rank blocks. Allocation and liveness always use eight-byte cells. Clients trace complete byte-relocatable records; the heap does not infer boundaries or run destructors. This storage contract extends beyond ISO C++ trivial-copy guarantees: moving representation bytes must preserve meaning after ptr fields are forwarded. Raw address-dependent state and required destruction are unsupported. Multiple markers may trace a frozen heap. Join them before compaction, mutation, allocation, or inspecting metadata. Borrows expire on movement. More...
class  jam::heap::root_handle
 A four-byte handle to a collector-updated external root slot.Copies share a registration; moves leave the source detached and null. Operations on registered handles require the owning heap current and a quiescent collector. The heap must outlive all its registered handles. More...
class  jam::heap::visitor
 One marker's claim and edge-discovery interface.Only a successful claimant visits the record's fields. The visitor is borrowed for one callback and must not escape it. More...
class  jam::root< T >
 A copyable external root, updated during collection.Four-byte slot index; no heap or registration address is stored. The heap must outlive the root and be current for operations and destruction. More...
class  jam::weak_root< T >
 An external weak slot, updated or cleared by collection without retaining its target.Keep it outside the managed heap. The heap must outlive even an expired attached root. Copies share a registration; moves leave the source detached and expired. Four-byte slot index; operations and destruction require the owning heap current. Operations require a quiescent collector. Old targets remain live during minor collection. More...
class  jam::weak< V >
 An external conditional weak-value handle; registration survives dropped handles.Keep this handle outside the managed heap. Copies share one registration. Finalization expires all copies before the callback runs; resurrection does not rearm it. More...

Typedefs

using jam::heap::word = std::uint64_t
 Eight-byte allocation cell.
using jam::heap::offset = std::uint32_t
 Stored reference, in eight-byte units from data().
using jam::heap::bitmap = offset
 Allocation/live bitmap.
using jam::heap::block = detail::heap_block
 Live bitmap, forwarding base and pointer-field bitmap.
template<class T>
using jam::heap::ptr = jam::ptr<T>
 The compact pointer type for this heap.

Functions

template<class T, class... Members>
requires (std::is_object_v<Members> && ...)
consteval auto jam::make_manifest (Members T::*... members)
 Describe the pointer-bearing members of T, including embedded values.T may still be incomplete. List pointers and embedded values that contain pointers; unlisted fields are data. Hooks take precedence over the manifest.
std::size_t jam::heap::generation::capacity () const noexcept
 Capacity in eight-byte cells, including the reserve.
std::size_t jam::heap::generation::reserved () const noexcept
 Reserved cells for bounded parallel compaction.
std::size_t jam::heap::generation::used () const noexcept
 Allocated prefix in eight-byte cells, including the reserved null cell.
std::size_t jam::heap::generation::start () const noexcept
 Current view's offset in the circular backing, in cells.
std::size_t jam::heap::generation::page_words () const noexcept
 Cells per native OS page (distinct from a rank block).
template<class Self>
auto jam::heap::generation::data (this Self &self) noexcept -> std::conditional_t< std::is_const_v< Self >, word const, word > *
 Borrow cells; dereference an offset as data()[offset].
template<class Self>
decltype(auto) jam::heap::generation::operator[] (this Self &self, offset index) noexcept
 Borrow an allocated cell.
offset jam::heap::generation::field (offset cell, unsigned slot=0) const noexcept
 Read one managed reference field by value.
void jam::heap::generation::set_field (offset cell, offset value, unsigned slot=0) noexcept
 Write a managed reference field's bytes.
std::span< block const > jam::heap::generation::blocks () const noexcept
 Borrow rank descriptors while markers and compaction are quiescent.
offset jam::heap::generation::allocate (std::size_t words, std::size_t alignment_bytes=8) noexcept
 Allocate a positive complete record measured in eight-byte cells.
void jam::heap::generation::clear_marks () noexcept
 Clear marks and alignment requirements; pointer declarations survive.
void jam::heap::generation::mark (offset first, std::size_t words=1, std::size_t alignment_bytes=8) noexcept
 Mark a complete reachable record; concurrent markers are permitted.
bool jam::heap::generation::claim (offset first, std::size_t words=1, std::size_t alignment_bytes=8) noexcept
 Claim traversal by atomically marking the record's first cell.
void jam::heap::generation::pointer (offset where, unsigned slot=0) noexcept
 Declare a managed reference field; may overlap frozen-heap markers.
void jam::heap::generation::compact (std::span< offset > roots={}) noexcept
 Pack marked records, forwarding managed fields and external roots.
 jam::heap::heap (heap_options config={})
 Construct a heap and one persistent pool sized for both collection phases.
heap_options jam::heap::configuration () const noexcept
 Read the immutable construction policy with typed page counts.
template<class T>
requires traceable<T>
jam::root< T > jam::heap::root (ptr< T > const &at) noexcept
 Register a typed external root with its type-specific tracing callback.
template<class T>
requires traceable<T>
jam::weak_root< T > jam::heap::weak_root (ptr< T > const &at) noexcept
 Register an external weak slot, forwarded but never used to seed marking.
void jam::heap::collect () noexcept
 Collect typed roots, running minor_collections minors between majors. The first minor_collections calls are minor; the next call is major. Explicit major collection resets the countdown; explicit minors leave it unchanged.Nonnull untyped roots or untyped visitor.field edges require collect(trace). External ptr copies expire, including stack variables and loaded snapshots. Only registered roots retain their meaning; reacquire pointers from them.
void jam::heap::collect_major () noexcept
 Trace both generations and compact survivors into old; reset the countdown.
void jam::heap::collect_minor (bool promote=false) noexcept
 Collect young without walking old; optionally promote survivors; preserve the countdown.
template<class Trace>
requires std::is_nothrow_invocable_v<Trace &, visitor &, offset>
void jam::heap::collect (Trace &&trace) noexcept
 Scheduled collection with a fallback tracer for untyped records.
template<class Trace>
requires std::is_nothrow_invocable_v<Trace &, visitor &, offset>
void jam::heap::collect_major (Trace &&trace) noexcept
 Major collection with a fallback tracer; reset the countdown.Uses the same tracing and synchronization contract as collect(trace).
template<class Trace>
requires std::is_nothrow_invocable_v<Trace &, visitor &, offset>
void jam::heap::collect_minor (Trace &&trace, bool promote=false) noexcept
 Minor collection with a fallback tracer and optional promotion; preserve the countdown.Uses the same tracing and synchronization contract as collect(trace).
template<class T, class... Args>
requires traceable<T>
ptr< T > jam::heap::mk (Args &&... args) noexcept
 Allocate and copy a typed record, returning an unrooted reference.Construct T from the arguments. Register a root before collecting; copies of the returned ptr do not keep the target alive. Allocation preserves pointers.
template<class T>
requires traceable<T>
T * jam::heap::address (ptr< T > const &at) noexcept
 Borrow a typed target; the address expires on growth or collection.
template<class T>
requires traceable<T>
T jam::heap::load (ptr< T > const &at) const noexcept
 Read a typed value snapshot; any pointers in it expire on collection.
template<class T>
requires traceable<T>
void jam::heap::store (ptr< T > const &at, T const &value) noexcept
 Replace a typed record's bytes without changing its extent or type.

Variables

static constexpr offset jam::heap::null = 0
 Unreachable reference preserved by forwarding.
static constexpr std::size_t jam::heap::block_words = 32
 Eight-byte cells in one rank block: 32.
static constexpr unsigned jam::heap::fields_per_word = 2
 Four-byte pointer fields per allocation cell.

Detailed Description

Function Documentation

◆ address()

template<class T>
requires traceable<T>
T * jam::heap::address ( ptr< T > const & at)
inlinenodiscardnoexcept

Borrow a typed target; the address expires on growth or collection.

Precondition
The nonnull pointer names a complete record in this heap. Typed borrowing is a mutator operation; it requires exclusive record access.

Definition at line 2257 of file heap.ccm.

◆ allocate()

offset jam::heap::generation::allocate ( std::size_t words,
std::size_t alignment_bytes = 8 )
inlinenodiscardnoexcept

Allocate a positive complete record measured in eight-byte cells.

Parameters
wordsExtent, including any padding within the record.
alignment_bytesAlignment: 8, 16, 32 or 64 bytes. Grows by doubling without copying payloads, capped by maximum (at most 16 GiB). Allocations preserve offsets. Cell zero is reserved for null; leading alignment padding is initialized. Resource failures terminate.

Definition at line 1406 of file heap.ccm.

◆ claim()

bool jam::heap::generation::claim ( offset first,
std::size_t words = 1,
std::size_t alignment_bytes = 8 )
inlinenodiscardnoexcept

Claim traversal by atomically marking the record's first cell.

Returns
Exactly one winning marker must trace this record's outgoing fields.
Precondition
Disjoint complete extents; all tracers agree on start, extent, alignment. The start must not be independently marked. A claim is not completion; join all markers before inspecting final marks or compacting.

Definition at line 1450 of file heap.ccm.

◆ collect()

template<class Trace>
requires std::is_nothrow_invocable_v<Trace &, visitor &, offset>
void jam::heap::collect ( Trace && trace)
inlinenoexcept

Scheduled collection with a fallback tracer for untyped records.

Parameters
traceA noexcept callable accepting visitor& and a record offset.
Precondition
Mutators are stopped, and the tracer permits concurrent invocation. Compiler fences bracket the collection. Worker completion synchronizes through the pool before forwarded roots and the new mapping become observable. The tracer claims a complete record before visiting its outgoing fields. Cycles and sharing terminate because only one claimant traverses each record. Raw offsets and borrowed pointers expire on return; registered roots are updated. External ptr copies on the stack or in containers and snapshots are not rewritten, even when their targets survive. Reacquire them from roots.

Definition at line 2127 of file heap.ccm.

◆ compact()

void jam::heap::generation::compact ( std::span< offset > roots = {})
inlinenoexcept

Pack marked records, forwarding managed fields and external roots.

Parameters
rootsMutable offsets outside the heap, including null. The construction policy selects the participating workers, including the caller.
Precondition
Nonnull strong roots and fields target marked cells; weak fields may target unmarked allocations. Mutators and markers are stopped. Payloads are relocatable and roots do not alias the heap. The view steps backward by the reserve. Copying never gets more than N native source pages ahead of the earliest unfinished page; completed pages release credit. Old rank descriptors remain frozen throughout copying. Retained alignment groups and destination padding count toward used(). Shrink once below the configured occupancy threshold if live cells and reserve fit. Resource failures terminate because a moving collection cannot unwind.

Definition at line 1488 of file heap.ccm.

◆ field()

offset jam::heap::generation::field ( offset cell,
unsigned slot = 0 ) const
inlinenodiscardnoexcept

Read one managed reference field by value.

Parameters
cellEight-byte cell offset.
slotZero or one. Fixed-size byte copies permit both halves to coexist with whole-cell access.

Definition at line 1374 of file heap.ccm.

◆ heap()

jam::heap::heap ( heap_options config = {})
inlineexplicit

Construct a heap and one persistent pool sized for both collection phases.

Precondition
Capacity holds at least twice the reserve; workers are positive.
Exceptions
std::length_errorif any generation size exceeds 16 GiB. Mapping/allocation/thread creation failures terminate; collection never unwinds.

Definition at line 2047 of file heap.ccm.

◆ load()

template<class T>
requires traceable<T>
T jam::heap::load ( ptr< T > const & at) const
inlinenodiscardnoexcept

Read a typed value snapshot; any pointers in it expire on collection.

Precondition
The reference names a complete T in this heap. No concurrent mutation.

Definition at line 2266 of file heap.ccm.

◆ make_manifest()

template<class T, class... Members>
requires (std::is_object_v<Members> && ...)
auto jam::make_manifest ( Members T::*... members)
nodiscardconstevalexport

Describe the pointer-bearing members of T, including embedded values.T may still be incomplete. List pointers and embedded values that contain pointers; unlisted fields are data. Hooks take precedence over the manifest.

struct node {
ptr<node> left, right;
std::uint64_t data;
static constexpr auto manifest = make_manifest<node>(&node::left, &node::right);
};
A typed heap offset, with no root registration or ownership.
Definition heap.ccm:570
consteval auto make_manifest(Members T::*... members)
Describe the pointer-bearing members of T, including embedded values.T may still be incomplete....
Definition heap.ccm:476

Allocation tracing claims sizeof(T) with alignof(T), declares the listed pointer slots, and queues their targets. The last nonnull same-type child found by structural enumeration continues in a loop; earlier children are queued. Embedded values share the enclosing allocation's claim and mask. Each successful claim polls the scheduler. Graph depth does not grow the stack.

Definition at line 476 of file heap.ccm.

◆ mark()

void jam::heap::generation::mark ( offset first,
std::size_t words = 1,
std::size_t alignment_bytes = 8 )
inlinenoexcept

Mark a complete reachable record; concurrent markers are permitted.

Parameters
firstRecord start in cells.
wordsComplete extent in cells.
alignment_bytesSame alignment used to allocate this record.
Precondition
Extent is allocated and the heap is frozen. Join markers before moving. Record boundaries prevent padding within straddling records.

Definition at line 1439 of file heap.ccm.

◆ pointer()

void jam::heap::generation::pointer ( offset where,
unsigned slot = 0 )
inlinenoexcept

Declare a managed reference field; may overlap frozen-heap markers.

Parameters
whereCell containing the field, rather than its target.
slotZero or one. Declarations survive until the containing cell is reclaimed. Unmarked fields retained solely by dilation are copied as data, never forwarded.

Definition at line 1468 of file heap.ccm.

◆ root()

template<class T>
requires traceable<T>
jam::root< T > jam::heap::root ( ptr< T > const & at)
inlinenodiscardnoexcept

Register a typed external root with its type-specific tracing callback.

Precondition
This heap is current; the reference is null or names a complete T in this heap.

Definition at line 2072 of file heap.ccm.

◆ set_field()

void jam::heap::generation::set_field ( offset cell,
offset value,
unsigned slot = 0 )
inlinenoexcept

Write a managed reference field's bytes.

Parameters
cellEight-byte cell offset.
valueReference or null to store.
slotZero or one. Declare its pointer bit separately with pointer(). Mutation must not overlap tracing or compaction; this operation does not synchronize field values.

Definition at line 1389 of file heap.ccm.

◆ store()

template<class T>
requires traceable<T>
void jam::heap::store ( ptr< T > const & at,
T const & value )
inlinenoexcept

Replace a typed record's bytes without changing its extent or type.

Precondition
The reference names a complete T in this heap; mutators are quiescent with GC.

Definition at line 2276 of file heap.ccm.

◆ weak_root()

template<class T>
requires traceable<T>
jam::weak_root< T > jam::heap::weak_root ( ptr< T > const & at)
inlinenodiscardnoexcept

Register an external weak slot, forwarded but never used to seed marking.

Precondition
This heap is current; the pointer is null or names a complete T in it; the heap outlives the root.

Definition at line 2081 of file heap.ccm.