concurrent-ruby 0.9.2-java → 1.0.0-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 (121) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +49 -1
  3. data/README.md +86 -120
  4. data/lib/concurrent.rb +14 -5
  5. data/lib/concurrent/agent.rb +587 -0
  6. data/lib/concurrent/array.rb +39 -0
  7. data/lib/concurrent/async.rb +296 -149
  8. data/lib/concurrent/atom.rb +135 -45
  9. data/lib/concurrent/atomic/abstract_thread_local_var.rb +38 -0
  10. data/lib/concurrent/atomic/atomic_boolean.rb +83 -118
  11. data/lib/concurrent/atomic/atomic_fixnum.rb +101 -163
  12. data/lib/concurrent/atomic/atomic_reference.rb +1 -8
  13. data/lib/concurrent/atomic/count_down_latch.rb +62 -103
  14. data/lib/concurrent/atomic/cyclic_barrier.rb +3 -1
  15. data/lib/concurrent/atomic/event.rb +1 -1
  16. data/lib/concurrent/atomic/java_count_down_latch.rb +39 -0
  17. data/lib/concurrent/atomic/java_thread_local_var.rb +50 -0
  18. data/lib/concurrent/atomic/mutex_atomic_boolean.rb +60 -0
  19. data/lib/concurrent/atomic/mutex_atomic_fixnum.rb +91 -0
  20. data/lib/concurrent/atomic/mutex_count_down_latch.rb +43 -0
  21. data/lib/concurrent/atomic/mutex_semaphore.rb +115 -0
  22. data/lib/concurrent/atomic/read_write_lock.rb +5 -4
  23. data/lib/concurrent/atomic/reentrant_read_write_lock.rb +3 -1
  24. data/lib/concurrent/atomic/ruby_thread_local_var.rb +172 -0
  25. data/lib/concurrent/atomic/semaphore.rb +84 -178
  26. data/lib/concurrent/atomic/thread_local_var.rb +65 -294
  27. data/lib/concurrent/atomic_reference/jruby+truffle.rb +1 -0
  28. data/lib/concurrent/atomic_reference/jruby.rb +1 -1
  29. data/lib/concurrent/atomic_reference/mutex_atomic.rb +14 -8
  30. data/lib/concurrent/atomic_reference/ruby.rb +1 -1
  31. data/lib/concurrent/atomics.rb +7 -37
  32. data/lib/concurrent/collection/copy_on_notify_observer_set.rb +7 -15
  33. data/lib/concurrent/collection/copy_on_write_observer_set.rb +7 -15
  34. data/lib/concurrent/collection/java_non_concurrent_priority_queue.rb +84 -0
  35. data/lib/concurrent/collection/map/atomic_reference_map_backend.rb +927 -0
  36. data/lib/concurrent/collection/map/mri_map_backend.rb +66 -0
  37. data/lib/concurrent/collection/map/non_concurrent_map_backend.rb +144 -0
  38. data/lib/concurrent/collection/map/synchronized_map_backend.rb +86 -0
  39. data/lib/concurrent/collection/non_concurrent_priority_queue.rb +143 -0
  40. data/lib/concurrent/collection/ruby_non_concurrent_priority_queue.rb +150 -0
  41. data/lib/concurrent/concern/dereferenceable.rb +9 -24
  42. data/lib/concurrent/concern/logging.rb +1 -1
  43. data/lib/concurrent/concern/obligation.rb +11 -20
  44. data/lib/concurrent/concern/observable.rb +38 -13
  45. data/lib/concurrent/configuration.rb +23 -152
  46. data/lib/concurrent/constants.rb +8 -0
  47. data/lib/concurrent/delay.rb +14 -12
  48. data/lib/concurrent/exchanger.rb +339 -41
  49. data/lib/concurrent/executor/abstract_executor_service.rb +134 -0
  50. data/lib/concurrent/executor/executor_service.rb +23 -359
  51. data/lib/concurrent/executor/immediate_executor.rb +3 -2
  52. data/lib/concurrent/executor/java_executor_service.rb +100 -0
  53. data/lib/concurrent/executor/java_single_thread_executor.rb +3 -3
  54. data/lib/concurrent/executor/java_thread_pool_executor.rb +3 -4
  55. data/lib/concurrent/executor/ruby_executor_service.rb +78 -0
  56. data/lib/concurrent/executor/ruby_single_thread_executor.rb +10 -66
  57. data/lib/concurrent/executor/ruby_thread_pool_executor.rb +25 -22
  58. data/lib/concurrent/executor/safe_task_executor.rb +6 -7
  59. data/lib/concurrent/executor/serial_executor_service.rb +34 -0
  60. data/lib/concurrent/executor/serialized_execution.rb +10 -33
  61. data/lib/concurrent/executor/serialized_execution_delegator.rb +28 -0
  62. data/lib/concurrent/executor/simple_executor_service.rb +1 -10
  63. data/lib/concurrent/executor/single_thread_executor.rb +20 -10
  64. data/lib/concurrent/executor/timer_set.rb +8 -10
  65. data/lib/concurrent/executors.rb +12 -2
  66. data/lib/concurrent/future.rb +6 -4
  67. data/lib/concurrent/hash.rb +35 -0
  68. data/lib/concurrent/immutable_struct.rb +5 -1
  69. data/lib/concurrent/ivar.rb +12 -16
  70. data/lib/concurrent/lazy_register.rb +11 -8
  71. data/lib/concurrent/map.rb +180 -0
  72. data/lib/concurrent/maybe.rb +6 -3
  73. data/lib/concurrent/mutable_struct.rb +7 -6
  74. data/lib/concurrent/mvar.rb +26 -2
  75. data/lib/concurrent/{executor/executor.rb → options.rb} +5 -29
  76. data/lib/concurrent/promise.rb +7 -5
  77. data/lib/concurrent/scheduled_task.rb +13 -71
  78. data/lib/concurrent/settable_struct.rb +5 -4
  79. data/lib/concurrent/synchronization.rb +15 -3
  80. data/lib/concurrent/synchronization/abstract_lockable_object.rb +98 -0
  81. data/lib/concurrent/synchronization/abstract_object.rb +7 -146
  82. data/lib/concurrent/synchronization/abstract_struct.rb +2 -3
  83. data/lib/concurrent/synchronization/condition.rb +6 -4
  84. data/lib/concurrent/synchronization/jruby_lockable_object.rb +13 -0
  85. data/lib/concurrent/synchronization/jruby_object.rb +44 -0
  86. data/lib/concurrent/synchronization/lock.rb +3 -2
  87. data/lib/concurrent/synchronization/lockable_object.rb +72 -0
  88. data/lib/concurrent/synchronization/mri_lockable_object.rb +71 -0
  89. data/lib/concurrent/synchronization/mri_object.rb +43 -0
  90. data/lib/concurrent/synchronization/object.rb +140 -73
  91. data/lib/concurrent/synchronization/rbx_lockable_object.rb +65 -0
  92. data/lib/concurrent/synchronization/rbx_object.rb +30 -73
  93. data/lib/concurrent/synchronization/volatile.rb +34 -0
  94. data/lib/concurrent/thread_safe/synchronized_delegator.rb +50 -0
  95. data/lib/concurrent/thread_safe/util.rb +14 -0
  96. data/lib/concurrent/thread_safe/util/adder.rb +74 -0
  97. data/lib/concurrent/thread_safe/util/array_hash_rbx.rb +30 -0
  98. data/lib/concurrent/thread_safe/util/cheap_lockable.rb +118 -0
  99. data/lib/concurrent/thread_safe/util/power_of_two_tuple.rb +38 -0
  100. data/lib/concurrent/thread_safe/util/striped64.rb +241 -0
  101. data/lib/concurrent/thread_safe/util/volatile.rb +75 -0
  102. data/lib/concurrent/thread_safe/util/xor_shift_random.rb +50 -0
  103. data/lib/concurrent/timer_task.rb +3 -4
  104. data/lib/concurrent/tuple.rb +86 -0
  105. data/lib/concurrent/tvar.rb +5 -1
  106. data/lib/concurrent/utility/at_exit.rb +1 -1
  107. data/lib/concurrent/utility/engine.rb +4 -0
  108. data/lib/concurrent/utility/monotonic_time.rb +3 -4
  109. data/lib/concurrent/utility/native_extension_loader.rb +50 -30
  110. data/lib/concurrent/version.rb +2 -2
  111. data/lib/concurrent_ruby_ext.jar +0 -0
  112. metadata +47 -12
  113. data/lib/concurrent/atomic/condition.rb +0 -78
  114. data/lib/concurrent/collection/priority_queue.rb +0 -360
  115. data/lib/concurrent/synchronization/java_object.rb +0 -34
  116. data/lib/concurrent/synchronization/monitor_object.rb +0 -27
  117. data/lib/concurrent/synchronization/mutex_object.rb +0 -43
  118. data/lib/concurrent/utilities.rb +0 -5
  119. data/lib/concurrent/utility/timeout.rb +0 -39
  120. data/lib/concurrent/utility/timer.rb +0 -26
  121. data/lib/concurrent_ruby.rb +0 -2
