@@ -2,15 +2,6 @@ module Concurrent
2
2
3
3
describe Condition do
4
4
5
- let ( :mutex ) { Mutex . new }
6
- subject { Condition . new }
7
-
8
- before ( :each ) do
9
- # rspec is not thread safe, without mutex initialization
10
- # we can experience race conditions
11
- mutex
12
- end
13
-
14
5
context 'with no waiting threads' do
15
6
describe '#signal' do
16
7
it 'should return immediately' do
@@ -32,25 +23,47 @@ module Concurrent
32
23
describe '#wait without timeout' do
33
24
34
25
it 'should block the thread' do
35
- latch = Concurrent ::CountDownLatch . new
26
+ latch_1 = Concurrent ::CountDownLatch . new
27
+ latch_2 = Concurrent ::CountDownLatch . new
28
+ mutex = Mutex . new
29
+
36
30
t = Thread . new do
37
31
mutex . synchronize do
38
- latch . count_down
32
+ latch_1 . count_down
39
33
subject . wait ( mutex )
34
+ latch_2 . count_down
40
35
end
41
36
end
42
37
43
- latch . wait ( 1 )
38
+ latch_1 . wait ( 1 )
39
+ latch_2 . wait ( 0.1 )
44
40
expect ( t . status ) . to eq 'sleep'
41
+ expect ( latch_2 . count ) . to eq 1
45
42
t . kill
46
43
end
47
44
48
45
it 'should return a woken up result when is woken up by #signal' do
49
46
result = nil
50
- t = Thread . new { mutex . synchronize { result = subject . wait ( mutex ) } }
51
- sleep ( 0.1 )
52
- mutex . synchronize { subject . signal }
53
- sleep ( 0.1 )
47
+ mutex = Mutex . new
48
+ latch_1 = Concurrent ::CountDownLatch . new
49
+ latch_2 = Concurrent ::CountDownLatch . new
50
+
51
+ t = Thread . new do
52
+ mutex . synchronize do
53
+ latch_1 . count_down
54
+ result = subject . wait ( mutex )
55
+ latch_2 . count_down
56
+ end
57
+ end
58
+
59
+ latch_1 . wait ( 1 )
60
+
61
+ mutex . synchronize do
62
+ subject . signal
63
+ end
64
+
65
+ latch_2 . wait ( 1 )
66
+
54
67
expect ( result ) . to be_woken_up
55
68
expect ( result ) . not_to be_timed_out
56
69
expect ( result . remaining_time ) . to be_nil
@@ -59,72 +72,136 @@ module Concurrent
59
72
60
73
it 'should return a woken up result when is woken up by #broadcast' do
61
74
result = nil
62
- t = Thread . new { mutex . synchronize { result = subject . wait ( mutex ) } }
63
- sleep ( 0.1 )
64
- mutex . synchronize { subject . broadcast }
65
- sleep ( 0.1 )
75
+ mutex = Mutex . new
76
+ latch_1 = Concurrent ::CountDownLatch . new
77
+ latch_2 = Concurrent ::CountDownLatch . new
78
+
79
+ t = Thread . new do
80
+ mutex . synchronize do
81
+ latch_1 . count_down
82
+ result = subject . wait ( mutex )
83
+ latch_2 . count_down
84
+ end
85
+ end
86
+
87
+ latch_1 . wait ( 1 )
88
+
89
+ mutex . synchronize do
90
+ subject . broadcast
91
+ end
92
+
93
+ latch_2 . wait ( 1 )
94
+
66
95
expect ( result ) . to be_woken_up
67
96
expect ( result ) . not_to be_timed_out
68
97
expect ( result . remaining_time ) . to be_nil
69
98
expect ( t . status ) . to be_falsey
70
99
end
71
100
end
72
-
73
101
end
74
102
75
103
context 'timeout' do
76
104
77
105
describe '#wait' do
78
106
79
107
it 'should block the thread' do
80
- latch = Concurrent ::CountDownLatch . new
108
+ latch_1 = Concurrent ::CountDownLatch . new
109
+ latch_2 = Concurrent ::CountDownLatch . new
110
+ mutex = Mutex . new
111
+
81
112
t = Thread . new do
82
113
mutex . synchronize do
83
- latch . count_down
114
+ latch_1 . count_down
84
115
subject . wait ( mutex , 1 )
116
+ latch_2 . count_down
85
117
end
86
118
end
87
119
88
- latch . wait ( 1 )
120
+ latch_1 . wait ( 1 )
121
+ latch_2 . wait ( 0.1 )
89
122
expect ( t . status ) . to eq 'sleep'
123
+ expect ( latch_2 . count ) . to eq 1
90
124
t . kill
91
125
end
92
126
93
127
it 'should return remaining time when is woken up by #signal' do
94
128
result = nil
95
- t = Thread . new { mutex . synchronize { result = subject . wait ( mutex , 1 ) } }
96
- sleep ( 0.1 )
97
- mutex . synchronize { subject . signal }
98
- sleep ( 0.1 )
129
+ mutex = Mutex . new
130
+ latch_1 = Concurrent ::CountDownLatch . new
131
+ latch_2 = Concurrent ::CountDownLatch . new
132
+
133
+ t = Thread . new do
134
+ mutex . synchronize do
135
+ latch_1 . count_down
136
+ result = subject . wait ( mutex , 1 )
137
+ latch_2 . count_down
138
+ end
139
+ end
140
+
141
+ latch_1 . wait ( 1 )
142
+
143
+ mutex . synchronize do
144
+ sleep ( 0.1 )
145
+ subject . signal
146
+ end
147
+
148
+ latch_2 . wait ( 1 )
149
+
99
150
expect ( result ) . to be_woken_up
100
151
expect ( result ) . not_to be_timed_out
101
- expect ( result . remaining_time ) . to be_within ( 0.1 ) . of ( 0.85 )
152
+ expect ( result . remaining_time ) . to be < 1.0
102
153
expect ( t . status ) . to be_falsey
103
154
end
104
155
105
156
it 'should return remaining time when is woken up by #broadcast' do
106
157
result = nil
107
- t = Thread . new { mutex . synchronize { result = subject . wait ( mutex , 1 ) } }
108
- sleep ( 0.1 )
109
- mutex . synchronize { subject . broadcast }
110
- sleep ( 0.1 )
158
+ mutex = Mutex . new
159
+ latch_1 = Concurrent ::CountDownLatch . new
160
+ latch_2 = Concurrent ::CountDownLatch . new
161
+
162
+ t = Thread . new do
163
+ mutex . synchronize do
164
+ latch_1 . count_down
165
+ result = subject . wait ( mutex , 1 )
166
+ latch_2 . count_down
167
+ end
168
+ end
169
+
170
+ latch_1 . wait ( 1 )
171
+
172
+ mutex . synchronize do
173
+ sleep ( 0.1 )
174
+ subject . broadcast
175
+ end
176
+
177
+ latch_2 . wait ( 1 )
178
+
111
179
expect ( result ) . to be_woken_up
112
180
expect ( result ) . not_to be_timed_out
113
- expect ( result . remaining_time ) . to be_within ( 0.1 ) . of ( 0.85 )
181
+ expect ( result . remaining_time ) . to be < 1.0
114
182
expect ( t . status ) . to be_falsey
115
183
end
116
184
117
185
it 'should return 0 or negative number if timed out' do
118
186
result = nil
119
- t = Thread . new { mutex . synchronize { result = subject . wait ( mutex , 0.1 ) } }
120
- sleep ( 0.2 )
187
+ mutex = Mutex . new
188
+ latch = Concurrent ::CountDownLatch . new
189
+
190
+ t = Thread . new do
191
+ mutex . synchronize do
192
+ result = subject . wait ( mutex , 0.1 )
193
+ latch . count_down
194
+ end
195
+ end
196
+
197
+ latch . wait ( 1 )
198
+
121
199
expect ( result ) . not_to be_woken_up
122
200
expect ( result ) . to be_timed_out
123
201
expect ( result . remaining_time ) . to be_less_than_or_equal_to ( 0 )
124
202
expect ( t . status ) . to be_falsey
125
203
end
126
204
end
127
-
128
205
end
129
206
end
130
207
@@ -135,34 +212,53 @@ module Concurrent
135
212
describe '#wait' do
136
213
137
214
it 'should block threads' do
138
- t1 = Thread . new { mutex . synchronize { subject . wait ( mutex ) } }
139
- t2 = Thread . new { mutex . synchronize { subject . wait ( mutex ) } }
215
+ mutex = Mutex . new
216
+ latch = Concurrent ::CountDownLatch . new ( 2 )
217
+ t1 = Thread . new { mutex . synchronize { latch . count_down ; subject . wait ( mutex ) } }
218
+ t2 = Thread . new { mutex . synchronize { latch . count_down ; subject . wait ( mutex ) } }
219
+ latch . wait ( 1 )
140
220
sleep ( 0.1 )
141
221
[ t1 , t2 ] . each { |t | expect ( t . status ) . to eq 'sleep' }
142
222
[ t1 , t2 ] . each { |t | t . kill }
143
223
end
144
-
145
224
end
146
225
147
226
describe '#signal' do
148
227
it 'wakes up only one thread' do
149
- latch = CountDownLatch . new ( 2 )
228
+ latch_1 = Concurrent ::CountDownLatch . new ( 2 )
229
+ latch_2 = Concurrent ::CountDownLatch . new ( 2 )
230
+ mutex = Mutex . new
150
231
151
- t1 = Thread . new { mutex . synchronize { subject . wait ( mutex ) ; latch . count_down } }
152
- t2 = Thread . new { mutex . synchronize { subject . wait ( mutex ) ; latch . count_down } }
232
+ t1 = Thread . new do
233
+ mutex . synchronize do
234
+ latch_1 . count_down
235
+ subject . wait ( mutex )
236
+ latch_2 . count_down
237
+ end
238
+ end
153
239
240
+ t2 = Thread . new do
241
+ mutex . synchronize do
242
+ latch_1 . count_down
243
+ subject . wait ( mutex )
244
+ latch_2 . count_down
245
+ end
246
+ end
247
+
248
+ latch_1 . wait ( 1 )
154
249
sleep ( 0.1 )
155
250
mutex . synchronize { subject . signal }
156
- sleep ( 0.2 )
251
+ sleep ( 0.1 )
157
252
158
- expect ( latch . count ) . to eq 1
253
+ expect ( latch_2 . count ) . to eq 1
159
254
[ t1 , t2 ] . each { |t | t . kill }
160
255
end
161
256
end
162
257
163
258
describe '#broadcast' do
164
259
it 'wakes up all threads' do
165
260
latch = CountDownLatch . new ( 2 )
261
+ mutex = Mutex . new
166
262
167
263
t1 = Thread . new { mutex . synchronize { subject . wait ( mutex ) ; latch . count_down } }
168
264
t2 = Thread . new { mutex . synchronize { subject . wait ( mutex ) ; latch . count_down } }
@@ -176,8 +272,6 @@ module Concurrent
176
272
end
177
273
end
178
274
end
179
-
180
275
end
181
-
182
276
end
183
277
end
0 commit comments