GraphForeachNode
Description
Iterate over each live node of given graph.
The loop variable is a GraphNode handle carrying the owning graph plus a stable node id. Marking nodes for deletion is allowed during iteration, but structural changes such as adding nodes, adding edges, clearing, or committing changes will invalidate the traversal and abort on the next iteration step.
Scratch-state operations such as
GraphNodeVisit, GraphNodeUnvisit, GraphMarkNodeForDeletion, GraphUnmarkNodeForDeletion, GraphMarkEdgeForRemoval, and GraphUnmarkEdgeForRemoval are the intended mutation tools inside traversal-driven analysis or rewrite passes.
Parameters
| Name | Direction | Description |
|---|---|---|
g |
in,out | Graph to iterate over. |
node |
in | Name of the GraphNode loop variable. |
Success
Loop body runs once per live node; node carries a fresh handle each step.
Failure
Aborts the traversal on a structural mutation (epoch mismatch) or empty graph; on validator failure (corrupted magic) the process aborts.
Usage example (Cross-references)
Usage examples (Cross-references)
- In
Ops.c:49:
GraphAddEdge(&graph, c, a);
GraphForeachNode(&graph, node) {
if (GraphNodeData(&graph, node) == 20) {
GraphMarkNodeForDeletion(node);- In
Ops.c:123:
GraphAddEdge(&graph, b, c);
GraphForeachNode(&graph, node) {
if (GraphNodeGetId(node) == a) {
GraphNodeForeachNeighbor(node, neighbor) {- In
Foreach.c:42:
static void city_reset_visits(CityGraph *graph) {
GraphForeachNode(graph, node) {
GraphNodeUnvisit(node);
}- In
Foreach.c:79:
static bool test_graph_city_reachability(void) {
WriteFmt("Testing GraphForeachNode and GraphNodeForeachNeighbor for reachability\n");
DefaultAllocator alloc = DefaultAllocatorInit();- In
Foreach.c:121:
city_reset_visits(&graph);
GraphForeachNode(&graph, node) {
result = result && (GraphNodeVisitCount(node) == 0);
}- In
Foreach.c:152:
GraphAddEdge(&graph, c, d);
GraphForeachNode(&graph, node) {
(void)MapEnsurePtr(&counts, GraphNodeGetId(node), 0);
GraphNodeForeachNeighbor(node, neighbor) {- In
Foreach.c:208:
static bool test_graph_node_iteration_rejects_structural_mutation_deadend(void) {
WriteFmt("Testing GraphForeachNode rejects structural mutation (should abort)\n");
DefaultAllocator alloc = DefaultAllocatorInit();- In
Foreach.c:218:
GraphAddNodeR(&graph, 2);
GraphForeachNode(&graph, node) {
(void)node;
(void)GraphAddNodeR(&graph, 3);- In
Foreach.c:298:
u64 visited = 0;
GraphForeachNode(&graph, node) {
if (visited == 0) {
// Reserve well within existing capacity: no realloc, so real code
- In
Foreach.c:322:
// visits exactly the surviving nodes; the mutant visits the free slot too.
static bool test_graph_foreach_skips_freed_slot(void) {
WriteFmt("Testing GraphForeachNode visits only occupied slots after a commit\n");
DefaultAllocator alloc = DefaultAllocatorInit();- In
Foreach.c:341:
u64 visited = 0;
GraphForeachNode(&graph, node) {
(void)node;
visited += 1;- In
Foreach.c:473:
// aborts. Mutant: no bump, no abort.
static bool test_node_iteration_rejects_grow_mutation_deadend(void) {
WriteFmt("Testing GraphForeachNode rejects a no-realloc slot-growing mutation (should abort)\n");
DefaultAllocator alloc = DefaultAllocatorInit();- In
Foreach.c:488:
bool added = false;
GraphForeachNode(&graph, node) {
(void)node;
if (!added) {- In
Foreach.c:518:
u64 visited = 0;
GraphForeachNode(&graph, node) {
(void)node;
if (visited == 0) {- In
Foreach.c:551:
(void)a;
GraphForeachNode(&graph, node) {
(void)node;
// Mark + commit a deletion mid-iteration. The commit bumps the
- In
Foreach.c:573:
// Caller-observable via the GraphForeachNode visit count.
static bool test_node_iter_no_overscan_extra_slot(void) {
WriteFmt("Testing GraphForeachNode does not over-walk the slot array\n");
DefaultAllocator alloc = DefaultAllocatorInit();- In
Foreach.c:594:
u64 visited = 0;
GraphForeachNode(&graph, node) {
(void)node;
visited += 1;
Last updated on