@@ -1,5 +1,6 @@
1
1
  require 'concurrent/atomic/event'
2
- require 'concurrent/executor/executor_service'
2
+ require 'concurrent/executor/abstract_executor_service'
3
+ require 'concurrent/executor/serial_executor_service'
3
4
 
4
5
  module Concurrent
5
6
 
@@ -13,7 +14,7 @@ module Concurrent
13
14
  # during testing because it makes all operations deterministic.
14
15
  #
15
16
  # @note Intended for use primarily in testing and debugging.
16
- class ImmediateExecutor
17
+ class ImmediateExecutor < AbstractExecutorService
17
18
  include SerialExecutorService
18
19
 
19
20
  # Creates a new executor
@@ -0,0 +1,100 @@
1
+ if Concurrent.on_jruby?
2
+
3
+ require 'concurrent/errors'
4
+ require 'concurrent/utility/engine'
5
+ require 'concurrent/executor/abstract_executor_service'
6
+
7
+ module Concurrent
8
+
9
+ # @!macro abstract_executor_service_public_api
10
+ # @!visibility private
11
+ class JavaExecutorService < AbstractExecutorService
12
+ java_import 'java.lang.Runnable'
13
+
14
+ FALLBACK_POLICY_CLASSES = {
15
+ abort: java.util.concurrent.ThreadPoolExecutor::AbortPolicy,
16
+ discard: java.util.concurrent.ThreadPoolExecutor::DiscardPolicy,
17
+ caller_runs: java.util.concurrent.ThreadPoolExecutor::CallerRunsPolicy
18
+ }.freeze
19
+ private_constant :FALLBACK_POLICY_CLASSES
20
+
21
+ def initialize(*args, &block)
22
+ super
23
+ ns_make_executor_runnable
24
+ end
25
+
26
+ def post(*args, &task)
27
+ raise ArgumentError.new('no block given') unless block_given?
28
+ return handle_fallback(*args, &task) unless running?
29
+ @executor.submit_runnable Job.new(args, task)
30
+ true
31
+ rescue Java::JavaUtilConcurrent::RejectedExecutionException
32
+ raise RejectedExecutionError
33
+ end
34
+
35
+ def wait_for_termination(timeout = nil)
36
+ if timeout.nil?
37
+ ok = @executor.awaitTermination(60, java.util.concurrent.TimeUnit::SECONDS) until ok
38
+ true
39
+ else
40
+ @executor.awaitTermination(1000 * timeout, java.util.concurrent.TimeUnit::MILLISECONDS)
41
+ end
42
+ end
43
+
44
+ def shutdown
45
+ synchronize do
46
+ self.ns_auto_terminate = false
47
+ @executor.shutdown
48
+ nil
49
+ end
50
+ end
51
+
52
+ def kill
53
+ synchronize do
54
+ self.ns_auto_terminate = false
55
+ @executor.shutdownNow
56
+ nil
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ def ns_running?
63
+ !(ns_shuttingdown? || ns_shutdown?)
64
+ end
65
+
66
+ def ns_shuttingdown?
67
+ if @executor.respond_to? :isTerminating
68
+ @executor.isTerminating
69
+ else
70
+ false
71
+ end
72
+ end
73
+
74
+ def ns_shutdown?
75
+ @executor.isShutdown || @executor.isTerminated
76
+ end
77
+
78
+ def ns_make_executor_runnable
79
+ if !defined?(@executor.submit_runnable)
80
+ @executor.class.class_eval do
81
+ java_alias :submit_runnable, :submit, [java.lang.Runnable.java_class]
82
+ end
83
+ end
84
+ end
85
+
86
+ class Job
87
+ include Runnable
88
+ def initialize(args, block)
89
+ @args = args
90
+ @block = block
91
+ end
92
+
93
+ def run
94
+ @block.call(*@args)
95
+ end
96
+ end
97
+ private_constant :Job
98
+ end
99
+ end
100
+ end
@@ -1,11 +1,11 @@
1
1
  if Concurrent.on_jruby?
