concurrent-ruby 0.6.0 → 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 +55 -51
- data/lib/concurrent/actress/ad_hoc.rb +6 -0
- data/lib/concurrent/actress/context.rb +10 -8
- data/lib/concurrent/actress/core.rb +44 -20
- data/lib/concurrent/actress/core_delegations.rb +5 -0
- data/lib/concurrent/actress/envelope.rb +21 -5
- data/lib/concurrent/actress/reference.rb +5 -5
- data/lib/concurrent/actress.rb +152 -6
- data/lib/concurrent/agent.rb +9 -9
- 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 +7 -2
- data/lib/concurrent/executor/ruby_thread_pool_executor.rb +0 -1
- data/lib/concurrent/executor/{one_by_one.rb → serialized_execution.rb} +21 -8
- data/lib/concurrent/executor/timer_set.rb +6 -1
- data/lib/concurrent/executors.rb +1 -1
- data/lib/concurrent/logging.rb +1 -1
- data/lib/concurrent/observable.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.rb +3 -4
- data/lib/concurrent_ruby_ext.so +0 -0
- data/lib/extension_helper.rb +9 -0
- metadata +19 -152
- 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/actress/doc.md +0 -53
- 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 -191
- 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 -71
- 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 -239
- 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 -342
- data/spec/concurrent/stoppable_shared.rb +0 -37
- data/spec/concurrent/supervisor_spec.rb +0 -1148
- data/spec/concurrent/timer_task_spec.rb +0 -258
- 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 -31
- data/spec/support/example_group_extensions.rb +0 -48
- data/spec/support/less_than_or_equal_to_matcher.rb +0 -5
- /data/{LICENSE → LICENSE.txt} +0 -0
|
@@ -1,500 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
require_relative 'dereferenceable_shared'
|
|
3
|
-
require_relative 'observable_shared'
|
|
4
|
-
|
|
5
|
-
module Concurrent
|
|
6
|
-
|
|
7
|
-
describe Agent do
|
|
8
|
-
|
|
9
|
-
let(:executor) { PerThreadExecutor.new }
|
|
10
|
-
|
|
11
|
-
subject { Agent.new(0, executor: executor) }
|
|
12
|
-
|
|
13
|
-
let(:observer) do
|
|
14
|
-
Class.new do
|
|
15
|
-
attr_reader :value
|
|
16
|
-
define_method(:update) do |time, value|
|
|
17
|
-
@value = value
|
|
18
|
-
end
|
|
19
|
-
end.new
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
context '#send_off' do
|
|
23
|
-
subject { Agent.new 2 }
|
|
24
|
-
|
|
25
|
-
it 'executes post and post-off in order' do
|
|
26
|
-
subject.post { |v| v + 2 }
|
|
27
|
-
subject.post_off { |v| v * 3 }
|
|
28
|
-
subject.await
|
|
29
|
-
subject.value.should eq 12
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
context 'behavior' do
|
|
34
|
-
|
|
35
|
-
# dereferenceable
|
|
36
|
-
|
|
37
|
-
def dereferenceable_subject(value, opts = {})
|
|
38
|
-
opts = opts.merge(executor: executor)
|
|
39
|
-
Agent.new(value, opts)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def dereferenceable_observable(opts = {})
|
|
43
|
-
opts = opts.merge(executor: executor)
|
|
44
|
-
Agent.new(0, opts)
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def execute_dereferenceable(subject)
|
|
48
|
-
subject.post { |value| 10 }
|
|
49
|
-
sleep(0.1)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
it_should_behave_like :dereferenceable
|
|
53
|
-
|
|
54
|
-
# observable
|
|
55
|
-
|
|
56
|
-
subject { Agent.new(0) }
|
|
57
|
-
|
|
58
|
-
def trigger_observable(observable)
|
|
59
|
-
observable.post { nil }
|
|
60
|
-
sleep(0.1)
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
it_should_behave_like :observable
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
context '#initialize' do
|
|
67
|
-
|
|
68
|
-
let(:executor) { ImmediateExecutor.new }
|
|
69
|
-
|
|
70
|
-
it 'sets the value to the given initial state' do
|
|
71
|
-
Agent.new(10).value.should eq 10
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
it 'sets the timeout to the given value' do
|
|
75
|
-
Agent.new(0, timeout: 5).timeout.should eq 5
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
it 'sets the timeout to the default when nil' do
|
|
79
|
-
Agent.new(0).timeout.should eq Agent::TIMEOUT
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
it 'uses the executor given with the :executor option' do
|
|
83
|
-
executor.should_receive(:post).with(any_args).and_return(0)
|
|
84
|
-
agent = Agent.new(0, executor: executor)
|
|
85
|
-
agent.post { |value| 0 }
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
it 'uses the global operation pool when :operation is true' do
|
|
89
|
-
Concurrent.configuration.should_receive(:global_operation_pool).and_return(executor)
|
|
90
|
-
agent = Agent.new(0, operation: true)
|
|
91
|
-
agent.post { |value| 0 }
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
it 'uses the global task pool when :task is true' do
|
|
95
|
-
Concurrent.configuration.should_receive(:global_task_pool).and_return(executor)
|
|
96
|
-
agent = Agent.new(0, task: true)
|
|
97
|
-
agent.post { |value| 0 }
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
it 'uses the global task pool by default' do
|
|
101
|
-
Concurrent.configuration.should_receive(:global_task_pool).and_return(executor)
|
|
102
|
-
agent = Agent.new(0)
|
|
103
|
-
agent.post { |value| 0 }
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
context '#rescue' do
|
|
108
|
-
|
|
109
|
-
it 'returns self when a block is given' do
|
|
110
|
-
a1 = subject
|
|
111
|
-
a2 = a1.rescue {}
|
|
112
|
-
|
|
113
|
-
a2.should be a1
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
it 'returns self when no block is given' do
|
|
117
|
-
a1 = subject
|
|
118
|
-
a2 = a1.rescue
|
|
119
|
-
|
|
120
|
-
a2.should be a1
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
it 'accepts an exception class as the first parameter' do
|
|
124
|
-
lambda {
|
|
125
|
-
subject.rescue(StandardError) {}
|
|
126
|
-
}.should_not raise_error
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
it 'ignores rescuers without a block' do
|
|
130
|
-
subject.rescue
|
|
131
|
-
subject.instance_variable_get(:@rescuers).should be_empty
|
|
132
|
-
end
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
context '#validate' do
|
|
136
|
-
|
|
137
|
-
it 'returns self when a block is given' do
|
|
138
|
-
a1 = subject
|
|
139
|
-
a2 = a1.validate {}
|
|
140
|
-
|
|
141
|
-
a2.should be a1
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
it 'returns self when no block is given' do
|
|
145
|
-
a1 = subject
|
|
146
|
-
a2 = a1.validate
|
|
147
|
-
|
|
148
|
-
a2.should be a1
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
it 'ignores validators without a block' do
|
|
152
|
-
default_validator = subject.instance_variable_get(:@validator)
|
|
153
|
-
subject.validate
|
|
154
|
-
subject.instance_variable_get(:@validator).should be default_validator
|
|
155
|
-
end
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
context '#post' do
|
|
159
|
-
|
|
160
|
-
it 'adds the given block to the queue' do
|
|
161
|
-
executor.should_receive(:post).with(no_args).exactly(1).times
|
|
162
|
-
subject.post { sleep(1) }
|
|
163
|
-
subject.post { nil }
|
|
164
|
-
subject.post { nil }
|
|
165
|
-
sleep(0.1)
|
|
166
|
-
subject.
|
|
167
|
-
instance_variable_get(:@one_by_one).
|
|
168
|
-
instance_variable_get(:@stash).
|
|
169
|
-
size.should eq 2
|
|
170
|
-
end
|
|
171
|
-
|
|
172
|
-
it 'does not add to the queue when no block is given' do
|
|
173
|
-
executor.should_receive(:post).with(no_args).exactly(0).times
|
|
174
|
-
subject.post
|
|
175
|
-
sleep(0.1)
|
|
176
|
-
end
|
|
177
|
-
|
|
178
|
-
it 'works with ImmediateExecutor' do
|
|
179
|
-
agent = Agent.new(0, executor: ImmediateExecutor.new)
|
|
180
|
-
agent.post { |old| old + 1 }
|
|
181
|
-
agent.post { |old| old + 1 }
|
|
182
|
-
agent.value.should eq 2
|
|
183
|
-
end
|
|
184
|
-
|
|
185
|
-
end
|
|
186
|
-
|
|
187
|
-
context '#await' do
|
|
188
|
-
|
|
189
|
-
it 'waits until already sent updates are done' do
|
|
190
|
-
fn = false
|
|
191
|
-
subject.post { fn = true; sleep 0.1 }
|
|
192
|
-
subject.await
|
|
193
|
-
fn.should be_true
|
|
194
|
-
end
|
|
195
|
-
|
|
196
|
-
it 'does not waits until updates sent after are done' do
|
|
197
|
-
fn = false
|
|
198
|
-
subject.await
|
|
199
|
-
subject.post { fn = true; sleep 0.1 }
|
|
200
|
-
fn.should be_false
|
|
201
|
-
end
|
|
202
|
-
|
|
203
|
-
it 'does not alter the value' do
|
|
204
|
-
subject.post { |v| v + 1 }
|
|
205
|
-
subject.await
|
|
206
|
-
subject.value.should eq 1
|
|
207
|
-
end
|
|
208
|
-
|
|
209
|
-
end
|
|
210
|
-
|
|
211
|
-
context 'fulfillment' do
|
|
212
|
-
|
|
213
|
-
it 'process each block in the queue' do
|
|
214
|
-
@expected = []
|
|
215
|
-
subject.post { @expected << 1 }
|
|
216
|
-
subject.post { @expected << 2 }
|
|
217
|
-
subject.post { @expected << 3 }
|
|
218
|
-
sleep(0.1)
|
|
219
|
-
@expected.sort.should eq [1, 2, 3]
|
|
220
|
-
end
|
|
221
|
-
|
|
222
|
-
it 'passes the current value to the handler' do
|
|
223
|
-
@expected = nil
|
|
224
|
-
Agent.new(10, executor: executor).post { |i| @expected = i }
|
|
225
|
-
sleep(0.1)
|
|
226
|
-
@expected.should eq 10
|
|
227
|
-
end
|
|
228
|
-
|
|
229
|
-
it 'sets the value to the handler return value on success' do
|
|
230
|
-
subject.post { 100 }
|
|
231
|
-
sleep(0.1)
|
|
232
|
-
subject.value.should eq 100
|
|
233
|
-
end
|
|
234
|
-
|
|
235
|
-
it 'rejects the handler after timeout reached' do
|
|
236
|
-
agent = Agent.new(0, timeout: 0.1, executor: executor)
|
|
237
|
-
agent.post { sleep(1); 10 }
|
|
238
|
-
agent.value.should eq 0
|
|
239
|
-
end
|
|
240
|
-
end
|
|
241
|
-
|
|
242
|
-
context 'validation' do
|
|
243
|
-
|
|
244
|
-
it 'processes the validator when present' do
|
|
245
|
-
@expected = nil
|
|
246
|
-
subject.validate { @expected = 10; true }
|
|
247
|
-
subject.post { nil }
|
|
248
|
-
sleep(0.1)
|
|
249
|
-
@expected.should eq 10
|
|
250
|
-
end
|
|
251
|
-
|
|
252
|
-
it 'passes the new value to the validator' do
|
|
253
|
-
@expected = nil
|
|
254
|
-
subject.validate { |v| @expected = v; true }
|
|
255
|
-
subject.post { 10 }
|
|
256
|
-
sleep(0.1)
|
|
257
|
-
@expected.should eq 10
|
|
258
|
-
end
|
|
259
|
-
|
|
260
|
-
it 'sets the new value when the validator returns true' do
|
|
261
|
-
agent = Agent.new(0, executor: executor).validate { true }
|
|
262
|
-
agent.post { 10 }
|
|
263
|
-
sleep(0.1)
|
|
264
|
-
agent.value.should eq 10
|
|
265
|
-
end
|
|
266
|
-
|
|
267
|
-
it 'does not change the value when the validator returns false' do
|
|
268
|
-
agent = Agent.new(0, executor: executor).validate { false }
|
|
269
|
-
agent.post { 10 }
|
|
270
|
-
sleep(0.1)
|
|
271
|
-
agent.value.should eq 0
|
|
272
|
-
end
|
|
273
|
-
|
|
274
|
-
it 'does not change the value when the validator raises an exception' do
|
|
275
|
-
agent = Agent.new(0, executor: executor).validate { raise StandardError }
|
|
276
|
-
agent.post { 10 }
|
|
277
|
-
sleep(0.1)
|
|
278
|
-
agent.value.should eq 0
|
|
279
|
-
end
|
|
280
|
-
end
|
|
281
|
-
|
|
282
|
-
context 'rejection' do
|
|
283
|
-
|
|
284
|
-
it 'calls the first exception block with a matching class' do
|
|
285
|
-
@expected = nil
|
|
286
|
-
subject.
|
|
287
|
-
rescue(StandardError) { |ex| @expected = 1 }.
|
|
288
|
-
rescue(StandardError) { |ex| @expected = 2 }.
|
|
289
|
-
rescue(StandardError) { |ex| @expected = 3 }
|
|
290
|
-
subject.post { raise StandardError }
|
|
291
|
-
sleep(0.1)
|
|
292
|
-
@expected.should eq 1
|
|
293
|
-
end
|
|
294
|
-
|
|
295
|
-
it 'matches all with a rescue with no class given' do
|
|
296
|
-
@expected = nil
|
|
297
|
-
subject.
|
|
298
|
-
rescue(LoadError) { |ex| @expected = 1 }.
|
|
299
|
-
rescue { |ex| @expected = 2 }.
|
|
300
|
-
rescue(StandardError) { |ex| @expected = 3 }
|
|
301
|
-
subject.post { raise NoMethodError }
|
|
302
|
-
sleep(0.1)
|
|
303
|
-
@expected.should eq 2
|
|
304
|
-
end
|
|
305
|
-
|
|
306
|
-
it 'searches associated rescue handlers in order' do
|
|
307
|
-
@expected = nil
|
|
308
|
-
subject.
|
|
309
|
-
rescue(ArgumentError) { |ex| @expected = 1 }.
|
|
310
|
-
rescue(LoadError) { |ex| @expected = 2 }.
|
|
311
|
-
rescue(StandardError) { |ex| @expected = 3 }
|
|
312
|
-
subject.post { raise ArgumentError }
|
|
313
|
-
sleep(0.1)
|
|
314
|
-
@expected.should eq 1
|
|
315
|
-
|
|
316
|
-
@expected = nil
|
|
317
|
-
subject.
|
|
318
|
-
rescue(ArgumentError) { |ex| @expected = 1 }.
|
|
319
|
-
rescue(LoadError) { |ex| @expected = 2 }.
|
|
320
|
-
rescue(StandardError) { |ex| @expected = 3 }
|
|
321
|
-
subject.post { raise LoadError }
|
|
322
|
-
sleep(0.1)
|
|
323
|
-
@expected.should eq 2
|
|
324
|
-
|
|
325
|
-
@expected = nil
|
|
326
|
-
subject.
|
|
327
|
-
rescue(ArgumentError) { |ex| @expected = 1 }.
|
|
328
|
-
rescue(LoadError) { |ex| @expected = 2 }.
|
|
329
|
-
rescue(StandardError) { |ex| @expected = 3 }
|
|
330
|
-
subject.post { raise StandardError }
|
|
331
|
-
sleep(0.1)
|
|
332
|
-
@expected.should eq 3
|
|
333
|
-
end
|
|
334
|
-
|
|
335
|
-
it 'passes the exception object to the matched block' do
|
|
336
|
-
@expected = nil
|
|
337
|
-
subject.
|
|
338
|
-
rescue(ArgumentError) { |ex| @expected = ex }.
|
|
339
|
-
rescue(LoadError) { |ex| @expected = ex }.
|
|
340
|
-
rescue(StandardError) { |ex| @expected = ex }
|
|
341
|
-
subject.post { raise StandardError }
|
|
342
|
-
sleep(0.1)
|
|
343
|
-
@expected.should be_a(StandardError)
|
|
344
|
-
end
|
|
345
|
-
|
|
346
|
-
it 'ignores rescuers without a block' do
|
|
347
|
-
@expected = nil
|
|
348
|
-
subject.
|
|
349
|
-
rescue(StandardError).
|
|
350
|
-
rescue(StandardError) { |ex| @expected = ex }
|
|
351
|
-
subject.post { raise StandardError }
|
|
352
|
-
sleep(0.1)
|
|
353
|
-
@expected.should be_a(StandardError)
|
|
354
|
-
end
|
|
355
|
-
|
|
356
|
-
it 'supresses the exception if no rescue matches' do
|
|
357
|
-
lambda {
|
|
358
|
-
subject.
|
|
359
|
-
rescue(ArgumentError) { |ex| @expected = ex }.
|
|
360
|
-
rescue(NotImplementedError) { |ex| @expected = ex }.
|
|
361
|
-
rescue(NoMethodError) { |ex| @expected = ex }
|
|
362
|
-
subject.post { raise StandardError }
|
|
363
|
-
sleep(0.1)
|
|
364
|
-
}.should_not raise_error
|
|
365
|
-
end
|
|
366
|
-
|
|
367
|
-
it 'suppresses exceptions thrown from rescue handlers' do
|
|
368
|
-
lambda {
|
|
369
|
-
subject.rescue(StandardError) { raise StandardError }
|
|
370
|
-
subject.post { raise ArgumentError }
|
|
371
|
-
sleep(0.1)
|
|
372
|
-
}.should_not raise_error
|
|
373
|
-
end
|
|
374
|
-
end
|
|
375
|
-
|
|
376
|
-
context 'observation' do
|
|
377
|
-
|
|
378
|
-
it 'notifies all observers when the value changes' do
|
|
379
|
-
agent = Agent.new(0, executor: executor)
|
|
380
|
-
agent.add_observer(observer)
|
|
381
|
-
agent.post { 10 }
|
|
382
|
-
sleep(0.1)
|
|
383
|
-
observer.value.should eq 10
|
|
384
|
-
end
|
|
385
|
-
|
|
386
|
-
it 'does not notify removed observers when the value changes' do
|
|
387
|
-
agent = Agent.new(0, executor: executor)
|
|
388
|
-
agent.add_observer(observer)
|
|
389
|
-
agent.delete_observer(observer)
|
|
390
|
-
agent.post { 10 }
|
|
391
|
-
sleep(0.1)
|
|
392
|
-
observer.value.should be_nil
|
|
393
|
-
end
|
|
394
|
-
|
|
395
|
-
it 'does not notify observers when validation fails' do
|
|
396
|
-
agent = Agent.new(0, executor: executor)
|
|
397
|
-
agent.validate { false }
|
|
398
|
-
agent.add_observer(observer)
|
|
399
|
-
agent.post { 10 }
|
|
400
|
-
sleep(0.1)
|
|
401
|
-
observer.value.should be_nil
|
|
402
|
-
end
|
|
403
|
-
|
|
404
|
-
it 'does not notify observers when the handler raises an exception' do
|
|
405
|
-
agent = Agent.new(0, executor: executor)
|
|
406
|
-
agent.add_observer(observer)
|
|
407
|
-
agent.post { raise StandardError }
|
|
408
|
-
sleep(0.1)
|
|
409
|
-
observer.value.should be_nil
|
|
410
|
-
end
|
|
411
|
-
end
|
|
412
|
-
|
|
413
|
-
context 'clojure-like behaviour' do
|
|
414
|
-
it 'does not block dereferencing when updating the value' do
|
|
415
|
-
continue = IVar.new
|
|
416
|
-
agent = Agent.new(0, executor: executor)
|
|
417
|
-
agent.post { |old| old + continue.value }
|
|
418
|
-
sleep 0.1
|
|
419
|
-
Concurrent.timeout(0.2) { agent.value.should eq 0 }
|
|
420
|
-
continue.set 1
|
|
421
|
-
sleep 0.1
|
|
422
|
-
end
|
|
423
|
-
|
|
424
|
-
it 'does not allow to execute two updates at the same time' do
|
|
425
|
-
agent = Agent.new(0, executor: executor)
|
|
426
|
-
continue1 = IVar.new
|
|
427
|
-
continue2 = IVar.new
|
|
428
|
-
f1 = f2 = false
|
|
429
|
-
agent.post { |old| f1 = true; old + continue1.value }
|
|
430
|
-
agent.post { |old| f2 = true; old + continue2.value }
|
|
431
|
-
|
|
432
|
-
sleep 0.1
|
|
433
|
-
f1.should eq true
|
|
434
|
-
f2.should eq false
|
|
435
|
-
agent.value.should eq 0
|
|
436
|
-
|
|
437
|
-
continue1.set 1
|
|
438
|
-
sleep 0.1
|
|
439
|
-
f1.should eq true
|
|
440
|
-
f2.should eq true
|
|
441
|
-
agent.value.should eq 1
|
|
442
|
-
|
|
443
|
-
continue2.set 1
|
|
444
|
-
sleep 0.1
|
|
445
|
-
f1.should eq true
|
|
446
|
-
f2.should eq true
|
|
447
|
-
agent.value.should eq 2
|
|
448
|
-
end
|
|
449
|
-
|
|
450
|
-
it 'waits with sending functions to other agents until update is done'
|
|
451
|
-
end
|
|
452
|
-
|
|
453
|
-
context 'aliases' do
|
|
454
|
-
|
|
455
|
-
it 'aliases #deref for #value' do
|
|
456
|
-
Agent.new(10, executor: executor).deref.should eq 10
|
|
457
|
-
end
|
|
458
|
-
|
|
459
|
-
it 'aliases #validates for :validate' do
|
|
460
|
-
@expected = nil
|
|
461
|
-
subject.validates { |v| @expected = v }
|
|
462
|
-
subject.post { 10 }
|
|
463
|
-
sleep(0.1)
|
|
464
|
-
@expected.should eq 10
|
|
465
|
-
end
|
|
466
|
-
|
|
467
|
-
it 'aliases #validate_with for :validate' do
|
|
468
|
-
@expected = nil
|
|
469
|
-
subject.validate_with { |v| @expected = v }
|
|
470
|
-
subject.post { 10 }
|
|
471
|
-
sleep(0.1)
|
|
472
|
-
@expected.should eq 10
|
|
473
|
-
end
|
|
474
|
-
|
|
475
|
-
it 'aliases #validates_with for :validate' do
|
|
476
|
-
@expected = nil
|
|
477
|
-
subject.validates_with { |v| @expected = v }
|
|
478
|
-
subject.post { 10 }
|
|
479
|
-
sleep(0.1)
|
|
480
|
-
@expected.should eq 10
|
|
481
|
-
end
|
|
482
|
-
|
|
483
|
-
it 'aliases #catch for #rescue' do
|
|
484
|
-
@expected = nil
|
|
485
|
-
subject.catch { @expected = true }
|
|
486
|
-
subject.post { raise StandardError }
|
|
487
|
-
sleep(0.1)
|
|
488
|
-
@expected.should be_true
|
|
489
|
-
end
|
|
490
|
-
|
|
491
|
-
it 'aliases #on_error for #rescue' do
|
|
492
|
-
@expected = nil
|
|
493
|
-
subject.on_error { @expected = true }
|
|
494
|
-
subject.post { raise StandardError }
|
|
495
|
-
sleep(0.1)
|
|
496
|
-
@expected.should be_true
|
|
497
|
-
end
|
|
498
|
-
end
|
|
499
|
-
end
|
|
500
|
-
end
|