v2 / vlib / v / tests / generics / generics_chans_select_test.v
125 lines · 109 sloc · 1.89 KB · 3d302a6dad1d1d9ac7b9492ffda488c762e766e4
Raw
1import time
2
3pub type EventListener[T] = fn (T) !
4
5@[heap]
6struct Chan[T] {
7 c chan T
8}
9
10pub type Check[T] = fn (T) bool
11
12struct EventWaiter[T] {
13 check ?Check[T]
14 c &Chan[T]
15}
16
17pub struct EventController[T] {
18mut:
19 id int
20 wait_fors map[int]EventWaiter[T]
21 listeners map[int]EventListener[T]
22}
23
24fn (mut ec EventController[T]) generate_id() int {
25 return ec.id++
26}
27
28@[params]
29pub struct EmitOptions {
30pub:
31 error_handler ?fn (int, IError)
32}
33
34pub fn (mut ec EventController[T]) emit(e T, options EmitOptions) {
35 for i, w in ec.wait_fors {
36 mut b := false
37 if w.check != none {
38 func := w.check
39 b = func(e)
40 } else {
41 assert false
42 }
43 if b {
44 w.c.c <- e
45 ec.wait_fors.delete(i)
46 return
47 }
48 }
49 mut ts := []thread{}
50 for i, l in ec.listeners {
51 ts << spawn fn [options] [T](f EventListener[T], j int, e T) {
52 f(e) or {
53 if g := options.error_handler {
54 g(j, err)
55 }
56 }
57 }(l, i, e)
58 }
59 ts.wait()
60}
61
62@[params]
63pub struct EventWaitParams[T] {
64pub:
65 check ?Check[T]
66 timeout ?time.Duration
67}
68
69pub struct Awaitable[T] {
70 id int
71 timeout ?time.Duration
72 c Chan[T]
73mut:
74 controller &EventController[T]
75}
76
77struct Zero[T] {
78 e T
79}
80
81pub fn (mut a Awaitable[T]) do() ?T {
82 defer {
83 a.controller.wait_fors.delete(a.id)
84 }
85 if timeout := a.timeout {
86 mut e := Zero[T]{}.e
87 select {
88 e = <-a.c.c {
89 r := e
90 return r
91 }
92 timeout.nanoseconds() {
93 return none
94 }
95 }
96 }
97 return <-a.c.c
98}
99
100pub fn (mut ec EventController[T]) wait(params EventWaitParams[T]) Awaitable[T] {
101 mut c := Chan[T]{}
102 id := ec.generate_id()
103 ec.wait_fors[id] = EventWaiter[T]{
104 check: params.check
105 c: &mut c
106 }
107 return Awaitable[T]{
108 id: id
109 timeout: params.timeout
110 controller: unsafe { &mut ec }
111 c: c
112 }
113}
114
115struct Foo {}
116
117struct Bar {}
118
119fn test_generics_chans_select() {
120 x := EventController[Foo]{}
121 println(x)
122 y := EventController[Bar]{}
123 println(y)
124 assert true
125}
126