2
2
 
3
- require 'concurrent/executor/executor_service'
3
+ require 'concurrent/executor/java_executor_service'
4
+ require 'concurrent/executor/serial_executor_service'
4
5
 
5
6
  module Concurrent
6
7
 
7
8
  # @!macro single_thread_executor
8
- # @!macro thread_pool_options
9
9
  # @!macro abstract_executor_service_public_api
10
10
  # @!visibility private
11
11
  class JavaSingleThreadExecutor < JavaExecutorService
@@ -16,7 +16,7 @@ if Concurrent.on_jruby?
16
16
  super(opts)
17
17
  end
18
18
 
19
- protected
19
+ private
20
20
 
21
21
  def ns_initialize(opts)
22
22
  @executor = java.util.concurrent.Executors.newSingleThreadExecutor
@@ -1,6 +1,6 @@
1
1
  if Concurrent.on_jruby?
2
2
 
3
- require 'concurrent/executor/executor_service'
3
+ require 'concurrent/executor/java_executor_service'
4
4
 
5
5
  module Concurrent
6
6
 
@@ -87,15 +87,14 @@ if Concurrent.on_jruby?
87
87
  super && !@executor.isTerminating
88
88
  end
89
89
 
90
- protected
90
+ private
91
91
 
92
92
  def ns_initialize(opts)
