v2 / vlib / v / tests / concurrency / shared_interface_test.v
122 lines · 109 sloc · 2.18 KB · f5145df533eaf5efcb6670d6e56a0ae67e19e0b5
Raw
1import time
2
3interface MyInterface {
4 foo() string
5}
6
7struct MyStruct {
8pub mut:
9 fooer shared MyInterface
10}
11
12struct MyImplementor {
13mut:
14 num int
15}
16
17fn (m MyImplementor) foo() string {
18 // Can read member properties:
19 num := m.num
20 return 'Hello World ${num}!'
21}
22
23fn test_shared_interface_lock_1() {
24 shared imp1 := MyImplementor{
25 num: 1
26 }
27 s1 := MyStruct{
28 fooer: imp1
29 }
30 lock s1.fooer {
31 assert s1.fooer.foo() == 'Hello World 1!'
32 }
33}
34
35fn test_shared_interface_lock_2() {
36 shared imp := MyOtherImplementor{
37 x: 1
38 y: 2
39 s: 'testing'
40 }
41 s := MyStruct{
42 fooer: imp
43 }
44
45 lock s.fooer {
46 assert s.fooer.foo() == 'Hello World (1, 2, testing)!'
47 }
48
49 // Lock is released and can be locked again:
50 lock s.fooer {
51 assert s.fooer.foo() == 'Hello World (1, 2, testing)!'
52 }
53}
54
55fn test_shared_interface_lock_blocks_the_original_shared_value() {
56 shared imp := MyImplementor{
57 num: 6
58 }
59 s := MyStruct{
60 fooer: imp
61 }
62 ready := chan bool{}
63 proceed := chan bool{}
64 done := chan bool{}
65 task := spawn modify_shared_interface_impl(shared imp, ready, proceed, done)
66 _ := <-ready
67 lock s.fooer {
68 proceed <- true
69 select {
70 _ := <-done {
71 assert false, 'shared interface value was modified before the field lock was released'
72 }
73 20 * time.millisecond {}
74 }
75 assert s.fooer.foo() == 'Hello World 6!'
76 }
77 _ := <-done
78 task.wait()
79 lock s.fooer {
80 assert s.fooer.foo() == 'Hello World 7!'
81 }
82}
83
84fn modify_shared_interface_impl(shared x MyImplementor, ready chan bool, proceed chan bool, done chan bool) {
85 ready <- true
86 _ := <-proceed
87 lock x {
88 x.num++
89 }
90 done <- true
91}
92
93// TODO: Fix modifying shared interface value
94// fn test_shared_interface_can_be_modified() {
95// shared imp1 := MyImplementor{num: 6}
96// shared imp2 := MyOtherImplementor{
97// x: 7
98// y: 3
99// s: 'here be dragons...'
100// }
101// s := MyStruct{
102// fooer: imp1
103// }
104// lock s.fooer {
105// assert(s.fooer.foo() == 'Hello World 6!')
106// s.fooer = imp2
107// }
108// lock s.fooer {
109// assert(s.fooer.foo() == 'Hello World (7, 3, here be dragons...)!')
110// }
111// }
112
113struct MyOtherImplementor {
114 x int
115 y int
116 s string
117}
118
119fn (m MyOtherImplementor) foo() string {
120 // Different implementation:
121 return 'Hello World (${m.x}, ${m.y}, ${m.s})!'
122}
123