concurrent-ruby 1.1.5 → 1.1.9

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 (131) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +51 -1
  3. data/Gemfile +5 -4
  4. data/{LICENSE.md → LICENSE.txt} +18 -20
  5. data/README.md +34 -7
  6. data/Rakefile +44 -32
  7. data/lib/{concurrent-ruby.rb → concurrent-ruby/concurrent-ruby.rb} +0 -0
  8. data/lib/{concurrent.rb → concurrent-ruby/concurrent.rb} +0 -0
  9. data/lib/{concurrent → concurrent-ruby/concurrent}/agent.rb +0 -0
  10. data/lib/{concurrent → concurrent-ruby/concurrent}/array.rb +6 -6
  11. data/lib/{concurrent → concurrent-ruby/concurrent}/async.rb +9 -20
  12. data/lib/{concurrent → concurrent-ruby/concurrent}/atom.rb +1 -1
  13. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/abstract_thread_local_var.rb +0 -0
  14. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_boolean.rb +2 -2
  15. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_fixnum.rb +0 -0
  16. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_markable_reference.rb +0 -0
  17. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_reference.rb +0 -0
  18. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/count_down_latch.rb +1 -1
  19. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/cyclic_barrier.rb +0 -0
  20. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/event.rb +0 -0
  21. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/java_count_down_latch.rb +0 -0
  22. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/java_thread_local_var.rb +0 -0
  23. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_atomic_boolean.rb +0 -0
  24. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_atomic_fixnum.rb +0 -0
  25. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_count_down_latch.rb +0 -0
  26. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_semaphore.rb +0 -0
  27. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/read_write_lock.rb +0 -0
  28. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/reentrant_read_write_lock.rb +0 -0
  29. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/ruby_thread_local_var.rb +60 -40
  30. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/semaphore.rb +0 -0
  31. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/thread_local_var.rb +1 -1
  32. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic_reference/mutex_atomic.rb +0 -0
  33. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic_reference/numeric_cas_wrapper.rb +0 -0
  34. data/lib/{concurrent → concurrent-ruby/concurrent}/atomics.rb +0 -0
  35. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/copy_on_notify_observer_set.rb +0 -0
  36. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/copy_on_write_observer_set.rb +0 -0
  37. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/java_non_concurrent_priority_queue.rb +0 -0
  38. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/lock_free_stack.rb +0 -0
  39. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/atomic_reference_map_backend.rb +0 -0
  40. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/mri_map_backend.rb +1 -1
  41. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/non_concurrent_map_backend.rb +0 -0
  42. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/synchronized_map_backend.rb +0 -0
  43. data/lib/concurrent-ruby/concurrent/collection/map/truffleruby_map_backend.rb +14 -0
  44. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/non_concurrent_priority_queue.rb +1 -1
  45. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/ruby_non_concurrent_priority_queue.rb +11 -1
  46. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/deprecation.rb +0 -0
  47. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/dereferenceable.rb +2 -2
  48. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/logging.rb +0 -0
  49. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/obligation.rb +0 -0
  50. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/observable.rb +0 -0
  51. data/lib/concurrent-ruby/concurrent/concurrent_ruby.jar +0 -0
  52. data/lib/{concurrent → concurrent-ruby/concurrent}/configuration.rb +13 -9
  53. data/lib/{concurrent → concurrent-ruby/concurrent}/constants.rb +0 -0
  54. data/lib/{concurrent → concurrent-ruby/concurrent}/dataflow.rb +0 -0
  55. data/lib/{concurrent → concurrent-ruby/concurrent}/delay.rb +0 -0
  56. data/lib/{concurrent → concurrent-ruby/concurrent}/errors.rb +0 -0
  57. data/lib/{concurrent → concurrent-ruby/concurrent}/exchanger.rb +0 -0
  58. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/abstract_executor_service.rb +17 -23
  59. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/cached_thread_pool.rb +4 -4
  60. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/executor_service.rb +2 -2
  61. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/fixed_thread_pool.rb +16 -12
  62. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/immediate_executor.rb +0 -0
  63. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/indirect_immediate_executor.rb +0 -0
  64. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_executor_service.rb +18 -6
  65. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_single_thread_executor.rb +4 -3
  66. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_thread_pool_executor.rb +15 -2
  67. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_executor_service.rb +0 -2
  68. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_single_thread_executor.rb +0 -1
  69. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_thread_pool_executor.rb +20 -5
  70. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/safe_task_executor.rb +0 -0
  71. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serial_executor_service.rb +0 -0
  72. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serialized_execution.rb +0 -0
  73. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serialized_execution_delegator.rb +0 -0
  74. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/simple_executor_service.rb +1 -1
  75. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/single_thread_executor.rb +1 -0
  76. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/thread_pool_executor.rb +2 -1
  77. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/timer_set.rb +0 -1
  78. data/lib/{concurrent → concurrent-ruby/concurrent}/executors.rb +0 -0
  79. data/lib/{concurrent → concurrent-ruby/concurrent}/future.rb +0 -0
  80. data/lib/{concurrent → concurrent-ruby/concurrent}/hash.rb +1 -1
  81. data/lib/{concurrent → concurrent-ruby/concurrent}/immutable_struct.rb +9 -1
  82. data/lib/{concurrent → concurrent-ruby/concurrent}/ivar.rb +0 -0
  83. data/lib/{concurrent → concurrent-ruby/concurrent}/map.rb +14 -4
  84. data/lib/{concurrent → concurrent-ruby/concurrent}/maybe.rb +0 -0
  85. data/lib/{concurrent → concurrent-ruby/concurrent}/mutable_struct.rb +12 -2
  86. data/lib/{concurrent → concurrent-ruby/concurrent}/mvar.rb +0 -0
  87. data/lib/{concurrent → concurrent-ruby/concurrent}/options.rb +0 -0
  88. data/lib/{concurrent → concurrent-ruby/concurrent}/promise.rb +1 -0
  89. data/lib/{concurrent → concurrent-ruby/concurrent}/promises.rb +0 -0
  90. data/lib/{concurrent → concurrent-ruby/concurrent}/re_include.rb +0 -0
  91. data/lib/{concurrent → concurrent-ruby/concurrent}/scheduled_task.rb +0 -0
  92. data/lib/{concurrent → concurrent-ruby/concurrent}/set.rb +19 -11
  93. data/lib/{concurrent → concurrent-ruby/concurrent}/settable_struct.rb +11 -1
  94. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization.rb +0 -0
  95. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_lockable_object.rb +0 -0
  96. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_object.rb +0 -0
  97. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_struct.rb +11 -0
  98. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/condition.rb +0 -0
  99. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/jruby_lockable_object.rb +0 -0
  100. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/jruby_object.rb +0 -0
  101. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/lock.rb +0 -0
  102. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/lockable_object.rb +2 -2
  103. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/mri_object.rb +0 -0
  104. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/mutex_lockable_object.rb +12 -0
  105. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/object.rb +0 -0
  106. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/rbx_lockable_object.rb +6 -0
  107. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/rbx_object.rb +0 -0
  108. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/truffleruby_object.rb +0 -0
  109. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/volatile.rb +0 -0
  110. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/synchronized_delegator.rb +0 -0
  111. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util.rb +0 -0
  112. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/adder.rb +0 -0
  113. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/cheap_lockable.rb +0 -0
  114. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/data_structures.rb +26 -1
  115. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/power_of_two_tuple.rb +0 -0
  116. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/striped64.rb +1 -1
  117. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/volatile.rb +0 -0
  118. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/xor_shift_random.rb +0 -0
  119. data/lib/{concurrent → concurrent-ruby/concurrent}/timer_task.rb +0 -1
  120. data/lib/{concurrent → concurrent-ruby/concurrent}/tuple.rb +0 -0
  121. data/lib/{concurrent → concurrent-ruby/concurrent}/tvar.rb +9 -6
  122. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/engine.rb +0 -0
  123. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/monotonic_time.rb +0 -0
  124. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/native_extension_loader.rb +0 -0
  125. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/native_integer.rb +0 -0
  126. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/processor_counter.rb +5 -0
  127. data/lib/concurrent-ruby/concurrent/version.rb +3 -0
  128. metadata +128 -128
  129. data/lib/concurrent/concurrent_ruby.jar +0 -0
  130. data/lib/concurrent/utility/at_exit.rb +0 -97
  131. data/lib/concurrent/version.rb +0 -3
