v2 / vlib / v / tests / reliability / semaphore_wait.v
140 lines · 126 sloc · 2.84 KB · d25f281b25d452a53586f3a764a4c2407eb83531
Raw
1/*
2This program can be used to test waiting for a semaphore
3in the presence of signals that might interrupt the `wait()` call.
4
5In particular the effect of Boehm-GC can be investigated.
6
7To do so compile this program with `v -gc boehm semaphore_wait.v`
8and run is as `./semaphore_wait > /dev/null` to test `sem.wait()`
9or `./semaphore_wait -t > /dev/null` to test `sem.timedwait()`
10on Windows: `.\semaphore_wait > NUL` or `.\semaphore_wait -t > NUL`
11
12On success (no interrupted `wait`) the output (from stderr) should like like:
13
14time: 524.228 result: `true`
15time: 521.122 result: `true`
16time: 523.714 result: `true`
17time: 527.001 result: `true`
18time: 521.696 result: `true`
19...
20Finished
21
22(The "result" is only printed with `-t`.)
23*/
24import os
25import time
26import rand
27import math
28import sync
29
30struct DataObj {
31mut:
32 data []f64
33}
34
35struct PtrObj {
36mut:
37 nxt []&DataObj
38}
39
40struct PtrPtrObj {
41mut:
42 nxt []&PtrObj
43}
44
45const log2n = 9
46const n = 1 << log2n
47const n4 = f64(u64(1) << (4 * log2n))
48
49fn waste_mem() ! {
50 mut objs := PtrPtrObj{
51 nxt: unsafe { []&PtrObj{len: n} }
52 }
53 for {
54 sz := rand.int_in_range(10, 1000)!
55 mut new_obj := &PtrObj{
56 nxt: unsafe { []&DataObj{len: sz} }
57 }
58 sz2 := rand.int_in_range(10, 500000)!
59 new_obj2 := &DataObj{
60 data: []f64{len: sz2}
61 }
62 idx2 := rand.int_in_range(0, sz)!
63 new_obj.nxt[idx2] = new_obj2
64 // non-equally distributed random index
65 idx := int(math.sqrt(math.sqrt(rand.f64n(n4)!)))
66 objs.nxt[idx] = new_obj
67 }
68}
69
70fn do_rec(mut sem sync.Semaphore, timed bool) {
71 mut start := time.sys_mono_now()
72 for {
73 r := if timed {
74 sem.timed_wait(600 * time.millisecond)
75 } else {
76 sem.wait()
77 false
78 }
79 end := time.sys_mono_now()
80 dur := f64(end - start) / f64(time.millisecond)
81 res_str := if timed { ' result: `${r}`' } else { '' }
82 if dur < 450.0 || dur > 550.0 {
83 eprintln('Problem: time: ${dur:.3f}${res_str}')
84 } else {
85 eprintln('time: ${dur:.3f}${res_str}')
86 }
87 start = end
88 }
89}
90
91fn do_send(mut sem sync.Semaphore) {
92 for {
93 time.sleep(500 * time.millisecond)
94 sem.post()
95 }
96}
97
98fn usage() {
99 eprintln('usage:\n\t${os.args[0]} [-t] [num_iterations]')
100 exit(1)
101}
102
103fn main() {
104 mut n_iterations := 5_000_000
105 mut timed := false
106 if os.args.len > 3 {
107 usage()
108 }
109 for i in 1 .. os.args.len {
110 if os.args[i][0].is_digit() {
111 if i > 1 && !timed {
112 usage()
113 }
114 n_iterations = os.args[1].int()
115 } else if os.args[i] == '-t' {
116 timed = true
117 } else {
118 usage()
119 }
120 }
121 if os.args.len > 3 || n_iterations <= 0 {
122 eprintln('usage:\n\t${os.args[0]} [num_iterations]')
123 exit(1)
124 }
125 mut sem := sync.new_semaphore()
126 spawn do_rec(mut sem, timed)
127 spawn do_send(mut sem)
128 for _ in 0 .. 4 {
129 spawn waste_mem()
130 }
131 mut last := time.sys_mono_now()
132 for _ in 0 .. n_iterations {
133 now := time.sys_mono_now()
134 interval := now - last
135 println(f64(interval) / f64(time.millisecond))
136 last = now
137 }
138 sem.destroy()
139 eprintln('Finished')
140}
141