concurrent-ruby 1.1.5

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 (143) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +478 -0
  3. data/Gemfile +41 -0
  4. data/LICENSE.md +23 -0
  5. data/README.md +381 -0
  6. data/Rakefile +327 -0
  7. data/ext/concurrent-ruby/ConcurrentRubyService.java +17 -0
  8. data/ext/concurrent-ruby/com/concurrent_ruby/ext/AtomicReferenceLibrary.java +175 -0
  9. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JRubyMapBackendLibrary.java +248 -0
  10. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicBooleanLibrary.java +93 -0
  11. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicFixnumLibrary.java +113 -0
  12. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaSemaphoreLibrary.java +159 -0
  13. data/ext/concurrent-ruby/com/concurrent_ruby/ext/SynchronizationLibrary.java +307 -0
  14. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMap.java +31 -0
  15. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMapV8.java +3863 -0
  16. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/LongAdder.java +203 -0
  17. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/Striped64.java +342 -0
  18. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/ConcurrentHashMapV8.java +3800 -0
  19. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/LongAdder.java +204 -0
  20. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/Striped64.java +291 -0
  21. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166y/ThreadLocalRandom.java +199 -0
  22. data/lib/concurrent-ruby.rb +1 -0
  23. data/lib/concurrent.rb +134 -0
  24. data/lib/concurrent/agent.rb +587 -0
  25. data/lib/concurrent/array.rb +66 -0
  26. data/lib/concurrent/async.rb +459 -0
  27. data/lib/concurrent/atom.rb +222 -0
  28. data/lib/concurrent/atomic/abstract_thread_local_var.rb +66 -0
  29. data/lib/concurrent/atomic/atomic_boolean.rb +126 -0
  30. data/lib/concurrent/atomic/atomic_fixnum.rb +143 -0
  31. data/lib/concurrent/atomic/atomic_markable_reference.rb +164 -0
  32. data/lib/concurrent/atomic/atomic_reference.rb +204 -0
  33. data/lib/concurrent/atomic/count_down_latch.rb +100 -0
  34. data/lib/concurrent/atomic/cyclic_barrier.rb +128 -0
  35. data/lib/concurrent/atomic/event.rb +109 -0
  36. data/lib/concurrent/atomic/java_count_down_latch.rb +42 -0
  37. data/lib/concurrent/atomic/java_thread_local_var.rb +37 -0
  38. data/lib/concurrent/atomic/mutex_atomic_boolean.rb +62 -0
  39. data/lib/concurrent/atomic/mutex_atomic_fixnum.rb +75 -0
  40. data/lib/concurrent/atomic/mutex_count_down_latch.rb +44 -0
  41. data/lib/concurrent/atomic/mutex_semaphore.rb +115 -0
  42. data/lib/concurrent/atomic/read_write_lock.rb +254 -0
  43. data/lib/concurrent/atomic/reentrant_read_write_lock.rb +379 -0
  44. data/lib/concurrent/atomic/ruby_thread_local_var.rb +161 -0
  45. data/lib/concurrent/atomic/semaphore.rb +145 -0
  46. data/lib/concurrent/atomic/thread_local_var.rb +104 -0
  47. data/lib/concurrent/atomic_reference/mutex_atomic.rb +56 -0
  48. data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +28 -0
  49. data/lib/concurrent/atomics.rb +10 -0
  50. data/lib/concurrent/collection/copy_on_notify_observer_set.rb +107 -0
  51. data/lib/concurrent/collection/copy_on_write_observer_set.rb +111 -0
  52. data/lib/concurrent/collection/java_non_concurrent_priority_queue.rb +84 -0
  53. data/lib/concurrent/collection/lock_free_stack.rb +158 -0
  54. data/lib/concurrent/collection/map/atomic_reference_map_backend.rb +927 -0
  55. data/lib/concurrent/collection/map/mri_map_backend.rb +66 -0
  56. data/lib/concurrent/collection/map/non_concurrent_map_backend.rb +140 -0
  57. data/lib/concurrent/collection/map/synchronized_map_backend.rb +82 -0
  58. data/lib/concurrent/collection/non_concurrent_priority_queue.rb +143 -0
  59. data/lib/concurrent/collection/ruby_non_concurrent_priority_queue.rb +150 -0
  60. data/lib/concurrent/concern/deprecation.rb +34 -0
  61. data/lib/concurrent/concern/dereferenceable.rb +73 -0
  62. data/lib/concurrent/concern/logging.rb +32 -0
  63. data/lib/concurrent/concern/obligation.rb +220 -0
  64. data/lib/concurrent/concern/observable.rb +110 -0
  65. data/lib/concurrent/concurrent_ruby.jar +0 -0
  66. data/lib/concurrent/configuration.rb +184 -0
  67. data/lib/concurrent/constants.rb +8 -0
  68. data/lib/concurrent/dataflow.rb +81 -0
  69. data/lib/concurrent/delay.rb +199 -0
  70. data/lib/concurrent/errors.rb +69 -0
  71. data/lib/concurrent/exchanger.rb +352 -0
  72. data/lib/concurrent/executor/abstract_executor_service.rb +134 -0
  73. data/lib/concurrent/executor/cached_thread_pool.rb +62 -0
  74. data/lib/concurrent/executor/executor_service.rb +185 -0
  75. data/lib/concurrent/executor/fixed_thread_pool.rb +206 -0
  76. data/lib/concurrent/executor/immediate_executor.rb +66 -0
  77. data/lib/concurrent/executor/indirect_immediate_executor.rb +44 -0
  78. data/lib/concurrent/executor/java_executor_service.rb +91 -0
  79. data/lib/concurrent/executor/java_single_thread_executor.rb +29 -0
  80. data/lib/concurrent/executor/java_thread_pool_executor.rb +123 -0
  81. data/lib/concurrent/executor/ruby_executor_service.rb +78 -0
  82. data/lib/concurrent/executor/ruby_single_thread_executor.rb +22 -0
  83. data/lib/concurrent/executor/ruby_thread_pool_executor.rb +362 -0
  84. data/lib/concurrent/executor/safe_task_executor.rb +35 -0
  85. data/lib/concurrent/executor/serial_executor_service.rb +34 -0
  86. data/lib/concurrent/executor/serialized_execution.rb +107 -0
  87. data/lib/concurrent/executor/serialized_execution_delegator.rb +28 -0
  88. data/lib/concurrent/executor/simple_executor_service.rb +100 -0
  89. data/lib/concurrent/executor/single_thread_executor.rb +56 -0
  90. data/lib/concurrent/executor/thread_pool_executor.rb +87 -0
  91. data/lib/concurrent/executor/timer_set.rb +173 -0
  92. data/lib/concurrent/executors.rb +20 -0
  93. data/lib/concurrent/future.rb +141 -0
  94. data/lib/concurrent/hash.rb +59 -0
  95. data/lib/concurrent/immutable_struct.rb +93 -0
  96. data/lib/concurrent/ivar.rb +207 -0
  97. data/lib/concurrent/map.rb +337 -0
  98. data/lib/concurrent/maybe.rb +229 -0
  99. data/lib/concurrent/mutable_struct.rb +229 -0
  100. data/lib/concurrent/mvar.rb +242 -0
  101. data/lib/concurrent/options.rb +42 -0
  102. data/lib/concurrent/promise.rb +579 -0
  103. data/lib/concurrent/promises.rb +2167 -0
  104. data/lib/concurrent/re_include.rb +58 -0
  105. data/lib/concurrent/scheduled_task.rb +318 -0
  106. data/lib/concurrent/set.rb +66 -0
  107. data/lib/concurrent/settable_struct.rb +129 -0
  108. data/lib/concurrent/synchronization.rb +30 -0
  109. data/lib/concurrent/synchronization/abstract_lockable_object.rb +98 -0
  110. data/lib/concurrent/synchronization/abstract_object.rb +24 -0
  111. data/lib/concurrent/synchronization/abstract_struct.rb +160 -0
  112. data/lib/concurrent/synchronization/condition.rb +60 -0
  113. data/lib/concurrent/synchronization/jruby_lockable_object.rb +13 -0
  114. data/lib/concurrent/synchronization/jruby_object.rb +45 -0
  115. data/lib/concurrent/synchronization/lock.rb +36 -0
  116. data/lib/concurrent/synchronization/lockable_object.rb +74 -0
  117. data/lib/concurrent/synchronization/mri_object.rb +44 -0
  118. data/lib/concurrent/synchronization/mutex_lockable_object.rb +76 -0
  119. data/lib/concurrent/synchronization/object.rb +183 -0
  120. data/lib/concurrent/synchronization/rbx_lockable_object.rb +65 -0
  121. data/lib/concurrent/synchronization/rbx_object.rb +49 -0
  122. data/lib/concurrent/synchronization/truffleruby_object.rb +47 -0
  123. data/lib/concurrent/synchronization/volatile.rb +36 -0
  124. data/lib/concurrent/thread_safe/synchronized_delegator.rb +50 -0
  125. data/lib/concurrent/thread_safe/util.rb +16 -0
  126. data/lib/concurrent/thread_safe/util/adder.rb +74 -0
  127. data/lib/concurrent/thread_safe/util/cheap_lockable.rb +118 -0
  128. data/lib/concurrent/thread_safe/util/data_structures.rb +63 -0
  129. data/lib/concurrent/thread_safe/util/power_of_two_tuple.rb +38 -0
  130. data/lib/concurrent/thread_safe/util/striped64.rb +246 -0
  131. data/lib/concurrent/thread_safe/util/volatile.rb +75 -0
  132. data/lib/concurrent/thread_safe/util/xor_shift_random.rb +50 -0
  133. data/lib/concurrent/timer_task.rb +334 -0
  134. data/lib/concurrent/tuple.rb +86 -0
  135. data/lib/concurrent/tvar.rb +258 -0
  136. data/lib/concurrent/utility/at_exit.rb +97 -0
  137. data/lib/concurrent/utility/engine.rb +56 -0
  138. data/lib/concurrent/utility/monotonic_time.rb +58 -0
  139. data/lib/concurrent/utility/native_extension_loader.rb +79 -0
  140. data/lib/concurrent/utility/native_integer.rb +53 -0
  141. data/lib/concurrent/utility/processor_counter.rb +158 -0
  142. data/lib/concurrent/version.rb +3 -0
  143. metadata +193 -0