@@ -1,7 +1,7 @@
1
1
  require 'concurrent/errors'
2
+ require 'concurrent/concern/deprecation'
2
3
  require 'concurrent/executor/executor_service'
3
4
  require 'concurrent/synchronization'
4
- require 'concurrent/utility/at_exit'
5
5
 
6
6
  module Concurrent
7
7
 
@@ -9,6 +9,7 @@ module Concurrent
9
9
  # @!visibility private
10
10
  class AbstractExecutorService < Synchronization::LockableObject
11
11
  include ExecutorService
12
+ include Concern::Deprecation
12
13
 
13
14
  # The set of possible fallback policies that may be set at thread pool creation.
14
15
  FALLBACK_POLICIES = [:abort, :discard, :caller_runs].freeze
@@ -16,10 +17,20 @@ module Concurrent
16
17
  # @!macro executor_service_attr_reader_fallback_policy
17
18
  attr_reader :fallback_policy
18
19
 
20
+ attr_reader :name
21
+
19
22
  # Create a new thread pool.
20
- def initialize(*args, &block)
23
+ def initialize(opts = {}, &block)
21
24
  super(&nil)
22
- synchronize { ns_initialize(*args, &block) }
25
+ synchronize do
26
+ @auto_terminate = opts.fetch(:auto_terminate, true)
27
+ @name = opts.fetch(:name) if opts.key?(:name)
28
+ ns_initialize(opts, &block)
29
+ end
30
+ end
31
+
32
+ def to_s
33
+ name ? "#{super[0..-2]} name: #{name}>" : super
23
34
  end
