concurrent-ruby 0.6.1 → 0.7.0.rc0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/concurrent.rb +3 -4
- data/lib/concurrent/atomic.rb +46 -0
- data/lib/concurrent/atomic_reference/concurrent_update_error.rb +7 -0
- data/lib/concurrent/atomic_reference/delegated_update.rb +28 -0
- data/lib/concurrent/atomic_reference/direct_update.rb +28 -0
- data/lib/concurrent/atomic_reference/jruby.rb +8 -0
- data/lib/concurrent/atomic_reference/mutex_atomic.rb +47 -0
- data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +24 -0
- data/lib/concurrent/atomic_reference/rbx.rb +16 -0
- data/lib/concurrent/atomic_reference/ruby.rb +16 -0
- data/lib/concurrent/atomics.rb +1 -1
- data/lib/concurrent/configuration.rb +1 -1
- data/lib/concurrent/supervisor.rb +1 -1
- data/lib/concurrent/timer_task.rb +0 -36
- data/lib/concurrent/version.rb +1 -1
- data/lib/concurrent_ruby_ext.so +0 -0
- data/lib/extension_helper.rb +9 -0
- metadata +16 -148
- data/lib/concurrent/actor/actor.rb +0 -270
- data/lib/concurrent/actor/postable.rb +0 -102
- data/lib/concurrent/actors.rb +0 -2
- data/lib/concurrent/atomic/atomic.rb +0 -48
- data/lib/concurrent/runnable.rb +0 -90
- data/lib/concurrent/stoppable.rb +0 -20
- data/spec/concurrent/actor/actor_spec.rb +0 -376
- data/spec/concurrent/actor/postable_shared.rb +0 -218
- data/spec/concurrent/actress_spec.rb +0 -211
- data/spec/concurrent/agent_spec.rb +0 -500
- data/spec/concurrent/async_spec.rb +0 -352
- data/spec/concurrent/atomic/atomic_boolean_spec.rb +0 -172
- data/spec/concurrent/atomic/atomic_fixnum_spec.rb +0 -186
- data/spec/concurrent/atomic/atomic_spec.rb +0 -133
- data/spec/concurrent/atomic/condition_spec.rb +0 -171
- data/spec/concurrent/atomic/copy_on_notify_observer_set_spec.rb +0 -10
- data/spec/concurrent/atomic/copy_on_write_observer_set_spec.rb +0 -10
- data/spec/concurrent/atomic/count_down_latch_spec.rb +0 -151
- data/spec/concurrent/atomic/cyclic_barrier_spec.rb +0 -248
- data/spec/concurrent/atomic/event_spec.rb +0 -200
- data/spec/concurrent/atomic/observer_set_shared.rb +0 -242
- data/spec/concurrent/atomic/thread_local_var_spec.rb +0 -113
- data/spec/concurrent/channel/buffered_channel_spec.rb +0 -151
- data/spec/concurrent/channel/channel_spec.rb +0 -39
- data/spec/concurrent/channel/probe_spec.rb +0 -77
- data/spec/concurrent/channel/unbuffered_channel_spec.rb +0 -132
- data/spec/concurrent/collection/blocking_ring_buffer_spec.rb +0 -149
- data/spec/concurrent/collection/priority_queue_spec.rb +0 -317
- data/spec/concurrent/collection/ring_buffer_spec.rb +0 -126
- data/spec/concurrent/configuration_spec.rb +0 -69
- data/spec/concurrent/dataflow_spec.rb +0 -242
- data/spec/concurrent/delay_spec.rb +0 -91
- data/spec/concurrent/dereferenceable_shared.rb +0 -146
- data/spec/concurrent/exchanger_spec.rb +0 -66
- data/spec/concurrent/executor/cached_thread_pool_shared.rb +0 -115
- data/spec/concurrent/executor/fixed_thread_pool_shared.rb +0 -136
- data/spec/concurrent/executor/global_thread_pool_shared.rb +0 -35
- data/spec/concurrent/executor/immediate_executor_spec.rb +0 -12
- data/spec/concurrent/executor/java_cached_thread_pool_spec.rb +0 -44
- data/spec/concurrent/executor/java_fixed_thread_pool_spec.rb +0 -64
- data/spec/concurrent/executor/java_single_thread_executor_spec.rb +0 -21
- data/spec/concurrent/executor/java_thread_pool_executor_spec.rb +0 -71
- data/spec/concurrent/executor/per_thread_executor_spec.rb +0 -57
- data/spec/concurrent/executor/ruby_cached_thread_pool_spec.rb +0 -69
- data/spec/concurrent/executor/ruby_fixed_thread_pool_spec.rb +0 -39
- data/spec/concurrent/executor/ruby_single_thread_executor_spec.rb +0 -18
- data/spec/concurrent/executor/ruby_thread_pool_executor_spec.rb +0 -171
- data/spec/concurrent/executor/safe_task_executor_spec.rb +0 -103
- data/spec/concurrent/executor/thread_pool_class_cast_spec.rb +0 -52
- data/spec/concurrent/executor/thread_pool_executor_shared.rb +0 -155
- data/spec/concurrent/executor/thread_pool_shared.rb +0 -269
- data/spec/concurrent/executor/timer_set_spec.rb +0 -183
- data/spec/concurrent/future_spec.rb +0 -329
- data/spec/concurrent/ivar_spec.rb +0 -215
- data/spec/concurrent/mvar_spec.rb +0 -380
- data/spec/concurrent/obligation_shared.rb +0 -102
- data/spec/concurrent/obligation_spec.rb +0 -282
- data/spec/concurrent/observable_shared.rb +0 -177
- data/spec/concurrent/observable_spec.rb +0 -56
- data/spec/concurrent/options_parser_spec.rb +0 -71
- data/spec/concurrent/promise_spec.rb +0 -367
- data/spec/concurrent/runnable_shared.rb +0 -68
- data/spec/concurrent/runnable_spec.rb +0 -235
- data/spec/concurrent/scheduled_task_spec.rb +0 -340
- data/spec/concurrent/stoppable_shared.rb +0 -37
- data/spec/concurrent/supervisor_spec.rb +0 -1149
- data/spec/concurrent/timer_task_spec.rb +0 -256
- data/spec/concurrent/tvar_spec.rb +0 -137
- data/spec/concurrent/utility/processor_count_spec.rb +0 -20
- data/spec/concurrent/utility/timeout_spec.rb +0 -50
- data/spec/concurrent/utility/timer_spec.rb +0 -52
- data/spec/spec_helper.rb +0 -41
- data/spec/support/example_group_extensions.rb +0 -52
- data/spec/support/less_than_or_equal_to_matcher.rb +0 -5
@@ -1,151 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
share_examples_for :count_down_latch do
|
4
|
-
|
5
|
-
let(:latch) { described_class.new(3) }
|
6
|
-
let(:zero_count_latch) { described_class.new(0) }
|
7
|
-
|
8
|
-
context '#initialize' do
|
9
|
-
|
10
|
-
it 'raises an exception if the initial count is less than zero' do
|
11
|
-
expect {
|
12
|
-
described_class.new(-1)
|
13
|
-
}.to raise_error(ArgumentError)
|
14
|
-
end
|
15
|
-
|
16
|
-
it 'raises an exception if the initial count is not an integer' do
|
17
|
-
expect {
|
18
|
-
described_class.new('foo')
|
19
|
-
}.to raise_error(ArgumentError)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
describe '#count' do
|
24
|
-
|
25
|
-
it 'should be the value passed to the constructor' do
|
26
|
-
latch.count.should eq 3
|
27
|
-
end
|
28
|
-
|
29
|
-
it 'should be decreased after every count down' do
|
30
|
-
latch.count_down
|
31
|
-
latch.count.should eq 2
|
32
|
-
end
|
33
|
-
|
34
|
-
it 'should not go below zero' do
|
35
|
-
5.times { latch.count_down }
|
36
|
-
latch.count.should eq 0
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
describe '#wait' do
|
41
|
-
|
42
|
-
context 'count set to zero' do
|
43
|
-
it 'should return true immediately' do
|
44
|
-
result = zero_count_latch.wait
|
45
|
-
result.should be_true
|
46
|
-
end
|
47
|
-
|
48
|
-
it 'should return true immediately with timeout' do
|
49
|
-
result = zero_count_latch.wait(5)
|
50
|
-
result.should be_true
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
context 'non zero count' do
|
55
|
-
|
56
|
-
it 'should block thread until counter is set to zero' do
|
57
|
-
3.times do
|
58
|
-
Thread.new { sleep(0.1); latch.count_down }
|
59
|
-
end
|
60
|
-
|
61
|
-
result = latch.wait
|
62
|
-
result.should be_true
|
63
|
-
latch.count.should eq 0
|
64
|
-
end
|
65
|
-
|
66
|
-
it 'should block until counter is set to zero with timeout' do
|
67
|
-
3.times do
|
68
|
-
Thread.new { sleep(0.1); latch.count_down }
|
69
|
-
end
|
70
|
-
|
71
|
-
result = latch.wait(1)
|
72
|
-
result.should be_true
|
73
|
-
latch.count.should eq 0
|
74
|
-
|
75
|
-
end
|
76
|
-
|
77
|
-
it 'should block until timeout and return false when counter is not set to zero' do
|
78
|
-
result = latch.wait(0.1)
|
79
|
-
result.should be_false
|
80
|
-
latch.count.should eq 3
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
module Concurrent
|
87
|
-
|
88
|
-
describe MutexCountDownLatch do
|
89
|
-
|
90
|
-
it_should_behave_like :count_down_latch
|
91
|
-
|
92
|
-
context 'spurious wake ups' do
|
93
|
-
|
94
|
-
subject { described_class.new(3) }
|
95
|
-
|
96
|
-
before(:each) do
|
97
|
-
def subject.simulate_spurious_wake_up
|
98
|
-
@mutex.synchronize do
|
99
|
-
@condition.signal
|
100
|
-
@condition.broadcast
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
it 'should resist to spurious wake ups without timeout' do
|
106
|
-
@expected = false
|
107
|
-
Thread.new { subject.wait; @expected = true }
|
108
|
-
|
109
|
-
sleep(0.1)
|
110
|
-
subject.simulate_spurious_wake_up
|
111
|
-
|
112
|
-
sleep(0.1)
|
113
|
-
@expected.should be_false
|
114
|
-
end
|
115
|
-
|
116
|
-
it 'should resist to spurious wake ups with timeout' do
|
117
|
-
@expected = false
|
118
|
-
Thread.new { subject.wait(0.5); @expected = true }
|
119
|
-
|
120
|
-
sleep(0.1)
|
121
|
-
subject.simulate_spurious_wake_up
|
122
|
-
|
123
|
-
sleep(0.1)
|
124
|
-
@expected.should be_false
|
125
|
-
|
126
|
-
sleep(0.4)
|
127
|
-
@expected.should be_true
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
if TestHelpers.jruby?
|
133
|
-
|
134
|
-
describe JavaCountDownLatch do
|
135
|
-
|
136
|
-
it_should_behave_like :count_down_latch
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
describe CountDownLatch do
|
141
|
-
if jruby?
|
142
|
-
it 'inherits from JavaCountDownLatch' do
|
143
|
-
CountDownLatch.ancestors.should include(JavaCountDownLatch)
|
144
|
-
end
|
145
|
-
else
|
146
|
-
it 'inherits from MutexCountDownLatch' do
|
147
|
-
CountDownLatch.ancestors.should include(MutexCountDownLatch)
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
@@ -1,248 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Concurrent
|
4
|
-
|
5
|
-
describe CyclicBarrier do
|
6
|
-
|
7
|
-
let(:parties) { 3 }
|
8
|
-
let!(:barrier) { described_class.new(3) }
|
9
|
-
|
10
|
-
context '#initialize' do
|
11
|
-
|
12
|
-
it 'raises an exception if the initial count is less than 1' do
|
13
|
-
expect {
|
14
|
-
described_class.new(0)
|
15
|
-
}.to raise_error(ArgumentError)
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'raises an exception if the initial count is not an integer' do
|
19
|
-
expect {
|
20
|
-
described_class.new('foo')
|
21
|
-
}.to raise_error(ArgumentError)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
describe '#parties' do
|
26
|
-
|
27
|
-
it 'should be the value passed to the constructor' do
|
28
|
-
barrier.parties.should eq 3
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|
32
|
-
|
33
|
-
describe '#number_waiting' do
|
34
|
-
context 'without any waiting thread' do
|
35
|
-
it 'should be equal to zero' do
|
36
|
-
barrier.number_waiting.should eq 0
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
context 'with waiting threads' do
|
41
|
-
it 'should be equal to the waiting threads count' do
|
42
|
-
Thread.new { barrier.wait }
|
43
|
-
Thread.new { barrier.wait }
|
44
|
-
|
45
|
-
sleep(0.1)
|
46
|
-
|
47
|
-
barrier.number_waiting.should eq 2
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
describe '#broken?' do
|
53
|
-
it 'should not be broken when created' do
|
54
|
-
barrier.broken?.should eq false
|
55
|
-
end
|
56
|
-
|
57
|
-
it 'should not be broken when reset is called without waiting thread' do
|
58
|
-
barrier.reset
|
59
|
-
barrier.broken?.should eq false
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
describe 'reset' do
|
64
|
-
it 'should release all waiting threads' do
|
65
|
-
latch = CountDownLatch.new(1)
|
66
|
-
|
67
|
-
Thread.new { barrier.wait; latch.count_down }
|
68
|
-
sleep(0.1)
|
69
|
-
barrier.reset
|
70
|
-
latch.wait(0.1).should be_true
|
71
|
-
|
72
|
-
barrier.should_not be_broken
|
73
|
-
barrier.number_waiting.should eq 0
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
describe '#wait' do
|
78
|
-
context 'without timeout' do
|
79
|
-
it 'should block the thread' do
|
80
|
-
t = Thread.new { barrier.wait }
|
81
|
-
sleep(0.1)
|
82
|
-
|
83
|
-
t.status.should eq 'sleep'
|
84
|
-
end
|
85
|
-
|
86
|
-
it 'should release all threads when their number matches the desired one' do
|
87
|
-
latch = CountDownLatch.new(parties)
|
88
|
-
|
89
|
-
parties.times { Thread.new { barrier.wait; latch.count_down } }
|
90
|
-
latch.wait(0.1).should be_true
|
91
|
-
barrier.number_waiting.should eq 0
|
92
|
-
barrier.should_not be_broken
|
93
|
-
end
|
94
|
-
|
95
|
-
it 'returns true when released' do
|
96
|
-
latch = CountDownLatch.new(parties)
|
97
|
-
|
98
|
-
parties.times { Thread.new { latch.count_down if barrier.wait == true } }
|
99
|
-
latch.wait(0.1).should be_true
|
100
|
-
end
|
101
|
-
|
102
|
-
it 'executes the block once' do
|
103
|
-
counter = AtomicFixnum.new
|
104
|
-
barrier = described_class.new(parties) { counter.increment }
|
105
|
-
|
106
|
-
latch = CountDownLatch.new(parties)
|
107
|
-
|
108
|
-
parties.times { Thread.new { latch.count_down if barrier.wait == true } }
|
109
|
-
latch.wait(0.1).should be_true
|
110
|
-
|
111
|
-
counter.value.should eq 1
|
112
|
-
end
|
113
|
-
|
114
|
-
it 'can be reused' do
|
115
|
-
first_latch = CountDownLatch.new(parties)
|
116
|
-
parties.times { Thread.new { barrier.wait; first_latch.count_down } }
|
117
|
-
first_latch.wait(0.1).should be_true
|
118
|
-
|
119
|
-
latch = CountDownLatch.new(parties)
|
120
|
-
parties.times { Thread.new { barrier.wait; latch.count_down } }
|
121
|
-
latch.wait(0.1).should be_true
|
122
|
-
end
|
123
|
-
|
124
|
-
it 'return false if barrier has been reset' do
|
125
|
-
latch = CountDownLatch.new(1)
|
126
|
-
|
127
|
-
Thread.new { latch.count_down if barrier.wait == false }
|
128
|
-
sleep(0.1)
|
129
|
-
barrier.reset
|
130
|
-
latch.wait(0.1).should be_true
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
context 'with timeout' do
|
135
|
-
context 'timeout not expiring' do
|
136
|
-
it 'should block the thread' do
|
137
|
-
t = Thread.new { barrier.wait(1) }
|
138
|
-
sleep(0.1)
|
139
|
-
|
140
|
-
t.status.should eq 'sleep'
|
141
|
-
end
|
142
|
-
|
143
|
-
it 'should release all threads when their number matches the desired one' do
|
144
|
-
latch = CountDownLatch.new(parties)
|
145
|
-
|
146
|
-
parties.times { Thread.new { barrier.wait(1); latch.count_down } }
|
147
|
-
latch.wait(0.2).should be_true
|
148
|
-
barrier.number_waiting.should eq 0
|
149
|
-
end
|
150
|
-
|
151
|
-
it 'returns true when released' do
|
152
|
-
latch = CountDownLatch.new(parties)
|
153
|
-
|
154
|
-
parties.times { Thread.new { latch.count_down if barrier.wait(1) == true } }
|
155
|
-
latch.wait(0.1).should be_true
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
context 'timeout expiring' do
|
160
|
-
|
161
|
-
it 'returns false' do
|
162
|
-
latch = CountDownLatch.new(1)
|
163
|
-
|
164
|
-
Thread.new { latch.count_down if barrier.wait(0.1) == false }
|
165
|
-
latch.wait(0.2).should be_true
|
166
|
-
end
|
167
|
-
|
168
|
-
it 'breaks the barrier and release all other threads' do
|
169
|
-
latch = CountDownLatch.new(2)
|
170
|
-
|
171
|
-
Thread.new { barrier.wait(0.1); latch.count_down }
|
172
|
-
Thread.new { barrier.wait; latch.count_down }
|
173
|
-
|
174
|
-
latch.wait(0.2).should be_true
|
175
|
-
barrier.should be_broken
|
176
|
-
end
|
177
|
-
|
178
|
-
it 'does not execute the block on timeout' do
|
179
|
-
counter = AtomicFixnum.new
|
180
|
-
barrier = described_class.new(parties) { counter.increment }
|
181
|
-
|
182
|
-
barrier.wait(0.1)
|
183
|
-
|
184
|
-
counter.value.should eq 0
|
185
|
-
end
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
context '#broken barrier' do
|
190
|
-
it 'should not accept new threads' do
|
191
|
-
Thread.new { barrier.wait(0.1) }
|
192
|
-
sleep(0.2)
|
193
|
-
|
194
|
-
barrier.should be_broken
|
195
|
-
|
196
|
-
barrier.wait.should be_false
|
197
|
-
end
|
198
|
-
|
199
|
-
it 'can be reset' do
|
200
|
-
Thread.new { barrier.wait(0.1) }
|
201
|
-
sleep(0.2)
|
202
|
-
|
203
|
-
barrier.should be_broken
|
204
|
-
|
205
|
-
barrier.reset
|
206
|
-
|
207
|
-
barrier.should_not be_broken
|
208
|
-
end
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
context 'spurious wake ups' do
|
213
|
-
|
214
|
-
before(:each) do
|
215
|
-
def barrier.simulate_spurious_wake_up
|
216
|
-
@mutex.synchronize do
|
217
|
-
@condition.signal
|
218
|
-
@condition.broadcast
|
219
|
-
end
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
|
-
it 'should resist to spurious wake ups without timeout' do
|
224
|
-
@expected = false
|
225
|
-
Thread.new { barrier.wait; @expected = true }
|
226
|
-
|
227
|
-
sleep(0.1)
|
228
|
-
barrier.simulate_spurious_wake_up
|
229
|
-
|
230
|
-
sleep(0.1)
|
231
|
-
@expected.should be_false
|
232
|
-
end
|
233
|
-
|
234
|
-
it 'should resist to spurious wake ups with timeout' do
|
235
|
-
@expected = false
|
236
|
-
Thread.new { barrier.wait(0.5); @expected = true }
|
237
|
-
|
238
|
-
sleep(0.1)
|
239
|
-
barrier.simulate_spurious_wake_up
|
240
|
-
|
241
|
-
sleep(0.1)
|
242
|
-
@expected.should be_false
|
243
|
-
|
244
|
-
end
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
end
|
@@ -1,200 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Concurrent
|
4
|
-
|
5
|
-
describe Event do
|
6
|
-
|
7
|
-
subject{ Event.new }
|
8
|
-
|
9
|
-
context '#initialize' do
|
10
|
-
|
11
|
-
it 'sets the state to unset' do
|
12
|
-
subject.should_not be_set
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
context '#set?' do
|
17
|
-
|
18
|
-
it 'returns true when the event has been set' do
|
19
|
-
subject.set
|
20
|
-
subject.should be_set
|
21
|
-
end
|
22
|
-
|
23
|
-
it 'returns false if the event is unset' do
|
24
|
-
subject.should_not be_set
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
context '#set' do
|
29
|
-
|
30
|
-
it 'triggers the event' do
|
31
|
-
@expected = false
|
32
|
-
Thread.new{ subject.wait; @expected = true }
|
33
|
-
sleep(0.1)
|
34
|
-
subject.set
|
35
|
-
sleep(0.1)
|
36
|
-
@expected.should be_true
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'sets the state to set' do
|
40
|
-
subject.set
|
41
|
-
subject.should be_set
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
context '#try?' do
|
46
|
-
|
47
|
-
it 'triggers the event if not already set' do
|
48
|
-
subject.try?
|
49
|
-
subject.should be_set
|
50
|
-
end
|
51
|
-
|
52
|
-
it 'returns true if not previously set' do
|
53
|
-
subject.try?.should be_true
|
54
|
-
end
|
55
|
-
|
56
|
-
it 'returns false if previously set' do
|
57
|
-
subject.set
|
58
|
-
subject.try?.should be_false
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
context '#reset' do
|
63
|
-
|
64
|
-
it 'does not change the state of an unset event' do
|
65
|
-
subject.reset
|
66
|
-
subject.should_not be_set
|
67
|
-
end
|
68
|
-
|
69
|
-
it 'does not trigger an unset event' do
|
70
|
-
@expected = false
|
71
|
-
Thread.new{ subject.wait; @expected = true }
|
72
|
-
sleep(0.1)
|
73
|
-
subject.reset
|
74
|
-
sleep(0.1)
|
75
|
-
@expected.should be_false
|
76
|
-
end
|
77
|
-
|
78
|
-
it 'does not interrupt waiting threads when event is unset' do
|
79
|
-
@expected = false
|
80
|
-
Thread.new{ subject.wait; @expected = true }
|
81
|
-
sleep(0.1)
|
82
|
-
subject.reset
|
83
|
-
sleep(0.1)
|
84
|
-
subject.set
|
85
|
-
sleep(0.1)
|
86
|
-
@expected.should be_true
|
87
|
-
end
|
88
|
-
|
89
|
-
it 'returns true when called on an unset event' do
|
90
|
-
subject.reset.should be_true
|
91
|
-
end
|
92
|
-
|
93
|
-
it 'sets the state of a set event to unset' do
|
94
|
-
subject.set
|
95
|
-
subject.should be_set
|
96
|
-
subject.reset
|
97
|
-
subject.should_not be_set
|
98
|
-
end
|
99
|
-
|
100
|
-
it 'returns true when called on a set event' do
|
101
|
-
subject.set
|
102
|
-
subject.should be_set
|
103
|
-
subject.reset.should be_true
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
context '#wait' do
|
108
|
-
|
109
|
-
it 'returns immediately when the event has been set' do
|
110
|
-
subject.reset
|
111
|
-
@expected = false
|
112
|
-
subject.set
|
113
|
-
Thread.new{ subject.wait(1000); @expected = true}
|
114
|
-
sleep(1)
|
115
|
-
@expected.should be_true
|
116
|
-
end
|
117
|
-
|
118
|
-
it 'returns true once the event is set' do
|
119
|
-
subject.set
|
120
|
-
subject.wait.should be_true
|
121
|
-
end
|
122
|
-
|
123
|
-
it 'blocks indefinitely when the timer is nil' do
|
124
|
-
subject.reset
|
125
|
-
@expected = false
|
126
|
-
Thread.new{ subject.wait; @expected = true}
|
127
|
-
subject.set
|
128
|
-
sleep(1)
|
129
|
-
@expected.should be_true
|
130
|
-
end
|
131
|
-
|
132
|
-
it 'stops waiting when the timer expires' do
|
133
|
-
subject.reset
|
134
|
-
@expected = false
|
135
|
-
Thread.new{ subject.wait(0.5); @expected = true}
|
136
|
-
sleep(1)
|
137
|
-
@expected.should be_true
|
138
|
-
end
|
139
|
-
|
140
|
-
it 'returns false when the timer expires' do
|
141
|
-
subject.reset
|
142
|
-
subject.wait(1).should be_false
|
143
|
-
end
|
144
|
-
|
145
|
-
it 'triggers multiple waiting threads' do
|
146
|
-
latch = CountDownLatch.new(5)
|
147
|
-
subject.reset
|
148
|
-
5.times{ Thread.new{ subject.wait; latch.count_down } }
|
149
|
-
subject.set
|
150
|
-
latch.wait(0.2).should be_true
|
151
|
-
end
|
152
|
-
|
153
|
-
it 'behaves appropriately if wait begins while #set is processing' do
|
154
|
-
subject.reset
|
155
|
-
latch = CountDownLatch.new(5)
|
156
|
-
5.times{ Thread.new{ subject.wait(5) } }
|
157
|
-
subject.set
|
158
|
-
5.times{ Thread.new{ subject.wait; latch.count_down } }
|
159
|
-
latch.wait(0.2).should be_true
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
context 'spurious wake ups' do
|
164
|
-
|
165
|
-
before(:each) do
|
166
|
-
def subject.simulate_spurious_wake_up
|
167
|
-
@mutex.synchronize do
|
168
|
-
@condition.signal
|
169
|
-
@condition.broadcast
|
170
|
-
end
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
it 'should resist to spurious wake ups without timeout' do
|
175
|
-
@expected = false
|
176
|
-
Thread.new { subject.wait; @expected = true }
|
177
|
-
|
178
|
-
sleep(0.1)
|
179
|
-
subject.simulate_spurious_wake_up
|
180
|
-
|
181
|
-
sleep(0.1)
|
182
|
-
@expected.should be_false
|
183
|
-
end
|
184
|
-
|
185
|
-
it 'should resist to spurious wake ups with timeout' do
|
186
|
-
@expected = false
|
187
|
-
Thread.new { subject.wait(0.5); @expected = true }
|
188
|
-
|
189
|
-
sleep(0.1)
|
190
|
-
subject.simulate_spurious_wake_up
|
191
|
-
|
192
|
-
sleep(0.1)
|
193
|
-
@expected.should be_false
|
194
|
-
|
195
|
-
sleep(0.4)
|
196
|
-
@expected.should be_true
|
197
|
-
end
|
198
|
-
end
|
199
|
-
end
|
200
|
-
end
|