Skip to content

GraphReserve

Description

Reserve space for at least n nodes in the graph. Does not change the node count, only ensures capacity.

Parameters

Name Direction Description
g in,out Graph handle.
n in Minimum number of nodes the graph should accommodate.

Success

Returns true. The slot array and free-index array now have capacity for at least n total nodes without triggering a regrow. live_count and the actual stored nodes are unchanged.

Failure

Returns false on allocation failure for either backing array. The graph is unchanged.

Usage example (Cross-references)

Usage examples (Cross-references)
    #define GraphMustReserve(g, n)                                                                                         \
        do {                                                                                                               \
            if (!GraphReserve((g), (n))) {                                                                                 \
                LOG_FATAL("GraphMustReserve failed");                                                                      \
            }                                                                                                              \
    
    static bool test_graph_reserve_clear(void) {
        WriteFmt("Testing GraphReserve and GraphClear\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        IntGraph graph = GraphInit(&alloc);
    
        GraphReserve(&graph, 8);
        ValidateGraph(&graph);
    // to at least the requested count.
    static bool test_graph_reserve_grows_capacity(void) {
        WriteFmt("Testing GraphReserve actually grows slot capacity\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        IntGraph graph = GraphInit(&alloc);
    
        bool result = GraphReserve(&graph, 64);
        result      = result && (VecCapacity(&graph.slots) >= 64);
    // detect concurrent structural mutation.
    static bool test_graph_reserve_growth_bumps_epoch(void) {
        WriteFmt("Testing GraphReserve growth bumps the mutation epoch\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        u64  old_epoch    = GraphMutationEpoch(&graph);
    
        bool grew = GraphReserve(&graph, 1024);
    
        bool result = grew;
        // Pre-reserve so the failing add appends a slot WITHOUT reallocating the
        // slot vector; the node-data buffer is then the only allocation in flight.
        bool result = GraphReserve(&graph, 8);
    
        size before = DebugAllocatorLiveCount(&dbg);
    // iteration completes over both nodes.
    static bool test_graph_reserve_no_grow_keeps_iterator_valid(void) {
        WriteFmt("Testing in-capacity GraphReserve does not invalidate traversal\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        // Pre-grow so the live capacity is deterministic and not 42.
        GraphReserve(&graph, 4);
    
        (void)GraphAddNodeR(&graph, 10);
                // Reserve well within existing capacity: no realloc, so real code
                // leaves the epoch untouched and the iterator stays valid.
                (void)GraphReserve(&graph, 2);
            }
            visited += 1;
        // Pre-reserve enough capacity that appending a third slot does NOT realloc,
        // so reserve_graph leaves the epoch untouched and line 604 stands alone.
        (void)GraphReserve(&graph, 8);
    
        GraphAddNodeR(&graph, 1);
Last updated on