24
35
 
25
36
  # @!macro executor_service_method_shutdown
@@ -54,12 +65,12 @@ module Concurrent
54
65
 
55
66
  # @!macro executor_service_method_auto_terminate_question
56
67
  def auto_terminate?
57
- synchronize { ns_auto_terminate? }
68
+ synchronize { @auto_terminate }
58
69
  end
59
70
 
60
71
  # @!macro executor_service_method_auto_terminate_setter
61
72
  def auto_terminate=(value)
62
- synchronize { self.ns_auto_terminate = value }
73
+ deprecated "Method #auto_terminate= has no effect. Set :auto_terminate option when executor is initialized."
63
74
  end
64
75
 
65
76
  private
@@ -110,25 +121,8 @@ module Concurrent
110
121
  end
111
122
 
112
123
  def ns_auto_terminate?
113
- !!@auto_terminate
124
+ @auto_terminate
114
125
  end
115
126
 
116
- def ns_auto_terminate=(value)
117
- case value
118
- when true
119
- AtExit.add(self) { terminate_at_exit }
120
- @auto_terminate = true
121
- when false
122
- AtExit.delete(self)
123
- @auto_terminate = false
124
- else
125
- raise ArgumentError
126
- end
127
- end
128
-
129
- def terminate_at_exit
130
- kill # TODO be gentle first
131
- wait_for_termination(10)
132
- end
133
127
  end
134
128
  end
@@ -37,7 +37,7 @@ module Concurrent
37
37
  #
38
38
  # @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executors.html#newCachedThreadPool--
39
39
  def initialize(opts = {})
40
- defaults = { idletime: DEFAULT_THREAD_IDLETIMEOUT }
40
+ defaults = { idletime: DEFAULT_THREAD_IDLETIMEOUT }
41
41
  overrides = { min_threads: 0,
42
42
  max_threads: DEFAULT_MAX_POOL_SIZE,
43
43
  max_queue: DEFAULT_MAX_QUEUE_SIZE }
@@ -51,11 +51,11 @@ module Concurrent
51
51
  def ns_initialize(opts)
52
52
  super(opts)
53
53
  if Concurrent.on_jruby?
54
- @max_queue = 0
55
- @executor = java.util.concurrent.Executors.newCachedThreadPool
54
+ @max_queue = 0
55
+ @executor = java.util.concurrent.Executors.newCachedThreadPool(
56
+ DaemonThreadFactory.new(ns_auto_terminate?))
56
57
  @executor.setRejectedExecutionHandler(FALLBACK_POLICY_CLASSES[@fallback_policy].new)
57
58
  @executor.setKeepAliveTime(opts.fetch(:idletime, DEFAULT_THREAD_IDLETIMEOUT), java.util.concurrent.TimeUnit::SECONDS)
