1 // The ring index word is the parking word (L21). Two properties are owed by
2 // any parking scheme, and both are asserted here:
3 //
4 // - no lost wakeup: a receiver parked on the write index is woken by the
5 // publish, so a ping-pong over a spawn channel completes every round;
6 // - no hang on peer death: a parent parked on a ring whose child died
7 // unpacks (bounded wait, then a liveness recheck) and reports the closed
8 // channel rather than sleeping forever.
9 package main
10 11 import (
12 "fmt"
13 "runtime"
14 "time"
15 )
16 17 // echoWorker receives each value and answers with twice it, so the parent can
18 // tell that the parked receive actually woke. It parks on `in` between
19 // messages: that park is the wakeup the test is about.
20 func echoWorker(in chan int32, out chan int32) {
21 for {
22 v, ok := <-in
23 if !ok {
24 return
25 }
26 out <- v * 2
27 }
28 }
29 30 // deadWorker returns without ever writing out, so its parent parks on out and
31 // then has to notice the peer died.
32 func deadWorker(in chan int32, out chan int32) {
33 time.Sleep(50 * time.Millisecond)
34 }
35 36 func main() {
37 // Chan memory must outlive this frame: the forked child reads the same
38 // channel memory, so allocate it in the root arena.
39 runtime.SovereignSetArena(runtime.RootArena())
40 in := chan int32{}
41 out := chan int32{}
42 done := spawn(echoWorker, in, out)
43 44 // 200 rounds: each one parks the worker on `in`, publishes, and requires
45 // the reply. If a wake were lost the round would stall until the bounded
46 // park timed out and the test would eventually fail on the value.
47 for i := int32(0); i < 200; i++ {
48 in <- i
49 v := <-out
50 if v != i*2 {
51 panic("echo value mismatch")
52 }
53 }
54 close(in)
55 <-done
56 fmt.Println("wake ok")
57 58 runtime.SovereignSetArena(runtime.RootArena())
59 in2 := chan int32{}
60 out2 := chan int32{}
61 done2 := spawn(deadWorker, in2, out2)
62 63 start := time.Now()
64 dv, ok := <-out2
65 elapsed := time.Since(start)
66 _ = dv
67 if ok {
68 panic("recv reported a value after the peer died")
69 }
70 if elapsed > 3*time.Second {
71 panic("recv did not unpark promptly after the peer died")
72 }
73 <-done2
74 fmt.Println("dead ok")
75 }
76