@@ -0,0 +1,66 @@
1
+ require 'concurrent/atomic/event'
2
+ require 'concurrent/executor/abstract_executor_service'
3
+ require 'concurrent/executor/serial_executor_service'
4
+
5
+ module Concurrent
6
+
7
+ # An executor service which runs all operations on the current thread,
8
+ # blocking as necessary. Operations are performed in the order they are
9
+ # received and no two operations can be performed simultaneously.
10
+ #
11
+ # This executor service exists mainly for testing an debugging. When used
12
+ # it immediately runs every `#post` operation on the current thread, blocking
13
+ # that thread until the operation is complete. This can be very beneficial
14
+ # during testing because it makes all operations deterministic.
15
+ #
16
+ # @note Intended for use primarily in testing and debugging.
17
+ class ImmediateExecutor < AbstractExecutorService
18
+ include SerialExecutorService
19
+
20
+ # Creates a new executor
21
+ def initialize
22
+ @stopped = Concurrent::Event.new
23
+ end
24
+
25
+ # @!macro executor_service_method_post
26
+ def post(*args, &task)
27
+ raise ArgumentError.new('no block given') unless block_given?
28
+ return false unless running?
29
+ task.call(*args)
30
+ true
31
+ end
32
+
33
+ # @!macro executor_service_method_left_shift
34
+ def <<(task)
35
+ post(&task)
36
+ self
37
+ end
38
+
39
+ # @!macro executor_service_method_running_question
40
+ def running?
41
+ ! shutdown?
42
+ end
43
+
44
+ # @!macro executor_service_method_shuttingdown_question
45
+ def shuttingdown?
46
+ false
47
+ end
48
+
49
+ # @!macro executor_service_method_shutdown_question
50
+ def shutdown?
51
+ @stopped.set?
52
+ end
53
+
54
+ # @!macro executor_service_method_shutdown
55
+ def shutdown
56
+ @stopped.set
57
+ true
58
+ end
59
+ alias_method :kill, :shutdown
60
+
61
+ # @!macro executor_service_method_wait_for_termination
62
+ def wait_for_termination(timeout = nil)
63
+ @stopped.wait(timeout)
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,44 @@
1
+ require 'concurrent/executor/immediate_executor'
2
+ require 'concurrent/executor/simple_executor_service'
3
+
4
+ module Concurrent
5
+ # An executor service which runs all operations on a new thread, blocking
6
+ # until it completes. Operations are performed in the order they are received
7
+ # and no two operations can be performed simultaneously.
8
+ #
9
+ # This executor service exists mainly for testing an debugging. When used it
10
+ # immediately runs every `#post` operation on a new thread, blocking the
11
+ # current thread until the operation is complete. This is similar to how the
12
+ # ImmediateExecutor works, but the operation has the full stack of the new
13
+ # thread at its disposal. This can be helpful when the operations will spawn
14
+ # more operations on the same executor and so on - such a situation might
15
+ # overflow the single stack in case of an ImmediateExecutor, which is
16
+ # inconsistent with how it would behave for a threaded executor.
17
+ #
18
+ # @note Intended for use primarily in testing and debugging.
19
+ class IndirectImmediateExecutor < ImmediateExecutor
20
+ # Creates a new executor
21
+ def initialize
22
+ super
23
+ @internal_executor = SimpleExecutorService.new
24
+ end
25
+
26
+ # @!macro executor_service_method_post
27
+ def post(*args, &task)
28
+ raise ArgumentError.new("no block given") unless block_given?
29
+ return false unless running?
30
+
31
+ event = Concurrent::Event.new
32
+ @internal_executor.post do
33
+ begin
34
+ task.call(*args)
35
+ ensure
36
+ event.set
37
+ end
38
+ end
39
+ event.wait
40
+
41
+ true
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,91 @@
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
+ end
24
+
25
+ def post(*args, &task)
26
+ raise ArgumentError.new('no block given') unless block_given?
27
+ return handle_fallback(*args, &task) unless running?
28
+ @executor.submit Job.new(args, task)
29
+ true
30
+ rescue Java::JavaUtilConcurrent::RejectedExecutionException
31
+ raise RejectedExecutionError
32
+ end
33
+
34
+ def wait_for_termination(timeout = nil)
35
+ if timeout.nil?
36
+ ok = @executor.awaitTermination(60, java.util.concurrent.TimeUnit::SECONDS) until ok
37
+ true
38
+ else
39
+ @executor.awaitTermination(1000 * timeout, java.util.concurrent.TimeUnit::MILLISECONDS)
40
+ end
41
+ end
42
+
43
+ def shutdown
44
+ synchronize do
45
+ self.ns_auto_terminate = false
46
+ @executor.shutdown
47
+ nil
48
+ end
49
+ end
50
+
51
+ def kill
52
+ synchronize do
53
+ self.ns_auto_terminate = false
54
+ @executor.shutdownNow
55
+ nil
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ def ns_running?
62
+ !(ns_shuttingdown? || ns_shutdown?)
63
+ end
64
+
65
+ def ns_shuttingdown?
66
+ if @executor.respond_to? :isTerminating
67
+ @executor.isTerminating
68
+ else
69
+ false
70
+ end
71
+ end
72
+
73
+ def ns_shutdown?
74
+ @executor.isShutdown || @executor.isTerminated
75
+ end
76
+
77
+ class Job
78
+ include Runnable
79
+ def initialize(args, block)
80
+ @args = args
81
+ @block = block
82
+ end
83
+
84
+ def run
85
+ @block.call(*@args)
86
+ end
87
+ end
88
+ private_constant :Job
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,29 @@
1
+ if Concurrent.on_jruby?
2
+
3
+ require 'concurrent/executor/java_executor_service'
4
+ require 'concurrent/executor/serial_executor_service'
5
+
6
+ module Concurrent
7
+
8
+ # @!macro single_thread_executor
9
+ # @!macro abstract_executor_service_public_api
10
+ # @!visibility private
11
+ class JavaSingleThreadExecutor < JavaExecutorService
12
+ include SerialExecutorService
13
+
14
+ # @!macro single_thread_executor_method_initialize
15
+ def initialize(opts = {})
16
+ super(opts)
17
+ end
18
+
19
+ private
20
+
21
+ def ns_initialize(opts)
22
+ @executor = java.util.concurrent.Executors.newSingleThreadExecutor
23
+ @fallback_policy = opts.fetch(:fallback_policy, :discard)
24
+ 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
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,123 @@
1
+ if Concurrent.on_jruby?
2
+
3
+ require 'concurrent/executor/java_executor_service'
4
+
5
+ module Concurrent
6
+
7
+ # @!macro thread_pool_executor
8
+ # @!macro thread_pool_options
9
+ # @!visibility private
10
+ class JavaThreadPoolExecutor < JavaExecutorService
11
+
12
+ # @!macro thread_pool_executor_constant_default_max_pool_size
13
+ DEFAULT_MAX_POOL_SIZE = java.lang.Integer::MAX_VALUE # 2147483647
14
+
15
+ # @!macro thread_pool_executor_constant_default_min_pool_size
16
+ DEFAULT_MIN_POOL_SIZE = 0
17
+
18
+ # @!macro thread_pool_executor_constant_default_max_queue_size
19
+ DEFAULT_MAX_QUEUE_SIZE = 0
20
+
21
+ # @!macro thread_pool_executor_constant_default_thread_timeout
22
+ DEFAULT_THREAD_IDLETIMEOUT = 60
23
+
24
+ # @!macro thread_pool_executor_attr_reader_max_length
25
+ attr_reader :max_length
26
+
27
+ # @!macro thread_pool_executor_attr_reader_max_queue
28
+ attr_reader :max_queue
29
+
30
+ # @!macro thread_pool_executor_method_initialize
31
+ def initialize(opts = {})
32
+ super(opts)
33
+ end
34
+
35
+ # @!macro executor_service_method_can_overflow_question
36
+ def can_overflow?
37
+ @max_queue != 0
38
+ end
39
+
40
+ # @!macro thread_pool_executor_attr_reader_min_length
41
+ def min_length
42
+ @executor.getCorePoolSize
43
+ end
44
+
45
+ # @!macro thread_pool_executor_attr_reader_max_length
46
+ def max_length
47
+ @executor.getMaximumPoolSize
48
+ end
49
+
50
+ # @!macro thread_pool_executor_attr_reader_length
51
+ def length
52
+ @executor.getPoolSize
53
+ end
54
+
55
+ # @!macro thread_pool_executor_attr_reader_largest_length
56
+ def largest_length
57
+ @executor.getLargestPoolSize
58
+ end
59
+
60
+ # @!macro thread_pool_executor_attr_reader_scheduled_task_count
61
+ def scheduled_task_count
62
+ @executor.getTaskCount
63
+ end
64
+
65
+ # @!macro thread_pool_executor_attr_reader_completed_task_count
66
+ def completed_task_count
67
+ @executor.getCompletedTaskCount
68
+ end
69
+
70
+ # @!macro thread_pool_executor_attr_reader_idletime
71
+ def idletime
72
+ @executor.getKeepAliveTime(java.util.concurrent.TimeUnit::SECONDS)
73
+ end
74
+
75
+ # @!macro thread_pool_executor_attr_reader_queue_length
76
+ def queue_length
77
+ @executor.getQueue.size
78
+ end
79
+
80
+ # @!macro thread_pool_executor_attr_reader_remaining_capacity
81
+ def remaining_capacity
82
+ @max_queue == 0 ? -1 : @executor.getQueue.remainingCapacity
83
+ end
84
+
85
+ # @!macro executor_service_method_running_question
86
+ def running?
87
+ super && !@executor.isTerminating
88
+ end
89
+
90
+ private
91
+
92
+ def ns_initialize(opts)
93
+ min_length = opts.fetch(:min_threads, DEFAULT_MIN_POOL_SIZE).to_i
94
+ max_length = opts.fetch(:max_threads, DEFAULT_MAX_POOL_SIZE).to_i
95
+ idletime = opts.fetch(:idletime, DEFAULT_THREAD_IDLETIMEOUT).to_i
96
+ @max_queue = opts.fetch(:max_queue, DEFAULT_MAX_QUEUE_SIZE).to_i
97
+ @fallback_policy = opts.fetch(:fallback_policy, :abort)
98
+
99
+ raise ArgumentError.new("`max_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}") if max_length < DEFAULT_MIN_POOL_SIZE
100
+ raise ArgumentError.new("`max_threads` cannot be greater than #{DEFAULT_MAX_POOL_SIZE}") if max_length > DEFAULT_MAX_POOL_SIZE
101
+ raise ArgumentError.new("`min_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}") if min_length < DEFAULT_MIN_POOL_SIZE
102
+ raise ArgumentError.new("`min_threads` cannot be more than `max_threads`") if min_length > max_length
103
+ raise ArgumentError.new("#{fallback_policy} is not a valid fallback policy") unless FALLBACK_POLICY_CLASSES.include?(@fallback_policy)
104
+
105
+ if @max_queue == 0
106
+ queue = java.util.concurrent.LinkedBlockingQueue.new
107
+ else
108
+ queue = java.util.concurrent.LinkedBlockingQueue.new(@max_queue)
109
+ end
110
+
111
+ @executor = java.util.concurrent.ThreadPoolExecutor.new(
112
+ min_length,
113
+ max_length,
114
+ idletime,
115
+ java.util.concurrent.TimeUnit::SECONDS,
116
+ queue,
117
+ FALLBACK_POLICY_CLASSES[@fallback_policy].new)
118
+
119
+ self.auto_terminate = opts.fetch(:auto_terminate, true)
120
+ end
121
+ end
122
+ end
123
+ end
@@ -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
@@ -0,0 +1,22 @@
1
+ require 'concurrent/executor/ruby_thread_pool_executor'
2
+
3
+ module Concurrent
4
+
5
+ # @!macro single_thread_executor
6
+ # @!macro abstract_executor_service_public_api
7
+ # @!visibility private
8
+ class RubySingleThreadExecutor < RubyThreadPoolExecutor
9
+
10
+ # @!macro single_thread_executor_method_initialize
11
+ def initialize(opts = {})
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
+ )
20
+ end
21
+ end
22
+ end