concurrent-ruby 1.1.4 → 1.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/Gemfile +9 -7
- data/README.md +34 -2
- data/Rakefile +33 -52
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/SynchronizationLibrary.java +9 -8
- data/lib/concurrent/array.rb +3 -3
- data/lib/concurrent/async.rb +14 -0
- data/lib/concurrent/atomic/atomic_fixnum.rb +2 -2
- data/lib/concurrent/collection/lock_free_stack.rb +1 -1
- data/lib/concurrent/concurrent_ruby.jar +0 -0
- data/lib/concurrent/executor/timer_set.rb +13 -15
- data/lib/concurrent/hash.rb +3 -3
- data/lib/concurrent/promises.rb +348 -117
- data/lib/concurrent/synchronization/abstract_struct.rb +1 -0
- data/lib/concurrent/synchronization/condition.rb +2 -0
- data/lib/concurrent/synchronization/jruby_object.rb +1 -0
- data/lib/concurrent/synchronization/lock.rb +2 -0
- data/lib/concurrent/synchronization/mri_object.rb +1 -0
- data/lib/concurrent/synchronization/object.rb +46 -20
- data/lib/concurrent/synchronization/rbx_object.rb +1 -0
- data/lib/concurrent/synchronization/truffleruby_object.rb +1 -0
- data/lib/concurrent/version.rb +1 -2
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 96f32c31090c8a0547e4ee452739bdc993aad1256e2c89cb9a46d7f7e7b5762a
|
4
|
+
data.tar.gz: 307d26bde3add56b7e2b37fb0b016c7726a3ba0755dcfec8202fb0760e4ac485
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b8cff93c6ef396aebbe5cf69734d9a91f0351e24b5c1846ae105b055254f972cd9d6bb99b90ce10d387627ed43c4e21db9ce47d1587e10278e80e33a53f8d4c4
|
7
|
+
data.tar.gz: f367f097759eedb8e18b0117543176c9f30ab29552888fcedab0baaea355cee3d100d2559dd16cf54483778545097f8b3340bebe44b0e3ab2a51c1af3830f5e1
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
## Current
|
2
2
|
|
3
|
+
## Release v1.1.5, edge v0.5.0 (10 mar 2019)
|
4
|
+
|
5
|
+
concurrent-ruby:
|
6
|
+
|
7
|
+
* fix potential leak of context on JRuby and Java 7
|
8
|
+
|
9
|
+
concurrent-ruby-edge:
|
10
|
+
|
11
|
+
* Add finalized Concurrent::Cancellation
|
12
|
+
* Add finalized Concurrent::Throttle
|
13
|
+
* Add finalized Concurrent::Promises::Channel
|
14
|
+
* Add new Concurrent::ErlangActor
|
15
|
+
|
3
16
|
## Release v1.1.4 (14 Dec 2018)
|
4
17
|
|
5
18
|
* (#780) Remove java_alias of 'submit' method of Runnable to let executor service work on java 11
|
data/Gemfile
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
require File.join(File.dirname(__FILE__
|
3
|
+
require File.join(File.dirname(__FILE__), 'lib/concurrent/version')
|
4
|
+
require File.join(File.dirname(__FILE__ ), 'lib-edge/concurrent/edge/version')
|
4
5
|
|
5
6
|
no_path = ENV['NO_PATH']
|
6
7
|
options = no_path ? {} : { path: '.' }
|
@@ -11,26 +12,27 @@ gem 'concurrent-ruby-ext', Concurrent::VERSION, options.merge(platform: :mri)
|
|
11
12
|
|
12
13
|
group :development do
|
13
14
|
gem 'rake', '~> 12.0'
|
14
|
-
gem 'rake-compiler', '~> 1.0'
|
15
|
-
gem 'rake-compiler-dock', '~> 0.
|
15
|
+
gem 'rake-compiler', '~> 1.0', '>= 1.0.7'
|
16
|
+
gem 'rake-compiler-dock', '~> 0.7.0'
|
16
17
|
gem 'pry', '~> 0.11', platforms: :mri
|
17
18
|
end
|
18
19
|
|
19
20
|
group :documentation, optional: true do
|
20
|
-
gem 'yard', '~> 0.9.0', :
|
21
|
+
gem 'yard', '~> 0.9.0', require: false
|
21
22
|
gem 'redcarpet', '~> 3.0', platforms: :mri # understands github markdown
|
22
|
-
gem 'md-ruby-eval', '~> 0.
|
23
|
+
gem 'md-ruby-eval', '~> 0.6'
|
23
24
|
end
|
24
25
|
|
25
26
|
group :testing do
|
26
27
|
gem 'rspec', '~> 3.7'
|
27
28
|
gem 'timecop', '~> 0.7.4'
|
29
|
+
gem 'sigdump', require: false
|
28
30
|
end
|
29
31
|
|
30
32
|
# made opt-in since it will not install on jruby 1.7
|
31
33
|
group :coverage, optional: !ENV['COVERAGE'] do
|
32
|
-
gem 'simplecov', '~> 0.
|
33
|
-
gem 'coveralls', '~> 0.8.2', :
|
34
|
+
gem 'simplecov', '~> 0.16.0', require: false
|
35
|
+
gem 'coveralls', '~> 0.8.2', require: false
|
34
36
|
end
|
35
37
|
|
36
38
|
group :benchmarks, optional: true do
|
data/README.md
CHANGED
@@ -42,7 +42,7 @@ appreciate your help. Would you like to contribute? Great! Have a look at
|
|
42
42
|
## Thread Safety
|
43
43
|
|
44
44
|
*Concurrent Ruby makes one of the strongest thread safety guarantees of any Ruby concurrency
|
45
|
-
library, providing consistent behavior and guarantees on all
|
45
|
+
library, providing consistent behavior and guarantees on all four of the main Ruby interpreters
|
46
46
|
(MRI/CRuby, JRuby, Rubinius, TruffleRuby).*
|
47
47
|
|
48
48
|
Every abstraction in this library is thread safe. Specific thread safety guarantees are documented
|
@@ -224,6 +224,35 @@ be obeyed though. Features developed in `concurrent-ruby-edge` are expected to m
|
|
224
224
|
*Status: will be moved to core soon.*
|
225
225
|
* [LockFreeStack](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/LockFreeStack.html)
|
226
226
|
*Status: missing documentation and tests.*
|
227
|
+
* [Promises::Channel](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Promises/Channel.html)
|
228
|
+
A first in first out channel that accepts messages with push family of methods and returns
|
229
|
+
messages with pop family of methods.
|
230
|
+
Pop and push operations can be represented as futures, see `#pop_op` and `#push_op`.
|
231
|
+
The capacity of the channel can be limited to support back pressure, use capacity option in `#initialize`.
|
232
|
+
`#pop` method blocks ans `#pop_op` returns pending future if there is no message in the channel.
|
233
|
+
If the capacity is limited the `#push` method blocks and `#push_op` returns pending future.
|
234
|
+
* [Cancellation](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Cancellation.html)
|
235
|
+
The Cancellation abstraction provides cooperative cancellation.
|
236
|
+
|
237
|
+
The standard methods `Thread#raise` of `Thread#kill` available in Ruby
|
238
|
+
are very dangerous (see linked the blog posts bellow).
|
239
|
+
Therefore concurrent-ruby provides an alternative.
|
240
|
+
|
241
|
+
* <https://jvns.ca/blog/2015/11/27/why-rubys-timeout-is-dangerous-and-thread-dot-raise-is-terrifying/>
|
242
|
+
* <http://www.mikeperham.com/2015/05/08/timeout-rubys-most-dangerous-api/>
|
243
|
+
* <http://blog.headius.com/2008/02/rubys-threadraise-threadkill-timeoutrb.html>
|
244
|
+
|
245
|
+
It provides an object which represents a task which can be executed,
|
246
|
+
the task has to get the reference to the object and periodically cooperatively check that it is not cancelled.
|
247
|
+
Good practices to make tasks cancellable:
|
248
|
+
* check cancellation every cycle of a loop which does significant work,
|
249
|
+
* do all blocking actions in a loop with a timeout then on timeout check cancellation
|
250
|
+
and if ok block again with the timeout
|
251
|
+
* [Throttle](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Throttle.html)
|
252
|
+
A tool managing concurrency level of tasks.
|
253
|
+
* [ErlangActor](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/ErlangActor.html)
|
254
|
+
Actor implementation which precisely matches Erlang actor behaviour.
|
255
|
+
Requires at least Ruby 2.1 otherwise it's not loaded.
|
227
256
|
|
228
257
|
## Supported Ruby versions
|
229
258
|
|
@@ -339,11 +368,14 @@ and to the past maintainers
|
|
339
368
|
* [Paweł Obrok](https://github.com/obrok)
|
340
369
|
* [Lucas Allan](https://github.com/lucasallan)
|
341
370
|
|
371
|
+
and to [Ruby Association](https://www.ruby.or.jp/en/) for sponsoring a project
|
372
|
+
["Enhancing Ruby’s concurrency tooling"](https://www.ruby.or.jp/en/news/20181106) in 2018.
|
373
|
+
|
342
374
|
## License and Copyright
|
343
375
|
|
344
376
|
*Concurrent Ruby* is free software released under the
|
345
377
|
[MIT License](http://www.opensource.org/licenses/MIT).
|
346
378
|
|
347
|
-
The *Concurrent Ruby* [logo](https://
|
379
|
+
The *Concurrent Ruby* [logo](https://raw.githubusercontent.com/ruby-concurrency/concurrent-ruby/master/docs-source/logo/concurrent-ruby-logo-300x300.png) was
|
348
380
|
designed by [David Jones](https://twitter.com/zombyboy). It is Copyright © 2014
|
349
381
|
[Jerry D'Antonio](https://twitter.com/jerrydantonio). All Rights Reserved.
|
data/Rakefile
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
#!/usr/bin/env rake
|
2
|
-
|
3
1
|
require_relative 'lib/concurrent/version'
|
4
2
|
require_relative 'lib/concurrent/utility/engine'
|
5
3
|
|
@@ -18,43 +16,7 @@ edge_gemspec = Gem::Specification.load File.join(__dir__, 'concurrent-ruby-edge.
|
|
18
16
|
|
19
17
|
require 'rake/javaextensiontask'
|
20
18
|
|
21
|
-
|
22
|
-
def java_classpath_arg(*args)
|
23
|
-
jruby_cpath = nil
|
24
|
-
|
25
|
-
if RUBY_PLATFORM =~ /java/
|
26
|
-
begin
|
27
|
-
cpath = Java::java.lang.System.getProperty('java.class.path').split(File::PATH_SEPARATOR)
|
28
|
-
cpath += Java::java.lang.System.getProperty('sun.boot.class.path').split(File::PATH_SEPARATOR)
|
29
|
-
jruby_cpath = cpath.compact.join(File::PATH_SEPARATOR)
|
30
|
-
rescue => e
|
31
|
-
end
|
32
|
-
|
33
|
-
unless jruby_cpath
|
34
|
-
libdir = RbConfig::CONFIG['libdir']
|
35
|
-
if libdir.start_with? "classpath:"
|
36
|
-
raise 'Cannot build with jruby-complete'
|
37
|
-
end
|
38
|
-
jruby_cpath = File.join(libdir, "jruby.jar")
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
unless jruby_cpath
|
43
|
-
jruby_home = ENV['JRUBY_HOME']
|
44
|
-
if jruby_home
|
45
|
-
candidate = File.join(jruby_home, 'lib', 'jruby.jar')
|
46
|
-
jruby_cpath = candidate if File.exist? candidate
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
raise "jruby.jar path not found" unless jruby_cpath
|
51
|
-
|
52
|
-
jruby_cpath += File::PATH_SEPARATOR + args.join(File::PATH_SEPARATOR) unless args.empty?
|
53
|
-
jruby_cpath ? "-cp \"#{jruby_cpath}\"" : ""
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
ConcurrentRubyJavaExtensionTask.new('concurrent_ruby', core_gemspec) do |ext|
|
19
|
+
Rake::JavaExtensionTask.new('concurrent_ruby', core_gemspec) do |ext|
|
58
20
|
ext.ext_dir = 'ext/concurrent-ruby'
|
59
21
|
ext.lib_dir = 'lib/concurrent'
|
60
22
|
end
|
@@ -80,9 +42,11 @@ namespace :repackage do
|
|
80
42
|
# store gems in vendor cache for docker
|
81
43
|
sh 'bundle package'
|
82
44
|
|
83
|
-
#
|
45
|
+
# build only the jar file not the whole gem for java platform, the jar is part the concurrent-ruby-x.y.z.gem
|
84
46
|
Rake::Task['lib/concurrent/concurrent_ruby.jar'].invoke
|
85
|
-
|
47
|
+
|
48
|
+
# build all gem files
|
49
|
+
RakeCompilerDock.sh 'bundle install --local && bundle exec rake cross native package --trace'
|
86
50
|
end
|
87
51
|
end
|
88
52
|
end
|
@@ -102,15 +66,14 @@ begin
|
|
102
66
|
|
103
67
|
RSpec::Core::RakeTask.new(:spec)
|
104
68
|
|
105
|
-
options = %w[ --color
|
106
|
-
--backtrace
|
107
|
-
--seed 1
|
108
|
-
--format documentation
|
109
|
-
--tag ~notravis ]
|
110
|
-
|
111
69
|
namespace :spec do
|
112
70
|
desc '* Configured for ci'
|
113
71
|
RSpec::Core::RakeTask.new(:ci) do |t|
|
72
|
+
options = %w[ --color
|
73
|
+
--backtrace
|
74
|
+
--order defined
|
75
|
+
--format documentation
|
76
|
+
--tag ~notravis ]
|
114
77
|
t.rspec_opts = [*options].join(' ')
|
115
78
|
end
|
116
79
|
|
@@ -135,7 +98,7 @@ rescue LoadError => e
|
|
135
98
|
puts 'RSpec is not installed, skipping test task definitions: ' + e.message
|
136
99
|
end
|
137
100
|
|
138
|
-
current_yard_version_name =
|
101
|
+
current_yard_version_name = Concurrent::VERSION
|
139
102
|
|
140
103
|
begin
|
141
104
|
require 'yard'
|
@@ -185,10 +148,19 @@ begin
|
|
185
148
|
end
|
186
149
|
|
187
150
|
define_yard_task = -> name do
|
151
|
+
output_dir = "docs/#{name}"
|
152
|
+
|
153
|
+
removal_name = "remove.#{name}"
|
154
|
+
task removal_name do
|
155
|
+
Dir.chdir __dir__ do
|
156
|
+
FileUtils.rm_rf output_dir
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
188
160
|
desc "* of #{name} into subdir #{name}"
|
189
161
|
YARD::Rake::YardocTask.new(name) do |yard|
|
190
162
|
yard.options.push(
|
191
|
-
'--output-dir',
|
163
|
+
'--output-dir', output_dir,
|
192
164
|
'--main', 'tmp/README.md',
|
193
165
|
*common_yard_options)
|
194
166
|
yard.files = ['./lib/**/*.rb',
|
@@ -197,10 +169,11 @@ begin
|
|
197
169
|
'-',
|
198
170
|
'docs-source/thread_pools.md',
|
199
171
|
'docs-source/promises.out.md',
|
172
|
+
'docs-source/medium-example.out.rb',
|
200
173
|
'LICENSE.md',
|
201
174
|
'CHANGELOG.md']
|
202
175
|
end
|
203
|
-
Rake::Task[name].prerequisites.push 'yard:eval_md', 'yard:update_readme'
|
176
|
+
Rake::Task[name].prerequisites.push removal_name, 'yard:eval_md', 'yard:update_readme'
|
204
177
|
end
|
205
178
|
|
206
179
|
define_yard_task.call current_yard_version_name
|
@@ -223,7 +196,15 @@ begin
|
|
223
196
|
begin
|
224
197
|
FileUtils.cp_r 'docs', 'docs-copy', verbose: true
|
225
198
|
Rake::Task["yard:#{name}"].invoke
|
226
|
-
sh 'diff -r docs/ docs-copy/'
|
199
|
+
sh 'diff -r docs/ docs-copy/' do |ok, res|
|
200
|
+
unless ok
|
201
|
+
begin
|
202
|
+
STDOUT.puts 'Command failed. Continue? (y/n)'
|
203
|
+
input = STDIN.gets.strip.downcase
|
204
|
+
end until %w(y n).include?(input)
|
205
|
+
exit 1 if input == 'n'
|
206
|
+
end
|
207
|
+
end
|
227
208
|
ensure
|
228
209
|
FileUtils.rm_rf 'docs-copy', verbose: true
|
229
210
|
end
|
@@ -275,7 +256,7 @@ namespace :release do
|
|
275
256
|
end
|
276
257
|
|
277
258
|
desc '* build all *.gem files necessary for release'
|
278
|
-
task :build => 'repackage:all'
|
259
|
+
task :build => [:clobber, 'repackage:all']
|
279
260
|
|
280
261
|
desc '* test actual installed gems instead of cloned repository on MRI and JRuby'
|
281
262
|
task :test do
|
@@ -23,6 +23,7 @@ import java.lang.reflect.Method;
|
|
23
23
|
public class SynchronizationLibrary implements Library {
|
24
24
|
|
25
25
|
private static final Unsafe UNSAFE = loadUnsafe();
|
26
|
+
private static final boolean FULL_FENCE = supportsFences();
|
26
27
|
|
27
28
|
private static Unsafe loadUnsafe() {
|
28
29
|
try {
|
@@ -140,17 +141,17 @@ public class SynchronizationLibrary implements Library {
|
|
140
141
|
// volatile threadContext is used as a memory barrier per the JVM memory model happens-before semantic
|
141
142
|
// on volatile fields. any volatile field could have been used but using the thread context is an
|
142
143
|
// attempt to avoid code elimination.
|
143
|
-
private static volatile
|
144
|
+
private static volatile int volatileField;
|
144
145
|
|
145
146
|
@JRubyMethod(name = "full_memory_barrier", visibility = Visibility.PUBLIC)
|
146
147
|
public static IRubyObject fullMemoryBarrier(ThreadContext context, IRubyObject self) {
|
147
148
|
// Prevent reordering of ivar writes with publication of this instance
|
148
|
-
if (!
|
149
|
+
if (!FULL_FENCE) {
|
149
150
|
// Assuming that following volatile read and write is not eliminated it simulates fullFence.
|
150
151
|
// If it's eliminated it'll cause problems only on non-x86 platforms.
|
151
152
|
// http://shipilev.net/blog/2014/jmm-pragmatics/#_happens_before_test_your_understanding
|
152
|
-
final
|
153
|
-
|
153
|
+
final int volatileRead = volatileField;
|
154
|
+
volatileField = context.getLine();
|
154
155
|
} else {
|
155
156
|
UNSAFE.fullFence();
|
156
157
|
}
|
@@ -163,9 +164,9 @@ public class SynchronizationLibrary implements Library {
|
|
163
164
|
IRubyObject self,
|
164
165
|
IRubyObject name) {
|
165
166
|
// Ensure we ses latest value with loadFence
|
166
|
-
if (!
|
167
|
+
if (!FULL_FENCE) {
|
167
168
|
// piggybacking on volatile read, simulating loadFence
|
168
|
-
final
|
169
|
+
final int volatileRead = volatileField;
|
169
170
|
return ((RubyBasicObject) self).instance_variable_get(context, name);
|
170
171
|
} else {
|
171
172
|
UNSAFE.loadFence();
|
@@ -180,10 +181,10 @@ public class SynchronizationLibrary implements Library {
|
|
180
181
|
IRubyObject name,
|
181
182
|
IRubyObject value) {
|
182
183
|
// Ensure we make last update visible
|
183
|
-
if (!
|
184
|
+
if (!FULL_FENCE) {
|
184
185
|
// piggybacking on volatile write, simulating storeFence
|
185
186
|
final IRubyObject result = ((RubyBasicObject) self).instance_variable_set(name, value);
|
186
|
-
|
187
|
+
volatileField = context.getLine();
|
187
188
|
return result;
|
188
189
|
} else {
|
189
190
|
// JRuby uses StampedVariableAccessor which calls fullFence
|
data/lib/concurrent/array.rb
CHANGED
@@ -21,8 +21,9 @@ module Concurrent
|
|
21
21
|
# @!macro internal_implementation_note
|
22
22
|
ArrayImplementation = case
|
23
23
|
when Concurrent.on_cruby?
|
24
|
-
#
|
25
|
-
#
|
24
|
+
# Array is thread-safe in practice because CRuby runs
|
25
|
+
# threads one at a time and does not do context
|
26
|
+
# switching during the execution of C functions.
|
26
27
|
::Array
|
27
28
|
|
28
29
|
when Concurrent.on_jruby?
|
@@ -63,4 +64,3 @@ module Concurrent
|
|
63
64
|
end
|
64
65
|
|
65
66
|
end
|
66
|
-
|
data/lib/concurrent/async.rb
CHANGED
@@ -333,6 +333,13 @@ module Concurrent
|
|
333
333
|
ivar
|
334
334
|
end
|
335
335
|
|
336
|
+
# Check whether the method is responsive
|
337
|
+
#
|
338
|
+
# @param [Symbol] method the method being called
|
339
|
+
def respond_to_missing?(method, include_private = false)
|
340
|
+
@delegate.respond_to?(method) || super
|
341
|
+
end
|
342
|
+
|
336
343
|
# Perform all enqueued tasks.
|
337
344
|
#
|
338
345
|
# This method must be called from within the executor. It must not be
|
@@ -383,6 +390,13 @@ module Concurrent
|
|
383
390
|
ivar.wait
|
384
391
|
ivar
|
385
392
|
end
|
393
|
+
|
394
|
+
# Check whether the method is responsive
|
395
|
+
#
|
396
|
+
# @param [Symbol] method the method being called
|
397
|
+
def respond_to_missing?(method, include_private = false)
|
398
|
+
@delegate.respond_to?(method) || super
|
399
|
+
end
|
386
400
|
end
|
387
401
|
private_constant :AwaitDelegator
|
388
402
|
|
@@ -79,10 +79,10 @@ module Concurrent
|
|
79
79
|
# @!method value=(value)
|
80
80
|
# @!macro atomic_fixnum_method_value_set
|
81
81
|
#
|
82
|
-
# @!method increment(delta)
|
82
|
+
# @!method increment(delta = 1)
|
83
83
|
# @!macro atomic_fixnum_method_increment
|
84
84
|
#
|
85
|
-
# @!method decrement(delta)
|
85
|
+
# @!method decrement(delta = 1)
|
86
86
|
# @!macro atomic_fixnum_method_decrement
|
87
87
|
#
|
88
88
|
# @!method compare_and_set(expect, update)
|
Binary file
|
@@ -48,11 +48,9 @@ module Concurrent
|
|
48
48
|
def post(delay, *args, &task)
|
49
49
|
raise ArgumentError.new('no block given') unless block_given?
|
50
50
|
return false unless running?
|
51
|
-
opts = {
|
52
|
-
|
53
|
-
|
54
|
-
timer_set: self
|
55
|
-
}
|
51
|
+
opts = { executor: @task_executor,
|
52
|
+
args: args,
|
53
|
+
timer_set: self }
|
56
54
|
task = ScheduledTask.execute(delay, opts, &task) # may raise exception
|
57
55
|
task.unscheduled? ? false : task
|
58
56
|
end
|
@@ -74,11 +72,11 @@ module Concurrent
|
|
74
72
|
# @param [Hash] opts the options to create the object with.
|
75
73
|
# @!visibility private
|
76
74
|
def ns_initialize(opts)
|
77
|
-
@queue
|
78
|
-
@task_executor
|
79
|
-
@timer_executor
|
80
|
-
@condition
|
81
|
-
@ruby_pid
|
75
|
+
@queue = Collection::NonConcurrentPriorityQueue.new(order: :min)
|
76
|
+
@task_executor = Options.executor_from_options(opts) || Concurrent.global_io_executor
|
77
|
+
@timer_executor = SingleThreadExecutor.new
|
78
|
+
@condition = Event.new
|
79
|
+
@ruby_pid = $$ # detects if Ruby has forked
|
82
80
|
self.auto_terminate = opts.fetch(:auto_terminate, true)
|
83
81
|
end
|
84
82
|
|
@@ -90,7 +88,7 @@ module Concurrent
|
|
90
88
|
#
|
91
89
|
# @!visibility private
|
92
90
|
def post_task(task)
|
93
|
-
synchronize{ ns_post_task(task) }
|
91
|
+
synchronize { ns_post_task(task) }
|
94
92
|
end
|
95
93
|
|
96
94
|
# @!visibility private
|
@@ -98,7 +96,7 @@ module Concurrent
|
|
98
96
|
return false unless ns_running?
|
99
97
|
ns_reset_if_forked
|
100
98
|
if (task.initial_delay) <= 0.01
|
101
|
-
task.executor.post{ task.process_task }
|
99
|
+
task.executor.post { task.process_task }
|
102
100
|
else
|
103
101
|
@queue.push(task)
|
104
102
|
# only post the process method when the queue is empty
|
@@ -116,7 +114,7 @@ module Concurrent
|
|
116
114
|
#
|
117
115
|
# @!visibility private
|
118
116
|
def remove_task(task)
|
119
|
-
synchronize{ @queue.delete(task) }
|
117
|
+
synchronize { @queue.delete(task) }
|
120
118
|
end
|
121
119
|
|
122
120
|
# `ExecutorService` callback called during shutdown.
|
@@ -148,7 +146,7 @@ module Concurrent
|
|
148
146
|
task = synchronize { @condition.reset; @queue.peek }
|
149
147
|
break unless task
|
150
148
|
|
151
|
-
now
|
149
|
+
now = Concurrent.monotonic_time
|
152
150
|
diff = task.schedule_time - now
|
153
151
|
|
154
152
|
if diff <= 0
|
@@ -165,7 +163,7 @@ module Concurrent
|
|
165
163
|
# queue now must have the same pop time, or a closer one, as
|
166
164
|
# when we peeked).
|
167
165
|
task = synchronize { @queue.pop }
|
168
|
-
task.executor.post{ task.process_task }
|
166
|
+
task.executor.post { task.process_task }
|
169
167
|
else
|
170
168
|
@condition.wait([diff, 60].min)
|
171
169
|
end
|