concurrent-ruby 0.6.1 → 0.7.0.rc0

Sign up to get free protection for your applications and to get access to all the features.
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