93
93
  min_length = opts.fetch(:min_threads, DEFAULT_MIN_POOL_SIZE).to_i
94
94
  max_length = opts.fetch(:max_threads, DEFAULT_MAX_POOL_SIZE).to_i
95
95
  idletime = opts.fetch(:idletime, DEFAULT_THREAD_IDLETIMEOUT).to_i
96
96
  @max_queue = opts.fetch(:max_queue, DEFAULT_MAX_QUEUE_SIZE).to_i
97
- @fallback_policy = opts.fetch(:fallback_policy, opts.fetch(:overflow_policy, :abort))
98
- deprecated ' :overflow_policy is deprecated terminology, please use :fallback_policy instead' if opts.has_key?(:overflow_policy)
97
+ @fallback_policy = opts.fetch(:fallback_policy, :abort)
99
98
 
100
99
  raise ArgumentError.new("`max_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}") if max_length < DEFAULT_MIN_POOL_SIZE
101
100
  raise ArgumentError.new("`max_threads` cannot be greater than #{DEFAULT_MAX_POOL_SIZE}") if max_length > DEFAULT_MAX_POOL_SIZE
@@ -0,0 +1,78 @@
1
+ require 'concurrent/executor/abstract_executor_service'
2
+ require 'concurrent/atomic/event'
3
+
4
+ module Concurrent
5
+
6
+ # @!macro abstract_executor_service_public_api
7
+ # @!visibility private
8
+ class RubyExecutorService < AbstractExecutorService
9
+ safe_initialization!
10
+
11
+ def initialize(*args, &block)
12
+ super
13
+ @StopEvent = Event.new
14
+ @StoppedEvent = Event.new
15
+ end
16
+
17
+ def post(*args, &task)
18
+ raise ArgumentError.new('no block given') unless block_given?
19
+ synchronize do
20
+ # If the executor is shut down, reject this task
21
+ return handle_fallback(*args, &task) unless running?
22
+ ns_execute(*args, &task)
23
+ true
24
+ end
25
+ end
26
+
27
+ def shutdown
28
+ synchronize do
29
+ break unless running?
30
+ self.ns_auto_terminate = false
31
+ stop_event.set
32
+ ns_shutdown_execution
33
+ end
34
+ true
35
+ end
36
+
37
+ def kill
38
+ synchronize do
39
+ break if shutdown?
40
+ self.ns_auto_terminate = false
41
+ stop_event.set
42
+ ns_kill_execution
43
+ stopped_event.set
44
+ end
45
+ true
46
+ end
47
+
48
+ def wait_for_termination(timeout = nil)
49
+ stopped_event.wait(timeout)
50
+ end
51
+
52
+ private
53
+
54
+ def stop_event
55
+ @StopEvent
56
+ end
57
+
58
+ def stopped_event
59
+ @StoppedEvent
60
+ end
61
+
62
+ def ns_shutdown_execution
63
+ stopped_event.set
64
+ end
65
+
66
+ def ns_running?
67
+ !stop_event.set?
68
+ end
69
+
70
+ def ns_shuttingdown?
71
+ !(ns_running? || ns_shutdown?)
72
+ end
73
+
74
+ def ns_shutdown?
75
+ stopped_event.set?
76
+ end
77
+ end
78
+ end
@@ -1,78 +1,22 @@
1
- require 'concurrent/executor/executor_service'
1
+ require 'concurrent/executor/ruby_thread_pool_executor'
2
2
 
