Skip to content
GenericGraphSlot

GenericGraphSlot

Description

Type-erased slot layout used by the runtime helpers in Source/Misra/Std/Container/Graph.c. GraphSlot(T) below is the typed variant; both have identical layout (the data field is a pointer, and void * / T * share representation).

Usage example (Cross-references)

Usage examples (Cross-references)
        u32            generation;
        u32            flags;
    } GenericGraphSlot;
    
    typedef Vec(GenericGraphSlot) GraphSlots;
    } GenericGraphSlot;
    
    typedef Vec(GenericGraphSlot) GraphSlots;
    typedef Vec(u32) GraphFreeIndices;
    }
    
    static bool graph_slot_is_occupied(const GenericGraphSlot *slot) {
        return (slot->flags & GRAPH_SLOT_OCCUPIED) != 0;
    }
    }
    
    static bool graph_slot_is_marked(const GenericGraphSlot *slot) {
        return (slot->flags & GRAPH_SLOT_MARKED) != 0;
    }
    }
    
    static GenericGraphSlot *graph_slot_ptr_raw(GenericGraph *graph, u32 index) {
        return VecPtrAt(&graph->slots, index);
    }
    }
    
    static const GenericGraphSlot *graph_slot_ptr_const_raw(const GenericGraph *graph, u32 index) {
        return VecPtrAt((GraphSlots *)&graph->slots, index);
    }
        u32                     index;
        u32                     generation;
        const GenericGraphSlot *slot;
    
        index      = GraphNodeIdIndex(node_id);
    }
    
    static GenericGraphSlot *graph_require_live_slot(GenericGraph *graph, GraphNodeId node_id) {
        graph_validate_node_id(graph, node_id);
        return graph_slot_ptr_raw(graph, GraphNodeIdIndex(node_id));
    }
    
    static const GenericGraphSlot *graph_require_live_slot_const(const GenericGraph *graph, GraphNodeId node_id) {
        graph_validate_node_id(graph, node_id);
        return graph_slot_ptr_const_raw(graph, GraphNodeIdIndex(node_id));
    }
    
    static void graph_ensure_slot_generation_available(GenericGraphSlot *slot) {
        if (slot->generation == UINT32_MAX) {
            LOG_FATAL("graph slot generation exhausted");
    }
    
    static void graph_release_slot(GenericGraph *graph, GenericGraphSlot *slot, size item_size) {
        if (!graph_slot_is_occupied(slot)) {
            return;
        while (idx < VecLen(neighbors)) {
            GraphNodeId             neighbor_id = VecAt(neighbors, idx);
            const GenericGraphSlot *slot;
    
            graph_validate_node_index_raw(graph, GraphNodeIdIndex(neighbor_id));
    
        for (slot_index = 0; slot_index < VecLen(&graph->slots); slot_index++) {
            const GenericGraphSlot *slot    = VecPtrAt((GraphSlots *)&graph->slots, slot_index);
            GraphNodeId             self_id = graph_make_node_id((u32)slot_index, slot->generation);
            u64                     neighbor_i;
                for (neighbor_i = 0; neighbor_i < VecLen(&slot->out_neighbors); neighbor_i++) {
                    GraphNodeId             neighbor_id = VecAt(&slot->out_neighbors, neighbor_i);
                    const GenericGraphSlot *target_slot;
    
                    graph_validate_node_id(graph, neighbor_id);
                for (neighbor_i = 0; neighbor_i < VecLen(&slot->in_neighbors); neighbor_i++) {
                    GraphNodeId             predecessor_id = VecAt(&slot->in_neighbors, neighbor_i);
                    const GenericGraphSlot *source_slot;
    
                    graph_validate_node_id(graph, predecessor_id);
    
        clear_graph(graph, item_size);
        deinit_vec(GENERIC_VEC(&graph->slots), sizeof(GenericGraphSlot));
        deinit_vec(GENERIC_VEC(&graph->free_indices), sizeof(u32));
        deinit_vec(GENERIC_VEC(&graph->pending_edge_removals), sizeof(GraphPendingEdgeRemoval));
    
        for (slot_index = 0; slot_index < VecLen(&graph->slots); slot_index++) {
            GenericGraphSlot *slot = VecPtrAt(&graph->slots, slot_index);
            if (graph_slot_is_occupied(slot)) {
                graph_release_slot(graph, slot, item_size);
    
        success = reserve_vec(GENERIC_VEC(&graph->free_indices), sizeof(u32), n) &&
                  reserve_vec(GENERIC_VEC(&graph->slots), sizeof(GenericGraphSlot), n);
        if (!success) {
            return false;
    GraphNodeId graph_push_node(GenericGraph *graph, const void *item_data, size item_size) {
        GraphNodeId       node_id;
        GenericGraphSlot  slot;
        GenericGraphSlot *slot_ptr;
        u32               slot_index;
        GraphNodeId       node_id;
        GenericGraphSlot  slot;
        GenericGraphSlot *slot_ptr;
        u32               slot_index;
                GENERIC_VEC(&graph->slots),
                (const u8 *)&slot,
                sizeof(GenericGraphSlot),
                VecLen(&graph->slots),
                1
        u32               index;
        u32               generation;
        GenericGraphSlot *slot;
    
        if (!graph) {
    u64 GraphNodeVisit(GraphNode node) {
        GenericGraph     *graph;
        GenericGraphSlot *slot;
    
        node  = graph_validate_node_handle(node);
    void GraphNodeUnvisit(GraphNode node) {
        GenericGraph     *graph;
        GenericGraphSlot *slot;
    
        node  = graph_validate_node_handle(node);
    u64 GraphNodeVisitCount(GraphNode node) {
        GenericGraph           *graph;
        const GenericGraphSlot *slot;
    
        node  = graph_validate_node_handle(node);
    bool GraphMarkNodeForDeletion(GraphNode node) {
        GenericGraph     *graph;
        GenericGraphSlot *slot;
    
        node  = graph_validate_node_handle(node);
    bool GraphNodeMarkedForDeletion(GraphNode node) {
        GenericGraph           *graph;
        const GenericGraphSlot *slot;
    
        node  = graph_validate_node_handle(node);
    bool GraphUnmarkNodeForDeletion(GraphNode node) {
        GenericGraph     *graph;
        GenericGraphSlot *slot;
    
        node  = graph_validate_node_handle(node);
    
        for (slot_index = 0; slot_index < VecLen(&graph->slots); slot_index++) {
            GenericGraphSlot *slot = VecPtrAt(&graph->slots, slot_index);
            if (graph_slot_is_occupied(slot) && graph_slot_is_marked(slot)) {
                GraphNodeId marked_id = graph_make_node_id((u32)slot_index, slot->generation);
    
        for (slot_index = 0; slot_index < VecLen(&graph->slots); slot_index++) {
            GenericGraphSlot *slot = VecPtrAt(&graph->slots, slot_index);
            if (graph_slot_is_occupied(slot) && !graph_slot_is_marked(slot)) {
                GraphNodeId live_id = graph_make_node_id((u32)slot_index, slot->generation);
    
        for (slot_index = 0; slot_index < VecLen(&graph->slots); slot_index++) {
            GenericGraphSlot *slot = VecPtrAt(&graph->slots, slot_index);
            if (graph_slot_is_occupied(slot) && graph_slot_is_marked(slot)) {
                if (VecLen(&slot->out_neighbors) || VecLen(&slot->in_neighbors)) {
        while (iter->slot_index < VecLen(&iter->graph->slots)) {
            u32               index  = (u32)iter->slot_index;
            GenericGraphSlot *slot   = VecPtrAt(&iter->graph->slots, iter->slot_index);
            iter->slot_index        += 1;
        // logical lengths to 0 (stale b remains in a.out's buffer at index 0) so
        // the graph looks edge-free while the pending removal still names a->b.
        GenericGraphSlot *slot_a     = (GenericGraphSlot *)VecPtrAt(&GENERIC_GRAPH(&graph)->slots, GraphNodeIdIndex(a));
        GenericGraphSlot *slot_b     = (GenericGraphSlot *)VecPtrAt(&GENERIC_GRAPH(&graph)->slots, GraphNodeIdIndex(b));
        slot_a->out_neighbors.length = 0;
        // the graph looks edge-free while the pending removal still names a->b.
        GenericGraphSlot *slot_a     = (GenericGraphSlot *)VecPtrAt(&GENERIC_GRAPH(&graph)->slots, GraphNodeIdIndex(a));
        GenericGraphSlot *slot_b     = (GenericGraphSlot *)VecPtrAt(&GENERIC_GRAPH(&graph)->slots, GraphNodeIdIndex(b));
        slot_a->out_neighbors.length = 0;
        slot_b->in_neighbors.length  = 0;
        // neighbor id so its generation is 0 (an always-invalid generation),
        // without bumping the mutation epoch or re-flagging the validated bit.
        GenericGraphSlot *slot_a = (GenericGraphSlot *)VecPtrAt(&GENERIC_GRAPH(&graph)->slots, GraphNodeIdIndex(a));
        GraphNodeId      *entry  = VecPtrAt(&slot_a->out_neighbors, 0);
        *entry                   = (GraphNodeId)GraphNodeIdIndex(b);
        // Intentional bypass: rewrite `b`'s sole in-neighbor (a) so its generation
        // is 0, leaving the epoch and validated bit untouched.
        GenericGraphSlot *slot_b = (GenericGraphSlot *)VecPtrAt(&GENERIC_GRAPH(&graph)->slots, GraphNodeIdIndex(b));
        GraphNodeId      *entry  = VecPtrAt(&slot_b->in_neighbors, 0);
        *entry                   = (GraphNodeId)GraphNodeIdIndex(a);
    
    // Fetch the type-erased slot for a node id (slots vec is shared-layout).
    static GenericGraphSlot *mutant_slot(void *graph_handle, GraphNodeId id) {
        GenericGraph *g = GENERIC_GRAPH(graph_handle);
        return (GenericGraphSlot *)VecPtrAt(&g->slots, GraphNodeIdIndex(id));
    static GenericGraphSlot *mutant_slot(void *graph_handle, GraphNodeId id) {
        GenericGraph *g = GENERIC_GRAPH(graph_handle);
        return (GenericGraphSlot *)VecPtrAt(&g->slots, GraphNodeIdIndex(id));
    }
        GraphAddEdge(&graph, c, b);
    
        GenericGraphSlot *b_slot = mutant_slot(&graph, b);
        // b.in_neighbors is [a, c]; overwrite the 'a' entry with 'c' -> [c, c].
        *VecPtrAt(&b_slot->in_neighbors, 0) = c;
        GraphAddEdge(&graph, b, c);
    
        GenericGraphSlot *c_slot = mutant_slot(&graph, c);
        // c.in_neighbors is [a, b]; overwrite the 'a' entry with 'b' -> [b, b].
        *VecPtrAt(&c_slot->in_neighbors, 0) = b;
        GraphAddEdge(&graph, b, c);
    
        GenericGraphSlot *b_slot = mutant_slot(&graph, b);
        // b.out_neighbors is [a, c]; overwrite the 'a' entry with 'c' -> [c, c].
        *VecPtrAt(&b_slot->out_neighbors, 0) = c;
        GraphAddEdge(&graph, c, b);
    
        GenericGraphSlot *c_slot = mutant_slot(&graph, c);
        // c.out_neighbors is [a, b]; overwrite the 'a' entry with 'b' -> [b, b].
        *VecPtrAt(&c_slot->out_neighbors, 0) = b;
            // `graph.slots` is the typed `Vec(GraphSlot(int))`, so iterate via
            // the runtime-shared layout to avoid an anonymous-struct annotation.
            GenericGraphSlot *slot = (GenericGraphSlot *)VecPtrAt(&GENERIC_GRAPH(&graph)->slots, slot_index);
            result                 = result && (slot->data == NULL);
            result                 = result && (slot->visit_count == 0);
Last updated on