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,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
@@ -1,146 +0,0 @@
1
- require 'spec_helper'
2
-
3
- share_examples_for :dereferenceable do
4
-
5
- it 'defaults :dup_on_deref to false' do
6
- value = 'value'
7
- value.should_not_receive(:dup).with(any_args)
8
-
9
- subject = dereferenceable_subject(value)
10
- subject.value.should eq 'value'
11
-
12
- subject = dereferenceable_subject(value, dup_on_deref: false)
13
- subject.value.should eq 'value'
14
-
15
- subject = dereferenceable_subject(value, dup: false)
16
- subject.value.should eq 'value'
17
- end
18
-
19
- it 'calls #dup when the :dup_on_deref option is true' do
20
- value = 'value'
21
-
22
- subject = dereferenceable_subject(value, dup_on_deref: true)
23
- subject.value.object_id.should_not eq value.object_id
24
- subject.value.should eq 'value'
25
-
26
- subject = dereferenceable_subject(value, dup: true)
27
- subject.value.object_id.should_not eq value.object_id
28
- subject.value.should eq 'value'
29
- end
30
-
31
- it 'defaults :freeze_on_deref to false' do
32
- value = 'value'
33
- value.should_not_receive(:freeze).with(any_args)
34
-
35
- subject = dereferenceable_subject(value)
36
- subject.value.should eq 'value'
37
-
38
- subject = dereferenceable_subject(value, freeze_on_deref: false)
39
- subject.value.should eq 'value'
40
-
41
- subject = dereferenceable_subject(value, freeze: false)
42
- subject.value.should eq 'value'
43
- end
44
-
45
- it 'calls #freeze when the :freeze_on_deref option is true' do
46
- value = 'value'
47
-
48
- subject = dereferenceable_subject(value, freeze_on_deref: true)
49
- subject.value.should be_frozen
50
- subject.value.should eq 'value'
51
-
52
- subject = dereferenceable_subject(value, freeze: true)
53
- subject.value.should be_frozen
54
- subject.value.should eq 'value'
55
- end
56
-
57
- it 'defaults :copy_on_deref to nil' do
58
- value = 'value'
59
-
60
- subject = dereferenceable_subject(value)
61
- subject.value.object_id.should == value.object_id
62
- subject.value.should eq 'value'
63
-
64
- subject = dereferenceable_subject(value, copy_on_deref: nil)
65
- subject.value.object_id.should == value.object_id
66
- subject.value.should eq 'value'
67
-
68
- subject = dereferenceable_subject(value, copy: nil)
69
- subject.value.object_id.should == value.object_id
70
- subject.value.should eq 'value'
71
- end
72
-
73
- it 'calls the block when the :copy_on_deref option is passed a proc' do
74
- value = 'value'
75
- copy = proc{|val| 'copy' }
76
-
77
- subject = dereferenceable_subject(value, copy_on_deref: copy)
78
- subject.value.object_id.should_not == value.object_id
79
-
80
- subject = dereferenceable_subject(value, copy: copy)
81
- subject.value.object_id.should_not == value.object_id
82
- end
83
-
84
- it 'calls the :copy block first followed by #dup followed by #freeze' do
85
- value = 'value'
86
- copied = 'copied'
87
- dup = 'dup'
88
- frozen = 'frozen'
89
- copy = proc{|val| copied }
90
-
91
- copied.should_receive(:dup).at_least(:once).with(no_args).and_return(dup)
92
- dup.should_receive(:freeze).at_least(:once).with(no_args).and_return(frozen)
93
-
94
- subject = dereferenceable_subject(value, dup_on_deref: true, freeze_on_deref: true, copy_on_deref: copy)
95
- subject.value.should eq frozen
96
- end
97
-
98
- it 'does not call #dup when #dup_on_deref is set and the value is nil' do
99
- allow_message_expectations_on_nil
100
- result = nil
101
- result.should_not_receive(:dup).with(any_args)
102
- subject = dereferenceable_subject(result, dup_on_deref: true)
103
- subject.value
104
- end
105
-
106
- it 'does not call #freeze when #freeze_on_deref is set and the value is nil' do
107
- allow_message_expectations_on_nil
108
- result = nil
109
- result.should_not_receive(:freeze).with(any_args)
110
- subject = dereferenceable_subject(result, freeze_on_deref: true)
111
- subject.value
112
- end
113
-
114
- it 'does not call the #copy_on_deref block when the value is nil' do
115
- copier = proc { 42 }
116
- subject = dereferenceable_subject(nil, copy_on_deref: copier)
117
- subject.value.should be_nil
118
- end
119
-
120
- it 'locks when all options are false' do
121
- subject = dereferenceable_subject(0)
122
- mutex = double('mutex')
123
- subject.stub(:mutex).and_return(mutex)
124
- mutex.should_receive(:lock).at_least(:once)
125
- mutex.should_receive(:unlock).at_least(:once)
126
- subject.value
127
- end
128
-
129
- it 'supports dereference flags with observers' do
130
- if dereferenceable_subject(0).respond_to?(:add_observer)
131
-
132
- result = 'result'
133
- result.should_receive(:dup).at_least(:once).and_return(result)
134
- result.should_receive(:freeze).at_least(:once).and_return(result)
135
- copier = proc { result }
136
-
137
- observer = double('observer')
138
- observer.should_receive(:update).at_least(:once).with(any_args)
139
-
140
- subject = dereferenceable_observable(dup_on_deref: true, freeze_on_deref: true, copy_on_deref: copier)
141
-
142
- subject.add_observer(observer)
143
- execute_dereferenceable(subject)
144
- end
145
- end
146
- end
@@ -1,66 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Concurrent
4
-
5
- describe Exchanger do
6
-
7
- subject { Exchanger.new }
8
- let!(:exchanger) { subject } # let is not thread safe, let! creates the object before ensuring uniqueness
9
-
10
- describe 'exchange' do
11
- context 'without timeout' do
12
- it 'should block' do
13
- t = Thread.new { exchanger.exchange(1) }
14
- sleep(0.1)
15
- t.status.should eq 'sleep'
16
- end
17
-
18
- it 'should receive the other value' do
19
- first_value = nil
20
- second_value = nil
21
-
22
- Thread.new { first_value = exchanger.exchange(2) }
23
- Thread.new { second_value = exchanger.exchange(4) }
24
-
25
- sleep(0.1)
26
-
27
- first_value.should eq 4
28
- second_value.should eq 2
29
- end
30
-
31
- it 'can be reused' do
32
- first_value = nil
33
- second_value = nil
34
-
35
- Thread.new { first_value = exchanger.exchange(1) }
36
- Thread.new { second_value = exchanger.exchange(0) }
37
-
38
- sleep(0.1)
39
-
40
- Thread.new { first_value = exchanger.exchange(10) }
41
- Thread.new { second_value = exchanger.exchange(12) }
42
-
43
- sleep(0.1)
44
-
45
- first_value.should eq 12
46
- second_value.should eq 10
47
- end
48
- end
49
-
50
- context 'with timeout' do
51
- it 'should block until timeout' do
52
-
53
- value = 0
54
- start = Time.now.to_f
55
-
56
- future = Concurrent::Future.execute do
57
- exchanger.exchange(2, 0.2)
58
- end
59
-
60
- future.value.should be_nil
61
- (Time.now.to_f - start).should >= 0.2
62
- end
63
- end
64
- end
65
- end
66
- end
@@ -1,115 +0,0 @@
1
- require 'spec_helper'
2
- require_relative 'thread_pool_shared'
3
-
4
- share_examples_for :cached_thread_pool do
5
-
6
- subject do
7
- described_class.new(overflow_policy: :discard)
8
- end
9
-
10
- after(:each) do
11
- subject.kill
12
- sleep(0.1)
13
- end
14
-
15
- it_should_behave_like :thread_pool
16
-
17
- context '#initialize' do
18
-
19
- it 'sets :max_length to DEFAULT_MAX_POOL_SIZE' do
20
- described_class.new.max_length.should eq described_class::DEFAULT_MAX_POOL_SIZE
21
- end
22
-
23
- it 'sets :min_length to DEFAULT_MIN_POOL_SIZE' do
24
- subject = described_class.new.min_length.should eq described_class::DEFAULT_MIN_POOL_SIZE
25
- end
26
-
27
- it 'sets :idletime to DEFAULT_THREAD_IDLETIMEOUT' do
28
- subject = described_class.new.idletime.should eq described_class::DEFAULT_THREAD_IDLETIMEOUT
29
- end
30
-
31
- it 'sets :max_queue to DEFAULT_MAX_QUEUE_SIZE' do
32
- subject = described_class.new.max_queue.should eq described_class::DEFAULT_MAX_QUEUE_SIZE
33
- end
34
- end
35
-
36
- context '#min_length' do
37
-
38
- it 'returns zero on creation' do
39
- subject.min_length.should eq 0
40
- end
41
-
42
- it 'returns zero while running' do
43
- 10.times{ subject.post{ nil } }
44
- sleep(0.1)
45
- subject.min_length.should eq 0
46
- end
47
-
48
- it 'returns zero once shutdown' do
49
- 10.times{ subject.post{ nil } }
50
- sleep(0.1)
51
- subject.shutdown
52
- subject.wait_for_termination(1)
53
- subject.min_length.should eq 0
54
- end
55
- end
56
-
57
- context '#max_length' do
58
-
59
- it 'returns :max_length on creation' do
60
- subject.max_length.should eq described_class::DEFAULT_MAX_POOL_SIZE
61
- end
62
-
63
- it 'returns :max_length while running' do
64
- 10.times{ subject.post{ nil } }
65
- sleep(0.1)
66
- subject.max_length.should eq described_class::DEFAULT_MAX_POOL_SIZE
67
- end
68
-
69
- it 'returns :max_length once shutdown' do
70
- 10.times{ subject.post{ nil } }
71
- sleep(0.1)
72
- subject.shutdown
73
- subject.wait_for_termination(1)
74
- subject.max_length.should eq described_class::DEFAULT_MAX_POOL_SIZE
75
- end
76
- end
77
-
78
- context '#largest_length' do
79
-
80
- it 'returns zero on creation' do
81
- subject.largest_length.should eq 0
82
- end
83
-
84
- it 'returns a non-zero number once tasks have been received' do
85
- 10.times{ subject.post{ sleep(0.1) } }
86
- sleep(0.1)
87
- subject.largest_length.should > 0
88
- end
89
-
90
- it 'returns a non-zero number after shutdown if tasks have been received' do
91
- 10.times{ subject.post{ sleep(0.1) } }
92
- sleep(0.1)
93
- subject.shutdown
94
- subject.wait_for_termination(1)
95
- subject.largest_length.should > 0
96
- end
97
- end
98
-
99
- context '#status' do
100
-
101
- it 'returns an array' do
102
- subject.stub(:warn)
103
- subject.status.should be_kind_of(Array)
104
- end
105
- end
106
-
107
- context '#idletime' do
108
-
109
- subject{ described_class.new(idletime: 42) }
110
-
111
- it 'returns the thread idletime' do
112
- subject.idletime.should eq described_class::DEFAULT_THREAD_IDLETIMEOUT
113
- end
114
- end
115
- end