3
3
  module Concurrent
4
4
 
5
5
  # @!macro single_thread_executor
6
- # @!macro thread_pool_options
7
6
  # @!macro abstract_executor_service_public_api
8
7
  # @!visibility private
9
- class RubySingleThreadExecutor < RubyExecutorService
10
- include SerialExecutorService
8
+ class RubySingleThreadExecutor < RubyThreadPoolExecutor
11
9
 
12
10
  # @!macro single_thread_executor_method_initialize
13
11
  def initialize(opts = {})
14
- super
15
- end
16
-
17
- protected
18
-
19
- def ns_initialize(opts)
20
- @queue = Queue.new
21
- @thread = nil
22
- @fallback_policy = opts.fetch(:fallback_policy, :discard)
23
- raise ArgumentError.new("#{@fallback_policy} is not a valid fallback policy") unless FALLBACK_POLICIES.include?(@fallback_policy)
24
- self.auto_terminate = opts.fetch(:auto_terminate, true)
25
- end
26
-
27
- # @!visibility private
28
- def execute(*args, &task)
29
- supervise
30
- @queue << [args, task]
31
- end
32
-
33
- # @!visibility private
34
- def shutdown_execution
35
- @queue << :stop
36
- stopped_event.set unless alive?
37
- end
38
-
39
- # @!visibility private
40
- def kill_execution
41
- @queue.clear
42
- @thread.kill if alive?
43
- end
44
-
45
- # @!visibility private
46
- def alive?
47
- @thread && @thread.alive?
48
- end
49
-
50
- # @!visibility private
51
- def supervise
52
- @thread = new_worker_thread unless alive?
53
- end
54
-
55
- # @!visibility private
56
- def new_worker_thread
57
- Thread.new do
58
- Thread.current.abort_on_exception = false
59
- work
60
- end
61
- end
62
-
63
- # @!visibility private
64
- def work
65
- loop do
66
- task = @queue.pop
67
- break if task == :stop
68
- begin
69
- task.last.call(*task.first)
70
- rescue => ex
71
- # let it fail
72
- log DEBUG, ex
73
- end
74
- end
75
- stopped_event.set
12
+ super(
13
+ min_threads: 1,
14
+ max_threads: 1,
15
+ max_queue: 0,
16
+ idletime: DEFAULT_THREAD_IDLETIMEOUT,
17
+ fallback_policy: opts.fetch(:fallback_policy, :discard),
18
+ auto_terminate: opts.fetch(:auto_terminate, true)
19
+ )
76
20
  end
77
21
  end
78
22
  end
@@ -1,8 +1,7 @@
1
1
  require 'thread'
2
-
3
2
  require 'concurrent/atomic/event'
4
3
  require 'concurrent/concern/logging'
5
- require 'concurrent/executor/executor_service'
4
+ require 'concurrent/executor/ruby_executor_service'
6
5
  require 'concurrent/utility/monotonic_time'
7
6
 
8
7
  module Concurrent
@@ -30,15 +29,6 @@ module Concurrent
30
29
  # @!macro thread_pool_executor_attr_reader_min_length
31
30
  attr_reader :min_length
32
31
 
33
- # @!macro thread_pool_executor_attr_reader_largest_length
34
- attr_reader :largest_length
35
-
36
- # @!macro thread_pool_executor_attr_reader_scheduled_task_count
37
- attr_reader :scheduled_task_count
38
-
39
- # @!macro thread_pool_executor_attr_reader_completed_task_count
40
- attr_reader :completed_task_count
41
-
42
32
  # @!macro thread_pool_executor_attr_reader_idletime
