-
Notifications
You must be signed in to change notification settings - Fork 3
/
findall.pml
143 lines (109 loc) · 2.17 KB
/
findall.pml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// model for https://utcc.utoronto.ca/~cks/space/blog/programming/GoConcurrencyStillNotEasy
// user configurable values
// number of processes to scan through
#ifndef NUM_PROCESSES
#define NUM_PROCESSES 10
#endif
// concurrency limit; program hangs is LIMIT < NUM_PROCESSES
#ifndef LIMIT
#define LIMIT 4
#endif
/*
func FindAll() []P {
pss, err := ps.Processes()
[...]
found := make(chan P)
limitCh := make(chan struct{}, concurrencyProcesses)
for _, pr := range pss {
limitCh <- struct{}{}
pr := pr
go func() {
defer func() { <-limitCh }()
[... get a P with some error checking ...]
found <- P
}()
}
[...]
var results []P
for p := range found {
results = append(results, p)
}
return results
}
*/
chan foundCh = [0] of { bool };
chan limitCh = [LIMIT] of { bool };
proctype find_one_buggy() {
foundCh ! 0;
bool x;
limitCh ? x;
}
inline find_all_buggy() {
byte i;
for (i : 1 .. NUM_PROCESSES) {
limitCh ! true;
run find_one_buggy();
}
bool x;
for (i : 1 .. NUM_PROCESSES) {
foundCh?x ;
}
}
// the prosed fixed version to have the goroutines send to limitCh
proctype find_one_fixed_1() {
limitCh ! true;
foundCh ! 0;
bool x;
limitCh ? x;
}
inline find_all_fixed() {
byte i;
for (i : 1 .. NUM_PROCESSES) {
run find_one_fixed_1();
}
bool x;
for (i : 1 .. NUM_PROCESSES) {
foundCh?x ;
}
}
// the proposed fixed version to have the goroutines send to limitCh before sending to found
proctype find_one_fixed_2() {
limitCh ! true;
bool x;
limitCh ? x;
foundCh ! 0;
}
inline find_all_fixed_2() {
byte i;
for (i : 1 .. NUM_PROCESSES) {
run find_one_fixed_2();
}
bool x;
for (i : 1 .. NUM_PROCESSES) {
foundCh?x ;
}
}
// the proposed fixed version to have the for loop its own goroutine
proctype find_one_fixed_3() {
foundCh ! 0;
bool x;
limitCh ? x;
}
proctype for_loop() {
byte i;
for (i : 1 .. NUM_PROCESSES) {
limitCh ! true;
run find_one_buggy();
}
}
inline find_all_fixed_3() {
byte i;
run for_loop();
bool x;
for (i : 1 .. NUM_PROCESSES) {
foundCh?x ;
}
}
init {
find_all_buggy();
}