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.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/concurrent.rb +3 -4
  4. data/lib/concurrent/atomic.rb +46 -0
  5. data/lib/concurrent/atomic_reference/concurrent_update_error.rb +7 -0
  6. data/lib/concurrent/atomic_reference/delegated_update.rb +28 -0
  7. data/lib/concurrent/atomic_reference/direct_update.rb +28 -0
  8. data/lib/concurrent/atomic_reference/jruby.rb +8 -0
  9. data/lib/concurrent/atomic_reference/mutex_atomic.rb +47 -0
  10. data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +24 -0
  11. data/lib/concurrent/atomic_reference/rbx.rb +16 -0
  12. data/lib/concurrent/atomic_reference/ruby.rb +16 -0
  13. data/lib/concurrent/atomics.rb +1 -1
  14. data/lib/concurrent/configuration.rb +1 -1
  15. data/lib/concurrent/supervisor.rb +1 -1
  16. data/lib/concurrent/timer_task.rb +0 -36
  17. data/lib/concurrent/version.rb +1 -1
  18. data/lib/concurrent_ruby_ext.so +0 -0
  19. data/lib/extension_helper.rb +9 -0
  20. metadata +16 -148
  21. data/lib/concurrent/actor/actor.rb +0 -270
  22. data/lib/concurrent/actor/postable.rb +0 -102
  23. data/lib/concurrent/actors.rb +0 -2
  24. data/lib/concurrent/atomic/atomic.rb +0 -48
  25. data/lib/concurrent/runnable.rb +0 -90
  26. data/lib/concurrent/stoppable.rb +0 -20
  27. data/spec/concurrent/actor/actor_spec.rb +0 -376
  28. data/spec/concurrent/actor/postable_shared.rb +0 -218
  29. data/spec/concurrent/actress_spec.rb +0 -211
  30. data/spec/concurrent/agent_spec.rb +0 -500
  31. data/spec/concurrent/async_spec.rb +0 -352
  32. data/spec/concurrent/atomic/atomic_boolean_spec.rb +0 -172
  33. data/spec/concurrent/atomic/atomic_fixnum_spec.rb +0 -186
  34. data/spec/concurrent/atomic/atomic_spec.rb +0 -133
  35. data/spec/concurrent/atomic/condition_spec.rb +0 -171
  36. data/spec/concurrent/atomic/copy_on_notify_observer_set_spec.rb +0 -10
  37. data/spec/concurrent/atomic/copy_on_write_observer_set_spec.rb +0 -10
  38. data/spec/concurrent/atomic/count_down_latch_spec.rb +0 -151
  39. data/spec/concurrent/atomic/cyclic_barrier_spec.rb +0 -248
  40. data/spec/concurrent/atomic/event_spec.rb +0 -200
  41. data/spec/concurrent/atomic/observer_set_shared.rb +0 -242
  42. data/spec/concurrent/atomic/thread_local_var_spec.rb +0 -113
  43. data/spec/concurrent/channel/buffered_channel_spec.rb +0 -151
  44. data/spec/concurrent/channel/channel_spec.rb +0 -39
  45. data/spec/concurrent/channel/probe_spec.rb +0 -77
  46. data/spec/concurrent/channel/unbuffered_channel_spec.rb +0 -132
  47. data/spec/concurrent/collection/blocking_ring_buffer_spec.rb +0 -149
  48. data/spec/concurrent/collection/priority_queue_spec.rb +0 -317
  49. data/spec/concurrent/collection/ring_buffer_spec.rb +0 -126
  50. data/spec/concurrent/configuration_spec.rb +0 -69
  51. data/spec/concurrent/dataflow_spec.rb +0 -242
  52. data/spec/concurrent/delay_spec.rb +0 -91
  53. data/spec/concurrent/dereferenceable_shared.rb +0 -146
  54. data/spec/concurrent/exchanger_spec.rb +0 -66
  55. data/spec/concurrent/executor/cached_thread_pool_shared.rb +0 -115
  56. data/spec/concurrent/executor/fixed_thread_pool_shared.rb +0 -136
  57. data/spec/concurrent/executor/global_thread_pool_shared.rb +0 -35
  58. data/spec/concurrent/executor/immediate_executor_spec.rb +0 -12
  59. data/spec/concurrent/executor/java_cached_thread_pool_spec.rb +0 -44
  60. data/spec/concurrent/executor/java_fixed_thread_pool_spec.rb +0 -64
  61. data/spec/concurrent/executor/java_single_thread_executor_spec.rb +0 -21
  62. data/spec/concurrent/executor/java_thread_pool_executor_spec.rb +0 -71
  63. data/spec/concurrent/executor/per_thread_executor_spec.rb +0 -57
  64. data/spec/concurrent/executor/ruby_cached_thread_pool_spec.rb +0 -69
  65. data/spec/concurrent/executor/ruby_fixed_thread_pool_spec.rb +0 -39
  66. data/spec/concurrent/executor/ruby_single_thread_executor_spec.rb +0 -18
  67. data/spec/concurrent/executor/ruby_thread_pool_executor_spec.rb +0 -171
  68. data/spec/concurrent/executor/safe_task_executor_spec.rb +0 -103
  69. data/spec/concurrent/executor/thread_pool_class_cast_spec.rb +0 -52
  70. data/spec/concurrent/executor/thread_pool_executor_shared.rb +0 -155
  71. data/spec/concurrent/executor/thread_pool_shared.rb +0 -269
  72. data/spec/concurrent/executor/timer_set_spec.rb +0 -183
  73. data/spec/concurrent/future_spec.rb +0 -329
  74. data/spec/concurrent/ivar_spec.rb +0 -215
  75. data/spec/concurrent/mvar_spec.rb +0 -380
  76. data/spec/concurrent/obligation_shared.rb +0 -102
  77. data/spec/concurrent/obligation_spec.rb +0 -282
  78. data/spec/concurrent/observable_shared.rb +0 -177
  79. data/spec/concurrent/observable_spec.rb +0 -56
  80. data/spec/concurrent/options_parser_spec.rb +0 -71
  81. data/spec/concurrent/promise_spec.rb +0 -367
  82. data/spec/concurrent/runnable_shared.rb +0 -68
  83. data/spec/concurrent/runnable_spec.rb +0 -235
  84. data/spec/concurrent/scheduled_task_spec.rb +0 -340
  85. data/spec/concurrent/stoppable_shared.rb +0 -37
  86. data/spec/concurrent/supervisor_spec.rb +0 -1149
  87. data/spec/concurrent/timer_task_spec.rb +0 -256
  88. data/spec/concurrent/tvar_spec.rb +0 -137
  89. data/spec/concurrent/utility/processor_count_spec.rb +0 -20
  90. data/spec/concurrent/utility/timeout_spec.rb +0 -50
  91. data/spec/concurrent/utility/timer_spec.rb +0 -52
  92. data/spec/spec_helper.rb +0 -41
  93. data/spec/support/example_group_extensions.rb +0 -52
  94. data/spec/support/less_than_or_equal_to_matcher.rb +0 -5