43
33
  attr_reader :idletime
44
34
 
@@ -50,6 +40,21 @@ module Concurrent
50
40
  super(opts)
51
41
  end
52
42
 
43
+ # @!macro thread_pool_executor_attr_reader_largest_length
44
+ def largest_length
45
+ synchronize { @largest_length }
46
+ end
47
+
48
+ # @!macro thread_pool_executor_attr_reader_scheduled_task_count
49
+ def scheduled_task_count
50
+ synchronize { @scheduled_task_count }
51
+ end
52
+
53
+ # @!macro thread_pool_executor_attr_reader_completed_task_count
54
+ def completed_task_count
55
+ synchronize { @completed_task_count }
56
+ end
57
+
53
58
  # @!macro executor_service_method_can_overflow_question
54
59
  def can_overflow?
55
60
  synchronize { ns_limited_queue? }
@@ -96,7 +101,12 @@ module Concurrent
96
101
  synchronize { ns_worker_died worker }
97
102
  end
98
103
 
99
- protected
104
+ # @!visibility private
105
+ def worker_task_completed
106
+ synchronize { @completed_task_count += 1 }
107
+ end
108
+
109
+ private
100
110
 
101
111
  # @!visibility private
102
112
  def ns_initialize(opts)
@@ -104,9 +114,8 @@ module Concurrent
104
114
  @max_length = opts.fetch(:max_threads, DEFAULT_MAX_POOL_SIZE).to_i
105
115
  @idletime = opts.fetch(:idletime, DEFAULT_THREAD_IDLETIMEOUT).to_i
106
116
  @max_queue = opts.fetch(:max_queue, DEFAULT_MAX_QUEUE_SIZE).to_i
107
- @fallback_policy = opts.fetch(:fallback_policy, opts.fetch(:overflow_policy, :abort))
117
+ @fallback_policy = opts.fetch(:fallback_policy, :abort)
108
118
  raise ArgumentError.new("#{@fallback_policy} is not a valid fallback policy") unless FALLBACK_POLICIES.include?(@fallback_policy)
109
- deprecated ':overflow_policy is deprecated terminology, please use :fallback_policy instead' if opts.has_key?(:overflow_policy)
110
119
 
111
120
  raise ArgumentError.new("`max_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}") if @max_length < DEFAULT_MIN_POOL_SIZE
112
121
  raise ArgumentError.new("`max_threads` cannot be greater than #{DEFAULT_MAX_POOL_SIZE}") if @max_length > DEFAULT_MAX_POOL_SIZE
@@ -144,8 +153,6 @@ module Concurrent
144
153
  # raise unless @ready.empty? || @queue.empty? # assert
145
154
  end
146
155
 
147
- alias_method :execute, :ns_execute
148
-
149
156
  # @!visibility private
150
157
  def ns_shutdown_execution
151
158
  if @pool.empty?
@@ -160,8 +167,6 @@ module Concurrent
160
167
  # raise unless @ready.empty? || @queue.empty? # assert
161
168
  end
162
169
 
163
- alias_method :shutdown_execution, :ns_shutdown_execution
164
-
165
170
  # @!visibility private
166
171
  def ns_kill_execution
167
172
  # TODO log out unprocessed tasks in queue
@@ -171,8 +176,6 @@ module Concurrent
171
176
  @ready.clear
172
177
  end
173
178
 
174
- alias_method :kill_execution, :ns_kill_execution
175
-
176
179
  # tries to assign task to a worker, tries to get one from @ready or to create new one
177
180
  # @return [true, false] if task is assigned to a worker
178
181
  #
@@ -227,8 +230,7 @@ module Concurrent
227
230
  #
228
231
  # @!visibility private
229
232
  def ns_ready_worker(worker, success = true)
230
- @completed_task_count += 1 if success
231
- task_and_args = @queue.shift
233
+ task_and_args = @queue.shift
232
234
  if task_and_args
233
235
  worker << task_and_args
234
236
  else
@@ -329,6 +331,7 @@ module Concurrent
329
331
 
330
332
  def run_task(pool, task, args)
331
333
  task.call(*args)
334
+ pool.worker_task_completed
332
335
  rescue => ex
333
336
  # let it fail
334
337
  log DEBUG, ex