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,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