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,186 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
share_examples_for :atomic_fixnum do
|
4
|
-
|
5
|
-
context 'construction' do
|
6
|
-
|
7
|
-
it 'sets the initial value' do
|
8
|
-
described_class.new(10).value.should eq 10
|
9
|
-
end
|
10
|
-
|
11
|
-
it 'defaults the initial value to zero' do
|
12
|
-
described_class.new.value.should eq 0
|
13
|
-
end
|
14
|
-
|
15
|
-
it 'raises en exception if the initial value is not a Fixnum' do
|
16
|
-
lambda {
|
17
|
-
described_class.new(10.01)
|
18
|
-
}.should raise_error
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
context '#value' do
|
23
|
-
|
24
|
-
it 'returns the current value' do
|
25
|
-
counter = described_class.new(10)
|
26
|
-
counter.value.should eq 10
|
27
|
-
counter.increment
|
28
|
-
counter.value.should eq 11
|
29
|
-
counter.decrement
|
30
|
-
counter.value.should eq 10
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
context '#value=' do
|
35
|
-
|
36
|
-
it 'sets the #value to the given `Fixnum`' do
|
37
|
-
atomic = described_class.new(0)
|
38
|
-
atomic.value = 10
|
39
|
-
atomic.value.should eq 10
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'returns the new value' do
|
43
|
-
atomic = described_class.new(0)
|
44
|
-
(atomic.value = 10).should eq 10
|
45
|
-
end
|
46
|
-
|
47
|
-
it 'raises and exception if the value is not a `Fixnum`' do
|
48
|
-
atomic = described_class.new(0)
|
49
|
-
expect {
|
50
|
-
atomic.value = 'foo'
|
51
|
-
}.to raise_error
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
context '#increment' do
|
56
|
-
|
57
|
-
it 'increases the value by one' do
|
58
|
-
counter = described_class.new(10)
|
59
|
-
3.times{ counter.increment }
|
60
|
-
counter.value.should eq 13
|
61
|
-
end
|
62
|
-
|
63
|
-
it 'returns the new value' do
|
64
|
-
counter = described_class.new(10)
|
65
|
-
counter.increment.should eq 11
|
66
|
-
end
|
67
|
-
|
68
|
-
it 'is aliased as #up' do
|
69
|
-
described_class.new(10).up.should eq 11
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
context '#decrement' do
|
74
|
-
|
75
|
-
it 'decreases the value by one' do
|
76
|
-
counter = described_class.new(10)
|
77
|
-
3.times{ counter.decrement }
|
78
|
-
counter.value.should eq 7
|
79
|
-
end
|
80
|
-
|
81
|
-
it 'returns the new value' do
|
82
|
-
counter = described_class.new(10)
|
83
|
-
counter.decrement.should eq 9
|
84
|
-
end
|
85
|
-
|
86
|
-
it 'is aliased as #down' do
|
87
|
-
described_class.new(10).down.should eq 9
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
context '#compare_and_set' do
|
92
|
-
|
93
|
-
it 'returns false if the value is not found' do
|
94
|
-
described_class.new(14).compare_and_set(2, 14).should eq false
|
95
|
-
end
|
96
|
-
|
97
|
-
it 'returns true if the value is found' do
|
98
|
-
described_class.new(14).compare_and_set(14, 2).should eq true
|
99
|
-
end
|
100
|
-
|
101
|
-
it 'sets if the value is found' do
|
102
|
-
f = described_class.new(14)
|
103
|
-
f.compare_and_set(14, 2)
|
104
|
-
f.value.should eq 2
|
105
|
-
end
|
106
|
-
|
107
|
-
it 'does not set if the value is not found' do
|
108
|
-
f = described_class.new(14)
|
109
|
-
f.compare_and_set(2, 12)
|
110
|
-
f.value.should eq 14
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
module Concurrent
|
116
|
-
|
117
|
-
describe MutexAtomicFixnum do
|
118
|
-
|
119
|
-
it_should_behave_like :atomic_fixnum
|
120
|
-
|
121
|
-
specify 'construction is synchronized' do
|
122
|
-
mutex = double('mutex')
|
123
|
-
Mutex.should_receive(:new).once.with(no_args).and_return(mutex)
|
124
|
-
described_class.new
|
125
|
-
end
|
126
|
-
|
127
|
-
specify 'value is synchronized' do
|
128
|
-
mutex = double('mutex')
|
129
|
-
Mutex.stub(:new).with(no_args).and_return(mutex)
|
130
|
-
mutex.should_receive(:lock)
|
131
|
-
mutex.should_receive(:unlock)
|
132
|
-
described_class.new.value
|
133
|
-
end
|
134
|
-
|
135
|
-
specify 'value= is synchronized' do
|
136
|
-
mutex = double('mutex')
|
137
|
-
Mutex.stub(:new).with(no_args).and_return(mutex)
|
138
|
-
mutex.should_receive(:lock)
|
139
|
-
mutex.should_receive(:unlock)
|
140
|
-
described_class.new.value = 10
|
141
|
-
end
|
142
|
-
|
143
|
-
specify 'increment is synchronized' do
|
144
|
-
mutex = double('mutex')
|
145
|
-
Mutex.stub(:new).with(no_args).and_return(mutex)
|
146
|
-
mutex.should_receive(:lock)
|
147
|
-
mutex.should_receive(:unlock)
|
148
|
-
described_class.new.increment
|
149
|
-
end
|
150
|
-
|
151
|
-
specify 'decrement is synchronized' do
|
152
|
-
mutex = double('mutex')
|
153
|
-
Mutex.stub(:new).with(no_args).and_return(mutex)
|
154
|
-
mutex.should_receive(:lock)
|
155
|
-
mutex.should_receive(:unlock)
|
156
|
-
described_class.new.decrement
|
157
|
-
end
|
158
|
-
|
159
|
-
specify 'compare_and_set is synchronized' do
|
160
|
-
mutex = double('mutex')
|
161
|
-
Mutex.stub(:new).with(no_args).and_return(mutex)
|
162
|
-
mutex.should_receive(:lock)
|
163
|
-
mutex.should_receive(:unlock)
|
164
|
-
described_class.new(14).compare_and_set(14, 2)
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
if TestHelpers.jruby?
|
169
|
-
|
170
|
-
describe JavaAtomicFixnum do
|
171
|
-
it_should_behave_like :atomic_fixnum
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
|
-
describe AtomicFixnum do
|
176
|
-
if jruby?
|
177
|
-
it 'inherits from JavaAtomicFixnum' do
|
178
|
-
AtomicFixnum.ancestors.should include(JavaAtomicFixnum)
|
179
|
-
end
|
180
|
-
else
|
181
|
-
it 'inherits from MutexAtomicFixnum' do
|
182
|
-
AtomicFixnum.ancestors.should include(MutexAtomicFixnum)
|
183
|
-
end
|
184
|
-
end
|
185
|
-
end
|
186
|
-
end
|
@@ -1,133 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
share_examples_for :atomic do
|
4
|
-
|
5
|
-
context 'construction' do
|
6
|
-
|
7
|
-
it 'sets the initial value' do
|
8
|
-
described_class.new(:foo).value.should eq :foo
|
9
|
-
end
|
10
|
-
|
11
|
-
it 'defaults the initial value to nil' do
|
12
|
-
described_class.new.value.should eq nil
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
context '#value' do
|
17
|
-
|
18
|
-
it 'returns the current value' do
|
19
|
-
counter = described_class.new(:foo)
|
20
|
-
counter.value.should eq :foo
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
context '#value=' do
|
25
|
-
|
26
|
-
it 'sets the #value to the given object' do
|
27
|
-
atomic = described_class.new(:foo)
|
28
|
-
atomic.value = :bar
|
29
|
-
atomic.value.should eq :bar
|
30
|
-
end
|
31
|
-
|
32
|
-
it 'returns the new value' do
|
33
|
-
atomic = described_class.new(:foo)
|
34
|
-
(atomic.value = :bar).should eq :bar
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
context '#modify' do
|
39
|
-
|
40
|
-
it 'yields the current value' do
|
41
|
-
atomic = described_class.new(:foo)
|
42
|
-
current = []
|
43
|
-
atomic.modify { |value| current << value }
|
44
|
-
current.should eq [:foo]
|
45
|
-
end
|
46
|
-
|
47
|
-
it 'stores the value returned from the yield' do
|
48
|
-
atomic = described_class.new(:foo)
|
49
|
-
atomic.modify { |value| :bar }
|
50
|
-
atomic.value.should eq :bar
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'returns the new value' do
|
54
|
-
atomic = described_class.new(:foo)
|
55
|
-
atomic.modify{ |value| :bar }.should eq :bar
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
context '#compare_and_set' do
|
60
|
-
|
61
|
-
it 'returns false if the value is not found' do
|
62
|
-
described_class.new(:foo).compare_and_set(:bar, :foo).should eq false
|
63
|
-
end
|
64
|
-
|
65
|
-
it 'returns true if the value is found' do
|
66
|
-
described_class.new(:foo).compare_and_set(:foo, :bar).should eq true
|
67
|
-
end
|
68
|
-
|
69
|
-
it 'sets if the value is found' do
|
70
|
-
f = described_class.new(:foo)
|
71
|
-
f.compare_and_set(:foo, :bar)
|
72
|
-
f.value.should eq :bar
|
73
|
-
end
|
74
|
-
|
75
|
-
it 'does not set if the value is not found' do
|
76
|
-
f = described_class.new(:foo)
|
77
|
-
f.compare_and_set(:bar, :baz)
|
78
|
-
f.value.should eq :foo
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
module Concurrent
|
84
|
-
|
85
|
-
describe MutexAtomic do
|
86
|
-
|
87
|
-
it_should_behave_like :atomic
|
88
|
-
|
89
|
-
specify 'construction is synchronized' do
|
90
|
-
mutex = double('mutex')
|
91
|
-
Mutex.should_receive(:new).once.with(no_args).and_return(mutex)
|
92
|
-
described_class.new
|
93
|
-
end
|
94
|
-
|
95
|
-
specify 'value is synchronized' do
|
96
|
-
mutex = double('mutex')
|
97
|
-
Mutex.stub(:new).with(no_args).and_return(mutex)
|
98
|
-
mutex.should_receive(:lock)
|
99
|
-
mutex.should_receive(:unlock)
|
100
|
-
described_class.new.value
|
101
|
-
end
|
102
|
-
|
103
|
-
specify 'value= is synchronized' do
|
104
|
-
mutex = double('mutex')
|
105
|
-
Mutex.stub(:new).with(no_args).and_return(mutex)
|
106
|
-
mutex.should_receive(:lock)
|
107
|
-
mutex.should_receive(:unlock)
|
108
|
-
described_class.new.value = 10
|
109
|
-
end
|
110
|
-
|
111
|
-
specify 'modify is synchronized' do
|
112
|
-
mutex = double('mutex')
|
113
|
-
Mutex.stub(:new).with(no_args).and_return(mutex)
|
114
|
-
mutex.should_receive(:lock)
|
115
|
-
mutex.should_receive(:unlock)
|
116
|
-
described_class.new(:foo).modify { |value| value }
|
117
|
-
end
|
118
|
-
|
119
|
-
specify 'compare_and_set is synchronized' do
|
120
|
-
mutex = double('mutex')
|
121
|
-
Mutex.stub(:new).with(no_args).and_return(mutex)
|
122
|
-
mutex.should_receive(:lock)
|
123
|
-
mutex.should_receive(:unlock)
|
124
|
-
described_class.new(14).compare_and_set(14, 2)
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
describe Atomic do
|
129
|
-
it 'inherits from MutexAtomic' do
|
130
|
-
Atomic.ancestors.should include(MutexAtomic)
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
@@ -1,171 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Concurrent
|
4
|
-
|
5
|
-
describe Condition do
|
6
|
-
|
7
|
-
let(:mutex) { Mutex.new }
|
8
|
-
subject{ Condition.new }
|
9
|
-
|
10
|
-
before(:each) do
|
11
|
-
# rspec is not thread safe, without mutex initialization
|
12
|
-
# we can experience race conditions
|
13
|
-
mutex
|
14
|
-
end
|
15
|
-
|
16
|
-
context 'with no waiting threads' do
|
17
|
-
describe '#signal' do
|
18
|
-
it 'should return immediately' do
|
19
|
-
subject.signal.should be_true
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
describe '#broadcast' do
|
24
|
-
it 'should return immediately' do
|
25
|
-
subject.broadcast.should be_true
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
context 'with one waiting thread' do
|
31
|
-
|
32
|
-
context 'signalled wake up' do
|
33
|
-
|
34
|
-
describe '#wait without timeout' do
|
35
|
-
|
36
|
-
it 'should block the thread' do
|
37
|
-
t = Thread.new { mutex.synchronize { subject.wait(mutex) } }
|
38
|
-
sleep(0.1)
|
39
|
-
t.status.should eq 'sleep'
|
40
|
-
t.kill
|
41
|
-
end
|
42
|
-
|
43
|
-
it 'should return a woken up result when is woken up by #signal' do
|
44
|
-
result = nil
|
45
|
-
t = Thread.new { mutex.synchronize { result = subject.wait(mutex) } }
|
46
|
-
sleep(0.1)
|
47
|
-
mutex.synchronize { subject.signal }
|
48
|
-
sleep(0.1)
|
49
|
-
result.should be_woken_up
|
50
|
-
result.should_not be_timed_out
|
51
|
-
result.remaining_time.should be_nil
|
52
|
-
t.status.should be_false
|
53
|
-
end
|
54
|
-
|
55
|
-
it 'should return a woken up result when is woken up by #broadcast' do
|
56
|
-
result = nil
|
57
|
-
t = Thread.new { mutex.synchronize { result = subject.wait(mutex) } }
|
58
|
-
sleep(0.1)
|
59
|
-
mutex.synchronize { subject.broadcast }
|
60
|
-
sleep(0.1)
|
61
|
-
result.should be_woken_up
|
62
|
-
result.should_not be_timed_out
|
63
|
-
result.remaining_time.should be_nil
|
64
|
-
t.status.should be_false
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
end
|
69
|
-
|
70
|
-
context 'timeout' do
|
71
|
-
|
72
|
-
describe '#wait' do
|
73
|
-
|
74
|
-
it 'should block the thread' do
|
75
|
-
t = Thread.new { mutex.synchronize { subject.wait(mutex, 1) } }
|
76
|
-
sleep(0.1)
|
77
|
-
t.status.should eq 'sleep'
|
78
|
-
t.kill
|
79
|
-
end
|
80
|
-
|
81
|
-
it 'should return remaining time when is woken up by #signal' do
|
82
|
-
result = nil
|
83
|
-
t = Thread.new { mutex.synchronize { result = subject.wait(mutex, 1) } }
|
84
|
-
sleep(0.1)
|
85
|
-
mutex.synchronize { subject.signal }
|
86
|
-
sleep(0.1)
|
87
|
-
result.should be_woken_up
|
88
|
-
result.should_not be_timed_out
|
89
|
-
result.remaining_time.should be_within(0.1).of(0.85)
|
90
|
-
t.status.should be_false
|
91
|
-
end
|
92
|
-
|
93
|
-
it 'should return remaining time when is woken up by #broadcast' do
|
94
|
-
result = nil
|
95
|
-
t = Thread.new { mutex.synchronize { result = subject.wait(mutex, 1) } }
|
96
|
-
sleep(0.1)
|
97
|
-
mutex.synchronize { subject.broadcast }
|
98
|
-
sleep(0.1)
|
99
|
-
result.should be_woken_up
|
100
|
-
result.should_not be_timed_out
|
101
|
-
result.remaining_time.should be_within(0.1).of(0.85)
|
102
|
-
t.status.should be_false
|
103
|
-
end
|
104
|
-
|
105
|
-
it 'should return 0 or negative number if timed out' do
|
106
|
-
result = nil
|
107
|
-
t = Thread.new { mutex.synchronize { result = subject.wait(mutex, 0.1) } }
|
108
|
-
sleep(0.2)
|
109
|
-
result.should_not be_woken_up
|
110
|
-
result.should be_timed_out
|
111
|
-
result.remaining_time.should be_less_than_or_equal_to(0)
|
112
|
-
t.status.should be_false
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
context 'with many waiting threads' do
|
120
|
-
|
121
|
-
context 'signalled wake up' do
|
122
|
-
|
123
|
-
describe '#wait' do
|
124
|
-
|
125
|
-
it 'should block threads' do
|
126
|
-
t1 = Thread.new { mutex.synchronize { subject.wait(mutex) } }
|
127
|
-
t2 = Thread.new { mutex.synchronize { subject.wait(mutex) } }
|
128
|
-
sleep(0.1)
|
129
|
-
[t1, t2].each { |t| t.status.should eq 'sleep' }
|
130
|
-
[t1, t2].each { |t| t.kill }
|
131
|
-
end
|
132
|
-
|
133
|
-
end
|
134
|
-
|
135
|
-
describe '#signal' do
|
136
|
-
it 'wakes up only one thread' do
|
137
|
-
latch = CountDownLatch.new(2)
|
138
|
-
|
139
|
-
t1 = Thread.new { mutex.synchronize { subject.wait(mutex); latch.count_down } }
|
140
|
-
t2 = Thread.new { mutex.synchronize { subject.wait(mutex); latch.count_down } }
|
141
|
-
|
142
|
-
sleep(0.1)
|
143
|
-
mutex.synchronize { subject.signal }
|
144
|
-
sleep(0.2)
|
145
|
-
|
146
|
-
latch.count.should eq 1
|
147
|
-
[t1, t2].each { |t| t.kill }
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
describe '#broadcast' do
|
152
|
-
it 'wakes up all threads' do
|
153
|
-
latch = CountDownLatch.new(2)
|
154
|
-
|
155
|
-
t1 = Thread.new { mutex.synchronize { subject.wait(mutex); latch.count_down } }
|
156
|
-
t2 = Thread.new { mutex.synchronize { subject.wait(mutex); latch.count_down } }
|
157
|
-
|
158
|
-
sleep(0.1)
|
159
|
-
mutex.synchronize { subject.broadcast }
|
160
|
-
sleep(0.2)
|
161
|
-
|
162
|
-
latch.count.should eq 0
|
163
|
-
[t1, t2].each { |t| t.kill }
|
164
|
-
end
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
end
|
169
|
-
|
170
|
-
end
|
171
|
-
end
|