58
- self.auto_terminate = opts.fetch(:auto_terminate, true)
59
59
  end
60
60
  end
61
61
  end
@@ -111,10 +111,10 @@ module Concurrent
111
111
 
112
112
  # @!macro executor_service_method_auto_terminate_setter
113
113
  #
114
- # Set the auto-terminate behavior for this executor.
115
114
  #
115
+ # Set the auto-terminate behavior for this executor.
116
+ # @deprecated Has no effect
116
117
  # @param [Boolean] value The new auto-terminate value to set for this executor.
117
- #
118
118
  # @return [Boolean] `true` when auto-termination is enabled else `false`.
119
119
 
120
120
  ###################################################################
@@ -16,6 +16,9 @@ module Concurrent
16
16
  # Default maximum number of seconds a thread in the pool may remain idle
17
17
  # before being reclaimed.
18
18
 
19
+ # @!macro thread_pool_executor_constant_default_synchronous
20
+ # Default value of the :synchronous option.
21
+
19
22
  # @!macro thread_pool_executor_attr_reader_max_length
20
23
  # The maximum number of threads that may be created in the pool.
21
24
  # @return [Integer] The maximum number of threads that may be created in the pool.
@@ -40,6 +43,10 @@ module Concurrent
40
43
  # The number of seconds that a thread may be idle before being reclaimed.
41
44
  # @return [Integer] The number of seconds that a thread may be idle before being reclaimed.
42
45
 
46
+ # @!macro thread_pool_executor_attr_reader_synchronous
47
+ # Whether or not a value of 0 for :max_queue option means the queue must perform direct hand-off or rather unbounded queue.
48
+ # @return [true, false]
49
+
43
50
  # @!macro thread_pool_executor_attr_reader_max_queue
44
51
  # The maximum number of tasks that may be waiting in the work queue at any one time.
45
52
  # When the queue size reaches `max_queue` subsequent tasks will be rejected in
@@ -115,12 +122,13 @@ module Concurrent
115
122
  # Thread pools support several configuration options:
116
123
  #
117
124
  # * `idletime`: The number of seconds that a thread may be idle before being reclaimed.
125
+ # * `name`: The name of the executor (optional). Printed in the executor's `#to_s` output and
126
+ # a `<name>-worker-<id>` name is given to its threads if supported by used Ruby
127
+ # implementation. `<id>` is uniq for each thread.
118
128
  # * `max_queue`: The maximum number of tasks that may be waiting in the work queue at
119
129
  # any one time. When the queue size reaches `max_queue` and no new threads can be created,
120
130
  # subsequent tasks will be rejected in accordance with the configured `fallback_policy`.
121
- # * `auto_terminate`: When true (default) an `at_exit` handler will be registered which
122
- # will stop the thread pool when the application exits. See below for more information
123
- # on shutting down thread pools.
131
+ # * `auto_terminate`: When true (default), the threads started will be marked as daemon.
124
132
  # * `fallback_policy`: The policy defining how rejected tasks are handled.
125
133
  #
126
134
  # Three fallback policies are supported:
@@ -145,16 +153,12 @@ module Concurrent
145
153
  #
146
154
  # On some runtime platforms (most notably the JVM) the application will not
147
155
  # exit until all thread pools have been shutdown. To prevent applications from
148
- # "hanging" on exit all thread pools include an `at_exit` handler that will
149
- # stop the thread pool when the application exits. This handler uses a brute
150
- # force method to stop the pool and makes no guarantees regarding resources being
151
- # used by any tasks still running. Registration of this `at_exit` handler can be
152
- # prevented by setting the thread pool's constructor `:auto_terminate` option to
153
- # `false` when the thread pool is created. All thread pools support this option.
156
+ # "hanging" on exit, all threads can be marked as daemon according to the
157
+ # `:auto_terminate` option.
154
158
  #
155
159
  # ```ruby
156
- # pool1 = Concurrent::FixedThreadPool.new(5) # an `at_exit` handler will be registered
157
- # pool2 = Concurrent::FixedThreadPool.new(5, auto_terminate: false) # prevent `at_exit` handler registration
160
+ # pool1 = Concurrent::FixedThreadPool.new(5) # threads will be marked as daemon
161
+ # pool2 = Concurrent::FixedThreadPool.new(5, auto_terminate: false) # mark threads as non-daemon
158
162
  # ```
