GraphGetNode
Description
Get a traversal handle for a live node id.
Parameters
| Name | Direction | Description |
|---|---|---|
g |
in,out | Graph owning the node. |
node_id |
in | Live node id to wrap as a GraphNode. |
Success
Returns a GraphNode handle that resolves back to the same slot and generation. The graph is not modified. The handle is valid until the slot is committed for deletion.
Failure
Does not return - aborts via LOG_FATAL for an invalid or stale node id (caller bug).
Usage example (Cross-references)
Usage examples (Cross-references)
- In
Ops.c:16:
GraphNodeId a = GraphAddNodeR(&graph, 10);
GraphNode node = GraphGetNode(&graph, a);
bool result = !GraphNodeVisited(node) && (GraphNodeVisitCount(node) == 0);- In
Ops.c:72:
result = result && (GraphNodeIdIndex(d) == GraphNodeIdIndex(b));
result = result && (GraphNodeIdGeneration(d) == (GraphNodeIdGeneration(b) + 1));
result = result && (GraphNodeData(&graph, GraphGetNode(&graph, d)) == 40);
result = result && !GraphNodeVisited(GraphGetNode(&graph, d));- In
Ops.c:73:
result = result && (GraphNodeIdGeneration(d) == (GraphNodeIdGeneration(b) + 1));
result = result && (GraphNodeData(&graph, GraphGetNode(&graph, d)) == 40);
result = result && !GraphNodeVisited(GraphGetNode(&graph, d));
GraphDeinit(&graph);- In
Ops.c:89:
GraphNodeId a = GraphAddNodeR(&graph, 10);
GraphNode node = GraphGetNode(&graph, a);
bool result = !GraphNodeMarkedForDeletion(node);- In
Ops.c:263:
bool result = GraphMarkEdgeForRemoval(&graph, a, b);
result = result && GraphMarkNodeForDeletion(GraphGetNode(&graph, b));
result = result && GraphEdgeMarkedForRemoval(&graph, a, b);
result = result && GraphNodeMarkedForDeletion(GraphGetNode(&graph, b));- In
Ops.c:265:
result = result && GraphMarkNodeForDeletion(GraphGetNode(&graph, b));
result = result && GraphEdgeMarkedForRemoval(&graph, a, b);
result = result && GraphNodeMarkedForDeletion(GraphGetNode(&graph, b));
result = result && (GraphCommitChanges(&graph) == 2);
result = result && !GraphContainsNode(&graph, b);- In
Ops.c:296:
counts[GraphNodeIdIndex(b)] = 29;
bool result = GraphMarkNodeForDeletion(GraphGetNode(&graph, b));
result = result && (GraphCommitChanges(&graph) == 1);
result = result && !GraphContainsNode(&graph, b);- In
Ops.c:325:
GraphNodeId a = GraphAddNodeR(&graph, 10);
GraphNode node = GraphGetNode(&graph, a);
(void)GraphMarkNodeForDeletion(node);- In
Ops.c:362:
GraphAddEdge(&graph, a, b);
GraphMarkNodeForDeletion(GraphGetNode(&graph, b));
u64 committed = GraphCommitChanges(&graph);- In
Ops.c:398:
// Delete b so its slot is free at the time GraphClear walks it.
bool result = GraphMarkNodeForDeletion(GraphGetNode(&graph, b));
result = result && (GraphCommitChanges(&graph) == 1);
result = result && !GraphContainsNode(&graph, b);- In
Ops.c:434:
// One deletion leaves a single entry in free_indices going into clear.
bool result = GraphMarkNodeForDeletion(GraphGetNode(&graph, b));
result = result && (GraphCommitChanges(&graph) == 1);- In
Ops.c:470:
// First commit frees b's slot (free-list entry, generation bumped).
bool result = GraphMarkNodeForDeletion(GraphGetNode(&graph, b));
u64 removed = GraphCommitChanges(&graph);
result = result && (removed == 1);- In
Ops.c:477:
// Second commit: a free slot (b's) is present. The marked/unmarked passes
// iterate every slot; the free slot must be skipped, not validated.
result = result && GraphMarkNodeForDeletion(GraphGetNode(&graph, a));
removed = GraphCommitChanges(&graph);- In
Ops.c:506:
GraphNodeId b = GraphAddNodeR(&graph, 20);
(void)GraphMarkNodeForDeletion(GraphGetNode(&graph, a));
(void)GraphCommitChanges(&graph);
(void)GraphAddNodeR(&graph, 99); // reuse a's slot, a is now stale
- In
Ops.c:530:
GraphNodeId b = GraphAddNodeR(&graph, 20);
(void)GraphMarkNodeForDeletion(GraphGetNode(&graph, b));
(void)GraphCommitChanges(&graph);
(void)GraphAddNodeR(&graph, 99); // reuse b's slot, b is now stale
- In
Ops.c:556:
GraphNodeId b = GraphAddNodeR(&graph, 20);
(void)GraphMarkNodeForDeletion(GraphGetNode(&graph, a));
(void)GraphCommitChanges(&graph);
(void)GraphAddNodeR(&graph, 99); // reuse a's slot, a is now stale
- In
Ops.c:580:
GraphNodeId b = GraphAddNodeR(&graph, 20);
(void)GraphMarkNodeForDeletion(GraphGetNode(&graph, b));
(void)GraphCommitChanges(&graph);
(void)GraphAddNodeR(&graph, 99); // reuse b's slot, b is now stale
- In
Ops.c:685:
// Mark a (index 0, in range after the shrink) so the commit has a node to
// delete (pending_delete_count > 0, so it does not early-return).
(void)GraphMarkNodeForDeletion(GraphGetNode(&graph, a));
// Clear the memoized validated bit on a consistent graph so commit's entry
- In
Ops.c:739:
// Mark both a (in range after the shrink) and c (the slot we hide at
// index == len). pending_delete_count = 2 so commit does real work.
(void)GraphMarkNodeForDeletion(GraphGetNode(&graph, a));
(void)GraphMarkNodeForDeletion(GraphGetNode(&graph, c));- In
Ops.c:740:
// index == len). pending_delete_count = 2 so commit does real work.
(void)GraphMarkNodeForDeletion(GraphGetNode(&graph, a));
(void)GraphMarkNodeForDeletion(GraphGetNode(&graph, c));
// Clear the memoized validated bit on a consistent graph.
- In
Ops.c:759:
result = result && !GraphContainsNode(&graph, a);
result = result && GraphContainsNode(&graph, c);
result = result && GraphNodeMarkedForDeletion(GraphGetNode(&graph, c));
GraphDeinit(&graph);- In
Init.c:41:
result = result && GraphAddEdge(&graph, third_id, first_id);
result = result && GraphAddEdge(&graph, third_id, third_id);
result = result && (GraphNodeVisit(GraphGetNode(&graph, first_id)) == 1);
result = result && GraphMarkNodeForDeletion(GraphGetNode(&graph, second_id));
result = result && GraphMarkEdgeForRemoval(&graph, third_id, third_id);- In
Init.c:42:
result = result && GraphAddEdge(&graph, third_id, third_id);
result = result && (GraphNodeVisit(GraphGetNode(&graph, first_id)) == 1);
result = result && GraphMarkNodeForDeletion(GraphGetNode(&graph, second_id));
result = result && GraphMarkEdgeForRemoval(&graph, third_id, third_id);- In
Init.c:91:
node_id = GraphAddNodeL(&graph, name);
node = GraphGetNode(&graph, node_id);
stored_name = GraphNodeDataPtr(&graph, node);- In
Init.c:115:
node_id = GraphAddNodeR(&graph, StrZ("alpha", &alloc));
node = GraphGetNode(&graph, node_id);
stored_name = GraphNodeDataPtr(&graph, node);- In
Insert.c:156:
(void)a;
(void)GraphMarkNodeForDeletion(GraphGetNode(&graph, b));
(void)GraphCommitChanges(&graph);- In
Insert.c:187:
(void)a;
(void)GraphMarkNodeForDeletion(GraphGetNode(&graph, b));
(void)GraphCommitChanges(&graph);- In
Insert.c:223:
GraphNodeId c = GraphAddNodeR(&graph, 30);
(void)GraphMarkNodeForDeletion(GraphGetNode(&graph, b));
(void)GraphCommitChanges(&graph);- In
Insert.c:304:
// Delete + commit b so its slot lands on the free list (reuse target).
bool result = GraphMarkNodeForDeletion(GraphGetNode(&graph, b));
result = result && (GraphCommitChanges(&graph) == 1);- In
Type.c:50:
GraphNodeId node_id = GraphAddNodeR(&graph, 11);
GraphNode node = GraphGetNode(&graph, node_id);
bool result = GraphAllocator(&graph)->alignment == 32 && GraphNodeIdIndex(node_id) == 0 &&- In
Type.c:82:
(void)a;
GraphMarkNodeForDeletion(GraphGetNode(&graph, b));
// A structural mutation that keeps b marked but re-arms the deep
- In
Type.c:376:
GraphNodeId b = GraphAddNodeR(&graph, 20);
(void)GraphMarkNodeForDeletion(GraphGetNode(&graph, b));
(void)GraphCommitChanges(&graph);- In
Type.c:406:
(void)a; // a keeps slot 0 occupied; only b is deleted to seed free_indices.
(void)GraphMarkNodeForDeletion(GraphGetNode(&graph, b));
(void)GraphCommitChanges(&graph);- In
Type.c:436:
GraphNodeId c = GraphAddNodeR(&graph, 30);
(void)GraphMarkNodeForDeletion(GraphGetNode(&graph, b));
(void)GraphMarkNodeForDeletion(GraphGetNode(&graph, c));
(void)GraphCommitChanges(&graph);- In
Type.c:437:
(void)GraphMarkNodeForDeletion(GraphGetNode(&graph, b));
(void)GraphMarkNodeForDeletion(GraphGetNode(&graph, c));
(void)GraphCommitChanges(&graph);- In
Foreach.c:75:
city_reset_visits(graph);
return city_reachable_from(GraphGetNode(graph, *from_id), *to_id);
}- In
Foreach.c:192:
u64 predecessor_count = 0;
GraphNodeForeachPredecessor(GraphGetNode(&graph, d), predecessor) {
predecessor_sum += GraphNodeData(&graph, predecessor);
predecessor_count += 1;- In
Foreach.c:242:
GraphAddEdge(&graph, a, b);
GraphNodeForeachNeighbor(GraphGetNode(&graph, a), neighbor) {
(void)neighbor;
(void)GraphAddEdge(&graph, a, c);- In
Foreach.c:268:
GraphAddEdge(&graph, b, c);
GraphNodeForeachPredecessor(GraphGetNode(&graph, c), predecessor) {
(void)predecessor;
(void)GraphAddEdge(&graph, d, c);- In
Foreach.c:337:
// Delete the middle node so its slot becomes a free hole between two
// live slots, then commit so the deletion materializes.
(void)GraphMarkNodeForDeletion(GraphGetNode(&graph, b));
(void)GraphCommitChanges(&graph);- In
Foreach.c:376:
// Begin runs the deep validator (clears the validated bit) and snapshots
// the current epoch.
GenericGraphNeighborIter iter = graph_neighbor_iter_begin(GraphGetNode(&graph, a));
// Intentional bypass: there is no public mutator for an individual
- In
Foreach.c:411:
GraphAddEdge(&graph, a, b);
GenericGraphPredecessorIter iter = graph_predecessor_iter_begin(GraphGetNode(&graph, b));
// Intentional bypass: rewrite `b`'s sole in-neighbor (a) so its generation
- In
Foreach.c:448:
// Capture a handle, then delete + commit + reuse a's slot so the captured
// id is stale (slot occupied, generation superseded).
GraphNode stale = GraphGetNode(&graph, a);
(void)GraphMarkNodeForDeletion(GraphGetNode(&graph, a));
(void)GraphCommitChanges(&graph);- In
Foreach.c:449:
// id is stale (slot occupied, generation superseded).
GraphNode stale = GraphGetNode(&graph, a);
(void)GraphMarkNodeForDeletion(GraphGetNode(&graph, a));
(void)GraphCommitChanges(&graph);
(void)GraphAddNodeR(&graph, 99); // reuse a's slot at a higher generation
- In
Foreach.c:555:
// Mark + commit a deletion mid-iteration. The commit bumps the
// mutation epoch, so the iterator's next step must abort.
(void)GraphMarkNodeForDeletion(GraphGetNode(&graph, b));
(void)GraphCommitChanges(&graph);
}- In
Access.c:34:
ValidateGraph(&graph);
node_b = GraphGetNode(&graph, b);
*GraphNodeDataPtr(&graph, node_b) = 25;- In
Access.c:92:
IntGraph graph_a = GraphInit(&alloc);
IntGraph graph_b = GraphInit(&alloc);
GraphNode node = GraphGetNode(&graph_a, GraphAddNodeR(&graph_a, 10));
(void)GraphNodeData(&graph_b, node);- In
Access.c:204:
// Delete + commit: slot 0 becomes free and its generation is bumped to
// GraphNodeIdGeneration(a) + 1.
result = result && GraphMarkNodeForDeletion(GraphGetNode(&graph, a));
result = result && (GraphCommitChanges(&graph) == 1);
result = result && !GraphContainsNode(&graph, a);- In
Access.c:248:
graph.slots.length -= 1;
(void)GraphGetNode(&graph, b);
GraphDeinit(&graph);- In
Access.c:259:
// without aborting. Real code aborts on the stale id.
static bool test_get_node_rejects_stale_id_deadend(void) {
WriteFmt("Testing GraphGetNode rejects a stale node id (should abort)\n");
DefaultAllocator alloc = DefaultAllocatorInit();- In
Access.c:268:
GraphNodeId a = GraphAddNodeR(&graph, 10);
(void)GraphMarkNodeForDeletion(GraphGetNode(&graph, a));
(void)GraphCommitChanges(&graph);- In
Access.c:272:
// a now refers to a freed slot with a stale generation.
(void)GraphGetNode(&graph, a);
GraphDeinit(&graph);- In
Access.c:317:
GraphNodeId a = GraphAddNodeR(&graph, 10);
(void)GraphMarkNodeForDeletion(GraphGetNode(&graph, a));
(void)GraphCommitChanges(&graph);
// Reuse a's slot at a higher generation; `a` is now stale.
- In
Access.c:349:
GraphNodeId a = GraphAddNodeR(&graph, 10);
(void)GraphMarkNodeForDeletion(GraphGetNode(&graph, a));
(void)GraphCommitChanges(&graph);- In
Access.c:357:
GraphNodeId free_match = make_raw_node_id(GraphNodeIdIndex(a), GraphNodeIdGeneration(a) + 1);
(void)GraphGetNode(&graph, free_match);
GraphDeinit(&graph);
Last updated on