feat(v4.0.0): the wait in the engine -- a node offers a word and sleeps

A node stores a word to offer on any of its ports and fetches the wait: it
is blocked until a word comes for it or one of its offers is taken, and
the fabric does the handing over in one step.  The port block moves in
the nucleus's map to make room for the new addresses.  Nothing uses it
yet.  MESH.md 7c; plan step 6d task 1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rajames
2026-10-07 23:15:11 -04:00
co-authored by Claude Opus 5.5
parent dfabfa46f6
commit 075385ab63
6 changed files with 275 additions and 8 deletions
+35
View File
@@ -209,6 +209,36 @@ unsigned v4_fabric_step(v4_fabric *f)
for (i = 0; i < f->capacity; i++)
if (awake(f, i) && f->place[i].node->n.reading && !f->place[i].node->n.given) done += hand_over_read(f, i);
/* THE WAIT (docs/v4.0.0/MESH.md 7c). A node in the wait that was given a
* word above is no longer in it: a word for a node comes before its own
* offer. Of the rest, each offer is taken by whoever is ready for it: a
* device that takes, or a node blocked reading that port or any -- which
* a node in the wait is, so of two that offer to each other the one at
* the lower place writes and the other's offers are withdrawn. */
for (i = 0; i < f->capacity; i++) {
v4_node *n;
unsigned k;
if (!awake(f, i)) continue;
n = &f->place[i].node->n;
if (!v4_node_in_wait(n)) continue;
for (k = 0; k < V4_PORTS; k++) {
const v4_wire *w = &f->place[i].wire[k];
if (!(n->offers & (1u << k))) continue;
if (w->kind == V4_WIRE_DEVICE) {
if (w->device->take && w->device->take(w->device->self, n->offer[k])) { (void)v4_node_offer_taken(n, k); done++; break; }
} else if (w->kind == V4_WIRE_NODE && awake(f, w->node)) {
v4_node *r = &f->place[w->node].node->n;
if (r->reading && !r->given && (r->read_port == w->port || r->read_port == V4_PORT_ANY)) {
v4_cell word = n->offer[k];
(void)v4_node_offer_taken(n, k);
v4_node_port_give(r, w->port, word);
done++;
break;
}
}
}
}
/* a node blocked on the first word of a message to a node that is not
* reading, while a device of its own has something for it */
if (f->interrupt_error != 0)
@@ -236,6 +266,11 @@ unsigned v4_fabric_step(v4_fabric *f)
if ((n->asking && f->place[i].wire[n->ask_port].kind == V4_WIRE_NONE)
|| (n->reading && !n->given && n->read_port != V4_PORT_ANY && f->place[i].wire[n->read_port].kind == V4_WIRE_NONE))
done += (unsigned)v4_node_port_gone(n, f->gone_error);
else if (v4_node_in_wait(n)) { /* an offer on a port with nothing on it */
unsigned k;
for (k = 0; k < V4_PORTS; k++)
if ((n->offers & (1u << k)) && f->place[i].wire[k].kind == V4_WIRE_NONE) { done += (unsigned)v4_node_port_gone(n, f->gone_error); break; }
}
}
return done;