concurrent-ruby 0.7.0.rc0-java → 0.7.0.rc1-java

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 (30) hide show
  1. data/README.md +13 -8
  2. data/lib/concurrent.rb +0 -1
  3. data/lib/concurrent/actress.rb +10 -6
  4. data/lib/concurrent/actress/core.rb +1 -1
  5. data/lib/concurrent/async.rb +39 -74
  6. data/lib/concurrent/atomic.rb +21 -1
  7. data/lib/concurrent/atomic_reference/concurrent_update_error.rb +1 -0
  8. data/lib/concurrent/atomic_reference/direct_update.rb +22 -0
  9. data/lib/concurrent/atomic_reference/jruby.rb +2 -0
  10. data/lib/concurrent/atomic_reference/mutex_atomic.rb +36 -6
  11. data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +8 -7
  12. data/lib/concurrent/atomic_reference/rbx.rb +7 -4
  13. data/lib/concurrent/atomic_reference/ruby.rb +2 -0
  14. data/lib/concurrent/executor/executor.rb +118 -70
  15. data/lib/concurrent/executor/immediate_executor.rb +50 -1
  16. data/lib/concurrent/executor/java_fixed_thread_pool.rb +14 -6
  17. data/lib/concurrent/executor/java_single_thread_executor.rb +1 -0
  18. data/lib/concurrent/executor/java_thread_pool_executor.rb +3 -10
  19. data/lib/concurrent/executor/per_thread_executor.rb +80 -4
  20. data/lib/concurrent/executor/ruby_cached_thread_pool.rb +1 -1
  21. data/lib/concurrent/executor/ruby_fixed_thread_pool.rb +4 -4
  22. data/lib/concurrent/executor/ruby_single_thread_executor.rb +1 -0
  23. data/lib/concurrent/executor/ruby_thread_pool_executor.rb +2 -0
  24. data/lib/concurrent/executor/serialized_execution.rb +23 -0
  25. data/lib/concurrent/version.rb +1 -1
  26. data/lib/concurrent_ruby_ext.bundle +0 -0
  27. data/lib/concurrent_ruby_ext.jar +0 -0
  28. metadata +2 -4
  29. data/lib/concurrent/atomic_reference/delegated_update.rb +0 -28
  30. data/lib/concurrent/supervisor.rb +0 -343
@@ -17,14 +17,22 @@ if RUBY_PLATFORM == 'java'
17
17
  #
18
18
  # @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executors.html#newFixedThreadPool-int-
19
19
  def initialize(num_threads, opts = {})
20
- @overflow_policy = opts.fetch(:overflow_policy, :abort)
21
- @max_queue = 0
22
20
 
23
- raise ArgumentError.new('number of threads must be greater than zero') if num_threads < 1
24
- raise ArgumentError.new("#{@overflow_policy} is not a valid overflow policy") unless OVERFLOW_POLICIES.keys.include?(@overflow_policy)
21
+ opts = {
22
+ min_threads: num_threads,
23
+ max_threads: num_threads
24
+ }.merge(opts)
25
+ super(opts)
25
26
 
26
- @executor = java.util.concurrent.Executors.newFixedThreadPool(num_threads)
27
- @executor.setRejectedExecutionHandler(OVERFLOW_POLICIES[@overflow_policy].new)
27
+
28
+ #@overflow_policy = opts.fetch(:overflow_policy, :abort)
29
+ #@max_queue = 0
30
+ #
31
+ #raise ArgumentError.new('number of threads must be greater than zero') if num_threads < 1
32
+ #raise ArgumentError.new("#{@overflow_policy} is not a valid overflow policy") unless OVERFLOW_POLICIES.keys.include?(@overflow_policy)
33
+ #
34
+ #@executor = java.util.concurrent.Executors.newFixedThreadPool(num_threads)
35
+ #@executor.setRejectedExecutionHandler(OVERFLOW_POLICIES[@overflow_policy].new)
28
36
 
29
37
  set_shutdown_hook
30
38
  end
@@ -6,6 +6,7 @@ if RUBY_PLATFORM == 'java'
6
6
  # @!macro single_thread_executor
7
7
  class JavaSingleThreadExecutor
8
8
  include JavaExecutor
9
+ include SerialExecutor
9
10
 
10
11
  # Create a new thread pool.
11
12
  #
@@ -71,6 +71,7 @@ if RUBY_PLATFORM == 'java'
71
71
 
