code wiki / (root) / nx_relchan.nx

nx_relchan.nx source

↩ module page · 42 lines · 2217 B

1// nx_relchan.nx -- sovereign RELIABLE, ORDERED, EXACTLY-ONCE channel for CRITICAL game events 2// (creature captured, block placed/broken, trade) over the unreliable relay. Position is unreliable- 3// frequent (interp/extrapolate cover its loss); events must never be lost OR double-applied. Sender 4// keeps an unacked window + retransmits; receiver dedups by seq + delivers strictly in order + 5// cumulative-acks. 100% nx, no syscalls -> wasm-friendly; the host just moves the bytes. 6// 7// Receiver state r[*i64]: [0]=expected (next in-order seq) [1]=delivered_total then [2 + seq] = received-bit 8// (capacity seqcap). Cumulative ack = expected-1 (highest contiguous delivered). 9// Sender state s[*i64]: [0]=acked_upto (cumulative, -1 = none) [1]=n (event count). Resends seqs > acked_upto. 10// license_tier: ORIGINAL 11 12func rc_rinit(r: *i64, seqcap: i64) -> i64 { 13 r[0] = 0; r[1] = 0 14 var i: i64 = 0 15 while i < seqcap { r[2 + i] = 0; i = i + 1 } 16 return 0 17} 18func rc_expected(r: *i64) -> i64 { return r[0] } 19func rc_delivered(r: *i64) -> i64 { return r[1] } 20func rc_ack_value(r: *i64) -> i64 { return r[0] - 1 } // cumulative ack to send back 21 22// receive event `seq`; returns the number of NEWLY in-order-delivered events (0 = duplicate/out-of-range, 23// >=1 = this arrival drained one or more contiguous events). Idempotent: a duplicate returns 0, no re-delivery. 24func rc_recv(r: *i64, seqcap: i64, seq: i64) -> i64 { 25 if seq < r[0] { return 0 } // already delivered -> dup 26 if seq >= seqcap { return 0 } // out of range 27 if r[2 + seq] == 1 { return 0 } // already buffered -> dup 28 r[2 + seq] = 1 29 var nd: i64 = 0 30 var go: i64 = 1 31 while go == 1 { 32 if r[0] >= seqcap { go = 0 } else { 33 if r[2 + r[0]] == 1 { r[0] = r[0] + 1; r[1] = r[1] + 1; nd = nd + 1 } else { go = 0 } 34 } 35 } 36 return nd 37} 38 39func rc_sinit(s: *i64, n: i64) -> i64 { s[0] = 0 - 1; s[1] = n; return 0 } 40func rc_ack(s: *i64, a: i64) -> i64 { if a > s[0] { s[0] = a } return 0 } 41func rc_unacked_lo(s: *i64) -> i64 { return s[0] + 1 } // first seq still needing (re)send 42func rc_all_acked(s: *i64) -> i64 { if s[0] >= s[1] - 1 { return 1 } return 0 }