concurrent-ruby 1.1.6.pre1 → 1.1.6
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -6
- data/Gemfile +2 -1
- data/Rakefile +3 -1
- data/lib/concurrent-ruby/concurrent/concurrent_ruby.jar +0 -0
- data/lib/concurrent-ruby/concurrent/configuration.rb +7 -5
- data/lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb +7 -22
- data/lib/concurrent-ruby/concurrent/executor/cached_thread_pool.rb +1 -2
- data/lib/concurrent-ruby/concurrent/executor/executor_service.rb +2 -2
- data/lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb +6 -12
- data/lib/concurrent-ruby/concurrent/executor/java_executor_service.rb +18 -2
- data/lib/concurrent-ruby/concurrent/executor/java_single_thread_executor.rb +4 -3
- data/lib/concurrent-ruby/concurrent/executor/java_thread_pool_executor.rb +1 -19
- data/lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb +0 -2
- data/lib/concurrent-ruby/concurrent/executor/ruby_single_thread_executor.rb +0 -1
- data/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb +0 -2
- data/lib/concurrent-ruby/concurrent/executor/timer_set.rb +0 -1
- data/lib/concurrent-ruby/concurrent/version.rb +1 -1
- metadata +4 -5
- data/lib/concurrent-ruby/concurrent/utility/at_exit.rb +0 -96
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 649de1a5e5c7c82652bd6ad21496f2c1061d7c75517271d8ca30c3ceb9c49038
|
4
|
+
data.tar.gz: 6274d2cd2dcda660a1e34436547eca26d6c74d03e9a527d7ce5d1a9f3f72f4be
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2adbf28bdf7034295709496964e8e70d22f59bf058bf18ca005c2ce536627160538de6c510ea1f39893de0ad90b2fb50d6f35c848c97f58bd8f71ff8d9e57fc2
|
7
|
+
data.tar.gz: 1cbc384488e0f70d19d742e54c34dbd7abfaffe89f75230b2f5b80d2ae4d161b731666ce6b64e8f5adeb561b6d32191ce6bd679e05d6bd9eec91b869ee379b2f
|
data/CHANGELOG.md
CHANGED
@@ -1,16 +1,24 @@
|
|
1
1
|
## Current
|
2
2
|
|
3
|
+
## Release v1.1.6, edge v0.6.0 (10 Feb 2020)
|
4
|
+
|
5
|
+
concurrent-ruby:
|
6
|
+
|
7
|
+
* (#841) Concurrent.disable_at_exit_handlers! is no longer needed and was deprecated.
|
8
|
+
* (#841) AbstractExecutorService#auto_terminate= was deprecated and has no effect.
|
9
|
+
Set :auto_terminate option instead when executor is initialized.
|
10
|
+
|
3
11
|
## Release v1.1.6.pre1, edge v0.6.0.pre1 (26 Jan 2020)
|
4
12
|
|
5
13
|
concurrent-ruby:
|
6
14
|
|
7
|
-
* Allow to name executors, the name is also used to name their threads
|
8
|
-
* Implement #dup and #clone for structs
|
9
|
-
* Safer finalizers for thread local variables
|
15
|
+
* (#828) Allow to name executors, the name is also used to name their threads
|
16
|
+
* (#838) Implement #dup and #clone for structs
|
17
|
+
* (#821) Safer finalizers for thread local variables
|
10
18
|
* Documentation fixes
|
11
|
-
* Use Ruby's Etc.nprocessors if available
|
12
|
-
* Fix directory structure not to mess with packaging tools
|
13
|
-
* Fix termination of pools on JRuby
|
19
|
+
* (#814) Use Ruby's Etc.nprocessors if available
|
20
|
+
* (#812) Fix directory structure not to mess with packaging tools
|
21
|
+
* (#840) Fix termination of pools on JRuby
|
14
22
|
|
15
23
|
concurrent-ruby-edge:
|
16
24
|
|
data/Gemfile
CHANGED
@@ -2,6 +2,7 @@ source 'https://rubygems.org'
|
|
2
2
|
|
3
3
|
require File.join(File.dirname(__FILE__), 'lib/concurrent-ruby/concurrent/version')
|
4
4
|
require File.join(File.dirname(__FILE__ ), 'lib/concurrent-ruby-edge/concurrent/edge/version')
|
5
|
+
require File.join(File.dirname(__FILE__ ), 'lib/concurrent-ruby/concurrent/utility/engine')
|
5
6
|
|
6
7
|
no_path = ENV['NO_PATH']
|
7
8
|
options = no_path ? {} : { path: '.' }
|
@@ -11,7 +12,7 @@ gem 'concurrent-ruby-edge', Concurrent::EDGE_VERSION, options
|
|
11
12
|
gem 'concurrent-ruby-ext', Concurrent::VERSION, options.merge(platform: :mri)
|
12
13
|
|
13
14
|
group :development do
|
14
|
-
gem 'rake', '~> 12.0'
|
15
|
+
gem 'rake', (Concurrent.ruby_version :<, 2, 2, 0) ? '~> 12.0' : '~> 13.0'
|
15
16
|
gem 'rake-compiler', '~> 1.0', '>= 1.0.7'
|
16
17
|
gem 'rake-compiler-dock', '~> 0.7.0'
|
17
18
|
gem 'pry', '~> 0.11', platforms: :mri
|
data/Rakefile
CHANGED
@@ -176,7 +176,9 @@ begin
|
|
176
176
|
'LICENSE.md',
|
177
177
|
'CHANGELOG.md']
|
178
178
|
end
|
179
|
-
Rake::Task[name].prerequisites.push removal_name,
|
179
|
+
Rake::Task[name].prerequisites.push removal_name,
|
180
|
+
# 'yard:eval_md',
|
181
|
+
'yard:update_readme'
|
180
182
|
end
|
181
183
|
|
182
184
|
define_yard_task.call current_yard_version_name
|
Binary file
|
@@ -3,13 +3,14 @@ require 'concurrent/delay'
|
|
3
3
|
require 'concurrent/errors'
|
4
4
|
require 'concurrent/atomic/atomic_reference'
|
5
5
|
require 'concurrent/concern/logging'
|
6
|
+
require 'concurrent/concern/deprecation'
|
6
7
|
require 'concurrent/executor/immediate_executor'
|
7
8
|
require 'concurrent/executor/cached_thread_pool'
|
8
|
-
require 'concurrent/utility/at_exit'
|
9
9
|
require 'concurrent/utility/processor_counter'
|
10
10
|
|
11
11
|
module Concurrent
|
12
12
|
extend Concern::Logging
|
13
|
+
extend Concern::Deprecation
|
13
14
|
|
14
15
|
autoload :Options, 'concurrent/options'
|
15
16
|
autoload :TimerSet, 'concurrent/executor/timer_set'
|
@@ -97,15 +98,15 @@ module Concurrent
|
|
97
98
|
end
|
98
99
|
|
99
100
|
# @!visibility private
|
100
|
-
GLOBAL_FAST_EXECUTOR = Delay.new { Concurrent.new_fast_executor
|
101
|
+
GLOBAL_FAST_EXECUTOR = Delay.new { Concurrent.new_fast_executor }
|
101
102
|
private_constant :GLOBAL_FAST_EXECUTOR
|
102
103
|
|
103
104
|
# @!visibility private
|
104
|
-
GLOBAL_IO_EXECUTOR = Delay.new { Concurrent.new_io_executor
|
105
|
+
GLOBAL_IO_EXECUTOR = Delay.new { Concurrent.new_io_executor }
|
105
106
|
private_constant :GLOBAL_IO_EXECUTOR
|
106
107
|
|
107
108
|
# @!visibility private
|
108
|
-
GLOBAL_TIMER_SET = Delay.new { TimerSet.new
|
109
|
+
GLOBAL_TIMER_SET = Delay.new { TimerSet.new }
|
109
110
|
private_constant :GLOBAL_TIMER_SET
|
110
111
|
|
111
112
|
# @!visibility private
|
@@ -125,9 +126,10 @@ module Concurrent
|
|
125
126
|
# @note This method should *never* be called
|
126
127
|
# from within a gem. It should *only* be used from within the main
|
127
128
|
# application and even then it should be used only when necessary.
|
129
|
+
# @deprecated Has no effect since it is no longer needed, see https://github.com/ruby-concurrency/concurrent-ruby/pull/841.
|
128
130
|
#
|
129
131
|
def self.disable_at_exit_handlers!
|
130
|
-
|
132
|
+
deprecated "Method #disable_at_exit_handlers! has no effect since it is no longer needed, see https://github.com/ruby-concurrency/concurrent-ruby/pull/841."
|
131
133
|
end
|
132
134
|
|
133
135
|
# Global thread pool optimized for short, fast *operations*.
|
@@ -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
|
@@ -22,8 +23,9 @@ module Concurrent
|
|
22
23
|
def initialize(opts = {}, &block)
|
23
24
|
super(&nil)
|
24
25
|
synchronize do
|
25
|
-
|
26
|
+
@auto_terminate = opts.fetch(:auto_terminate, true)
|
26
27
|
@name = opts.fetch(:name) if opts.key?(:name)
|
28
|
+
ns_initialize(opts, &block)
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
@@ -63,12 +65,12 @@ module Concurrent
|
|
63
65
|
|
64
66
|
# @!macro executor_service_method_auto_terminate_question
|
65
67
|
def auto_terminate?
|
66
|
-
synchronize {
|
68
|
+
synchronize { @auto_terminate }
|
67
69
|
end
|
68
70
|
|
69
71
|
# @!macro executor_service_method_auto_terminate_setter
|
70
72
|
def auto_terminate=(value)
|
71
|
-
|
73
|
+
deprecated "Method #auto_terminate= has no effect. Set :auto_terminate option when executor is initialized."
|
72
74
|
end
|
73
75
|
|
74
76
|
private
|
@@ -119,25 +121,8 @@ module Concurrent
|
|
119
121
|
end
|
120
122
|
|
121
123
|
def ns_auto_terminate?
|
122
|
-
|
124
|
+
@auto_terminate
|
123
125
|
end
|
124
126
|
|
125
|
-
def ns_auto_terminate=(value)
|
126
|
-
case value
|
127
|
-
when true
|
128
|
-
AT_EXIT.add(self) { terminate_at_exit }
|
129
|
-
@auto_terminate = true
|
130
|
-
when false
|
131
|
-
AT_EXIT.delete(self)
|
132
|
-
@auto_terminate = false
|
133
|
-
else
|
134
|
-
raise ArgumentError
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
def terminate_at_exit
|
139
|
-
kill # TODO be gentle first
|
140
|
-
wait_for_termination(10)
|
141
|
-
end
|
142
127
|
end
|
143
128
|
end
|
@@ -51,10 +51,9 @@ module Concurrent
|
|
51
51
|
def ns_initialize(opts)
|
52
52
|
super(opts)
|
53
53
|
if Concurrent.on_jruby?
|
54
|
-
self.auto_terminate = opts.fetch(:auto_terminate, true)
|
55
54
|
@max_queue = 0
|
56
55
|
@executor = java.util.concurrent.Executors.newCachedThreadPool(
|
57
|
-
DaemonThreadFactory.new(
|
56
|
+
DaemonThreadFactory.new(ns_auto_terminate?))
|
58
57
|
@executor.setRejectedExecutionHandler(FALLBACK_POLICY_CLASSES[@fallback_policy].new)
|
59
58
|
@executor.setKeepAliveTime(opts.fetch(:idletime, DEFAULT_THREAD_IDLETIMEOUT), java.util.concurrent.TimeUnit::SECONDS)
|
60
59
|
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
|
###################################################################
|
@@ -121,9 +121,7 @@ module Concurrent
|
|
121
121
|
# * `max_queue`: The maximum number of tasks that may be waiting in the work queue at
|
122
122
|
# any one time. When the queue size reaches `max_queue` and no new threads can be created,
|
123
123
|
# subsequent tasks will be rejected in accordance with the configured `fallback_policy`.
|
124
|
-
# * `auto_terminate`: When true (default)
|
125
|
-
# will stop the thread pool when the application exits. See below for more information
|
126
|
-
# on shutting down thread pools.
|
124
|
+
# * `auto_terminate`: When true (default), the threads started will be marked as daemon.
|
127
125
|
# * `fallback_policy`: The policy defining how rejected tasks are handled.
|
128
126
|
#
|
129
127
|
# Three fallback policies are supported:
|
@@ -148,16 +146,12 @@ module Concurrent
|
|
148
146
|
#
|
149
147
|
# On some runtime platforms (most notably the JVM) the application will not
|
150
148
|
# exit until all thread pools have been shutdown. To prevent applications from
|
151
|
-
# "hanging" on exit all
|
152
|
-
#
|
153
|
-
# force method to stop the pool and makes no guarantees regarding resources being
|
154
|
-
# used by any tasks still running. Registration of this `at_exit` handler can be
|
155
|
-
# prevented by setting the thread pool's constructor `:auto_terminate` option to
|
156
|
-
# `false` when the thread pool is created. All thread pools support this option.
|
149
|
+
# "hanging" on exit, all threads can be marked as daemon according to the
|
150
|
+
# `:auto_terminate` option.
|
157
151
|
#
|
158
152
|
# ```ruby
|
159
|
-
# pool1 = Concurrent::FixedThreadPool.new(5) #
|
160
|
-
# pool2 = Concurrent::FixedThreadPool.new(5, auto_terminate: false) #
|
153
|
+
# pool1 = Concurrent::FixedThreadPool.new(5) # threads will be marked as daemon
|
154
|
+
# pool2 = Concurrent::FixedThreadPool.new(5, auto_terminate: false) # mark threads as non-daemon
|
161
155
|
# ```
|
162
156
|
#
|
163
157
|
# @note Failure to properly shutdown a thread pool can lead to unpredictable results.
|
@@ -166,7 +160,7 @@ module Concurrent
|
|
166
160
|
# @see http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html Java Tutorials: Thread Pools
|
167
161
|
# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html Java Executors class
|
168
162
|
# @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html Java ExecutorService interface
|
169
|
-
# @see
|
163
|
+
# @see https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setDaemon-boolean-
|
170
164
|
|
171
165
|
|
172
166
|
|
@@ -38,7 +38,6 @@ if Concurrent.on_jruby?
|
|
38
38
|
|
39
39
|
def shutdown
|
40
40
|
synchronize do
|
41
|
-
self.ns_auto_terminate = false
|
42
41
|
@executor.shutdown
|
43
42
|
nil
|
44
43
|
end
|
@@ -46,7 +45,6 @@ if Concurrent.on_jruby?
|
|
46
45
|
|
47
46
|
def kill
|
48
47
|
synchronize do
|
49
|
-
self.ns_auto_terminate = false
|
50
48
|
@executor.shutdownNow
|
51
49
|
nil
|
52
50
|
end
|
@@ -83,5 +81,23 @@ if Concurrent.on_jruby?
|
|
83
81
|
end
|
84
82
|
private_constant :Job
|
85
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
|
+
|
86
102
|
end
|
87
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
|
@@ -108,35 +108,17 @@ if Concurrent.on_jruby?
|
|
108
108
|
queue = java.util.concurrent.LinkedBlockingQueue.new(@max_queue)
|
109
109
|
end
|
110
110
|
|
111
|
-
self.auto_terminate = opts.fetch(:auto_terminate, true)
|
112
|
-
|
113
111
|
@executor = java.util.concurrent.ThreadPoolExecutor.new(
|
114
112
|
min_length,
|
115
113
|
max_length,
|
116
114
|
idletime,
|
117
115
|
java.util.concurrent.TimeUnit::SECONDS,
|
118
116
|
queue,
|
119
|
-
DaemonThreadFactory.new(
|
117
|
+
DaemonThreadFactory.new(ns_auto_terminate?),
|
120
118
|
FALLBACK_POLICY_CLASSES[@fallback_policy].new)
|
121
119
|
|
122
120
|
end
|
123
121
|
end
|
124
122
|
|
125
|
-
class DaemonThreadFactory
|
126
|
-
# hide include from YARD
|
127
|
-
send :include, java.util.concurrent.ThreadFactory
|
128
|
-
|
129
|
-
def initialize(daemonize = true)
|
130
|
-
@daemonize = daemonize
|
131
|
-
end
|
132
|
-
|
133
|
-
def newThread(runnable)
|
134
|
-
thread = java.util.concurrent.Executors.defaultThreadFactory().newThread(runnable)
|
135
|
-
thread.setDaemon(@daemonize)
|
136
|
-
return thread
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
private_constant :DaemonThreadFactory
|
141
123
|
end
|
142
124
|
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
|
@@ -122,8 +122,6 @@ module Concurrent
|
|
122
122
|
raise ArgumentError.new("`min_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}") if @min_length < DEFAULT_MIN_POOL_SIZE
|
123
123
|
raise ArgumentError.new("`min_threads` cannot be more than `max_threads`") if min_length > max_length
|
124
124
|
|
125
|
-
self.auto_terminate = opts.fetch(:auto_terminate, true)
|
126
|
-
|
127
125
|
@pool = [] # all workers
|
128
126
|
@ready = [] # used as a stash (most idle worker is at the start)
|
129
127
|
@queue = [] # used as queue
|
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: 1.1.6
|
4
|
+
version: 1.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jerry D'Antonio
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2020-
|
13
|
+
date: 2020-02-10 00:00:00.000000000 Z
|
14
14
|
dependencies: []
|
15
15
|
description: |
|
16
16
|
Modern concurrency tools including agents, futures, promises, thread pools, actors, supervisors, and more.
|
@@ -157,7 +157,6 @@ files:
|
|
157
157
|
- lib/concurrent-ruby/concurrent/timer_task.rb
|
158
158
|
- lib/concurrent-ruby/concurrent/tuple.rb
|
159
159
|
- lib/concurrent-ruby/concurrent/tvar.rb
|
160
|
-
- lib/concurrent-ruby/concurrent/utility/at_exit.rb
|
161
160
|
- lib/concurrent-ruby/concurrent/utility/engine.rb
|
162
161
|
- lib/concurrent-ruby/concurrent/utility/monotonic_time.rb
|
163
162
|
- lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb
|
@@ -181,9 +180,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
181
180
|
version: 1.9.3
|
182
181
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
183
182
|
requirements:
|
184
|
-
- - "
|
183
|
+
- - ">="
|
185
184
|
- !ruby/object:Gem::Version
|
186
|
-
version:
|
185
|
+
version: '0'
|
187
186
|
requirements: []
|
188
187
|
rubyforge_project:
|
189
188
|
rubygems_version: 2.7.9
|
@@ -1,96 +0,0 @@
|
|
1
|
-
require 'logger'
|
2
|
-
require 'concurrent/synchronization'
|
3
|
-
|
4
|
-
module Concurrent
|
5
|
-
|
6
|
-
# Provides ability to add and remove handlers to be run at `Kernel#at_exit`, order is undefined.
|
7
|
-
# Each handler is executed at most once.
|
8
|
-
#
|
9
|
-
# @!visibility private
|
10
|
-
class AtExitImplementation < Synchronization::LockableObject
|
11
|
-
include Logger::Severity
|
12
|
-
|
13
|
-
def initialize(*args)
|
14
|
-
super()
|
15
|
-
synchronize { ns_initialize(*args) }
|
16
|
-
end
|
17
|
-
|
18
|
-
# Add a handler to be run at `Kernel#at_exit`
|
19
|
-
# @param [Object] handler_id optionally provide an id, if already present, handler is replaced
|
20
|
-
# @yield the handler
|
21
|
-
# @return id of the handler
|
22
|
-
def add(handler_id = nil, &handler)
|
23
|
-
id = handler_id || handler.object_id
|
24
|
-
synchronize { @handlers[id] = handler }
|
25
|
-
id
|
26
|
-
end
|
27
|
-
|
28
|
-
# Delete a handler by handler_id
|
29
|
-
# @return [true, false]
|
30
|
-
def delete(handler_id)
|
31
|
-
!!synchronize { @handlers.delete handler_id }
|
32
|
-
end
|
33
|
-
|
34
|
-
# Is handler with handler_id rpesent?
|
35
|
-
# @return [true, false]
|
36
|
-
def handler?(handler_id)
|
37
|
-
synchronize { @handlers.key? handler_id }
|
38
|
-
end
|
39
|
-
|
40
|
-
# @return copy of the handlers
|
41
|
-
def handlers
|
42
|
-
synchronize { @handlers }.clone
|
43
|
-
end
|
44
|
-
|
45
|
-
# install `Kernel#at_exit` callback to execute added handlers
|
46
|
-
def install
|
47
|
-
synchronize do
|
48
|
-
@installed ||= begin
|
49
|
-
at_exit { runner }
|
50
|
-
true
|
51
|
-
end
|
52
|
-
self
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
# Will it run during `Kernel#at_exit`
|
57
|
-
def enabled?
|
58
|
-
synchronize { @enabled }
|
59
|
-
end
|
60
|
-
|
61
|
-
# Configure if it runs during `Kernel#at_exit`
|
62
|
-
def enabled=(value)
|
63
|
-
synchronize { @enabled = value }
|
64
|
-
end
|
65
|
-
|
66
|
-
# run the handlers manually
|
67
|
-
# @return ids of the handlers
|
68
|
-
def run
|
69
|
-
handlers, _ = synchronize { handlers, @handlers = @handlers, {} }
|
70
|
-
handlers.each do |_, handler|
|
71
|
-
begin
|
72
|
-
handler.call
|
73
|
-
rescue => error
|
74
|
-
Concurrent.global_logger.call(ERROR, error)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
handlers.keys
|
78
|
-
end
|
79
|
-
|
80
|
-
private
|
81
|
-
|
82
|
-
def ns_initialize(enabled = true)
|
83
|
-
@handlers = {}
|
84
|
-
@enabled = enabled
|
85
|
-
end
|
86
|
-
|
87
|
-
def runner
|
88
|
-
run if synchronize { @enabled }
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
private_constant :AtExitImplementation
|
93
|
-
|
94
|
-
# @!visibility private
|
95
|
-
AT_EXIT = AtExitImplementation.new.install
|
96
|
-
end
|