72
72
  raise ArgumentError.new('max_threads must be greater than zero') if max_length <= 0
73
73
  raise ArgumentError.new('min_threads cannot be less than zero') if min_length < 0
74
+ raise ArgumentError.new('min_threads cannot be more than max_threads') if min_length > max_length
74
75
  raise ArgumentError.new("#{@overflow_policy} is not a valid overflow policy") unless OVERFLOW_POLICIES.keys.include?(@overflow_policy)
75
76
 
76
77
  if min_length == 0 && @max_queue == 0
@@ -89,6 +90,7 @@ if RUBY_PLATFORM == 'java'
89
90
  set_shutdown_hook
90
91
  end
91
92
 
93
+ # @!macro executor_module_method_can_overflow_question
92
94
  def can_overflow?
93
95
  @max_queue != 0
94
96
  end
@@ -171,16 +173,7 @@ if RUBY_PLATFORM == 'java'
171
173
  #
172
174
  # @return [Boolean] `true` when running, `false` when shutting down or shutdown
173
175
  def running?
174
- super && ! @executor.isTerminating
175
- end
176
-
177
- # Begin an orderly shutdown. Tasks already in the queue will be executed,
178
- # but no new tasks will be accepted. Has no additional effect if the
179
- # thread pool is not running.
180
- def shutdown
181
- super
182
- @executor.getQueue.clear
183
- nil
176
+ super && !@executor.isTerminating
184
177
  end
185
178
  end
186
179
  end
@@ -1,24 +1,100 @@
1
+ require 'concurrent/atomics'
2
+ require 'concurrent/executor/executor'
3
+
1
4
  module Concurrent
2
5
 
6
+ # An executor service in which every operation spawns a new,
7
+ # independently operating thread.
8
+ #
9
+ # This is perhaps the most inefficient executor service in this
10
+ # library. It exists mainly for testing an debugging. Thread creation
11
+ # and management is expensive in Ruby and this executor performs no
12
+ # resource pooling. This can be very beneficial during testing and
13
+ # debugging because it decouples the using code from the underlying
14
+ # executor implementation. In production this executor will likely
15
+ # lead to suboptimal performance.
16
+ #
17
+ # @note Intended for use primarily in testing and debugging.
3
18
  class PerThreadExecutor
4
19
  include Executor
5
20
 
21
+ # Creates a new executor
22
+ def initialize
23
+ @running = Concurrent::AtomicBoolean.new(true)
24
+ @stopped = Concurrent::Event.new
25
+ @count = Concurrent::AtomicFixnum.new(0)
26
+ end
27
+
28
+ # @!macro executor_method_post
6
29
  def self.post(*args)
7
30
  raise ArgumentError.new('no block given') unless block_given?
8
31
  Thread.new(*args) do
9
32
  Thread.current.abort_on_exception = false
10
33
  yield(*args)
11
34
  end
12
- return true
35
+ true
13
36
  end
14
37
 
38
+ # @!macro executor_method_left_shift
39
+ def self.<<(task)
40
+ post(&task)
41
+ self
42
+ end
43
+
44
+ # @!macro executor_method_post
15
45
  def post(*args, &task)
16
- return PerThreadExecutor.post(*args, &task)
46
+ raise ArgumentError.new('no block given') unless block_given?
47
+ return false unless running?
48
+ @count.increment
49
+ Thread.new(*args) do
50
+ Thread.current.abort_on_exception = false
51
+ begin
52
+ yield(*args)
53
+ ensure
54
+ @count.decrement
55
+ @stopped.set if @running.false? && @count.value == 0
56
+ end
57
+ end
17
58
  end
18
59
 
60
+ # @!macro executor_method_left_shift
19
61
  def <<(task)
20
- PerThreadExecutor.post(&task)
21
- return self
62
+ post(&task)
63
+ self
64
+ end
65
+
66
+ # @!macro executor_method_running_question
67
+ def running?
68
+ @running.true?
69
+ end
70
+
71
+ # @!macro executor_method_shuttingdown_question
72
+ def shuttingdown?
73
+ @running.false? && ! @stopped.set?
74
+ end
75
+
76
+ # @!macro executor_method_shutdown_question
77
+ def shutdown?
78
+ @stopped.set?
79
+ end
80
+
81
+ # @!macro executor_method_shutdown
82
+ def shutdown
83
+ @running.make_false
84
+ @stopped.set if @count.value == 0
85
+ true
86
+ end
87
+
88
+ # @!macro executor_method_kill
89
+ def kill
90
+ @running.make_false
91
+ @stopped.set
92
+ true
93
+ end
94
+
95
+ # @!macro executor_method_wait_for_termination
96
+ def wait_for_termination(timeout = nil)
97
+ @stopped.wait(timeout)
22
98
  end