159
163
  #
160
164
  # @note Failure to properly shutdown a thread pool can lead to unpredictable results.
@@ -163,7 +167,7 @@ module Concurrent
163
167
  # @see http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html Java Tutorials: Thread Pools
164
168
  # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html Java Executors class
165
169
  # @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html Java ExecutorService interface
166
- # @see http://ruby-doc.org//core-2.2.0/Kernel.html#method-i-at_exit Kernel#at_exit
170
+ # @see https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setDaemon-boolean-
167
171
 
168
172
 
169
173
 
@@ -18,10 +18,6 @@ if Concurrent.on_jruby?
18
18
  }.freeze
19
19
  private_constant :FALLBACK_POLICY_CLASSES
20
20
 
21
- def initialize(*args, &block)
22
- super
23
- end
24
-
25
21
  def post(*args, &task)
26
22
  raise ArgumentError.new('no block given') unless block_given?
27
23
  return handle_fallback(*args, &task) unless running?
@@ -42,7 +38,6 @@ if Concurrent.on_jruby?
42
38
 
43
39
  def shutdown
44
40
  synchronize do
45
- self.ns_auto_terminate = false
46
41
  @executor.shutdown
47
42
  nil
48
43
  end
@@ -50,7 +45,6 @@ if Concurrent.on_jruby?
50
45
 
51
46
  def kill
52
47
  synchronize do
53
- self.ns_auto_terminate = false
54
48
  @executor.shutdownNow
55
49
  nil
56
50
  end
@@ -87,5 +81,23 @@ if Concurrent.on_jruby?
87
81
  end
88
82
  private_constant :Job
89
83
  end
84
+
85
+ class DaemonThreadFactory
86
+ # hide include from YARD
87
+ send :include, java.util.concurrent.ThreadFactory
88
+
89
+ def initialize(daemonize = true)
90
+ @daemonize = daemonize
91
+ end
92
+
93
+ def newThread(runnable)
94
+ thread = java.util.concurrent.Executors.defaultThreadFactory().newThread(runnable)
95
+ thread.setDaemon(@daemonize)
96
+ return thread
97
+ end
98
+ end
99
+
100
+ private_constant :DaemonThreadFactory
101
+
90
102
  end
91
103
  end
@@ -17,12 +17,13 @@ if Concurrent.on_jruby?
17
17
  end
18
18
 
19
19
  private
20
-
20
+
21
21
  def ns_initialize(opts)
22
- @executor = java.util.concurrent.Executors.newSingleThreadExecutor
22
+ @executor = java.util.concurrent.Executors.newSingleThreadExecutor(
23
+ DaemonThreadFactory.new(ns_auto_terminate?)
24
+ )
23
25
  @fallback_policy = opts.fetch(:fallback_policy, :discard)
24
26
  raise ArgumentError.new("#{@fallback_policy} is not a valid fallback policy") unless FALLBACK_POLICY_CLASSES.keys.include?(@fallback_policy)
25
- self.auto_terminate = opts.fetch(:auto_terminate, true)
26
27
  end
27
28
  end
28
29
  end
@@ -21,12 +21,18 @@ if Concurrent.on_jruby?
21
21
  # @!macro thread_pool_executor_constant_default_thread_timeout
22
22
  DEFAULT_THREAD_IDLETIMEOUT = 60
23
23
 
24
+ # @!macro thread_pool_executor_constant_default_synchronous
25
+ DEFAULT_SYNCHRONOUS = false
26
+
24
27
  # @!macro thread_pool_executor_attr_reader_max_length
25
28
  attr_reader :max_length
26
29
 
27
30
  # @!macro thread_pool_executor_attr_reader_max_queue
28
31
  attr_reader :max_queue
29
32
 
33
+ # @!macro thread_pool_executor_attr_reader_synchronous
34
+ attr_reader :synchronous
35
+
30
36
  # @!macro thread_pool_executor_method_initialize
31
37
  def initialize(opts = {})
32
38
  super(opts)
@@ -94,8 +100,10 @@ if Concurrent.on_jruby?
94
100
  max_length = opts.fetch(:max_threads, DEFAULT_MAX_POOL_SIZE).to_i
