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.
Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +55 -51
  3. data/lib/concurrent/actress/ad_hoc.rb +6 -0
  4. data/lib/concurrent/actress/context.rb +10 -8
  5. data/lib/concurrent/actress/core.rb +44 -20
  6. data/lib/concurrent/actress/core_delegations.rb +5 -0
  7. data/lib/concurrent/actress/envelope.rb +21 -5
  8. data/lib/concurrent/actress/reference.rb +5 -5
  9. data/lib/concurrent/actress.rb +152 -6
  10. data/lib/concurrent/agent.rb +9 -9
  11. data/lib/concurrent/atomic.rb +46 -0
  12. data/lib/concurrent/atomic_reference/concurrent_update_error.rb +7 -0
  13. data/lib/concurrent/atomic_reference/delegated_update.rb +28 -0
  14. data/lib/concurrent/atomic_reference/direct_update.rb +28 -0
  15. data/lib/concurrent/atomic_reference/jruby.rb +8 -0
  16. data/lib/concurrent/atomic_reference/mutex_atomic.rb +47 -0
  17. data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +24 -0
  18. data/lib/concurrent/atomic_reference/rbx.rb +16 -0
  19. data/lib/concurrent/atomic_reference/ruby.rb +16 -0
  20. data/lib/concurrent/atomics.rb +1 -1
  21. data/lib/concurrent/configuration.rb +7 -2
  22. data/lib/concurrent/executor/ruby_thread_pool_executor.rb +0 -1
  23. data/lib/concurrent/executor/{one_by_one.rb → serialized_execution.rb} +21 -8
  24. data/lib/concurrent/executor/timer_set.rb +6 -1
  25. data/lib/concurrent/executors.rb +1 -1
  26. data/lib/concurrent/logging.rb +1 -1
  27. data/lib/concurrent/observable.rb +1 -1
  28. data/lib/concurrent/supervisor.rb +1 -1
  29. data/lib/concurrent/timer_task.rb +0 -36
  30. data/lib/concurrent/version.rb +1 -1
  31. data/lib/concurrent.rb +3 -4
  32. data/lib/concurrent_ruby_ext.so +0 -0
  33. data/lib/extension_helper.rb +9 -0
  34. metadata +19 -152
  35. data/lib/concurrent/actor/actor.rb +0 -270
  36. data/lib/concurrent/actor/postable.rb +0 -102
  37. data/lib/concurrent/actors.rb +0 -2
  38. data/lib/concurrent/actress/doc.md +0 -53
  39. data/lib/concurrent/atomic/atomic.rb +0 -48
  40. data/lib/concurrent/runnable.rb +0 -90
  41. data/lib/concurrent/stoppable.rb +0 -20
  42. data/spec/concurrent/actor/actor_spec.rb +0 -376
  43. data/spec/concurrent/actor/postable_shared.rb +0 -218
  44. data/spec/concurrent/actress_spec.rb +0 -191
  45. data/spec/concurrent/agent_spec.rb +0 -500
  46. data/spec/concurrent/async_spec.rb +0 -352
  47. data/spec/concurrent/atomic/atomic_boolean_spec.rb +0 -172
  48. data/spec/concurrent/atomic/atomic_fixnum_spec.rb +0 -186
  49. data/spec/concurrent/atomic/atomic_spec.rb +0 -133
  50. data/spec/concurrent/atomic/condition_spec.rb +0 -171
  51. data/spec/concurrent/atomic/copy_on_notify_observer_set_spec.rb +0 -10
  52. data/spec/concurrent/atomic/copy_on_write_observer_set_spec.rb +0 -10
  53. data/spec/concurrent/atomic/count_down_latch_spec.rb +0 -151
  54. data/spec/concurrent/atomic/cyclic_barrier_spec.rb +0 -248
  55. data/spec/concurrent/atomic/event_spec.rb +0 -200
  56. data/spec/concurrent/atomic/observer_set_shared.rb +0 -242
  57. data/spec/concurrent/atomic/thread_local_var_spec.rb +0 -113
  58. data/spec/concurrent/channel/buffered_channel_spec.rb +0 -151
  59. data/spec/concurrent/channel/channel_spec.rb +0 -39
  60. data/spec/concurrent/channel/probe_spec.rb +0 -77
  61. data/spec/concurrent/channel/unbuffered_channel_spec.rb +0 -132
  62. data/spec/concurrent/collection/blocking_ring_buffer_spec.rb +0 -149
  63. data/spec/concurrent/collection/priority_queue_spec.rb +0 -317
  64. data/spec/concurrent/collection/ring_buffer_spec.rb +0 -126
  65. data/spec/concurrent/configuration_spec.rb +0 -71
  66. data/spec/concurrent/dataflow_spec.rb +0 -242
  67. data/spec/concurrent/delay_spec.rb +0 -91
  68. data/spec/concurrent/dereferenceable_shared.rb +0 -146
  69. data/spec/concurrent/exchanger_spec.rb +0 -66
  70. data/spec/concurrent/executor/cached_thread_pool_shared.rb +0 -115
  71. data/spec/concurrent/executor/fixed_thread_pool_shared.rb +0 -136
  72. data/spec/concurrent/executor/global_thread_pool_shared.rb +0 -35
  73. data/spec/concurrent/executor/immediate_executor_spec.rb +0 -12
  74. data/spec/concurrent/executor/java_cached_thread_pool_spec.rb +0 -44
  75. data/spec/concurrent/executor/java_fixed_thread_pool_spec.rb +0 -64
  76. data/spec/concurrent/executor/java_single_thread_executor_spec.rb +0 -21
  77. data/spec/concurrent/executor/java_thread_pool_executor_spec.rb +0 -71
  78. data/spec/concurrent/executor/per_thread_executor_spec.rb +0 -57
  79. data/spec/concurrent/executor/ruby_cached_thread_pool_spec.rb +0 -69
  80. data/spec/concurrent/executor/ruby_fixed_thread_pool_spec.rb +0 -39
  81. data/spec/concurrent/executor/ruby_single_thread_executor_spec.rb +0 -18
  82. data/spec/concurrent/executor/ruby_thread_pool_executor_spec.rb +0 -171
  83. data/spec/concurrent/executor/safe_task_executor_spec.rb +0 -103
  84. data/spec/concurrent/executor/thread_pool_class_cast_spec.rb +0 -52
  85. data/spec/concurrent/executor/thread_pool_executor_shared.rb +0 -155
  86. data/spec/concurrent/executor/thread_pool_shared.rb +0 -239
  87. data/spec/concurrent/executor/timer_set_spec.rb +0 -183
  88. data/spec/concurrent/future_spec.rb +0 -329
  89. data/spec/concurrent/ivar_spec.rb +0 -215
  90. data/spec/concurrent/mvar_spec.rb +0 -380
  91. data/spec/concurrent/obligation_shared.rb +0 -102
  92. data/spec/concurrent/obligation_spec.rb +0 -282
  93. data/spec/concurrent/observable_shared.rb +0 -177
  94. data/spec/concurrent/observable_spec.rb +0 -56
  95. data/spec/concurrent/options_parser_spec.rb +0 -71
  96. data/spec/concurrent/promise_spec.rb +0 -367
  97. data/spec/concurrent/runnable_shared.rb +0 -68
  98. data/spec/concurrent/runnable_spec.rb +0 -235
  99. data/spec/concurrent/scheduled_task_spec.rb +0 -342
  100. data/spec/concurrent/stoppable_shared.rb +0 -37
  101. data/spec/concurrent/supervisor_spec.rb +0 -1148
  102. data/spec/concurrent/timer_task_spec.rb +0 -258
  103. data/spec/concurrent/tvar_spec.rb +0 -137
  104. data/spec/concurrent/utility/processor_count_spec.rb +0 -20
  105. data/spec/concurrent/utility/timeout_spec.rb +0 -50
  106. data/spec/concurrent/utility/timer_spec.rb +0 -52
  107. data/spec/spec_helper.rb +0 -31
  108. data/spec/support/example_group_extensions.rb +0 -48
  109. data/spec/support/less_than_or_equal_to_matcher.rb +0 -5
  110. /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