23
99
  end
24
100
  end
@@ -19,7 +19,7 @@ module Concurrent
19
19
  opts = opts.merge(
20
20
  min_threads: 0,
21
21
  max_threads: DEFAULT_MAX_POOL_SIZE,
22
- num_threads: overflow_policy,
22
+ overflow_policy: overflow_policy,
23
23
  max_queue: DEFAULT_MAX_QUEUE_SIZE,
24
24
  idletime: DEFAULT_THREAD_IDLETIMEOUT
25
25
  )
@@ -19,13 +19,13 @@ module Concurrent
19
19
  raise ArgumentError.new('number of threads must be greater than zero') if num_threads < 1
20
20
  raise ArgumentError.new("#{overflow_policy} is not a valid overflow policy") unless OVERFLOW_POLICIES.include?(overflow_policy)
21
21
 
22
- opts = opts.merge(
22
+ opts = {
23
23
  min_threads: num_threads,
24
24
  max_threads: num_threads,
25
- num_threads: overflow_policy,
25
+ overflow_policy: overflow_policy,
26
26
  max_queue: DEFAULT_MAX_QUEUE_SIZE,
27
- idletime: 0
28
- )
27
+ idletime: DEFAULT_THREAD_IDLETIMEOUT,
28
+ }.merge(opts)
29
29
  super(opts)
30
30
  end
31
31
  end
@@ -5,6 +5,7 @@ module Concurrent
5
5
  # @!macro single_thread_executor
6
6
  class RubySingleThreadExecutor
7
7
  include RubyExecutor
8
+ include SerialExecutor
8
9
 
9
10
  # Create a new thread pool.
10
11
  #
@@ -86,6 +86,7 @@ module Concurrent
86
86
  raise ArgumentError.new('max_threads must be greater than zero') if @max_length <= 0
87
87
  raise ArgumentError.new('min_threads cannot be less than zero') if @min_length < 0
88
88
  raise ArgumentError.new("#{overflow_policy} is not a valid overflow policy") unless OVERFLOW_POLICIES.include?(@overflow_policy)
89
+ raise ArgumentError.new('min_threads cannot be more than max_threads') if min_length > max_length
89
90
 
90
91
  init_executor
91
92
 
@@ -99,6 +100,7 @@ module Concurrent
99
100
  @last_gc_time = Time.now.to_f - [1.0, (@gc_interval * 2.0)].max
100
101
  end
101
102
 
103
+ # @!macro executor_module_method_can_overflow_question
102
104
  def can_overflow?
103
105
  @max_queue != 0
104
106
  end
@@ -1,3 +1,5 @@
1
+ require 'delegate'
2
+ require 'concurrent/executor/executor'
1
3
  require 'concurrent/logging'
2
4
 
3
5
  module Concurrent
@@ -85,6 +87,27 @@ module Concurrent
85
87
 
86
88
  call_job job if job
87
89
  end
90
+ end
91
+
92
+ # A wrapper/delegator for any `Executor` or `ExecutorService` that
93
+ # guarantees serialized execution of tasks.
94
+ #
95
+ # @see [SimpleDelegator](http://www.ruby-doc.org/stdlib-2.1.2/libdoc/delegate/rdoc/SimpleDelegator.html)
96
+ # @see Concurrent::SerializedExecution
97
+ class SerializedExecutionDelegator < SimpleDelegator
98
+ include SerialExecutor
88
99
 
100
+ def initialize(executor)
101
+ @executor = executor
102
+ @serializer = SerializedExecution.new
103
+ super(executor)
104
+ end
105
+
106
+ # @!macro executor_method_post
107
+ def post(*args, &task)
108
+ raise ArgumentError.new('no block given') unless block_given?
109
+ return false unless running?
110
+ @serializer.post(@executor, *args, &task)
111
+ end
89
112
  end
90
113
  end
@@ -1,3 +1,3 @@
1
1
  module Concurrent
2
- VERSION = '0.7.0.rc0'
2
+ VERSION = '0.7.0.rc1'
3
3
  end
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: concurrent-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0.rc0
4
+ version: 0.7.0.rc1
5
5
  prerelease: 6
