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,126 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Concurrent
|
4
|
-
|
5
|
-
describe RingBuffer do
|
6
|
-
|
7
|
-
let(:capacity) { 3 }
|
8
|
-
let(:buffer) { RingBuffer.new(capacity) }
|
9
|
-
|
10
|
-
def fill_buffer
|
11
|
-
capacity.times { buffer.offer 3 }
|
12
|
-
end
|
13
|
-
|
14
|
-
describe '#capacity' do
|
15
|
-
it 'returns the value passed in constructor' do
|
16
|
-
buffer.capacity.should eq capacity
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
describe '#count' do
|
21
|
-
it 'is zero when created' do
|
22
|
-
buffer.count.should eq 0
|
23
|
-
end
|
24
|
-
|
25
|
-
it 'increases when an element is added' do
|
26
|
-
buffer.offer 5
|
27
|
-
buffer.count.should eq 1
|
28
|
-
|
29
|
-
buffer.offer 1
|
30
|
-
buffer.count.should eq 2
|
31
|
-
end
|
32
|
-
|
33
|
-
it 'decreases when an element is removed' do
|
34
|
-
buffer.offer 10
|
35
|
-
buffer.poll
|
36
|
-
|
37
|
-
buffer.count.should eq 0
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
describe '#empty?' do
|
42
|
-
it 'is true when count is zero' do
|
43
|
-
buffer.empty?.should be_true
|
44
|
-
end
|
45
|
-
|
46
|
-
it 'is false when count is not zero' do
|
47
|
-
buffer.offer 82
|
48
|
-
buffer.empty?.should be_false
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
describe '#full?' do
|
53
|
-
it 'is true when count is capacity' do
|
54
|
-
fill_buffer
|
55
|
-
buffer.full?.should be_true
|
56
|
-
end
|
57
|
-
|
58
|
-
it 'is false when count is not capacity' do
|
59
|
-
buffer.full?.should be_false
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
describe '#offer' do
|
64
|
-
it 'returns false when buffer is full' do
|
65
|
-
fill_buffer
|
66
|
-
buffer.offer(3).should be_false
|
67
|
-
end
|
68
|
-
|
69
|
-
it 'returns true when the buffer is not full' do
|
70
|
-
buffer.offer(5).should be_true
|
71
|
-
end
|
72
|
-
|
73
|
-
end
|
74
|
-
|
75
|
-
describe '#poll' do
|
76
|
-
it 'returns the first added value' do
|
77
|
-
buffer.offer 'hi'
|
78
|
-
buffer.offer 'foo'
|
79
|
-
buffer.offer 'bar'
|
80
|
-
|
81
|
-
buffer.poll.should eq 'hi'
|
82
|
-
buffer.poll.should eq 'foo'
|
83
|
-
buffer.poll.should eq 'bar'
|
84
|
-
end
|
85
|
-
|
86
|
-
it 'returns nil when buffer is empty' do
|
87
|
-
buffer.poll.should be_nil
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
describe '#peek' do
|
92
|
-
context 'buffer empty' do
|
93
|
-
it 'returns nil when buffer is empty' do
|
94
|
-
buffer.peek.should be_nil
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
context 'not empty' do
|
99
|
-
|
100
|
-
before(:each) { buffer.offer 'element' }
|
101
|
-
|
102
|
-
it 'returns the first value' do
|
103
|
-
buffer.peek.should eq 'element'
|
104
|
-
end
|
105
|
-
|
106
|
-
it 'does not change buffer' do
|
107
|
-
buffer.peek
|
108
|
-
buffer.count.should eq 1
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
context 'circular condition' do
|
114
|
-
it 'can filled many times' do
|
115
|
-
fill_buffer
|
116
|
-
capacity.times { buffer.poll }
|
117
|
-
|
118
|
-
buffer.offer 'hi'
|
119
|
-
|
120
|
-
buffer.poll.should eq 'hi'
|
121
|
-
buffer.capacity.should eq capacity
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
end
|
126
|
-
end
|
@@ -1,69 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Concurrent
|
4
|
-
|
5
|
-
describe Configuration do
|
6
|
-
it 'creates a global timer pool' do
|
7
|
-
Concurrent.configuration.global_timer_set.should_not be_nil
|
8
|
-
Concurrent.configuration.global_timer_set.should respond_to(:post)
|
9
|
-
end
|
10
|
-
|
11
|
-
context 'global task pool' do
|
12
|
-
|
13
|
-
specify 'reader creates a default pool when first called if none exists' do
|
14
|
-
Concurrent.configuration.global_task_pool.should_not be_nil
|
15
|
-
Concurrent.configuration.global_task_pool.should respond_to(:post)
|
16
|
-
end
|
17
|
-
|
18
|
-
specify 'writer memoizes the given executor' do
|
19
|
-
executor = ImmediateExecutor.new
|
20
|
-
Concurrent.configure do |config|
|
21
|
-
config.global_task_pool = executor
|
22
|
-
end
|
23
|
-
Concurrent.configuration.global_task_pool.should eq executor
|
24
|
-
end
|
25
|
-
|
26
|
-
specify 'writer raises an exception if called after initialization' do
|
27
|
-
executor = ImmediateExecutor.new
|
28
|
-
Concurrent.configure do |config|
|
29
|
-
config.global_task_pool = executor
|
30
|
-
end
|
31
|
-
Concurrent.configuration.global_task_pool
|
32
|
-
expect {
|
33
|
-
Concurrent.configure do |config|
|
34
|
-
config.global_task_pool = executor
|
35
|
-
end
|
36
|
-
}.to raise_error(ConfigurationError)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
context 'global operation pool' do
|
41
|
-
|
42
|
-
specify 'reader creates a default pool when first called if none exists' do
|
43
|
-
Concurrent.configuration.global_operation_pool.should_not be_nil
|
44
|
-
Concurrent.configuration.global_operation_pool.should respond_to(:post)
|
45
|
-
end
|
46
|
-
|
47
|
-
specify 'writer memoizes the given executor' do
|
48
|
-
executor = ImmediateExecutor.new
|
49
|
-
Concurrent.configure do |config|
|
50
|
-
config.global_operation_pool = executor
|
51
|
-
end
|
52
|
-
Concurrent.configuration.global_operation_pool.should eq executor
|
53
|
-
end
|
54
|
-
|
55
|
-
specify 'writer raises an exception if called after initialization' do
|
56
|
-
executor = ImmediateExecutor.new
|
57
|
-
Concurrent.configure do |config|
|
58
|
-
config.global_operation_pool = executor
|
59
|
-
end
|
60
|
-
Concurrent.configuration.global_operation_pool
|
61
|
-
expect {
|
62
|
-
Concurrent.configure do |config|
|
63
|
-
config.global_operation_pool = executor
|
64
|
-
end
|
65
|
-
}.to raise_error(ConfigurationError)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
@@ -1,242 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Concurrent
|
4
|
-
|
5
|
-
describe 'dataflow' do
|
6
|
-
|
7
|
-
let(:executor) { ImmediateExecutor.new }
|
8
|
-
let(:root_executor) { PerThreadExecutor.new }
|
9
|
-
|
10
|
-
it 'raises an exception when no block given' do
|
11
|
-
expect { Concurrent::dataflow }.to raise_error(ArgumentError)
|
12
|
-
expect { Concurrent::dataflow_with(root_executor) }.to raise_error(ArgumentError)
|
13
|
-
end
|
14
|
-
|
15
|
-
specify '#dataflow uses the global task pool' do
|
16
|
-
input = Future.execute{0}
|
17
|
-
Concurrent.should_receive(:dataflow_with).once.
|
18
|
-
with(Concurrent.configuration.global_task_pool, input)
|
19
|
-
Concurrent::dataflow(input){0}
|
20
|
-
end
|
21
|
-
|
22
|
-
specify '#dataflow_with uses the given executor' do
|
23
|
-
input = Future.execute{0}
|
24
|
-
result = Future.new{0}
|
25
|
-
|
26
|
-
Future.should_receive(:new).with(executor: root_executor).and_return(result)
|
27
|
-
Concurrent::dataflow_with(root_executor, input){0}
|
28
|
-
end
|
29
|
-
|
30
|
-
specify '#dataflow_with raises an exception when no executor given' do
|
31
|
-
expect {
|
32
|
-
Concurrent::dataflow_with(nil){ nil }
|
33
|
-
}.to raise_error(ArgumentError)
|
34
|
-
end
|
35
|
-
|
36
|
-
it 'accepts zero or more dependencies' do
|
37
|
-
Concurrent::dataflow(){0}
|
38
|
-
Concurrent::dataflow(Future.execute{0}){0}
|
39
|
-
Concurrent::dataflow(Future.execute{0}, Future.execute{0}){0}
|
40
|
-
|
41
|
-
Concurrent::dataflow_with(root_executor, ){0}
|
42
|
-
Concurrent::dataflow_with(root_executor, Future.execute{0}){0}
|
43
|
-
Concurrent::dataflow_with(root_executor, Future.execute{0}, Future.execute{0}){0}
|
44
|
-
end
|
45
|
-
|
46
|
-
it 'accepts uncompleted dependencies' do
|
47
|
-
d = Future.new(executor: executor){0}
|
48
|
-
Concurrent::dataflow(d){0}
|
49
|
-
d.execute
|
50
|
-
|
51
|
-
d = Future.new(executor: executor){0}
|
52
|
-
Concurrent::dataflow_with(root_executor, d){0}
|
53
|
-
d.execute
|
54
|
-
end
|
55
|
-
|
56
|
-
it 'accepts completed dependencies' do
|
57
|
-
d = Future.new(executor: executor){0}
|
58
|
-
d.execute
|
59
|
-
Concurrent::dataflow(d){0}
|
60
|
-
|
61
|
-
d = Future.new(executor: executor){0}
|
62
|
-
d.execute
|
63
|
-
Concurrent::dataflow_with(root_executor, d){0}
|
64
|
-
end
|
65
|
-
|
66
|
-
it 'raises an exception if any dependencies are not IVars' do
|
67
|
-
expect { Concurrent::dataflow(nil) }.to raise_error(ArgumentError)
|
68
|
-
expect { Concurrent::dataflow(Future.execute{0}, nil) }.to raise_error(ArgumentError)
|
69
|
-
expect { Concurrent::dataflow(nil, Future.execute{0}) }.to raise_error(ArgumentError)
|
70
|
-
|
71
|
-
expect { Concurrent::dataflow_with(root_executor, nil) }.to raise_error(ArgumentError)
|
72
|
-
expect { Concurrent::dataflow_with(root_executor, Future.execute{0}, nil) }.to raise_error(ArgumentError)
|
73
|
-
expect { Concurrent::dataflow_with(root_executor, nil, Future.execute{0}) }.to raise_error(ArgumentError)
|
74
|
-
end
|
75
|
-
|
76
|
-
it 'returns a Future' do
|
77
|
-
Concurrent::dataflow{0}.should be_a(Future)
|
78
|
-
Concurrent::dataflow{0}.should be_a(Future)
|
79
|
-
end
|
80
|
-
|
81
|
-
context 'does not schedule the Future' do
|
82
|
-
|
83
|
-
specify 'if no dependencies are completed' do
|
84
|
-
d = Future.new(executor: executor){0}
|
85
|
-
f = Concurrent::dataflow(d){0}
|
86
|
-
f.should be_unscheduled
|
87
|
-
d.execute
|
88
|
-
|
89
|
-
d = Future.new(executor: executor){0}
|
90
|
-
f = Concurrent::dataflow_with(root_executor, d){0}
|
91
|
-
f.should be_unscheduled
|
92
|
-
d.execute
|
93
|
-
end
|
94
|
-
|
95
|
-
specify 'if one dependency of two is completed' do
|
96
|
-
d1 = Future.new(executor: executor){0}
|
97
|
-
d2 = Future.new(executor: executor){0}
|
98
|
-
f = Concurrent::dataflow(d1, d2){0}
|
99
|
-
d1.execute
|
100
|
-
f.should be_unscheduled
|
101
|
-
d2.execute
|
102
|
-
|
103
|
-
d1 = Future.new(executor: executor){0}
|
104
|
-
d2 = Future.new(executor: executor){0}
|
105
|
-
f = Concurrent::dataflow_with(root_executor, d1, d2){0}
|
106
|
-
d1.execute
|
107
|
-
f.should be_unscheduled
|
108
|
-
d2.execute
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
context 'schedules the Future when all dependencies are available' do
|
113
|
-
|
114
|
-
specify 'if there is just one' do
|
115
|
-
d = Future.new(executor: executor){0}
|
116
|
-
f = Concurrent::dataflow(d){0}
|
117
|
-
d.execute
|
118
|
-
f.value.should eq 0
|
119
|
-
|
120
|
-
d = Future.new(executor: executor){0}
|
121
|
-
f = Concurrent::dataflow_with(root_executor, d){0}
|
122
|
-
d.execute
|
123
|
-
f.value.should eq 0
|
124
|
-
end
|
125
|
-
|
126
|
-
specify 'if there is more than one' do
|
127
|
-
d1 = Future.new(executor: executor){0}
|
128
|
-
d2 = Future.new(executor: executor){0}
|
129
|
-
f = Concurrent::dataflow(d1, d2){0}
|
130
|
-
d1.execute
|
131
|
-
d2.execute
|
132
|
-
f.value.should eq 0
|
133
|
-
|
134
|
-
d1 = Future.new(executor: executor){0}
|
135
|
-
d2 = Future.new(executor: executor){0}
|
136
|
-
f = Concurrent::dataflow_with(root_executor, d1, d2){0}
|
137
|
-
d1.execute
|
138
|
-
d2.execute
|
139
|
-
f.value.should eq 0
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
context 'counts already executed dependencies' do
|
144
|
-
|
145
|
-
specify 'if there is just one' do
|
146
|
-
d = Future.new(executor: executor){0}
|
147
|
-
d.execute
|
148
|
-
f = Concurrent::dataflow(d){0}
|
149
|
-
f.value.should eq 0
|
150
|
-
|
151
|
-
d = Future.new(executor: executor){0}
|
152
|
-
d.execute
|
153
|
-
f = Concurrent::dataflow_with(root_executor, d){0}
|
154
|
-
f.value.should eq 0
|
155
|
-
end
|
156
|
-
|
157
|
-
specify 'if there is more than one' do
|
158
|
-
d1 = Future.new(executor: executor){0}
|
159
|
-
d2 = Future.new(executor: executor){0}
|
160
|
-
d1.execute
|
161
|
-
d2.execute
|
162
|
-
f = Concurrent::dataflow(d1, d2){0}
|
163
|
-
f.value.should eq 0
|
164
|
-
|
165
|
-
d1 = Future.new(executor: executor){0}
|
166
|
-
d2 = Future.new(executor: executor){0}
|
167
|
-
d1.execute
|
168
|
-
d2.execute
|
169
|
-
f = Concurrent::dataflow_with(root_executor, d1, d2){0}
|
170
|
-
f.value.should eq 0
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
context 'passes the values of dependencies into the block' do
|
175
|
-
|
176
|
-
specify 'if there is just one' do
|
177
|
-
d = Future.new(executor: executor){14}
|
178
|
-
f = Concurrent::dataflow(d){|v| v }
|
179
|
-
d.execute
|
180
|
-
f.value.should eq 14
|
181
|
-
|
182
|
-
d = Future.new(executor: executor){14}
|
183
|
-
f = Concurrent::dataflow_with(root_executor, d){|v| v }
|
184
|
-
d.execute
|
185
|
-
f.value.should eq 14
|
186
|
-
end
|
187
|
-
|
188
|
-
specify 'if there is more than one' do
|
189
|
-
d1 = Future.new(executor: executor){14}
|
190
|
-
d2 = Future.new(executor: executor){2}
|
191
|
-
f = Concurrent::dataflow(d1, d2) {|v1, v2| v1 + v2}
|
192
|
-
d1.execute
|
193
|
-
d2.execute
|
194
|
-
f.value.should eq 16
|
195
|
-
|
196
|
-
d1 = Future.new(executor: executor){14}
|
197
|
-
d2 = Future.new(executor: executor){2}
|
198
|
-
f = Concurrent::dataflow_with(root_executor, d1, d2) {|v1, v2| v1 + v2}
|
199
|
-
d1.execute
|
200
|
-
d2.execute
|
201
|
-
f.value.should eq 16
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
context 'module function' do
|
206
|
-
|
207
|
-
it 'can be called as Concurrent.dataflow and Concurrent.dataflow_with' do
|
208
|
-
|
209
|
-
def fib_with_dot(n)
|
210
|
-
if n < 2
|
211
|
-
Concurrent.dataflow { n }
|
212
|
-
else
|
213
|
-
n1 = fib_with_dot(n - 1)
|
214
|
-
n2 = fib_with_dot(n - 2)
|
215
|
-
Concurrent.dataflow_with(root_executor, n1, n2) { n1.value + n2.value }
|
216
|
-
end
|
217
|
-
end
|
218
|
-
|
219
|
-
expected = fib_with_dot(14)
|
220
|
-
sleep(0.1)
|
221
|
-
expected.value.should eq 377
|
222
|
-
end
|
223
|
-
|
224
|
-
it 'can be called as Concurrent::dataflow and Concurrent::dataflow_with' do
|
225
|
-
|
226
|
-
def fib_with_colons(n)
|
227
|
-
if n < 2
|
228
|
-
Concurrent::dataflow { n }
|
229
|
-
else
|
230
|
-
n1 = fib_with_colons(n - 1)
|
231
|
-
n2 = fib_with_colons(n - 2)
|
232
|
-
Concurrent::dataflow_with(root_executor, n1, n2) { n1.value + n2.value }
|
233
|
-
end
|
234
|
-
end
|
235
|
-
|
236
|
-
expected = fib_with_colons(14)
|
237
|
-
sleep(0.1)
|
238
|
-
expected.value.should eq 377
|
239
|
-
end
|
240
|
-
end
|
241
|
-
end
|
242
|
-
end
|
@@ -1,91 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require_relative 'dereferenceable_shared'
|
3
|
-
require_relative 'obligation_shared'
|
4
|
-
|
5
|
-
module Concurrent
|
6
|
-
|
7
|
-
describe Delay do
|
8
|
-
|
9
|
-
context 'behavior' do
|
10
|
-
|
11
|
-
# dereferenceable
|
12
|
-
|
13
|
-
def dereferenceable_subject(value, opts = {})
|
14
|
-
delay = Delay.new(opts){ value }
|
15
|
-
delay.tap{ delay.value }
|
16
|
-
end
|
17
|
-
|
18
|
-
it_should_behave_like :dereferenceable
|
19
|
-
|
20
|
-
# obligation
|
21
|
-
|
22
|
-
let!(:fulfilled_value) { 10 }
|
23
|
-
let!(:rejected_reason) { StandardError.new('mojo jojo') }
|
24
|
-
|
25
|
-
let(:pending_subject) do
|
26
|
-
Delay.new{ fulfilled_value }
|
27
|
-
end
|
28
|
-
|
29
|
-
let(:fulfilled_subject) do
|
30
|
-
delay = Delay.new{ fulfilled_value }
|
31
|
-
delay.tap{ delay.value }
|
32
|
-
end
|
33
|
-
|
34
|
-
let(:rejected_subject) do
|
35
|
-
delay = Delay.new{ raise rejected_reason }
|
36
|
-
delay.tap{ delay.value }
|
37
|
-
end
|
38
|
-
|
39
|
-
it_should_behave_like :obligation
|
40
|
-
end
|
41
|
-
|
42
|
-
context '#initialize' do
|
43
|
-
|
44
|
-
it 'sets the state to :pending' do
|
45
|
-
Delay.new{ nil }.state.should eq :pending
|
46
|
-
Delay.new{ nil }.should be_pending
|
47
|
-
end
|
48
|
-
|
49
|
-
it 'raises an exception when no block given' do
|
50
|
-
expect {
|
51
|
-
Delay.new
|
52
|
-
}.to raise_error(ArgumentError)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
|
57
|
-
context '#reconfigure' do
|
58
|
-
it 'returns value of block used in reconfiguration' do
|
59
|
-
Delay.new { nil }.tap { |d| d.reconfigure { true } }.value.should be_true
|
60
|
-
end
|
61
|
-
|
62
|
-
it 'returns false when process completed?' do
|
63
|
-
d = Delay.new { 1 }
|
64
|
-
d.reconfigure { 2 }.should be_true
|
65
|
-
d.value.should be 2
|
66
|
-
d.reconfigure { 3 }.should be_false
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
context '#value' do
|
71
|
-
|
72
|
-
let(:task){ proc{ nil } }
|
73
|
-
|
74
|
-
it 'does not call the block before #value is called' do
|
75
|
-
task.should_not_receive(:call).with(any_args)
|
76
|
-
Delay.new(&task)
|
77
|
-
end
|
78
|
-
|
79
|
-
it 'calls the block when #value is called' do
|
80
|
-
task.should_receive(:call).once.with(any_args).and_return(nil)
|
81
|
-
Delay.new(&task).value
|
82
|
-
end
|
83
|
-
|
84
|
-
it 'only calls the block once no matter how often #value is called' do
|
85
|
-
task.should_receive(:call).once.with(any_args).and_return(nil)
|
86
|
-
delay = Delay.new(&task)
|
87
|
-
5.times{ delay.value }
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|