Skip to content

GraphNodeId

Description

Stable identifier used to refer to a graph node.

Node ids are opaque 64-bit values. Internally they pack a per-slot generation in the high 32 bits and a slot index in the low 32 bits.

A node id is stable only while that node remains live. After GraphCommitChanges deletes a node, any old id or handle referring to that slot becomes stale and must not be used with live-node access APIs.

Usage example (Cross-references)

Usage examples (Cross-references)
    #define MISRA_GRAPH_SLOT_MARKED   ((u32)1u << 1)
    
    static GraphNodeId graph_make_node_id(u32 index, u32 generation) {
        return (((u64)generation) << 32) | (u64)index;
    }
    }
    
    static void graph_validate_node_id(const GenericGraph *graph, GraphNodeId node_id) {
        u32                     index;
        u32                     generation;
    }
    
    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));
        slot->data = NULL;
    
        deinit_vec(GENERIC_VEC(&slot->out_neighbors), sizeof(GraphNodeId));
        slot->out_neighbors = VecInitT(slot->out_neighbors);
        deinit_vec(GENERIC_VEC(&slot->in_neighbors), sizeof(GraphNodeId));
        deinit_vec(GENERIC_VEC(&slot->out_neighbors), sizeof(GraphNodeId));
        slot->out_neighbors = VecInitT(slot->out_neighbors);
        deinit_vec(GENERIC_VEC(&slot->in_neighbors), sizeof(GraphNodeId));
        slot->in_neighbors = VecInitT(slot->in_neighbors);
    }
    
    static bool graph_neighbors_contains(const GraphNeighbors *neighbors, GraphNodeId node_id) {
        size idx;
    }
    
    static size graph_find_neighbor_index(const GraphNeighbors *neighbors, GraphNodeId node_id) {
        size idx;
    }
    
    static size graph_find_pending_edge_removal_index(const GenericGraph *graph, GraphNodeId from, GraphNodeId to) {
        size idx;
    }
    
    static bool graph_remove_edge_now(GenericGraph *graph, GraphNodeId from, GraphNodeId to) {
        GraphNeighbors *out_neighbors;
        GraphNeighbors *in_neighbors;
        }
    
        remove_range_vec(GENERIC_VEC(out_neighbors), NULL, sizeof(GraphNodeId), out_idx, 1);
        remove_range_vec(GENERIC_VEC(in_neighbors), NULL, sizeof(GraphNodeId), in_idx, 1);
        graph->edge_count -= 1;
    
        remove_range_vec(GENERIC_VEC(out_neighbors), NULL, sizeof(GraphNodeId), out_idx, 1);
        remove_range_vec(GENERIC_VEC(in_neighbors), NULL, sizeof(GraphNodeId), in_idx, 1);
        graph->edge_count -= 1;
        return true;
    }
    
    static size graph_remove_marked_outgoing_edges(GenericGraph *graph, GraphNodeId from) {
        size            removed   = 0;
        GraphNeighbors *neighbors = graph_out_neighbors_ptr(graph, from);
    
        while (idx < neighbors->length) {
            GraphNodeId             neighbor_id = VecAt(neighbors, idx);
            const GenericGraphSlot *slot;
    }
    
    static size graph_remove_all_outgoing_edges(GenericGraph *graph, GraphNodeId from) {
        size            removed   = 0;
        GraphNeighbors *neighbors = graph_out_neighbors_ptr(graph, from);
    
        while (neighbors->length) {
            GraphNodeId to = VecAt(neighbors, neighbors->length - 1);
            if (!graph_remove_edge_now(graph, from, to)) {
                LOG_FATAL("Graph failed to remove outgoing edge during node deletion");
        for (slot_index = 0; slot_index < graph->slots.length; 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 < slot->out_neighbors.length; neighbor_i++) {
                    GraphNodeId             neighbor_id  = VecAt(&slot->out_neighbors, neighbor_i);
                    const GenericGraphSlot *target_slot;
    
                for (neighbor_i = 0; neighbor_i < slot->in_neighbors.length; neighbor_i++) {
                    GraphNodeId             predecessor_id = VecAt(&slot->in_neighbors, neighbor_i);
                    const GenericGraphSlot *source_slot;
                graph_release_slot(graph, slot, item_size);
            } else {
                deinit_vec(GENERIC_VEC(&slot->out_neighbors), sizeof(GraphNodeId));
                slot->out_neighbors = VecInitT(slot->out_neighbors);
                deinit_vec(GENERIC_VEC(&slot->in_neighbors), sizeof(GraphNodeId));
                deinit_vec(GENERIC_VEC(&slot->out_neighbors), sizeof(GraphNodeId));
                slot->out_neighbors = VecInitT(slot->out_neighbors);
                deinit_vec(GENERIC_VEC(&slot->in_neighbors), sizeof(GraphNodeId));
                slot->in_neighbors = VecInitT(slot->in_neighbors);
                slot->visit_count   = 0;
    }
    
    GraphNodeId graph_push_node(GenericGraph *graph, const void *item_data, size item_size) {
        GraphNodeId       node_id;
        GenericGraphSlot  slot;
    
    GraphNodeId graph_push_node(GenericGraph *graph, const void *item_data, size item_size) {
        GraphNodeId       node_id;
        GenericGraphSlot  slot;
        GenericGraphSlot *slot_ptr;
    }
    
    GraphNodeId graph_push_node_owned(GenericGraph *graph, void *item_data, size item_size) {
        GraphNodeId node_id;
    
    GraphNodeId graph_push_node_owned(GenericGraph *graph, void *item_data, size item_size) {
        GraphNodeId node_id;
    
        if (!graph || !item_data || !item_size) {
    }
    
    bool graph_contains_node(GenericGraph *graph, GraphNodeId node_id) {
        u32               index;
        u32               generation;
    }
    
    GraphNode graph_get_node(GenericGraph *graph, GraphNodeId node_id) {
        GraphNode node;
    }
    
    void *graph_node_ptr_at(GenericGraph *graph, GraphNodeId node_id) {
        return graph_require_live_slot(graph, node_id)->data;
    }
    }
    
    GraphNeighbors *graph_out_neighbors_ptr(GenericGraph *graph, GraphNodeId node_id) {
        return &graph_require_live_slot(graph, node_id)->out_neighbors;
    }
    }
    
    GraphNeighbors *graph_in_neighbors_ptr(GenericGraph *graph, GraphNodeId node_id) {
        return &graph_require_live_slot(graph, node_id)->in_neighbors;
    }
    }
    
    size graph_out_degree(GenericGraph *graph, GraphNodeId node_id) {
        return graph_out_neighbors_ptr(graph, node_id)->length;
    }
    }
    
    size graph_in_degree(GenericGraph *graph, GraphNodeId node_id) {
        return graph_in_neighbors_ptr(graph, node_id)->length;
    }
    }
    
    GraphNodeId graph_neighbor_at(GenericGraph *graph, GraphNodeId from, size neighbor_idx) {
        GraphNeighbors *neighbors;
    }
    
    GraphNodeId graph_predecessor_at(GenericGraph *graph, GraphNodeId to, size predecessor_idx) {
        GraphNeighbors *neighbors;
    }
    
    bool graph_has_edge(GenericGraph *graph, GraphNodeId from, GraphNodeId to) {
        GraphNeighbors *neighbors;
    }
    
    bool graph_add_edge(GenericGraph *graph, GraphNodeId from, GraphNodeId to) {
        GraphNeighbors *out_neighbors;
        GraphNeighbors *in_neighbors;
    
        in_neighbors = graph_in_neighbors_ptr(graph, to);
        insert_range_into_vec(GENERIC_VEC(out_neighbors), (char *)&to, sizeof(GraphNodeId), out_neighbors->length, 1);
        insert_range_into_vec(GENERIC_VEC(in_neighbors), (char *)&from, sizeof(GraphNodeId), in_neighbors->length, 1);
        graph->edge_count += 1;
        in_neighbors = graph_in_neighbors_ptr(graph, to);
        insert_range_into_vec(GENERIC_VEC(out_neighbors), (char *)&to, sizeof(GraphNodeId), out_neighbors->length, 1);
        insert_range_into_vec(GENERIC_VEC(in_neighbors), (char *)&from, sizeof(GraphNodeId), in_neighbors->length, 1);
        graph->edge_count += 1;
        graph_bump_mutation_epoch(graph);
    }
    
    bool graph_mark_edge_for_removal(GenericGraph *graph, GraphNodeId from, GraphNodeId to) {
        GraphPendingEdgeRemoval pending;
    }
    
    bool graph_edge_marked_for_removal(GenericGraph *graph, GraphNodeId from, GraphNodeId to) {
        ValidateGraph(graph);
        graph_validate_node_id(graph, from);
    }
    
    bool graph_unmark_edge_for_removal(GenericGraph *graph, GraphNodeId from, GraphNodeId to) {
        size idx;
            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);
                (void)graph_remove_all_outgoing_edges(graph, marked_id);
            }
            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);
                (void)graph_remove_marked_outgoing_edges(graph, live_id);
            }
    
        while (iter->neighbor_index < neighbors->length) {
            GraphNodeId neighbor_id = VecAt(neighbors, iter->neighbor_index);
            iter->neighbor_index += 1;
    
        while (iter->predecessor_index < neighbors->length) {
            GraphNodeId predecessor_id = VecAt(neighbors, iter->predecessor_index);
            iter->predecessor_index += 1;
    
    static u64 node_id_hash(const void *data, u32 size) {
        u64 x = *(const GraphNodeId *)data;
        (void)size;
    
    static i32 node_id_compare(const void *lhs, const void *rhs) {
        GraphNodeId a = *(const GraphNodeId *)lhs;
        GraphNodeId b = *(const GraphNodeId *)rhs;
        return (a > b) - (a < b);
    static i32 node_id_compare(const void *lhs, const void *rhs) {
        GraphNodeId a = *(const GraphNodeId *)lhs;
        GraphNodeId b = *(const GraphNodeId *)rhs;
        return (a > b) - (a < b);
    }
    
    typedef Graph(Str)                 CityGraph;
    typedef Map(const char *, GraphNodeId) CityIndex;
    
    static GraphNodeId city_add_intersection(CityGraph *graph, CityIndex *index, const char *name) {
    typedef Map(const char *, GraphNodeId) CityIndex;
    
    static GraphNodeId city_add_intersection(CityGraph *graph, CityIndex *index, const char *name) {
        Str         intersection = StrInitFromZstr(name);
        GraphNodeId id           = GraphAddNodeL(graph, intersection);
    static GraphNodeId city_add_intersection(CityGraph *graph, CityIndex *index, const char *name) {
        Str         intersection = StrInitFromZstr(name);
        GraphNodeId id           = GraphAddNodeL(graph, intersection);
    
        MapInsertR(index, name, id);
    }
    
    static bool city_reachable_from(GraphNode node, GraphNodeId goal_id) {
        if (GraphNodeVisitCount(node) > 0) {
            return false;
    
    static bool city_reachable(CityGraph *graph, CityIndex *index, const char *from, const char *to) {
        GraphNodeId *from_id = MapTryGetPtr(index, from);
        GraphNodeId *to_id   = MapTryGetPtr(index, to);
    static bool city_reachable(CityGraph *graph, CityIndex *index, const char *from, const char *to) {
        GraphNodeId *from_id = MapTryGetPtr(index, from);
        GraphNodeId *to_id   = MapTryGetPtr(index, to);
    
        if (!from_id || !to_id) {
        CityIndex index = MapInitWithDeepCopy(zstr_hash, zstr_compare_ptr, ZstrInitClone, ZstrDeinit, NULL, NULL);
    
        GraphNodeId alpha = city_add_intersection(&graph, &index, "Alpha");
        GraphNodeId beta  = city_add_intersection(&graph, &index, "Beta");
        GraphNodeId gamma = city_add_intersection(&graph, &index, "Gamma");
    
        GraphNodeId alpha = city_add_intersection(&graph, &index, "Alpha");
        GraphNodeId beta  = city_add_intersection(&graph, &index, "Beta");
        GraphNodeId gamma = city_add_intersection(&graph, &index, "Gamma");
        GraphNodeId delta = city_add_intersection(&graph, &index, "Delta");
        GraphNodeId alpha = city_add_intersection(&graph, &index, "Alpha");
        GraphNodeId beta  = city_add_intersection(&graph, &index, "Beta");
        GraphNodeId gamma = city_add_intersection(&graph, &index, "Gamma");
        GraphNodeId delta = city_add_intersection(&graph, &index, "Delta");
        GraphNodeId echo  = city_add_intersection(&graph, &index, "Echo");
        GraphNodeId beta  = city_add_intersection(&graph, &index, "Beta");
        GraphNodeId gamma = city_add_intersection(&graph, &index, "Gamma");
        GraphNodeId delta = city_add_intersection(&graph, &index, "Delta");
        GraphNodeId echo  = city_add_intersection(&graph, &index, "Echo");
        GraphNodeId gamma = city_add_intersection(&graph, &index, "Gamma");
        GraphNodeId delta = city_add_intersection(&graph, &index, "Delta");
        GraphNodeId echo  = city_add_intersection(&graph, &index, "Echo");
    
        GraphAddEdge(&graph, alpha, beta);
    
        typedef Graph(int) IntGraph;
        typedef Map(GraphNodeId, u64) CountMap;
    
        IntGraph graph  = GraphInit();
        CountMap counts = MapInit(node_id_hash, node_id_compare);
    
        GraphNodeId a = GraphAddNodeR(&graph, 1);
        GraphNodeId b = GraphAddNodeR(&graph, 2);
        GraphNodeId c = GraphAddNodeR(&graph, 3);
    
        GraphNodeId a = GraphAddNodeR(&graph, 1);
        GraphNodeId b = GraphAddNodeR(&graph, 2);
        GraphNodeId c = GraphAddNodeR(&graph, 3);
        GraphNodeId d = GraphAddNodeR(&graph, 4);
        GraphNodeId a = GraphAddNodeR(&graph, 1);
        GraphNodeId b = GraphAddNodeR(&graph, 2);
        GraphNodeId c = GraphAddNodeR(&graph, 3);
        GraphNodeId d = GraphAddNodeR(&graph, 4);
        GraphNodeId b = GraphAddNodeR(&graph, 2);
        GraphNodeId c = GraphAddNodeR(&graph, 3);
        GraphNodeId d = GraphAddNodeR(&graph, 4);
    
        GraphAddEdge(&graph, a, b);
        IntGraph graph = GraphInit();
    
        GraphNodeId a = GraphAddNodeR(&graph, 1);
        GraphNodeId b = GraphAddNodeR(&graph, 2);
        GraphNodeId c = GraphAddNodeR(&graph, 3);
    
        GraphNodeId a = GraphAddNodeR(&graph, 1);
        GraphNodeId b = GraphAddNodeR(&graph, 2);
        GraphNodeId c = GraphAddNodeR(&graph, 3);
        GraphNodeId d = GraphAddNodeR(&graph, 4);
        GraphNodeId a = GraphAddNodeR(&graph, 1);
        GraphNodeId b = GraphAddNodeR(&graph, 2);
        GraphNodeId c = GraphAddNodeR(&graph, 3);
        GraphNodeId d = GraphAddNodeR(&graph, 4);
        GraphNodeId b = GraphAddNodeR(&graph, 2);
        GraphNodeId c = GraphAddNodeR(&graph, 3);
        GraphNodeId d = GraphAddNodeR(&graph, 4);
    
        GraphAddEdge(&graph, a, d);
        IntGraph graph = GraphInit();
    
        GraphNodeId a = GraphAddNodeR(&graph, 1);
        GraphNodeId b = GraphAddNodeR(&graph, 2);
        GraphNodeId c = GraphAddNodeR(&graph, 3);
    
        GraphNodeId a = GraphAddNodeR(&graph, 1);
        GraphNodeId b = GraphAddNodeR(&graph, 2);
        GraphNodeId c = GraphAddNodeR(&graph, 3);
        GraphNodeId a = GraphAddNodeR(&graph, 1);
        GraphNodeId b = GraphAddNodeR(&graph, 2);
        GraphNodeId c = GraphAddNodeR(&graph, 3);
    
        GraphAddEdge(&graph, a, b);
        IntGraph graph = GraphInit();
    
        GraphNodeId a = GraphAddNodeR(&graph, 1);
        GraphNodeId b = GraphAddNodeR(&graph, 2);
        GraphNodeId c = GraphAddNodeR(&graph, 3);
    
        GraphNodeId a = GraphAddNodeR(&graph, 1);
        GraphNodeId b = GraphAddNodeR(&graph, 2);
        GraphNodeId c = GraphAddNodeR(&graph, 3);
        GraphNodeId d = GraphAddNodeR(&graph, 4);
        GraphNodeId a = GraphAddNodeR(&graph, 1);
        GraphNodeId b = GraphAddNodeR(&graph, 2);
        GraphNodeId c = GraphAddNodeR(&graph, 3);
        GraphNodeId d = GraphAddNodeR(&graph, 4);
        GraphNodeId b = GraphAddNodeR(&graph, 2);
        GraphNodeId c = GraphAddNodeR(&graph, 3);
        GraphNodeId d = GraphAddNodeR(&graph, 4);
    
        GraphAddEdge(&graph, a, c);
        IntGraph graph = GraphInit();
    
        GraphNodeId a    = GraphAddNodeR(&graph, 10);
        GraphNode   node = GraphGetNode(&graph, a);
        IntGraph graph = GraphInit();
    
        GraphNodeId a = GraphAddNodeR(&graph, 10);
        GraphNodeId b = GraphAddNodeR(&graph, 20);
        GraphNodeId c = GraphAddNodeR(&graph, 30);
    
        GraphNodeId a = GraphAddNodeR(&graph, 10);
        GraphNodeId b = GraphAddNodeR(&graph, 20);
        GraphNodeId c = GraphAddNodeR(&graph, 30);
        GraphNodeId a = GraphAddNodeR(&graph, 10);
        GraphNodeId b = GraphAddNodeR(&graph, 20);
        GraphNodeId c = GraphAddNodeR(&graph, 30);
    
        GraphAddEdge(&graph, a, b);
        result = result && (GraphPredecessorAt(&graph, a, 0) == c);
    
        GraphNodeId d = GraphAddNodeR(&graph, 40);
    
        result = result && (GraphNodeIdIndex(d) == GraphNodeIdIndex(b));
        IntGraph graph = GraphInit();
    
        GraphNodeId a    = GraphAddNodeR(&graph, 10);
        GraphNode   node = GraphGetNode(&graph, a);
        IntGraph graph = GraphInit();
    
        GraphNodeId a = GraphAddNodeR(&graph, 10);
        GraphNodeId b = GraphAddNodeR(&graph, 20);
        GraphNodeId c = GraphAddNodeR(&graph, 30);
    
        GraphNodeId a = GraphAddNodeR(&graph, 10);
        GraphNodeId b = GraphAddNodeR(&graph, 20);
        GraphNodeId c = GraphAddNodeR(&graph, 30);
        GraphNodeId a = GraphAddNodeR(&graph, 10);
        GraphNodeId b = GraphAddNodeR(&graph, 20);
        GraphNodeId c = GraphAddNodeR(&graph, 30);
    
        GraphAddEdge(&graph, a, b);
        IntGraph graph = GraphInit();
    
        GraphNodeId a = GraphAddNodeR(&graph, 10);
        GraphNodeId b = GraphAddNodeR(&graph, 20);
    
        GraphNodeId a = GraphAddNodeR(&graph, 10);
        GraphNodeId b = GraphAddNodeR(&graph, 20);
    
        GraphAddEdge(&graph, a, b);
        IntGraph graph = GraphInit();
    
        GraphNodeId a = GraphAddNodeR(&graph, 10);
        GraphNodeId b = GraphAddNodeR(&graph, 20);
        GraphNodeId c = GraphAddNodeR(&graph, 30);
    
        GraphNodeId a = GraphAddNodeR(&graph, 10);
        GraphNodeId b = GraphAddNodeR(&graph, 20);
        GraphNodeId c = GraphAddNodeR(&graph, 30);
        GraphNodeId a = GraphAddNodeR(&graph, 10);
        GraphNodeId b = GraphAddNodeR(&graph, 20);
        GraphNodeId c = GraphAddNodeR(&graph, 30);
    
        GraphAddEdge(&graph, a, b);
        IntGraph graph = GraphInit();
    
        GraphNodeId a = GraphAddNodeR(&graph, 10);
    
        bool result = GraphAddEdge(&graph, a, a);
        IntGraph graph = GraphInit();
    
        GraphNodeId a = GraphAddNodeR(&graph, 10);
        GraphNodeId b = GraphAddNodeR(&graph, 20);
        GraphNodeId c = GraphAddNodeR(&graph, 30);
    
        GraphNodeId a = GraphAddNodeR(&graph, 10);
        GraphNodeId b = GraphAddNodeR(&graph, 20);
        GraphNodeId c = GraphAddNodeR(&graph, 30);
        GraphNodeId d = GraphAddNodeR(&graph, 40);
        GraphNodeId a = GraphAddNodeR(&graph, 10);
        GraphNodeId b = GraphAddNodeR(&graph, 20);
        GraphNodeId c = GraphAddNodeR(&graph, 30);
        GraphNodeId d = GraphAddNodeR(&graph, 40);
        GraphNodeId b = GraphAddNodeR(&graph, 20);
        GraphNodeId c = GraphAddNodeR(&graph, 30);
        GraphNodeId d = GraphAddNodeR(&graph, 40);
    
        GraphAddEdge(&graph, a, b);
        IntGraph graph = GraphInit();
    
        GraphNodeId a = GraphAddNodeR(&graph, 10);
        GraphNodeId b = GraphAddNodeR(&graph, 20);
        u64         counts[2] = {0};
    
        GraphNodeId a = GraphAddNodeR(&graph, 10);
        GraphNodeId b = GraphAddNodeR(&graph, 20);
        u64         counts[2] = {0};
        result      = result && !GraphContainsNode(&graph, b);
    
        GraphNodeId reused = GraphAddNodeR(&graph, 99);
    
        result = result && (GraphNodeIdIndex(reused) == GraphNodeIdIndex(b));
        IntGraph graph = GraphInit();
    
        GraphNodeId a    = GraphAddNodeR(&graph, 10);
        GraphNode   node = GraphGetNode(&graph, a);
    
        bool        result           = graph.slots.capacity >= 8;
        GraphNodeId first_id         = GraphAddNodeR(&graph, 10);
        GraphNodeId second_id        = GraphAddNodeR(&graph, 20);
        GraphNodeId third_id         = GraphAddNodeR(&graph, 30);
        bool        result           = graph.slots.capacity >= 8;
        GraphNodeId first_id         = GraphAddNodeR(&graph, 10);
        GraphNodeId second_id        = GraphAddNodeR(&graph, 20);
        GraphNodeId third_id         = GraphAddNodeR(&graph, 30);
        u64         slot_count       = graph.slots.length;
        GraphNodeId first_id         = GraphAddNodeR(&graph, 10);
        GraphNodeId second_id        = GraphAddNodeR(&graph, 20);
        GraphNodeId third_id         = GraphAddNodeR(&graph, 30);
        u64         slot_count       = graph.slots.length;
        size        slot_capacity    = graph.slots.capacity;
        StrGraph   graph = GraphInitWithDeepCopy(StrInitCopy, StrDeinit);
        Str        name  = StrInitFromZstr("alpha");
        GraphNodeId node_id;
        GraphNode   node;
        Str        *stored_name;
        IntGraph graph = GraphInitAligned(32);
    
        GraphNodeId node_id = GraphAddNodeR(&graph, 11);
        GraphNode   node    = GraphGetNode(&graph, node_id);
        IntGraph graph = GraphInit();
    
        GraphNodeId a = GraphAddNodeR(&graph, 10);
        GraphNodeId b = GraphAddNodeR(&graph, 20);
        GraphNodeId c = GraphAddNodeR(&graph, 30);
    
        GraphNodeId a = GraphAddNodeR(&graph, 10);
        GraphNodeId b = GraphAddNodeR(&graph, 20);
        GraphNodeId c = GraphAddNodeR(&graph, 30);
        GraphNode   node_b;
        GraphNodeId a = GraphAddNodeR(&graph, 10);
        GraphNodeId b = GraphAddNodeR(&graph, 20);
        GraphNodeId c = GraphAddNodeR(&graph, 30);
        GraphNode   node_b;
        GraphAddEdge(&graph, a, b);
        ZstrGraph graph = GraphInit();
    
        GraphNodeId red   = GraphAddNodeR(&graph, "red");
        GraphNodeId green = GraphAddNodeR(&graph, "green");
        GraphNodeId blue  = GraphAddNodeR(&graph, "blue");
    
        GraphNodeId red   = GraphAddNodeR(&graph, "red");
        GraphNodeId green = GraphAddNodeR(&graph, "green");
        GraphNodeId blue  = GraphAddNodeR(&graph, "blue");
        GraphNodeId red   = GraphAddNodeR(&graph, "red");
        GraphNodeId green = GraphAddNodeR(&graph, "green");
        GraphNodeId blue  = GraphAddNodeR(&graph, "blue");
    
        GraphAddEdge(&graph, red, green);
        IntGraph graph = GraphInit();
    
        GraphNodeId a = GraphAddNodeR(&graph, 10);
        GraphNodeId b = GraphAddNodeR(&graph, 20);
    
        GraphNodeId a = GraphAddNodeR(&graph, 10);
        GraphNodeId b = GraphAddNodeR(&graph, 20);
    
        GraphAddEdge(&graph, a, b);
        IntGraph graph = GraphInit();
    
        GraphNodeId a = GraphAddNodeR(&graph, 10);
        GraphNodeId b = GraphAddNodeR(&graph, 20);
    
        GraphNodeId a = GraphAddNodeR(&graph, 10);
        GraphNodeId b = GraphAddNodeR(&graph, 20);
    
        GraphAddEdge(&graph, a, b);
        int      shared = 7;
    
        GraphNodeId id0 = GraphAddNodeL(&graph, owned);
        GraphNodeId id1 = GraphAddNodeR(&graph, shared);
    
        GraphNodeId id0 = GraphAddNodeL(&graph, owned);
        GraphNodeId id1 = GraphAddNodeR(&graph, shared);
    
        bool result = GraphNodeIdIndex(id0) == 0 && GraphNodeIdGeneration(id0) == 1 && GraphNodeIdIndex(id1) == 1;
        IntGraph graph = GraphInit();
    
        GraphNodeId a = GraphAddNodeR(&graph, 1);
        GraphNodeId b = GraphAddNodeR(&graph, 2);
        GraphNodeId c = GraphAddNodeR(&graph, 3);
    
        GraphNodeId a = GraphAddNodeR(&graph, 1);
        GraphNodeId b = GraphAddNodeR(&graph, 2);
        GraphNodeId c = GraphAddNodeR(&graph, 3);
        GraphNodeId a = GraphAddNodeR(&graph, 1);
        GraphNodeId b = GraphAddNodeR(&graph, 2);
        GraphNodeId c = GraphAddNodeR(&graph, 3);
    
        bool result = GraphAddEdge(&graph, a, b);
        IntGraph graph = GraphInit();
    
        GraphNodeId a = GraphAddNodeR(&graph, 1);
        GraphNodeId b = GraphAddNodeR(&graph, 2);
        GraphNodeId c = GraphAddNodeR(&graph, 3);
    
        GraphNodeId a = GraphAddNodeR(&graph, 1);
        GraphNodeId b = GraphAddNodeR(&graph, 2);
        GraphNodeId c = GraphAddNodeR(&graph, 3);
        GraphNodeId a = GraphAddNodeR(&graph, 1);
        GraphNodeId b = GraphAddNodeR(&graph, 2);
        GraphNodeId c = GraphAddNodeR(&graph, 3);
    
        bool result = GraphAddEdge(&graph, a, a);
    /// TAGS: Graph, Node, Id, Index
    ///
    #define GraphNodeIdIndex(id) ((u32)((GraphNodeId)(id) & UINT32_MAX))
    
    ///
    /// TAGS: Graph, Node, Id, Generation
    ///
    #define GraphNodeIdGeneration(id) ((u32)(((GraphNodeId)(id) >> 32) & UINT32_MAX))
    
    ///
    typedef struct {
        void       *__graph;
        GraphNodeId __id;
    } GraphNode;
    /// TAGS: Graph, Edge, Neighbor, Vec
    ///
    typedef Vec(GraphNodeId) GraphNeighbors;
    
    typedef struct {
    
    typedef struct {
        GraphNodeId from;
        GraphNodeId to;
    } GraphPendingEdgeRemoval;
    typedef struct {
        GraphNodeId from;
        GraphNodeId to;
    } GraphPendingEdgeRemoval;
Last updated on