@@ -1,183 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Concurrent
4
-
5
- describe TimerSet do
6
-
7
- subject{ TimerSet.new(executor: ImmediateExecutor.new) }
8
-
9
- after(:each){ subject.kill }
10
-
11
- it 'uses the executor given at construction' do
12
- executor = double(:executor)
13
- executor.should_receive(:post).with(no_args)
14
- subject = TimerSet.new(executor: executor)
15
- subject.post(0){ nil }
16
- sleep(0.1)
17
- end
18
-
19
- it 'uses the global task pool be default' do
20
- Concurrent.configuration.global_task_pool.should_receive(:post).with(no_args)
21
- subject = TimerSet.new
22
- subject.post(0){ nil }
23
- sleep(0.1)
24
- end
25
-
26
- it 'executes a given task when given a Time' do
27
- latch = CountDownLatch.new(1)
28
- subject.post(Time.now + 0.1){ latch.count_down }
29
- latch.wait(0.2).should be_true
30
- end
31
-
32
- it 'executes a given task when given an interval in seconds' do
33
- latch = CountDownLatch.new(1)
34
- subject.post(0.1){ latch.count_down }
35
- latch.wait(0.2).should be_true
36
- end
37
-
38
- it 'passes all arguments to the task on execution' do
39
- expected = nil
40
- latch = CountDownLatch.new(1)
41
- subject.post(0.1, 1, 2, 3) do |*args|
42
- expected = args
43
- latch.count_down
44
- end
45
- latch.wait(0.2).should be_true
46
- expected.should eq [1, 2, 3]
47
- end
48
-
49
- it 'immediately posts a task when the delay is zero' do
50
- Thread.should_not_receive(:new).with(any_args)
51
- subject.post(0){ true }
52
- end
53
-
54
- it 'does not execute tasks early' do
55
- expected = AtomicFixnum.new(0)
56
- subject.post(0.2){ expected.increment }
57
- sleep(0.15)
58
- expected.value.should eq 0
59
- sleep(0.10)
60
- expected.value.should eq 1
61
- end
62
-
63
- it 'raises an exception when given a task with a past Time value' do
64
- expect {
65
- subject.post(Time.now - 10){ nil }
66
- }.to raise_error(ArgumentError)
67
- end
68
-
69
- it 'raises an exception when given a task with a delay less than zero' do
70
- expect {
71
- subject.post(-10){ nil }
72
- }.to raise_error(ArgumentError)
73
- end
74
-
75
- it 'raises an exception when no block given' do
76
- expect {
77
- subject.post(10)
78
- }.to raise_error(ArgumentError)
79
- end
80
-
81
- it 'executes all tasks scheduled for the same time' do
82
- latch = CountDownLatch.new(5)
83
- 5.times{ subject.post(0.1){ latch.count_down } }
84
- latch.wait(0.2).should be_true
85
- end
86
-
87
- it 'executes tasks with different times in schedule order' do
88
- expected = []
89
- 3.times{|i| subject.post(i/10){ expected << i } }
90
- sleep(0.3)
91
- expected.should eq [0, 1, 2]
92
- end
93
-
94
- it 'cancels all pending tasks on #shutdown' do
95
- expected = AtomicFixnum.new(0)
96
- 10.times{ subject.post(0.2){ expected.increment } }
97
- sleep(0.1)
98
- subject.shutdown
99
- sleep(0.2)
100
- expected.value.should eq 0
101
- end
102
-
103
- it 'cancels all pending tasks on #kill' do
104
- expected = AtomicFixnum.new(0)
105
- 10.times{ subject.post(0.2){ expected.increment } }
106
- sleep(0.1)
107
- subject.kill
108
- sleep(0.2)
109
- expected.value.should eq 0
110
- end
111
-
112
- it 'stops the monitor thread on #shutdown' do
113
- timer_executor = subject.instance_variable_get(:@timer_executor)
114
- subject.shutdown
115
- sleep(0.1)
116
- timer_executor.should_not be_running
117
- end
118
-
119
- it 'kills the monitor thread on #kill' do
120
- timer_executor = subject.instance_variable_get(:@timer_executor)
121
- subject.kill
122
- sleep(0.1)
123
- timer_executor.should_not be_running
124
- end
125
-
126
- it 'rejects tasks once shutdown' do
127
- expected = AtomicFixnum.new(0)
128
- subject.shutdown
129
- sleep(0.1)
130
- subject.post(0){ expected.increment }.should be_false
131
- sleep(0.1)
132
- expected.value.should eq 0
133
- end
134
-
135
- it 'rejects tasks once killed' do
136
- expected = AtomicFixnum.new(0)
137
- subject.kill
138
- sleep(0.1)
139
- subject.post(0){ expected.increment }.should be_false
140
- sleep(0.1)
141
- expected.value.should eq 0
142
- end
143
-
144
- it 'is running? when first created' do
145
- subject.should be_running
146
- subject.should_not be_shutdown
147
- end
148
-
149
- it 'is running? after tasks have been post' do
150
- subject.post(0.1){ nil }
151
- subject.should be_running
152
- subject.should_not be_shutdown
153
- end
154
-
155
- it 'is shutdown? after shutdown completes' do
156
- subject.shutdown
157
- sleep(0.1)
158
- subject.should_not be_running
159
- subject.should be_shutdown
160
- end
161
-
162
- it 'is shutdown? after being killed' do
163
- subject.kill
164
- sleep(0.1)
165
- subject.should_not be_running
166
- subject.should be_shutdown
167
- end
168
-
169
- specify '#wait_for_termination returns true if shutdown completes before timeout' do
170
- subject.post(0.1){ nil }
171
- sleep(0.1)
172
- subject.shutdown
173
- subject.wait_for_termination(0.1).should be_true
174
- end
175
-
176
- specify '#wait_for_termination returns false on timeout' do
177
- subject.post(0.1){ nil }
178
- sleep(0.1)
179
- # do not call shutdown -- force timeout
180
- subject.wait_for_termination(0.1).should be_false
181
- end
182
- end
183
- end
@@ -1,329 +0,0 @@
1
- require 'spec_helper'
2
- require_relative 'dereferenceable_shared'
3
- require_relative 'obligation_shared'
4
- require_relative 'observable_shared'
5
-
6
- module Concurrent
7
-
8
- describe Future do
9
-
10
- let!(:value) { 10 }
11
- let(:executor) { PerThreadExecutor.new }
12
-
13
- subject do
14
- Future.new(executor: executor){
15
- value
16
- }.execute.tap{ sleep(0.1) }
17
- end
18
-
19
- context 'behavior' do
20
-
21
- # obligation
22
-
23
- let!(:fulfilled_value) { 10 }
24
- let!(:rejected_reason) { StandardError.new('mojo jojo') }
25
-
26
- let(:pending_subject) do
27
- Future.new(executor: executor){ sleep(3); fulfilled_value }.execute
28
- end
29
-
30
- let(:fulfilled_subject) do
31
- Future.new(executor: executor){ fulfilled_value }.execute.tap{ sleep(0.1) }
32
- end
33
-
34
- let(:rejected_subject) do
35
- Future.new(executor: executor){ raise rejected_reason }.execute.tap{ sleep(0.1) }
36
- end
37
-
38
- it_should_behave_like :obligation
39
-
40
- # dereferenceable
41
-
42
- def dereferenceable_subject(value, opts = {})
43
- opts = opts.merge(executor: executor)
44
- Future.new(opts){ value }.execute.tap{ sleep(0.1) }
45
- end
46
-
47
- def dereferenceable_observable(opts = {})
48
- opts = opts.merge(executor: executor)
49
- Future.new(opts){ 'value' }
50
- end
51
-
52
- def execute_dereferenceable(subject)
53
- subject.execute
54
- sleep(0.1)
55
- end
56
-
57
- it_should_behave_like :dereferenceable
58
-
59
- # observable
60
-
61
- subject{ Future.new{ nil } }
62
-
63
- def trigger_observable(observable)
64
- observable.execute
65
- sleep(0.1)
66
- end
67
-
68
- it_should_behave_like :observable
69
- end
70
-
71
- context 'subclassing' do
72
-
73
- subject{ Future.execute(executor: executor){ 42 } }
74
-
75
- it 'protects #set' do
76
- expect{ subject.set(100) }.to raise_error
77
- end
78
-
79
- it 'protects #fail' do
80
- expect{ subject.fail }.to raise_error
81
- end
82
-
83
- it 'protects #complete' do
84
- expect{ subject.complete(true, 100, nil) }.to raise_error
85
- end
86
- end
87
-
88
- context '#initialize' do
89
-
90
- let(:executor) { ImmediateExecutor.new }
91
-
92
- it 'sets the state to :unscheduled' do
93
- Future.new(executor: executor){ nil }.should be_unscheduled
94
- end
95
-
96
- it 'raises an exception when no block given' do
97
- expect {
98
- Future.new.execute
99
- }.to raise_error(ArgumentError)
100
- end
101
-
102
- it 'uses the executor given with the :executor option' do
103
- executor.should_receive(:post)
104
- Future.execute(executor: executor){ nil }
105
- end
106
-
107
- it 'uses the global operation pool when :operation is true' do
108
- Concurrent.configuration.should_receive(:global_operation_pool).and_return(executor)
109
- Future.execute(operation: true){ nil }
110
- end
111
-
112
- it 'uses the global task pool when :task is true' do
113
- Concurrent.configuration.should_receive(:global_task_pool).and_return(executor)
114
- Future.execute(task: true){ nil }
115
- end
116
-
117
- it 'uses the global task pool by default' do
118
- Concurrent.configuration.should_receive(:global_task_pool).and_return(executor)
119
- Future.execute{ nil }
120
- end
121
- end
122
-
123
- context 'instance #execute' do
124
-
125
- it 'does nothing unless the state is :unscheduled' do
126
- executor = ImmediateExecutor.new
127
- executor.should_not_receive(:post).with(any_args)
128
- future = Future.new(executor: executor){ nil }
129
- future.instance_variable_set(:@state, :pending)
130
- future.execute
131
- future.instance_variable_set(:@state, :rejected)
132
- future.execute
133
- future.instance_variable_set(:@state, :fulfilled)
134
- future.execute
135
- end
136
-
137
- it 'posts the block given on construction' do
138
- executor.should_receive(:post).with(any_args)
139
- future = Future.new(executor: executor){ nil }
140
- future.execute
141
- end
142
-
143
- it 'sets the state to :pending' do
144
- future = Future.new(executor: executor){ sleep(0.1) }
145
- future.execute
146
- future.should be_pending
147
- end
148
-
149
- it 'returns self' do
150
- future = Future.new(executor: executor){ nil }
151
- future.execute.should be future
152
- end
153
- end
154
-
155
- context 'class #execute' do
156
-
157
- let(:executor) { ImmediateExecutor.new }
158
-
159
- it 'creates a new Future' do
160
- future = Future.execute(executor: executor){ nil }
161
- future.should be_a(Future)
162
- end
163
-
164
- it 'passes the block to the new Future' do
165
- @expected = false
166
- Future.execute(executor: executor){ @expected = true }
167
- @expected.should be_true
168
- end
169
-
170
- it 'calls #execute on the new Future' do
171
- future = double('future')
172
- Future.stub(:new).with(any_args).and_return(future)
173
- future.should_receive(:execute).with(no_args)
174
- Future.execute{ nil }
175
- end
176
- end
177
-
178
- context 'fulfillment' do
179
-
180
- let(:executor) { ImmediateExecutor.new }
181
-
182
- it 'passes all arguments to handler' do
183
- @expected = false
184
- Future.new(executor: executor){ @expected = true }.execute
185
- @expected.should be_true
186
- end
187
-
188
- it 'sets the value to the result of the handler' do
189
- future = Future.new(executor: executor){ 42 }.execute
190
- future.value.should eq 42
191
- end
192
-
193
- it 'sets the state to :fulfilled when the block completes' do
194
- future = Future.new(executor: executor){ 42 }.execute
195
- future.should be_fulfilled
196
- end
197
-
198
- it 'sets the value to nil when the handler raises an exception' do
199
- future = Future.new(executor: executor){ raise StandardError }.execute
200
- future.value.should be_nil
201
- end
202
-
203
- it 'sets the state to :rejected when the handler raises an exception' do
204
- future = Future.new(executor: executor){ raise StandardError }.execute
205
- future.should be_rejected
206
- end
207
-
208
- context 'aliases' do
209
-
210
- it 'aliases #realized? for #fulfilled?' do
211
- subject.should be_realized
212
- end
213
-
214
- it 'aliases #deref for #value' do
215
- subject.deref.should eq value
216
- end
217
- end
218
- end
219
-
220
- context 'observation' do
221
-
222
- let(:executor) { ImmediateExecutor.new }
223
-
224
- let(:clazz) do
225
- Class.new do
226
- attr_reader :value
227
- attr_reader :reason
228
- attr_reader :count
229
- define_method(:update) do |time, value, reason|
230
- @count = @count.to_i + 1
231
- @value = value
232
- @reason = reason
233
- end
234
- end
235
- end
236
-
237
- let(:observer) { clazz.new }
238
-
239
- it 'notifies all observers on fulfillment' do
240
- future = Future.new(executor: executor){ 42 }
241
- future.add_observer(observer)
242
-
243
- future.execute
244
-
245
- observer.value.should == 42
246
- observer.reason.should be_nil
247
- end
248
-
249
- it 'notifies all observers on rejection' do
250
- future = Future.new(executor: executor){ raise StandardError }
251
- future.add_observer(observer)
252
-
253
- future.execute
254
-
255
- observer.value.should be_nil
256
- observer.reason.should be_a(StandardError)
257
- end
258
-
259
- it 'notifies an observer added after fulfillment' do
260
- future = Future.new(executor: executor){ 42 }.execute
261
- future.add_observer(observer)
262
- observer.value.should == 42
263
- end
264
-
265
- it 'notifies an observer added after rejection' do
266
- future = Future.new(executor: executor){ raise StandardError }.execute
267
- future.add_observer(observer)
268
- observer.reason.should be_a(StandardError)
269
- end
270
-
271
- it 'does not notify existing observers when a new observer added after fulfillment' do
272
- future = Future.new(executor: executor){ 42 }.execute
273
- future.add_observer(observer)
274
-
275
- observer.count.should == 1
276
-
277
- o2 = clazz.new
278
- future.add_observer(o2)
279
-
280
- observer.count.should == 1
281
- o2.value.should == 42
282
- end
283
-
284
- it 'does not notify existing observers when a new observer added after rejection' do
285
- future = Future.new(executor: executor){ raise StandardError }.execute
286
- future.add_observer(observer)
287
-
288
- observer.count.should == 1
289
-
290
- o2 = clazz.new
291
- future.add_observer(o2)
292
-
293
- observer.count.should == 1
294
- o2.reason.should be_a(StandardError)
295
- end
296
-
297
- context 'deadlock avoidance' do
298
-
299
- def reentrant_observer(future)
300
- obs = Object.new
301
- obs.define_singleton_method(:update) do |time, value, reason|
302
- @value = future.value
303
- end
304
- obs.define_singleton_method(:value) { @value }
305
- obs
306
- end
307
-
308
- it 'should notify observers outside mutex lock' do
309
- future = Future.new(executor: executor){ 42 }
310
- obs = reentrant_observer(future)
311
-
312
- future.add_observer(obs)
313
- future.execute
314
-
315
- obs.value.should eq 42
316
- end
317
-
318
- it 'should notify a new observer added after fulfillment outside lock' do
319
- future = Future.new(executor: executor){ 42 }.execute
320
- obs = reentrant_observer(future)
321
-
322
- future.add_observer(obs)
323
-
324
- obs.value.should eq 42
325
- end
326
- end
327
- end
328
- end
329
- end