11require 'spec_helper'
2+ require_relative 'dereferenceable_shared'
23
34module Concurrent
45
@@ -16,7 +17,7 @@ def dereferenceable_subject(value, opts = {})
1617
1718 end
1819
19- context '#initialize' do
20+ describe '#initialize' do
2021
2122 it 'accepts no initial value' do
2223 m = MVar . new
@@ -40,7 +41,7 @@ def dereferenceable_subject(value, opts = {})
4041
4142 end
4243
43- context '#take' do
44+ describe '#take' do
4445
4546 it 'sets the MVar to empty' do
4647 m = MVar . new ( 14 )
@@ -57,21 +58,21 @@ def dereferenceable_subject(value, opts = {})
5758 m = MVar . new
5859
5960 putter = Thread . new {
60- sleep ( 0.5 )
61- m . put 14
61+ sleep ( 0.1 )
62+ m . put 14
6263 }
6364
6465 m . take . should eq 14
6566 end
6667
6768 it 'returns TIMEOUT on timeout on an empty MVar' do
6869 m = MVar . new
69- m . take ( 0.5 ) . should eq MVar ::TIMEOUT
70+ m . take ( 0.1 ) . should eq MVar ::TIMEOUT
7071 end
7172
7273 end
7374
74- context '#put' do
75+ describe '#put' do
7576
7677 it 'sets the MVar to be empty' do
7778 m = MVar . new ( 14 )
@@ -89,7 +90,7 @@ def dereferenceable_subject(value, opts = {})
8990 m = MVar . new ( 14 )
9091
9192 putter = Thread . new {
92- sleep ( 0.5 )
93+ sleep ( 0.1 )
9394 m . take
9495 }
9596
@@ -98,7 +99,7 @@ def dereferenceable_subject(value, opts = {})
9899
99100 it 'returns TIMEOUT on timeout on a full MVar' do
100101 m = MVar . new ( 14 )
101- m . put ( 14 , 0.5 ) . should eq MVar ::TIMEOUT
102+ m . put ( 14 , 0.1 ) . should eq MVar ::TIMEOUT
102103 end
103104
104105 it 'returns the value' do
@@ -108,7 +109,7 @@ def dereferenceable_subject(value, opts = {})
108109
109110 end
110111
111- context '#empty?' do
112+ describe '#empty?' do
112113
113114 it 'returns true on an empty MVar' do
114115 m = MVar . new
@@ -122,7 +123,7 @@ def dereferenceable_subject(value, opts = {})
122123
123124 end
124125
125- context '#full?' do
126+ describe '#full?' do
126127
127128 it 'returns false on an empty MVar' do
128129 m = MVar . new
@@ -136,7 +137,7 @@ def dereferenceable_subject(value, opts = {})
136137
137138 end
138139
139- context '#modify' do
140+ describe '#modify' do
140141
141142 it 'raises an exception when no block given' do
142143 m = MVar . new ( 14 )
@@ -158,7 +159,7 @@ def dereferenceable_subject(value, opts = {})
158159 m = MVar . new
159160
160161 putter = Thread . new {
161- sleep ( 0.5 )
162+ sleep ( 0.1 )
162163 m . put 14
163164 }
164165
@@ -173,24 +174,24 @@ def dereferenceable_subject(value, opts = {})
173174
174175 modifier = Thread . new {
175176 m . modify do |v |
176- sleep ( 1 )
177+ sleep ( 0.5 )
177178 1
178179 end
179180 }
180181
181- sleep ( 0.5 )
182- m . put ( 2 , 1 ) . should eq MVar ::TIMEOUT
182+ sleep ( 0.1 )
183+ m . put ( 2 , 0.5 ) . should eq MVar ::TIMEOUT
183184 m . take . should eq 1
184185 end
185186
186187 it 'returns TIMEOUT on timeout on an empty MVar' do
187188 m = MVar . new
188- m . modify ( 0.5 ) { |v | v + 2 } . should eq MVar ::TIMEOUT
189+ m . modify ( 0.1 ) { |v | v + 2 } . should eq MVar ::TIMEOUT
189190 end
190191
191192 end
192193
193- context '#try_put!' do
194+ describe '#try_put!' do
194195
195196 it 'returns true an empty MVar' do
196197 m = MVar . new
@@ -210,7 +211,7 @@ def dereferenceable_subject(value, opts = {})
210211
211212 end
212213
213- context '#try_take!' do
214+ describe '#try_take!' do
214215
215216 it 'returns EMPTY an empty MVar' do
216217 m = MVar . new
@@ -230,7 +231,7 @@ def dereferenceable_subject(value, opts = {})
230231
231232 end
232233
233- context '#set!' do
234+ describe '#set!' do
234235
235236 it 'sets an empty MVar to be full' do
236237 m = MVar . new
@@ -257,7 +258,7 @@ def dereferenceable_subject(value, opts = {})
257258
258259 end
259260
260- context '#modify!' do
261+ describe '#modify!' do
261262
262263 it 'raises an exception when no block given' do
263264 m = MVar . new ( 14 )
@@ -295,6 +296,86 @@ def dereferenceable_subject(value, opts = {})
295296
296297 end
297298
299+ context 'spurious wake ups' do
300+
301+ let ( :m ) { MVar . new }
302+
303+ before ( :each ) do
304+ def m . simulate_spurious_wake_up
305+ @mutex . synchronize do
306+ @full_condition . broadcast
307+ @empty_condition . broadcast
308+ end
309+ end
310+ end
311+
312+ describe '#take' do
313+ it 'waits for another thread to #put' do
314+ Thread . new { sleep ( 0.5 ) ; m . put 14 }
315+ Thread . new { sleep ( 0.1 ) ; m . simulate_spurious_wake_up }
316+
317+ m . take . should eq 14
318+ end
319+
320+ it 'returns TIMEOUT on timeout on an empty MVar' do
321+ result = nil
322+ Thread . new { result = m . take ( 0.3 ) }
323+ sleep ( 0.1 )
324+ Thread . new { m . simulate_spurious_wake_up }
325+ sleep ( 0.1 )
326+ result . should be_nil
327+ sleep ( 0.2 )
328+ result . should eq MVar ::TIMEOUT
329+ end
330+ end
331+
332+ describe '#modify' do
333+
334+ it 'waits for another thread to #put' do
335+ Thread . new { sleep ( 0.5 ) ; m . put 14 }
336+ Thread . new { sleep ( 0.1 ) ; m . simulate_spurious_wake_up }
337+
338+ m . modify { |v | v + 2 } . should eq 14
339+ end
340+
341+ it 'returns TIMEOUT on timeout on an empty MVar' do
342+ result = nil
343+ Thread . new { result = m . modify ( 0.3 ) { |v | v + 2 } }
344+ sleep ( 0.1 )
345+ Thread . new { m . simulate_spurious_wake_up }
346+ sleep ( 0.1 )
347+ result . should be_nil
348+ sleep ( 0.2 )
349+ result . should eq MVar ::TIMEOUT
350+ end
351+ end
352+
353+ describe '#put' do
354+
355+ before ( :each ) { m . put ( 42 ) }
356+
357+ it 'waits for another thread to #take' do
358+ Thread . new { sleep ( 0.5 ) ; m . take }
359+ Thread . new { sleep ( 0.1 ) ; m . simulate_spurious_wake_up }
360+
361+ m . put ( 14 ) . should eq 14
362+ end
363+
364+ it 'returns TIMEOUT on timeout on a full MVar' do
365+ result = nil
366+ Thread . new { result = m . put ( 14 , 0.3 ) }
367+ sleep ( 0.1 )
368+ Thread . new { m . simulate_spurious_wake_up }
369+ sleep ( 0.1 )
370+ result . should be_nil
371+ sleep ( 0.2 )
372+ result . should eq MVar ::TIMEOUT
373+ end
374+ end
375+
376+
377+ end
378+
298379 end
299380
300381end
0 commit comments