Compare commits

..
2 Commits
Author SHA1 Message Date
smarm cc4000a165 fix bug in test that only shows on multicore enviroments 2026-06-12 00:05:55 +02:00
smarm 156dcca496 doc: note bug report form urus agent 2026-06-12 00:05:33 +02:00
2 changed files with 24 additions and 14 deletions
+8
View File
@@ -151,6 +151,14 @@ sizes, append-only) once the cap is actually hit. Do not let it calcify.
hardware. Build + run full test suite on an aarch64 device; check
`chained_spawn` / `yield_many` bench medians; merge and update README.
---
## Look into
### app actors block AllDone; no external stop path
Agent working on urus (see same git server as smarm) reported a lazily spawned actor never returning, blocking program shutdown. Maybe we should do something about it. Agent worked around it by giving the actor an atomic bool to spin on. See urus example crud for exact impl.
---
## Invariants & gotchas (respect these across all cycles)
+16 -14
View File
@@ -6,22 +6,22 @@
use smarm::{channel, run, select, spawn};
use std::sync::atomic::{AtomicI64, Ordering};
use std::sync::Arc;
use std::time::{Duration, Instant};
static OUT: AtomicI64 = AtomicI64::new(0);
#[test]
fn ready_arm_returns_immediately_without_parking() {
OUT.store(0, Ordering::SeqCst);
run(|| {
let out = Arc::new(AtomicI64::new(0));
let out2 = out.clone();
run(move || {
let (txa, rxa) = channel::<i64>();
let (_txb, rxb) = channel::<i64>();
txa.send(42).unwrap();
let i = select(&[&rxb, &rxa]);
assert_eq!(i, 1);
OUT.store(rxa.try_recv().unwrap().expect("ready arm must hold a message"), Ordering::SeqCst);
out2.store(rxa.try_recv().unwrap().expect("ready arm must hold a message"), Ordering::SeqCst);
});
assert_eq!(OUT.load(Ordering::SeqCst), 42);
assert_eq!(out.load(Ordering::SeqCst), 42);
}
#[test]
@@ -39,8 +39,9 @@ fn lower_index_wins_when_several_arms_are_ready() {
#[test]
fn parks_until_any_arm_fires() {
OUT.store(0, Ordering::SeqCst);
run(|| {
let out = Arc::new(AtomicI64::new(0));
let out2 = out.clone();
run(move || {
let (txa, _rxa_keepalive) = (channel::<i64>().0, ());
let _hold = txa; // arm a: sender alive, never sends
let (txa, rxa) = channel::<i64>();
@@ -52,10 +53,10 @@ fn parks_until_any_arm_fires() {
});
let i = select(&[&rxa, &rxb]);
assert_eq!(i, 1);
OUT.store(rxb.try_recv().unwrap().unwrap(), Ordering::SeqCst);
out2.store(rxb.try_recv().unwrap().unwrap(), Ordering::SeqCst);
h.join().unwrap();
});
assert_eq!(OUT.load(Ordering::SeqCst), 7);
assert_eq!(out.load(Ordering::SeqCst), 7);
}
#[test]
@@ -164,8 +165,9 @@ fn select_then_plain_recv_on_a_loser_arm() {
#[test]
fn select_loop_drains_two_producers_completely() {
const N: i64 = 200;
OUT.store(0, Ordering::SeqCst);
run(|| {
let out = Arc::new(AtomicI64::new(0));
let out2 = out.clone();
run(move || {
let (txa, rxa) = channel::<i64>();
let (txb, rxb) = channel::<i64>();
let ha = spawn(move || {
@@ -204,11 +206,11 @@ fn select_loop_drains_two_producers_completely() {
Err(_) => break,
}
}
OUT.store(sum, Ordering::SeqCst);
out2.store(sum, Ordering::SeqCst);
ha.join().unwrap();
hb.join().unwrap();
});
assert_eq!(OUT.load(Ordering::SeqCst), 2 * (0..200i64).sum::<i64>());
assert_eq!(out.load(Ordering::SeqCst), 2 * (0..200i64).sum::<i64>());
}
#[test]