95
101
  idletime = opts.fetch(:idletime, DEFAULT_THREAD_IDLETIMEOUT).to_i
96
102
  @max_queue = opts.fetch(:max_queue, DEFAULT_MAX_QUEUE_SIZE).to_i
103
+ @synchronous = opts.fetch(:synchronous, DEFAULT_SYNCHRONOUS)
97
104
  @fallback_policy = opts.fetch(:fallback_policy, :abort)
98
105
 
106
+ raise ArgumentError.new("`synchronous` cannot be set unless `max_queue` is 0") if @synchronous && @max_queue > 0
99
107
  raise ArgumentError.new("`max_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}") if max_length < DEFAULT_MIN_POOL_SIZE
100
108
  raise ArgumentError.new("`max_threads` cannot be greater than #{DEFAULT_MAX_POOL_SIZE}") if max_length > DEFAULT_MAX_POOL_SIZE
101
109
  raise ArgumentError.new("`min_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}") if min_length < DEFAULT_MIN_POOL_SIZE
@@ -103,7 +111,11 @@ if Concurrent.on_jruby?
103
111
  raise ArgumentError.new("#{fallback_policy} is not a valid fallback policy") unless FALLBACK_POLICY_CLASSES.include?(@fallback_policy)
104
112
 
105
113
  if @max_queue == 0
106
- queue = java.util.concurrent.LinkedBlockingQueue.new
114
+ if @synchronous
115
+ queue = java.util.concurrent.SynchronousQueue.new
116
+ else
117
+ queue = java.util.concurrent.LinkedBlockingQueue.new
118
+ end
107
119
  else
108
120
  queue = java.util.concurrent.LinkedBlockingQueue.new(@max_queue)
109
121
  end
@@ -114,10 +126,11 @@ if Concurrent.on_jruby?
114
126
  idletime,
115
127
  java.util.concurrent.TimeUnit::SECONDS,
116
128
  queue,
129
+ DaemonThreadFactory.new(ns_auto_terminate?),
117
130
  FALLBACK_POLICY_CLASSES[@fallback_policy].new)
118
131
 
119
- self.auto_terminate = opts.fetch(:auto_terminate, true)
120
132
  end
121
133
  end
134
+
122
135
  end
123
136
  end
@@ -27,7 +27,6 @@ module Concurrent
27
27
  def shutdown
28
28
  synchronize do
29
29
  break unless running?
30
- self.ns_auto_terminate = false
31
30
  stop_event.set
32
31
  ns_shutdown_execution
33
32
  end
@@ -37,7 +36,6 @@ module Concurrent
37
36
  def kill
38
37
  synchronize do
39
38
  break if shutdown?
40
- self.ns_auto_terminate = false
41
39
  stop_event.set
42
40
  ns_kill_execution
43
41
  stopped_event.set
@@ -15,7 +15,6 @@ module Concurrent
15
15
  max_queue: 0,
16
16
  idletime: DEFAULT_THREAD_IDLETIMEOUT,
17
17
  fallback_policy: opts.fetch(:fallback_policy, :discard),
18
- auto_terminate: opts.fetch(:auto_terminate, true)
19
18
  )
20
19
  end
21
20
  end
@@ -23,6 +23,9 @@ module Concurrent
23
23
  # @!macro thread_pool_executor_constant_default_thread_timeout
24
24
  DEFAULT_THREAD_IDLETIMEOUT = 60
25
25
 
26
+ # @!macro thread_pool_executor_constant_default_synchronous
27
+ DEFAULT_SYNCHRONOUS = false
28
+
26
29
  # @!macro thread_pool_executor_attr_reader_max_length
27
30
  attr_reader :max_length
28
31
 
@@ -35,6 +38,9 @@ module Concurrent
35
38
  # @!macro thread_pool_executor_attr_reader_max_queue
36
39
  attr_reader :max_queue
37
40
 
41
+ # @!macro thread_pool_executor_attr_reader_synchronous
42
+ attr_reader :synchronous
43
+
38
44
  # @!macro thread_pool_executor_method_initialize
39
45
  def initialize(opts = {})
40
46
  super(opts)
