concurrent-ruby 1.1.7 → 1.1.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +31 -0
- data/Gemfile +2 -7
- data/README.md +40 -20
- data/Rakefile +31 -34
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicFixnumLibrary.java +0 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaSemaphoreLibrary.java +52 -22
- data/lib/concurrent-ruby/concurrent/async.rb +1 -0
- data/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb +1 -0
- data/lib/concurrent-ruby/concurrent/atomic/event.rb +2 -2
- data/lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb +18 -2
- data/lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb +4 -6
- data/lib/concurrent-ruby/concurrent/atomic/ruby_thread_local_var.rb +4 -1
- data/lib/concurrent-ruby/concurrent/atomic/semaphore.rb +26 -5
- data/lib/concurrent-ruby/concurrent/collection/map/truffleruby_map_backend.rb +14 -0
- data/lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb +11 -1
- data/lib/concurrent-ruby/concurrent/concurrent_ruby.jar +0 -0
- data/lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb +16 -13
- data/lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb +13 -3
- data/lib/concurrent-ruby/concurrent/executor/java_executor_service.rb +1 -1
- data/lib/concurrent-ruby/concurrent/executor/java_thread_pool_executor.rb +4 -0
- data/lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb +10 -4
- data/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb +26 -37
- data/lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb +5 -5
- data/lib/concurrent-ruby/concurrent/map.rb +13 -4
- data/lib/concurrent-ruby/concurrent/promise.rb +1 -0
- data/lib/concurrent-ruby/concurrent/scheduled_task.rb +29 -16
- data/lib/concurrent-ruby/concurrent/set.rb +14 -6
- data/lib/concurrent-ruby/concurrent/synchronization/lockable_object.rb +1 -3
- data/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb +12 -0
- data/lib/concurrent-ruby/concurrent/synchronization/rbx_lockable_object.rb +6 -0
- data/lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb +26 -1
- data/lib/concurrent-ruby/concurrent/timer_task.rb +11 -33
- data/lib/concurrent-ruby/concurrent/tvar.rb +19 -56
- data/lib/concurrent-ruby/concurrent/utility/monotonic_time.rb +67 -35
- data/lib/concurrent-ruby/concurrent/utility/processor_counter.rb +2 -35
- data/lib/concurrent-ruby/concurrent/version.rb +1 -1
- data/lib/concurrent-ruby/concurrent-ruby.rb +5 -1
- metadata +8 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e2508d8671dc3f93a6d41204a69a2444669688ac1e9e7790104162ac5180579e
|
4
|
+
data.tar.gz: 5eba3636194c783d376ed010bd3d6ec8796fe409870e07a84c6b0b0ea2704b41
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4c1cbc5311e939aecda5e291bb579a690807de5240bb2fb30600a9d1d9de8c353558de7d6e3e0dff871fcca364bd7caa76b304428e0fdaba323cbe04be300056
|
7
|
+
data.tar.gz: 863635cad877062864813b9ba72685b3afdadabf258a62b36f8d7093a5be9c7115d64aade01c9a98b9e68ef86dff2698e5e0cef7766b9c4dfc740e0e76eccf0c
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,36 @@
|
|
1
1
|
## Current
|
2
2
|
|
3
|
+
## Release v1.1.10
|
4
|
+
|
5
|
+
concurrent-ruby:
|
6
|
+
|
7
|
+
* (#951) Set the Ruby compatibility version at 2.2
|
8
|
+
* (#939, #933) The `caller_runs` fallback policy no longer blocks reads from the job queue by worker threads
|
9
|
+
* (#938, #761, #652) You can now explicitly `prune_pool` a thread pool (Sylvain Joyeux)
|
10
|
+
* (#937, #757, #670) We switched the Yahoo stock API for demos to Alpha Vantage (Gustavo Caso)
|
11
|
+
* (#932, #931) We changed how `SafeTaskExecutor` handles local jump errors (Aaron Jensen)
|
12
|
+
* (#927) You can use keyword arguments in your initialize when using `Async` (Matt Larraz)
|
13
|
+
* (#926, #639) We removed timeout from `TimerTask` because it wasn't sound, and now it's a no-op with a warning (Jacob Atzen)
|
14
|
+
* (#919) If you double-lock a re-entrant read-write lock, we promote to locked for writing (zp yuan)
|
15
|
+
* (#915) `monotonic_time` now accepts an optional unit parameter, as Ruby's `clock_gettime` (Jean Boussier)
|
16
|
+
|
17
|
+
## Release v1.1.9 (5 Jun 2021)
|
18
|
+
|
19
|
+
concurrent-ruby:
|
20
|
+
|
21
|
+
* (#866) Child promise state not set to :pending immediately after #execute when parent has completed
|
22
|
+
* (#905, #872) Fix RubyNonConcurrentPriorityQueue#delete method
|
23
|
+
* (2df0337d) Make sure locks are not shared on shared when objects are dup/cloned
|
24
|
+
* (#900, #906, #796, #847, #911) Fix Concurrent::Set tread-safety issues on CRuby
|
25
|
+
* (#907) Add new ConcurrentMap backend for TruffleRuby
|
26
|
+
|
27
|
+
## Release v1.1.8 (20 January 2021)
|
28
|
+
|
29
|
+
concurrent-ruby:
|
30
|
+
|
31
|
+
* (#885) Fix race condition in TVar for stale reads
|
32
|
+
* (#884) RubyThreadLocalVar: Do not iterate over hash which might conflict with new pair addition
|
33
|
+
|
3
34
|
## Release v1.1.7 (6 August 2020)
|
4
35
|
|
5
36
|
concurrent-ruby:
|
data/Gemfile
CHANGED
@@ -12,7 +12,7 @@ gem 'concurrent-ruby-edge', Concurrent::EDGE_VERSION, options
|
|
12
12
|
gem 'concurrent-ruby-ext', Concurrent::VERSION, options.merge(platform: :mri)
|
13
13
|
|
14
14
|
group :development do
|
15
|
-
gem 'rake',
|
15
|
+
gem 'rake', '~> 13.0'
|
16
16
|
gem 'rake-compiler', '~> 1.0', '>= 1.0.7'
|
17
17
|
gem 'rake-compiler-dock', '~> 1.0'
|
18
18
|
gem 'pry', '~> 0.11', platforms: :mri
|
@@ -26,7 +26,7 @@ end
|
|
26
26
|
|
27
27
|
group :testing do
|
28
28
|
gem 'rspec', '~> 3.7'
|
29
|
-
gem 'timecop', '~> 0.
|
29
|
+
gem 'timecop', '~> 0.9'
|
30
30
|
gem 'sigdump', require: false
|
31
31
|
end
|
32
32
|
|
@@ -35,8 +35,3 @@ group :coverage, optional: !ENV['COVERAGE'] do
|
|
35
35
|
gem 'simplecov', '~> 0.16.0', require: false
|
36
36
|
gem 'coveralls', '~> 0.8.2', require: false
|
37
37
|
end
|
38
|
-
|
39
|
-
group :benchmarks, optional: true do
|
40
|
-
gem 'benchmark-ips', '~> 2.7'
|
41
|
-
gem 'bench9000'
|
42
|
-
end
|
data/README.md
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
# Concurrent Ruby
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/concurrent-ruby.svg)](http://badge.fury.io/rb/concurrent-ruby)
|
4
|
-
[![Build Status](https://travis-ci.org/ruby-concurrency/concurrent-ruby.svg?branch=master)](https://travis-ci.org/ruby-concurrency/concurrent-ruby)
|
5
|
-
[![Build status](https://ci.appveyor.com/api/projects/status/iq8aboyuu3etad4w?svg=true)](https://ci.appveyor.com/project/rubyconcurrency/concurrent-ruby)
|
6
4
|
[![License](https://img.shields.io/badge/license-MIT-green.svg)](http://opensource.org/licenses/MIT)
|
7
5
|
[![Gitter chat](https://img.shields.io/badge/IRC%20(gitter)-devs%20%26%20users-brightgreen.svg)](https://gitter.im/ruby-concurrency/concurrent-ruby)
|
8
6
|
|
@@ -39,6 +37,8 @@ The design goals of this gem are:
|
|
39
37
|
appreciate your help. Would you like to contribute? Great! Have a look at
|
40
38
|
[issues with `looking-for-contributor` label](https://github.com/ruby-concurrency/concurrent-ruby/issues?q=is%3Aissue+is%3Aopen+label%3Alooking-for-contributor).** And if you pick something up let us know on the issue.
|
41
39
|
|
40
|
+
You can also get started by triaging issues which may include reproducing bug reports or asking for vital information, such as version numbers or reproduction instructions. If you would like to start triaging issues, one easy way to get started is to [subscribe to concurrent-ruby on CodeTriage](https://www.codetriage.com/ruby-concurrency/concurrent-ruby). [![Open Source Helpers](https://www.codetriage.com/ruby-concurrency/concurrent-ruby/badges/users.svg)](https://www.codetriage.com/ruby-concurrency/concurrent-ruby)
|
41
|
+
|
42
42
|
## Thread Safety
|
43
43
|
|
44
44
|
*Concurrent Ruby makes one of the strongest thread safety guarantees of any Ruby concurrency
|
@@ -259,15 +259,11 @@ be obeyed though. Features developed in `concurrent-ruby-edge` are expected to m
|
|
259
259
|
|
260
260
|
## Supported Ruby versions
|
261
261
|
|
262
|
-
* MRI 2.
|
263
|
-
* JRuby 9000
|
264
|
-
* TruffleRuby
|
265
|
-
* Any Ruby interpreter that is compliant with Ruby 2.0 or newer.
|
266
|
-
|
267
|
-
Actually we still support mri 1.9.3 and jruby 1.7.27 but we are looking at ways how to drop the support.
|
268
|
-
Java 8 is preferred for JRuby but every Java version on which JRuby 9000 runs is supported.
|
262
|
+
* MRI 2.2 and above
|
263
|
+
* Latest JRuby 9000
|
264
|
+
* Latest TruffleRuby
|
269
265
|
|
270
|
-
The legacy support for Rubinius is kept but it is no longer maintained
|
266
|
+
The legacy support for Rubinius is kept for the moment but it is no longer maintained and is liable to be removed. If you would like to help
|
271
267
|
please respond to [#739](https://github.com/ruby-concurrency/concurrent-ruby/issues/739).
|
272
268
|
|
273
269
|
## Usage
|
@@ -353,23 +349,47 @@ and load the appropriate C extensions.
|
|
353
349
|
No gems should depend on `concurrent-ruby-ext`. Doing so will force C extensions on your users. The
|
354
350
|
best practice is to depend on `concurrent-ruby` and let users to decide if they want C extensions.
|
355
351
|
|
352
|
+
## Building the gem
|
353
|
+
|
354
|
+
### Requirements
|
355
|
+
|
356
|
+
* Recent CRuby
|
357
|
+
* JRuby, `rbenv install jruby-9.2.17.0`
|
358
|
+
* Set env variable `CONCURRENT_JRUBY_HOME` to point to it, e.g. `/usr/local/opt/rbenv/versions/jruby-9.2.17.0`
|
359
|
+
* Install Docker, required for Windows builds
|
360
|
+
|
361
|
+
### Publishing the Gem
|
362
|
+
|
363
|
+
* Update `version.rb`
|
364
|
+
* Update the CHANGELOG
|
365
|
+
* Update the Yard documentation
|
366
|
+
- Add the new version to `docs-source/signpost.md`. Needs to be done only if there are visible changes in the
|
367
|
+
documentation.
|
368
|
+
- Run `bundle exec rake yard` to update the master documentation and signpost.
|
369
|
+
- Run `bundle exec rake yard:<new-version>` to add or update the documentation of the new version.
|
370
|
+
* Commit (and push) the changes.
|
371
|
+
* Use `be rake release` to release the gem. It consists
|
372
|
+
of `['release:checks', 'release:build', 'release:test', 'release:publish']` steps. It will ask at the end before
|
373
|
+
publishing anything. Steps can also be executed individually.
|
374
|
+
|
356
375
|
## Maintainers
|
357
376
|
|
358
|
-
*
|
359
|
-
*
|
360
|
-
* [Chris Seaton](https://github.com/chrisseaton)
|
377
|
+
* [Chris Seaton](https://github.com/chrisseaton) — Lead maintainer, point-of-contact.
|
378
|
+
* [Benoit Daloze](https://github.com/eregon) — If Chris is not available Benoit can help.
|
361
379
|
|
362
380
|
### Special Thanks to
|
363
381
|
|
364
|
-
*
|
365
|
-
*
|
366
|
-
*
|
382
|
+
* [Jerry D'Antonio](https://github.com/jdantonio) for creating the gem
|
383
|
+
* [Brian Durand](https://github.com/bdurand) for the `ref` gem
|
384
|
+
* [Charles Oliver Nutter](https://github.com/headius) for the `atomic` and `thread_safe` gems
|
385
|
+
* [thedarkone](https://github.com/thedarkone) for the `thread_safe` gem
|
367
386
|
|
368
|
-
|
387
|
+
to the past maintainers
|
369
388
|
|
370
|
-
*
|
371
|
-
*
|
372
|
-
*
|
389
|
+
* [Petr Chalupa](https://github.com/pitr-ch)
|
390
|
+
* [Michele Della Torre](https://github.com/mighe)
|
391
|
+
* [Paweł Obrok](https://github.com/obrok)
|
392
|
+
* [Lucas Allan](https://github.com/lucasallan)
|
373
393
|
|
374
394
|
and to [Ruby Association](https://www.ruby.or.jp/en/) for sponsoring a project
|
375
395
|
["Enhancing Ruby’s concurrency tooling"](https://www.ruby.or.jp/en/news/20181106) in 2018.
|
data/Rakefile
CHANGED
@@ -2,15 +2,6 @@ require_relative 'lib/concurrent-ruby/concurrent/version'
|
|
2
2
|
require_relative 'lib/concurrent-ruby-edge/concurrent/edge/version'
|
3
3
|
require_relative 'lib/concurrent-ruby/concurrent/utility/engine'
|
4
4
|
|
5
|
-
if Concurrent.ruby_version :<, 2, 0, 0
|
6
|
-
# @!visibility private
|
7
|
-
module Kernel
|
8
|
-
def __dir__
|
9
|
-
File.dirname __FILE__
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
5
|
core_gemspec = Gem::Specification.load File.join(__dir__, 'concurrent-ruby.gemspec')
|
15
6
|
ext_gemspec = Gem::Specification.load File.join(__dir__, 'concurrent-ruby-ext.gemspec')
|
16
7
|
edge_gemspec = Gem::Specification.load File.join(__dir__, 'concurrent-ruby-edge.gemspec')
|
@@ -24,7 +15,7 @@ Rake::JavaExtensionTask.new('concurrent_ruby', core_gemspec) do |ext|
|
|
24
15
|
ext.lib_dir = 'lib/concurrent-ruby/concurrent'
|
25
16
|
end
|
26
17
|
|
27
|
-
unless Concurrent.on_jruby?
|
18
|
+
unless Concurrent.on_jruby? || Concurrent.on_truffleruby?
|
28
19
|
require 'rake/extensiontask'
|
29
20
|
|
30
21
|
Rake::ExtensionTask.new('concurrent_ruby_ext', ext_gemspec) do |ext|
|
@@ -49,7 +40,9 @@ namespace :repackage do
|
|
49
40
|
Rake::Task['lib/concurrent-ruby/concurrent/concurrent_ruby.jar'].invoke
|
50
41
|
|
51
42
|
# build all gem files
|
52
|
-
|
43
|
+
%w[x86-mingw32 x64-mingw32].each do |plat|
|
44
|
+
RakeCompilerDock.sh "bundle install --local && bundle exec rake native:#{plat} gem --trace", platform: plat
|
45
|
+
end
|
53
46
|
end
|
54
47
|
end
|
55
48
|
end
|
@@ -75,8 +68,7 @@ begin
|
|
75
68
|
options = %w[ --color
|
76
69
|
--backtrace
|
77
70
|
--order defined
|
78
|
-
--format documentation
|
79
|
-
--tag ~notravis ]
|
71
|
+
--format documentation ]
|
80
72
|
t.rspec_opts = [*options].join(' ')
|
81
73
|
end
|
82
74
|
|
@@ -133,7 +125,7 @@ begin
|
|
133
125
|
task :update_readme do
|
134
126
|
Dir.chdir __dir__ do
|
135
127
|
content = File.read(File.join('README.md')).
|
136
|
-
|
128
|
+
gsub(/\[([\w ]+)\]\(http:\/\/ruby-concurrency\.github\.io\/concurrent-ruby\/master\/.*\)/) do |_|
|
137
129
|
case $1
|
138
130
|
when 'LockFreeLinkedSet'
|
139
131
|
"{Concurrent::Edge::#{$1} #{$1}}"
|
@@ -163,9 +155,9 @@ begin
|
|
163
155
|
desc "* of #{name} into subdir #{name}"
|
164
156
|
YARD::Rake::YardocTask.new(name) do |yard|
|
165
157
|
yard.options.push(
|
166
|
-
|
167
|
-
|
168
|
-
|
158
|
+
'--output-dir', output_dir,
|
159
|
+
'--main', 'tmp/README.md',
|
160
|
+
*common_yard_options)
|
169
161
|
yard.files = ['./lib/concurrent-ruby/**/*.rb',
|
170
162
|
'./lib/concurrent-ruby-edge/**/*.rb',
|
171
163
|
'./ext/concurrent_ruby_ext/**/*.c',
|
@@ -187,9 +179,9 @@ begin
|
|
187
179
|
desc "* signpost for versions"
|
188
180
|
YARD::Rake::YardocTask.new(:signpost) do |yard|
|
189
181
|
yard.options.push(
|
190
|
-
|
191
|
-
|
192
|
-
|
182
|
+
'--output-dir', 'docs',
|
183
|
+
'--main', 'docs-source/signpost.md',
|
184
|
+
*common_yard_options)
|
193
185
|
yard.files = ['no-lib']
|
194
186
|
end
|
195
187
|
|
@@ -204,7 +196,7 @@ begin
|
|
204
196
|
sh 'diff -r docs/ docs-copy/' do |ok, res|
|
205
197
|
unless ok
|
206
198
|
begin
|
207
|
-
STDOUT.puts
|
199
|
+
STDOUT.puts "yard:#{name} is not properly generated and committed.", "Continue? (y/n)"
|
208
200
|
input = STDIN.gets.strip.downcase
|
209
201
|
end until %w(y n).include?(input)
|
210
202
|
exit 1 if input == 'n'
|
@@ -232,15 +224,13 @@ task :release => ['release:checks', 'release:build', 'release:test', 'release:pu
|
|
232
224
|
namespace :release do
|
233
225
|
# Depends on environment of @pitr-ch
|
234
226
|
|
235
|
-
mri_version = '2.6.5'
|
236
|
-
jruby_version = 'jruby-9.2.9.0'
|
237
|
-
|
238
227
|
task :checks => "yard:#{current_yard_version_name}:uptodate" do
|
239
228
|
Dir.chdir(__dir__) do
|
240
229
|
sh 'test -z "$(git status --porcelain)"' do |ok, res|
|
241
230
|
unless ok
|
242
231
|
begin
|
243
|
-
|
232
|
+
status = `git status --porcelain`
|
233
|
+
STDOUT.puts 'There are local changes that you might want to commit.', status, 'Continue? (y/n)'
|
244
234
|
input = STDIN.gets.strip.downcase
|
245
235
|
end until %w(y n).include?(input)
|
246
236
|
exit 1 if input == 'n'
|
@@ -248,10 +238,10 @@ namespace :release do
|
|
248
238
|
end
|
249
239
|
sh 'git fetch'
|
250
240
|
sh 'test $(git show-ref --verify --hash refs/heads/master) = ' +
|
251
|
-
|
241
|
+
'$(git show-ref --verify --hash refs/remotes/origin/master)' do |ok, res|
|
252
242
|
unless ok
|
253
243
|
begin
|
254
|
-
STDOUT.puts '
|
244
|
+
STDOUT.puts 'Local master branch is not pushed to origin.', 'Continue? (y/n)'
|
255
245
|
input = STDIN.gets.strip.downcase
|
256
246
|
end until %w(y n).include?(input)
|
257
247
|
exit 1 if input == 'n'
|
@@ -268,6 +258,12 @@ namespace :release do
|
|
268
258
|
Dir.chdir(__dir__) do
|
269
259
|
old = ENV['RBENV_VERSION']
|
270
260
|
|
261
|
+
mri_version = `ruby -e 'puts RUBY_VERSION'`.chomp
|
262
|
+
jruby_version = File.basename(ENV['CONCURRENT_JRUBY_HOME'])
|
263
|
+
|
264
|
+
puts "Using following version:"
|
265
|
+
pp mri_version: mri_version, jruby_version: jruby_version
|
266
|
+
|
271
267
|
ENV['RBENV_VERSION'] = mri_version
|
272
268
|
sh 'rbenv version'
|
273
269
|
sh 'bundle exec rake spec:installed'
|
@@ -290,19 +286,19 @@ namespace :release do
|
|
290
286
|
|
291
287
|
task :ask do
|
292
288
|
begin
|
293
|
-
STDOUT.puts 'Do you want to publish anything? (y/n)'
|
289
|
+
STDOUT.puts 'Do you want to publish anything now? (y/n)'
|
294
290
|
input = STDIN.gets.strip.downcase
|
295
291
|
end until %w(y n).include?(input)
|
296
292
|
exit 1 if input == 'n'
|
297
293
|
begin
|
298
|
-
STDOUT.puts 'Do you want to publish edge
|
294
|
+
STDOUT.puts 'It will publish `concurrent-ruby`. Do you want to publish `concurrent-ruby-edge`? (y/n)'
|
299
295
|
input = STDIN.gets.strip.downcase
|
300
296
|
end until %w(y n).include?(input)
|
301
297
|
publish_edge = input == 'y'
|
302
298
|
end
|
303
299
|
|
304
300
|
desc '** tag HEAD with current version and push to github'
|
305
|
-
task :tag do
|
301
|
+
task :tag => :ask do
|
306
302
|
Dir.chdir(__dir__) do
|
307
303
|
sh "git tag v#{Concurrent::VERSION}"
|
308
304
|
sh "git push origin v#{Concurrent::VERSION}"
|
@@ -312,7 +308,7 @@ namespace :release do
|
|
312
308
|
end
|
313
309
|
|
314
310
|
desc '** push all *.gem files to rubygems'
|
315
|
-
task :rubygems do
|
311
|
+
task :rubygems => :ask do
|
316
312
|
Dir.chdir(__dir__) do
|
317
313
|
sh "gem push pkg/concurrent-ruby-#{Concurrent::VERSION}.gem"
|
318
314
|
sh "gem push pkg/concurrent-ruby-edge-#{Concurrent::EDGE_VERSION}.gem" if publish_edge
|
@@ -324,9 +320,10 @@ namespace :release do
|
|
324
320
|
|
325
321
|
desc '** print post release steps'
|
326
322
|
task :post_steps do
|
327
|
-
|
328
|
-
puts 'Manually:
|
329
|
-
puts 'Manually:
|
323
|
+
# TODO: (petr 05-Jun-2021) automate and renew the process
|
324
|
+
# puts 'Manually: create a release on GitHub with relevant changelog part'
|
325
|
+
# puts 'Manually: send email same as release with relevant changelog part'
|
326
|
+
# puts 'Manually: tweet'
|
330
327
|
end
|
331
328
|
end
|
332
329
|
end
|
File without changes
|
@@ -10,6 +10,7 @@ import org.jruby.RubyNumeric;
|
|
10
10
|
import org.jruby.RubyObject;
|
11
11
|
import org.jruby.anno.JRubyClass;
|
12
12
|
import org.jruby.anno.JRubyMethod;
|
13
|
+
import org.jruby.runtime.Block;
|
13
14
|
import org.jruby.runtime.ObjectAllocator;
|
14
15
|
import org.jruby.runtime.ThreadContext;
|
15
16
|
import org.jruby.runtime.builtin.IRubyObject;
|
@@ -45,9 +46,13 @@ public class JavaSemaphoreLibrary {
|
|
45
46
|
}
|
46
47
|
|
47
48
|
@JRubyMethod
|
48
|
-
public IRubyObject acquire(ThreadContext context,
|
49
|
-
this.
|
50
|
-
|
49
|
+
public IRubyObject acquire(ThreadContext context, final Block block) throws InterruptedException {
|
50
|
+
return this.acquire(context, 1, block);
|
51
|
+
}
|
52
|
+
|
53
|
+
@JRubyMethod
|
54
|
+
public IRubyObject acquire(ThreadContext context, IRubyObject permits, final Block block) throws InterruptedException {
|
55
|
+
return this.acquire(context, rubyFixnumToPositiveInt(permits, "permits"), block);
|
51
56
|
}
|
52
57
|
|
53
58
|
@JRubyMethod(name = "available_permits")
|
@@ -60,30 +65,32 @@ public class JavaSemaphoreLibrary {
|
|
60
65
|
return getRuntime().newFixnum(this.semaphore.drainPermits());
|
61
66
|
}
|
62
67
|
|
63
|
-
@JRubyMethod
|
64
|
-
public IRubyObject acquire(ThreadContext context) throws InterruptedException {
|
65
|
-
this.semaphore.acquire(1);
|
66
|
-
return context.nil;
|
67
|
-
}
|
68
|
-
|
69
68
|
@JRubyMethod(name = "try_acquire")
|
70
|
-
public IRubyObject tryAcquire(ThreadContext context) throws InterruptedException {
|
71
|
-
|
69
|
+
public IRubyObject tryAcquire(ThreadContext context, final Block block) throws InterruptedException {
|
70
|
+
int permitsInt = 1;
|
71
|
+
boolean acquired = semaphore.tryAcquire(permitsInt);
|
72
|
+
|
73
|
+
return triedAcquire(context, permitsInt, acquired, block);
|
72
74
|
}
|
73
75
|
|
74
76
|
@JRubyMethod(name = "try_acquire")
|
75
|
-
public IRubyObject tryAcquire(ThreadContext context, IRubyObject permits) throws InterruptedException {
|
76
|
-
|
77
|
+
public IRubyObject tryAcquire(ThreadContext context, IRubyObject permits, final Block block) throws InterruptedException {
|
78
|
+
int permitsInt = rubyFixnumToPositiveInt(permits, "permits");
|
79
|
+
boolean acquired = semaphore.tryAcquire(permitsInt);
|
80
|
+
|
81
|
+
return triedAcquire(context, permitsInt, acquired, block);
|
77
82
|
}
|
78
83
|
|
79
84
|
@JRubyMethod(name = "try_acquire")
|
80
|
-
public IRubyObject tryAcquire(ThreadContext context, IRubyObject permits, IRubyObject timeout) throws InterruptedException {
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
85
|
+
public IRubyObject tryAcquire(ThreadContext context, IRubyObject permits, IRubyObject timeout, final Block block) throws InterruptedException {
|
86
|
+
int permitsInt = rubyFixnumToPositiveInt(permits, "permits");
|
87
|
+
boolean acquired = semaphore.tryAcquire(
|
88
|
+
permitsInt,
|
89
|
+
rubyNumericToLong(timeout, "timeout"),
|
90
|
+
java.util.concurrent.TimeUnit.SECONDS
|
91
|
+
);
|
92
|
+
|
93
|
+
return triedAcquire(context, permitsInt, acquired, block);
|
87
94
|
}
|
88
95
|
|
89
96
|
@JRubyMethod
|
@@ -93,8 +100,8 @@ public class JavaSemaphoreLibrary {
|
|
93
100
|
}
|
94
101
|
|
95
102
|
@JRubyMethod
|
96
|
-
public IRubyObject release(ThreadContext context, IRubyObject
|
97
|
-
this.semaphore.release(rubyFixnumToPositiveInt(
|
103
|
+
public IRubyObject release(ThreadContext context, IRubyObject permits) {
|
104
|
+
this.semaphore.release(rubyFixnumToPositiveInt(permits, "permits"));
|
98
105
|
return getRuntime().newBoolean(true);
|
99
106
|
}
|
100
107
|
|
@@ -104,6 +111,29 @@ public class JavaSemaphoreLibrary {
|
|
104
111
|
return context.nil;
|
105
112
|
}
|
106
113
|
|
114
|
+
private IRubyObject acquire(ThreadContext context, int permits, final Block block) throws InterruptedException {
|
115
|
+
this.semaphore.acquire(permits);
|
116
|
+
|
117
|
+
if (!block.isGiven()) return context.nil;
|
118
|
+
|
119
|
+
try {
|
120
|
+
return block.yieldSpecific(context);
|
121
|
+
} finally {
|
122
|
+
this.semaphore.release(permits);
|
123
|
+
}
|
124
|
+
}
|
125
|
+
|
126
|
+
private IRubyObject triedAcquire(ThreadContext context, int permits, boolean acquired, final Block block) {
|
127
|
+
if (!block.isGiven()) return getRuntime().newBoolean(acquired);
|
128
|
+
if (!acquired) return context.nil;
|
129
|
+
|
130
|
+
try {
|
131
|
+
return block.yieldSpecific(context);
|
132
|
+
} finally {
|
133
|
+
this.semaphore.release(permits);
|
134
|
+
}
|
135
|
+
}
|
136
|
+
|
107
137
|
private int rubyFixnumInt(IRubyObject value, String paramName) {
|
108
138
|
if (value instanceof RubyFixnum) {
|
109
139
|
RubyFixnum fixNum = (RubyFixnum) value;
|
@@ -170,6 +170,7 @@ module Concurrent
|
|
170
170
|
alias_method :compare_and_swap, :compare_and_set
|
171
171
|
alias_method :swap, :get_and_set
|
172
172
|
end
|
173
|
+
TruffleRubyAtomicReference
|
173
174
|
when Concurrent.on_rbx?
|
174
175
|
# @note Extends `Rubinius::AtomicReference` version adding aliases
|
175
176
|
# and numeric logic.
|
@@ -19,7 +19,7 @@ module Concurrent
|
|
19
19
|
# t1 = Thread.new do
|
20
20
|
# puts "t1 is waiting"
|
21
21
|
# event.wait(1)
|
22
|
-
# puts "event
|
22
|
+
# puts "event occurred"
|
23
23
|
# end
|
24
24
|
#
|
25
25
|
# t2 = Thread.new do
|
@@ -30,8 +30,8 @@ module Concurrent
|
|
30
30
|
# [t1, t2].each(&:join)
|
31
31
|
#
|
32
32
|
# # prints:
|
33
|
-
# # t2 calling set
|
34
33
|
# # t1 is waiting
|
34
|
+
# # t2 calling set
|
35
35
|
# # event occurred
|
36
36
|
class Event < Synchronization::LockableObject
|
37
37
|
|
@@ -23,7 +23,14 @@ module Concurrent
|
|
23
23
|
|
24
24
|
synchronize do
|
25
25
|
try_acquire_timed(permits, nil)
|
26
|
-
|
26
|
+
end
|
27
|
+
|
28
|
+
return unless block_given?
|
29
|
+
|
30
|
+
begin
|
31
|
+
yield
|
32
|
+
ensure
|
33
|
+
release(permits)
|
27
34
|
end
|
28
35
|
end
|
29
36
|
|
@@ -48,13 +55,22 @@ module Concurrent
|
|
48
55
|
Utility::NativeInteger.ensure_integer_and_bounds permits
|
49
56
|
Utility::NativeInteger.ensure_positive permits
|
50
57
|
|
51
|
-
synchronize do
|
58
|
+
acquired = synchronize do
|
52
59
|
if timeout.nil?
|
53
60
|
try_acquire_now(permits)
|
54
61
|
else
|
55
62
|
try_acquire_timed(permits, timeout)
|
56
63
|
end
|
57
64
|
end
|
65
|
+
|
66
|
+
return acquired unless block_given?
|
67
|
+
return unless acquired
|
68
|
+
|
69
|
+
begin
|
70
|
+
yield
|
71
|
+
ensure
|
72
|
+
release(permits)
|
73
|
+
end
|
58
74
|
end
|
59
75
|
|
60
76
|
# @!macro semaphore_method_release
|
@@ -267,12 +267,10 @@ module Concurrent
|
|
267
267
|
# running right now, AND no writers who came before us still waiting to
|
268
268
|
# acquire the lock
|
269
269
|
# Additionally, if any read locks have been taken, we must hold all of them
|
270
|
-
if
|
271
|
-
# If we successfully swap the RUNNING_WRITER bit on, then we can go ahead
|
272
|
-
|
273
|
-
|
274
|
-
return true
|
275
|
-
end
|
270
|
+
if held > 0 && @Counter.compare_and_set(1, c+RUNNING_WRITER)
|
271
|
+
# If we are the only one reader and successfully swap the RUNNING_WRITER bit on, then we can go ahead
|
272
|
+
@HeldCount.value = held + WRITE_LOCK_HELD
|
273
|
+
return true
|
276
274
|
elsif @Counter.compare_and_set(c, c+WAITING_WRITER)
|
277
275
|
while true
|
278
276
|
# Now we have successfully incremented, so no more readers will be able to increment
|
@@ -97,7 +97,10 @@ module Concurrent
|
|
97
97
|
# The cost of GC'ing a TLV is linear in the number of threads using TLVs
|
98
98
|
# But that is natural! More threads means more storage is used per TLV
|
99
99
|
# So naturally more CPU time is required to free more storage
|
100
|
-
|
100
|
+
#
|
101
|
+
# DO NOT use each_value which might conflict with new pair assignment
|
102
|
+
# into the hash in #value= method
|
103
|
+
THREAD_LOCAL_ARRAYS.values.each { |array| array[index] = nil }
|
101
104
|
# free index has to be published after the arrays are cleared
|
102
105
|
FREE.push(index)
|
103
106
|
end
|
@@ -16,14 +16,16 @@ module Concurrent
|
|
16
16
|
# @!macro semaphore_method_acquire
|
17
17
|
#
|
18
18
|
# Acquires the given number of permits from this semaphore,
|
19
|
-
# blocking until all are available.
|
19
|
+
# blocking until all are available. If a block is given,
|
20
|
+
# yields to it and releases the permits afterwards.
|
20
21
|
#
|
21
22
|
# @param [Fixnum] permits Number of permits to acquire
|
22
23
|
#
|
23
24
|
# @raise [ArgumentError] if `permits` is not an integer or is less than
|
24
25
|
# one
|
25
26
|
#
|
26
|
-
# @return [nil]
|
27
|
+
# @return [nil, BasicObject] Without a block, `nil` is returned. If a block
|
28
|
+
# is given, its return value is returned.
|
27
29
|
|
28
30
|
# @!macro semaphore_method_available_permits
|
29
31
|
#
|
@@ -41,7 +43,9 @@ module Concurrent
|
|
41
43
|
#
|
42
44
|
# Acquires the given number of permits from this semaphore,
|
43
45
|
# only if all are available at the time of invocation or within
|
44
|
-
# `timeout` interval
|
46
|
+
# `timeout` interval. If a block is given, yields to it if the permits
|
47
|
+
# were successfully acquired, and releases them afterward, returning the
|
48
|
+
# block's return value.
|
45
49
|
#
|
46
50
|
# @param [Fixnum] permits the number of permits to acquire
|
47
51
|
#
|
@@ -51,8 +55,10 @@ module Concurrent
|
|
51
55
|
# @raise [ArgumentError] if `permits` is not an integer or is less than
|
52
56
|
# one
|
53
57
|
#
|
54
|
-
# @return [
|
55
|
-
# acquired a permit
|
58
|
+
# @return [true, false, nil, BasicObject] `false` if no permits are
|
59
|
+
# available, `true` when acquired a permit. If a block is given, the
|
60
|
+
# block's return value is returned if the permits were acquired; if not,
|
61
|
+
# `nil` is returned.
|
56
62
|
|
57
63
|
# @!macro semaphore_method_release
|
58
64
|
#
|
@@ -106,6 +112,8 @@ module Concurrent
|
|
106
112
|
# releasing a blocking acquirer.
|
107
113
|
# However, no actual permit objects are used; the Semaphore just keeps a
|
108
114
|
# count of the number available and acts accordingly.
|
115
|
+
# Alternatively, permits may be acquired within a block, and automatically
|
116
|
+
# released after the block finishes executing.
|
109
117
|
#
|
110
118
|
# @!macro semaphore_public_api
|
111
119
|
# @example
|
@@ -140,6 +148,19 @@ module Concurrent
|
|
140
148
|
# # Thread 4 releasing semaphore
|
141
149
|
# # Thread 1 acquired semaphore
|
142
150
|
#
|
151
|
+
# @example
|
152
|
+
# semaphore = Concurrent::Semaphore.new(1)
|
153
|
+
#
|
154
|
+
# puts semaphore.available_permits
|
155
|
+
# semaphore.acquire do
|
156
|
+
# puts semaphore.available_permits
|
157
|
+
# end
|
158
|
+
# puts semaphore.available_permits
|
159
|
+
#
|
160
|
+
# # prints:
|
161
|
+
# # 1
|
162
|
+
# # 0
|
163
|
+
# # 1
|
143
164
|
class Semaphore < SemaphoreImplementation
|
144
165
|
end
|
145
166
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Concurrent
|
2
|
+
|
3
|
+
# @!visibility private
|
4
|
+
module Collection
|
5
|
+
|
6
|
+
# @!visibility private
|
7
|
+
class TruffleRubyMapBackend < TruffleRuby::ConcurrentMap
|
8
|
+
def initialize(options = nil)
|
9
|
+
options ||= {}
|
10
|
+
super(initial_capacity: options[:initial_capacity], load_factor: options[:load_factor])
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|