6
6
  platform: java
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-06-18 00:00:00.000000000 Z
12
+ date: 2014-06-27 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: |2
15
15
  Modern concurrency tools including agents, futures, promises, thread pools, actors, supervisors, and more.
@@ -49,7 +49,6 @@ files:
49
49
  - lib/concurrent/options_parser.rb
50
50
  - lib/concurrent/promise.rb
51
51
  - lib/concurrent/scheduled_task.rb
52
- - lib/concurrent/supervisor.rb
53
52
  - lib/concurrent/timer_task.rb
54
53
  - lib/concurrent/tvar.rb
55
54
  - lib/concurrent/utilities.rb
@@ -72,7 +71,6 @@ files:
72
71
  - lib/concurrent/atomic/event.rb
73
72
  - lib/concurrent/atomic/thread_local_var.rb
74
73
  - lib/concurrent/atomic_reference/concurrent_update_error.rb
75
- - lib/concurrent/atomic_reference/delegated_update.rb
76
74
  - lib/concurrent/atomic_reference/direct_update.rb
77
75
  - lib/concurrent/atomic_reference/jruby.rb
78
76
  - lib/concurrent/atomic_reference/mutex_atomic.rb
@@ -1,28 +0,0 @@
1
- require 'concurrent/atomic_reference/concurrent_update_error'
2
-
3
- module Concurrent
4
-
5
- # Define update methods that delegate to @ref field
6
- class Atomic
7
- # Pass the current value to the given block, replacing it
8
- # with the block's result. May retry if the value changes
9
- # during the block's execution.
10
- def update
11
- true until @ref.compare_and_set(old_value = @ref.get, new_value = yield(old_value))
12
- new_value
13
- end
14
-
15
- def try_update
16
- old_value = @ref.get
17
- new_value = yield old_value
18
- unless @ref.compare_and_set(old_value, new_value)
19
- if $VERBOSE
20
- raise ConcurrentUpdateError, "Update failed"
21
- else
22
- raise ConcurrentUpdateError, "Update failed", ConcurrentUpdateError::CONC_UP_ERR_BACKTRACE
23
- end
24
- end
25
- new_value
26
- end
27
- end
28
- end
@@ -1,343 +0,0 @@
1
- require 'thread'
2
-
3
- require 'concurrent/errors'
4
-
5
- module Concurrent
6
-
7
- class Supervisor
8
-
9
- DEFAULT_MONITOR_INTERVAL = 1
10
- RESTART_STRATEGIES = [:one_for_one, :one_for_all, :rest_for_one]
11
- DEFAULT_MAX_RESTART = 5
12
- DEFAULT_MAX_TIME = 60
13
- WORKER_API = {run: 0, stop: 0, running?: 0}
14
-
15
- CHILD_TYPES = [:worker, :supervisor]
16
- CHILD_RESTART_OPTIONS = [:permanent, :transient, :temporary]
17
-
18
- WorkerContext = Struct.new(:worker, :type, :restart) do
19
- attr_accessor :thread
20
- attr_accessor :terminated
21
-
22
- def alive?() return thread && thread.alive?; end
23
-
24
- def needs_restart?
25
- return false if thread && thread.alive?
26
- return false if terminated
27
- case self.restart
28
- when :permanent
29
- return true
30
- when :transient
31
- return thread.nil? || thread.status.nil?
32
- else #when :temporary
33
- return false
34
- end
35
- end
36
- end
37
-
38
- WorkerCounts = Struct.new(:specs, :supervisors, :workers) do
39
- attr_accessor :status
40
- def add(context)
41
- self.specs += 1
42
- self.supervisors += 1 if context.type == :supervisor
43
- self.workers += 1 if context.type == :worker
44
- end
45
- def active() sleeping + running + aborting end
46
- def sleeping() @status.reduce(0){|x, s| x += (s == 'sleep' ? 1 : 0) } end
47
- def running() @status.reduce(0){|x, s| x += (s == 'run' ? 1 : 0) } end
48
- def aborting() @status.reduce(0){|x, s| x += (s == 'aborting' ? 1 : 0) } end
49
- def stopped() @status.reduce(0){|x, s| x += (s == false ? 1 : 0) } end
50
- def abend() @status.reduce(0){|x, s| x += (s.nil? ? 1 : 0) } end
51
- end
52
-
53
- attr_reader :monitor_interval
54
- attr_reader :restart_strategy
55
- attr_reader :max_restart
56
- attr_reader :max_time
57
-
58
- alias_method :strategy, :restart_strategy
59
- alias_method :max_r, :max_restart
60
- alias_method :max_t, :max_time
61
-
62
- def initialize(opts = {})
63
- warn '[EXPERIMENTAL] Supervisor is being completely rewritten and will change soon.'
64
- @restart_strategy = opts[:restart_strategy] || opts[:strategy] || :one_for_one
65
- @monitor_interval = (opts[:monitor_interval] || DEFAULT_MONITOR_INTERVAL).to_f
66
- @max_restart = (opts[:max_restart] || opts[:max_r] || DEFAULT_MAX_RESTART).to_i
67
- @max_time = (opts[:max_time] || opts[:max_t] || DEFAULT_MAX_TIME).to_i
68
-
69
- raise ArgumentError.new(":#{@restart_strategy} is not a valid restart strategy") unless RESTART_STRATEGIES.include?(@restart_strategy)
70
- raise ArgumentError.new(':monitor_interval must be greater than zero') unless @monitor_interval > 0.0
71
- raise ArgumentError.new(':max_restart must be greater than zero') unless @max_restart > 0
72
- raise ArgumentError.new(':max_time must be greater than zero') unless @max_time > 0
73
-
74
- @running = false
75
- @mutex = Mutex.new
76
- @workers = []
77
- @monitor = nil
78
-
79
- @count = WorkerCounts.new(0, 0, 0)
80
- @restart_times = []
81
-
82
- add_worker(opts[:worker]) unless opts[:worker].nil?
83
- add_workers(opts[:workers]) unless opts[:workers].nil?
84
- end
85
-
86
- def run!
87
- @mutex.synchronize do
88
- raise StandardError.new('already running') if @running
89
- @running = true
90
- @monitor = Thread.new do
91
- Thread.current.abort_on_exception = false
92
- monitor
93
- end
94
- end
95
- Thread.pass
96
- end
97
-
98
- def run
99
- @mutex.synchronize do
100
- raise StandardError.new('already running') if @running
101
- @running = true
102
- end
103
- monitor
104
- true
105
- end
106
-
107
- def stop
108
- @mutex.synchronize do
109
- return true unless @running
110
-
111
- @running = false
112
- unless @monitor.nil?
113
- @monitor.run if @monitor.status == 'sleep'
114
- if @monitor.join(0.1).nil?
115
- @monitor.kill
116
- end
117
- @monitor = nil
118
- end
119
- @restart_times.clear
120
-
121
- @workers.length.times do |i|
122
- context = @workers[-1-i]
123
- terminate_worker(context)
124
- end
125
- prune_workers
126
- end
127
-
128
- true
129
- end
130
-
131
- def running?
132
- @mutex.synchronize { @running }
133
- end
134
-
135
- def length
136
- @mutex.synchronize { @workers.length }
137
- end
138
- alias_method :size, :length
139
-
140
- def current_restart_count
141
- @restart_times.length
142
- end
143
-
144
- def count
145
- @mutex.synchronize do
146
- @count.status = @workers.collect{|w| w.thread ? w.thread.status : false }
147
- @count.dup.freeze
148
- end
149
- end
150
-
151
- def add_worker(worker, opts = {})
152
- return nil if worker.nil? || ! behaves_as_worker?(worker)
153
- @mutex.synchronize {
154
- restart = opts[:restart] || :permanent
155
- type = opts[:type] || (worker.is_a?(Supervisor) ? :supervisor : nil) || :worker
156
- raise ArgumentError.new(":#{restart} is not a valid restart option") unless CHILD_RESTART_OPTIONS.include?(restart)
157
- raise ArgumentError.new(":#{type} is not a valid child type") unless CHILD_TYPES.include?(type)
158
- context = WorkerContext.new(worker, type, restart)
159
- @workers << context
160
- @count.add(context)
161
- worker.run if @running
162
- context.object_id
163
- }
164
- end
165
- alias_method :add_child, :add_worker
166
-
167
- def add_workers(workers, opts = {})
168
- workers.collect do |worker|
169
- add_worker(worker, opts)
170
- end
171
- end
172
- alias_method :add_children, :add_workers
173
-
174
- def remove_worker(worker_id)
175
- @mutex.synchronize do
176
- index, context = find_worker(worker_id)
177
- break(nil) if context.nil?
178
- break(false) if context.alive?
179
- @workers.delete_at(index)
180
- context.worker
181
- end
182
- end
183
- alias_method :remove_child, :remove_worker
184
-
185
- def stop_worker(worker_id)
186
- @mutex.synchronize do
187
- return true unless @running
188
-
189
- index, context = find_worker(worker_id)
190
- break(nil) if index.nil?
191
- context.terminated = true
192
- terminate_worker(context)
193
- @workers.delete_at(index) if @workers[index].restart == :temporary
194
- true
195
- end
196
- end
197
- alias_method :stop_child, :stop_worker
198
-
199
- def start_worker(worker_id)
200
- @mutex.synchronize do
201
- return false unless @running
202
-
203
- index, context = find_worker(worker_id)
204
- break(nil) if context.nil?
205
- context.terminated = false
206
- run_worker(context) unless context.alive?
207
- true
208
- end
209
- end
210
- alias_method :start_child, :start_worker
211
-
212
- def restart_worker(worker_id)
213
- @mutex.synchronize do
214
- return false unless @running
215
-
216
- index, context = find_worker(worker_id)
217
- break(nil) if context.nil?
218
- break(false) if context.restart == :temporary
219
- context.terminated = false
220
- terminate_worker(context)
221
- run_worker(context)
222
- true
223
- end
224
- end
225
- alias_method :restart_child, :restart_worker
226
-
227
- private
228
-
229
- def behaves_as_worker?(obj)
230
- WORKER_API.each do |method, arity|
231
- break(false) unless obj.respond_to?(method) && obj.method(method).arity == arity
232
- true
233
- end
234
- end
235
-
236
- def monitor
237
- @workers.each{|context| run_worker(context)}
238
- loop do
239
- sleep(@monitor_interval)
240
- break unless running?
241
- @mutex.synchronize do
242
- prune_workers
243
- self.send(@restart_strategy)
244
- end
245
- break unless running?
246
- end
247
- rescue MaxRestartFrequencyError => ex
248
- stop
249
- end
250
-
251
- def run_worker(context)
252
- context.thread = Thread.new do
253
- Thread.current.abort_on_exception = false
254
- context.worker.run
255
- end
256
- context
257
- end
258
-
259
- def terminate_worker(context)
260
- if context.alive?
261
- context.worker.stop
262
- Thread.pass
263
- end
264
- rescue Exception => ex
265
- begin
266
- Thread.kill(context.thread)
267
- rescue
268
- # suppress
269
- end
270
- ensure
271
- context.thread = nil
272
- end
273
-
274
- def prune_workers
275
- @workers.delete_if{|w| w.restart == :temporary && ! w.alive? }
276
- end
277
-
278
- def find_worker(worker_id)
279
- index = @workers.find_index{|worker| worker.object_id == worker_id}
280
- if index.nil?
281
- [nil, nil]
282
- else
283
- [index, @workers[index]]
284
- end
285
- end
286
-
287
- def exceeded_max_restart_frequency?
288
- @restart_times.unshift(Time.now.to_i)
289
- diff = (@restart_times.first - @restart_times.last).abs
290
- if @restart_times.length >= @max_restart && diff <= @max_time
291
- return true
292
- elsif diff >= @max_time
293
- @restart_times.pop
294
- end
295
- false
296
- end
297
-
298
- #----------------------------------------------------------------
299
- # restart strategies
300
-
301
- def one_for_one
302
- @workers.each do |context|
303
- if context.needs_restart?
304
- raise MaxRestartFrequencyError if exceeded_max_restart_frequency?
305
- run_worker(context)
306
- end
307
- end
308
- end
309
-
310
- def one_for_all
311
- restart = false
312
-
313
- restart = @workers.each do |context|
314
- if context.needs_restart?
315
- raise MaxRestartFrequencyError if exceeded_max_restart_frequency?
316
- break(true)
317
- end
318
- end
319
-
320
- if restart
321
- @workers.each do |context|
322
- terminate_worker(context)
323
- end
324
- @workers.each{|context| run_worker(context)}
325
- end
326
- end
327
-
328
- def rest_for_one
329
- restart = false
330
-
331
- @workers.each do |context|
332
- if restart
333
- terminate_worker(context)
334
- elsif context.needs_restart?
335
- raise MaxRestartFrequencyError if exceeded_max_restart_frequency?
336
- restart = true
337
- end
338
- end
339
-
340
- one_for_one if restart
341
- end
342
- end
343
- end