@@ -114,16 +120,16 @@ module Concurrent
114
120
  @max_length = opts.fetch(:max_threads, DEFAULT_MAX_POOL_SIZE).to_i
115
121
  @idletime = opts.fetch(:idletime, DEFAULT_THREAD_IDLETIMEOUT).to_i
116
122
  @max_queue = opts.fetch(:max_queue, DEFAULT_MAX_QUEUE_SIZE).to_i
123
+ @synchronous = opts.fetch(:synchronous, DEFAULT_SYNCHRONOUS)
117
124
  @fallback_policy = opts.fetch(:fallback_policy, :abort)
118
- raise ArgumentError.new("#{@fallback_policy} is not a valid fallback policy") unless FALLBACK_POLICIES.include?(@fallback_policy)
119
125
 
126
+ raise ArgumentError.new("`synchronous` cannot be set unless `max_queue` is 0") if @synchronous && @max_queue > 0
127
+ raise ArgumentError.new("#{@fallback_policy} is not a valid fallback policy") unless FALLBACK_POLICIES.include?(@fallback_policy)
120
128
  raise ArgumentError.new("`max_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}") if @max_length < DEFAULT_MIN_POOL_SIZE
121
129
  raise ArgumentError.new("`max_threads` cannot be greater than #{DEFAULT_MAX_POOL_SIZE}") if @max_length > DEFAULT_MAX_POOL_SIZE
122
130
  raise ArgumentError.new("`min_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}") if @min_length < DEFAULT_MIN_POOL_SIZE
123
131
  raise ArgumentError.new("`min_threads` cannot be more than `max_threads`") if min_length > max_length
124
132
 
125
- self.auto_terminate = opts.fetch(:auto_terminate, true)
126
-
127
133
  @pool = [] # all workers
128
134
  @ready = [] # used as a stash (most idle worker is at the start)
129
135
  @queue = [] # used as queue
@@ -131,6 +137,7 @@ module Concurrent
131
137
  @scheduled_task_count = 0
132
138
  @completed_task_count = 0
133
139
  @largest_length = 0
140
+ @workers_counter = 0
134
141
  @ruby_pid = $$ # detects if Ruby has forked
135
142
 
136
143
  @gc_interval = opts.fetch(:gc_interval, @idletime / 2.0).to_i # undocumented
@@ -202,6 +209,8 @@ module Concurrent
202
209
  #
203
210
  # @!visibility private
204
211
  def ns_enqueue(*args, &task)
212
+ return false if @synchronous
213
+
205
214
  if !ns_limited_queue? || @queue.size < @max_queue
206
215
  @queue << [task, args]
207
216
  true
@@ -224,7 +233,8 @@ module Concurrent
224
233
  def ns_add_busy_worker
225
234
  return if @pool.size >= @max_length
226
235
 
227
- @pool << (worker = Worker.new(self))
236
+ @workers_counter += 1
237
+ @pool << (worker = Worker.new(self, @workers_counter))
228
238
  @largest_length = @pool.length if @pool.length > @largest_length
229
239
  worker
230
240
  end
@@ -284,6 +294,7 @@ module Concurrent
284
294
  @scheduled_task_count = 0
285
295
  @completed_task_count = 0
286
296
  @largest_length = 0
297
+ @workers_counter = 0
287
298
  @ruby_pid = $$
288
299
  end
289
300
  end
@@ -292,11 +303,15 @@ module Concurrent
292
303
  class Worker
293
304
  include Concern::Logging
294
305
 
295
- def initialize(pool)
306
+ def initialize(pool, id)
296
307
  # instance variables accessed only under pool's lock so no need to sync here again
297
308
  @queue = Queue.new
298
309
  @pool = pool
299
310
  @thread = create_worker @queue, pool, pool.idletime
311
+
312
+ if @thread.respond_to?(:name=)
313
+ @thread.name = [pool.name, 'worker', id].compact.join('-')
314
+ end
300
315
  end
301
316
 
302
317
  def <<(message)
@@ -91,7 +91,7 @@ module Concurrent
91
91
 
92
92
  private
93
93
 
94
- def ns_initialize
94
+ def ns_initialize(*args)
95
95
  @running = Concurrent::AtomicBoolean.new(true)
96
96
  @stopped = Concurrent::Event.new
97
97
  @count = Concurrent::AtomicFixnum.new(0)