concurrent-ruby 1.1.6 → 1.1.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +40 -0
  3. data/Gemfile +3 -8
  4. data/{LICENSE.md → LICENSE.txt} +18 -20
  5. data/README.md +43 -23
  6. data/Rakefile +32 -35
  7. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicFixnumLibrary.java +0 -0
  8. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaSemaphoreLibrary.java +52 -22
  9. data/lib/concurrent-ruby/concurrent/array.rb +1 -1
  10. data/lib/concurrent-ruby/concurrent/async.rb +10 -20
  11. data/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb +1 -0
  12. data/lib/concurrent-ruby/concurrent/atomic/event.rb +2 -2
  13. data/lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb +18 -2
  14. data/lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb +4 -6
  15. data/lib/concurrent-ruby/concurrent/atomic/ruby_thread_local_var.rb +52 -42
  16. data/lib/concurrent-ruby/concurrent/atomic/semaphore.rb +26 -5
  17. data/lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb +1 -1
  18. data/lib/concurrent-ruby/concurrent/collection/map/truffleruby_map_backend.rb +14 -0
  19. data/lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb +11 -1
  20. data/lib/concurrent-ruby/concurrent/concurrent_ruby.jar +0 -0
  21. data/lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb +16 -13
  22. data/lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb +20 -3
  23. data/lib/concurrent-ruby/concurrent/executor/java_executor_service.rb +1 -1
  24. data/lib/concurrent-ruby/concurrent/executor/java_thread_pool_executor.rb +17 -1
  25. data/lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb +10 -4
  26. data/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb +37 -38
  27. data/lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb +5 -5
  28. data/lib/concurrent-ruby/concurrent/executor/thread_pool_executor.rb +2 -1
  29. data/lib/concurrent-ruby/concurrent/hash.rb +1 -1
  30. data/lib/concurrent-ruby/concurrent/immutable_struct.rb +1 -1
  31. data/lib/concurrent-ruby/concurrent/map.rb +13 -4
  32. data/lib/concurrent-ruby/concurrent/mutable_struct.rb +2 -2
  33. data/lib/concurrent-ruby/concurrent/promise.rb +1 -0
  34. data/lib/concurrent-ruby/concurrent/scheduled_task.rb +29 -16
  35. data/lib/concurrent-ruby/concurrent/set.rb +14 -6
  36. data/lib/concurrent-ruby/concurrent/settable_struct.rb +1 -1
  37. data/lib/concurrent-ruby/concurrent/synchronization/lockable_object.rb +3 -5
  38. data/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb +12 -0
  39. data/lib/concurrent-ruby/concurrent/synchronization/rbx_lockable_object.rb +6 -0
  40. data/lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb +26 -1
  41. data/lib/concurrent-ruby/concurrent/thread_safe/util/striped64.rb +1 -1
  42. data/lib/concurrent-ruby/concurrent/timer_task.rb +11 -34
  43. data/lib/concurrent-ruby/concurrent/tvar.rb +19 -56
  44. data/lib/concurrent-ruby/concurrent/utility/monotonic_time.rb +67 -35
  45. data/lib/concurrent-ruby/concurrent/utility/processor_counter.rb +2 -35
  46. data/lib/concurrent-ruby/concurrent/version.rb +1 -1
  47. data/lib/concurrent-ruby/concurrent-ruby.rb +5 -1
  48. metadata +10 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 649de1a5e5c7c82652bd6ad21496f2c1061d7c75517271d8ca30c3ceb9c49038
4
- data.tar.gz: 6274d2cd2dcda660a1e34436547eca26d6c74d03e9a527d7ce5d1a9f3f72f4be
3
+ metadata.gz: e2508d8671dc3f93a6d41204a69a2444669688ac1e9e7790104162ac5180579e
4
+ data.tar.gz: 5eba3636194c783d376ed010bd3d6ec8796fe409870e07a84c6b0b0ea2704b41
5
5
  SHA512:
6
- metadata.gz: 2adbf28bdf7034295709496964e8e70d22f59bf058bf18ca005c2ce536627160538de6c510ea1f39893de0ad90b2fb50d6f35c848c97f58bd8f71ff8d9e57fc2
7
- data.tar.gz: 1cbc384488e0f70d19d742e54c34dbd7abfaffe89f75230b2f5b80d2ae4d161b731666ce6b64e8f5adeb561b6d32191ce6bd679e05d6bd9eec91b869ee379b2f
6
+ metadata.gz: 4c1cbc5311e939aecda5e291bb579a690807de5240bb2fb30600a9d1d9de8c353558de7d6e3e0dff871fcca364bd7caa76b304428e0fdaba323cbe04be300056
7
+ data.tar.gz: 863635cad877062864813b9ba72685b3afdadabf258a62b36f8d7093a5be9c7115d64aade01c9a98b9e68ef86dff2698e5e0cef7766b9c4dfc740e0e76eccf0c
data/CHANGELOG.md CHANGED
@@ -1,5 +1,45 @@
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
+
34
+ ## Release v1.1.7 (6 August 2020)
35
+
36
+ concurrent-ruby:
37
+
38
+ * (#879) Consider falsy value on `Concurrent::Map#compute_if_absent` for fast non-blocking path
39
+ * (#876) Reset Async queue on forking, makes Async fork-safe
40
+ * (#856) Avoid running problematic code in RubyThreadLocalVar on MRI that occasionally results in segfault
41
+ * (#853) Introduce ThreadPoolExecutor without a Queue
42
+
3
43
  ## Release v1.1.6, edge v0.6.0 (10 Feb 2020)
4
44
 
5
45
  concurrent-ruby:
data/Gemfile CHANGED
@@ -12,9 +12,9 @@ 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', (Concurrent.ruby_version :<, 2, 2, 0) ? '~> 12.0' : '~> 13.0'
15
+ gem 'rake', '~> 13.0'
16
16
  gem 'rake-compiler', '~> 1.0', '>= 1.0.7'
17
- gem 'rake-compiler-dock', '~> 0.7.0'
17
+ gem 'rake-compiler-dock', '~> 1.0'
18
18
  gem 'pry', '~> 0.11', platforms: :mri
19
19
  end
20
20
 
@@ -26,7 +26,7 @@ end
26
26
 
27
27
  group :testing do
28
28
  gem 'rspec', '~> 3.7'
29
- gem 'timecop', '~> 0.7.4'
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
@@ -1,23 +1,21 @@
1
- ```
2
1
  Copyright (c) Jerry D'Antonio -- released under the MIT license.
3
2
 
4
- http://www.opensource.org/licenses/mit-license.php
3
+ http://www.opensource.org/licenses/mit-license.php
5
4
 
6
- Permission is hereby granted, free of charge, to any person obtaining a copy
7
- of this software and associated documentation files (the "Software"), to deal
8
- in the Software without restriction, including without limitation the rights
9
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
- copies of the Software, and to permit persons to whom the Software is
11
- furnished to do so, subject to the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be included in
14
- all copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
- THE SOFTWARE.
23
- ```
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
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
@@ -105,9 +105,9 @@ We also have a [IRC (gitter)](https://gitter.im/ruby-concurrency/concurrent-ruby
105
105
  Collection classes that were originally part of the (deprecated) `thread_safe` gem:
106
106
 
107
107
  * [Array](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Array.html) A thread-safe
108
- subclass of Ruby's standard [Array](http://ruby-doc.org/core-2.2.0/Array.html).
108
+ subclass of Ruby's standard [Array](http://ruby-doc.org/core/Array.html).
109
109
  * [Hash](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Hash.html) A thread-safe
110
- subclass of Ruby's standard [Hash](http://ruby-doc.org/core-2.2.0/Hash.html).
110
+ subclass of Ruby's standard [Hash](http://ruby-doc.org/core/Hash.html).
111
111
  * [Set](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Set.html) A thread-safe
112
112
  subclass of Ruby's standard [Set](http://ruby-doc.org/stdlib-2.4.0/libdoc/set/rdoc/Set.html).
113
113
  * [Map](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Map.html) A hash-like object
@@ -122,7 +122,7 @@ Value objects inspired by other languages:
122
122
  immutable object representing an optional value, based on
123
123
  [Haskell Data.Maybe](https://hackage.haskell.org/package/base-4.2.0.1/docs/Data-Maybe.html).
124
124
 
125
- Structure classes derived from Ruby's [Struct](http://ruby-doc.org/core-2.2.0/Struct.html):
125
+ Structure classes derived from Ruby's [Struct](http://ruby-doc.org/core/Struct.html):
126
126
 
127
127
  * [ImmutableStruct](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/ImmutableStruct.html)
128
128
  Immutable struct where values are set at construction and cannot be changed later.
@@ -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.0 and above
263
- * JRuby 9000
264
- * TruffleRuby are supported.
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, if you would like to help
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
- * [Petr Chalupa](https://github.com/pitr-ch) (lead maintainer, point-of-contact)
359
- * [Jerry D'Antonio](https://github.com/jdantonio) (creator)
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
- * [Brian Durand](https://github.com/bdurand) for the `ref` gem
365
- * [Charles Oliver Nutter](https://github.com/headius) for the `atomic` and `thread_safe` gems
366
- * [thedarkone](https://github.com/thedarkone) for the `thread_safe` gem
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
- and to the past maintainers
387
+ to the past maintainers
369
388
 
370
- * [Michele Della Torre](https://github.com/mighe)
371
- * [Paweł Obrok](https://github.com/obrok)
372
- * [Lucas Allan](https://github.com/lucasallan)
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
- RakeCompilerDock.sh 'bundle install --local && bundle exec rake cross native package --trace'
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
- gsub(/\[([\w ]+)\]\(http:\/\/ruby-concurrency\.github\.io\/concurrent-ruby\/master\/.*\)/) do |_|
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
- '--output-dir', output_dir,
167
- '--main', 'tmp/README.md',
168
- *common_yard_options)
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',
@@ -173,7 +165,7 @@ begin
173
165
  'docs-source/thread_pools.md',
174
166
  'docs-source/promises.out.md',
175
167
  'docs-source/medium-example.out.rb',
176
- 'LICENSE.md',
168
+ 'LICENSE.txt',
177
169
  'CHANGELOG.md']
178
170
  end
179
171
  Rake::Task[name].prerequisites.push removal_name,
@@ -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
- '--output-dir', 'docs',
191
- '--main', 'docs-source/signpost.md',
192
- *common_yard_options)
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 'Command failed. Continue? (y/n)'
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
- STDOUT.puts 'Command failed. Continue? (y/n)'
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
- '$(git show-ref --verify --hash refs/remotes/origin/master)' do |ok, res|
241
+ '$(git show-ref --verify --hash refs/remotes/origin/master)' do |ok, res|
252
242
  unless ok
253
243
  begin
254
- STDOUT.puts 'Command failed. Continue? (y/n)'
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? (y/n)'
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
- puts 'Manually: create a release on GitHub with relevant changelog part'
328
- puts 'Manually: send email same as release with relevant changelog part'
329
- puts 'Manually: tweet'
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
@@ -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, IRubyObject value) throws InterruptedException {
49
- this.semaphore.acquire(rubyFixnumToPositiveInt(value, "permits"));
50
- return context.nil;
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
- return getRuntime().newBoolean(semaphore.tryAcquire(1));
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
- return getRuntime().newBoolean(semaphore.tryAcquire(rubyFixnumToPositiveInt(permits, "permits")));
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
- return getRuntime().newBoolean(
82
- semaphore.tryAcquire(
83
- rubyFixnumToPositiveInt(permits, "permits"),
84
- rubyNumericToLong(timeout, "timeout"),
85
- java.util.concurrent.TimeUnit.SECONDS)
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 value) {
97
- this.semaphore.release(rubyFixnumToPositiveInt(value, "permits"));
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;
@@ -16,7 +16,7 @@ module Concurrent
16
16
  # operation therefore when two `+=` operations are executed concurrently updates
17
17
  # may be lost. Use `#concat` instead.
18
18
  #
19
- # @see http://ruby-doc.org/core-2.2.0/Array.html Ruby standard library `Array`
19
+ # @see http://ruby-doc.org/core/Array.html Ruby standard library `Array`
20
20
 
21
21
  # @!macro internal_implementation_note
22
22
  ArrayImplementation = case
@@ -58,26 +58,6 @@ module Concurrent
58
58
  # end
59
59
  # ```
60
60
  #
61
- # When defining a constructor it is critical that the first line be a call to
62
- # `super` with no arguments. The `super` method initializes the background
63
- # thread and other asynchronous components.
64
- #
65
- # ```
66
- # class BackgroundLogger
67
- # include Concurrent::Async
68
- #
69
- # def initialize(level)
70
- # super()
71
- # @logger = Logger.new(STDOUT)
72
- # @logger.level = level
73
- # end
74
- #
75
- # def info(msg)
76
- # @logger.info(msg)
77
- # end
78
- # end
79
- # ```
80
- #
81
61
  # Mixing this module into a class provides each object two proxy methods:
82
62
  # `async` and `await`. These methods are thread safe with respect to the
83
63
  # enclosing object. The former proxy allows methods to be called
@@ -292,6 +272,7 @@ module Concurrent
292
272
  obj.send(:init_synchronization)
293
273
  obj
294
274
  end
275
+ ruby2_keywords :new if respond_to?(:ruby2_keywords, true)
295
276
  end
296
277
  private_constant :ClassMethods
297
278
 
@@ -309,6 +290,7 @@ module Concurrent
309
290
  @delegate = delegate
310
291
  @queue = []
311
292
  @executor = Concurrent.global_io_executor
293
+ @ruby_pid = $$
312
294
  end
313
295
 
314
296
  # Delegates method calls to the wrapped object.
@@ -326,6 +308,7 @@ module Concurrent
326
308
 
327
309
  ivar = Concurrent::IVar.new
328
310
  synchronize do
311
+ reset_if_forked
329
312
  @queue.push [ivar, method, args, block]
330
313
  @executor.post { perform } if @queue.length == 1
331
314
  end
@@ -361,6 +344,13 @@ module Concurrent
361
344
  end
362
345
  end
363
346
  end
347
+
348
+ def reset_if_forked
349
+ if $$ != @ruby_pid
350
+ @queue.clear
351
+ @ruby_pid = $$
352
+ end
353
+ end
364
354
  end
365
355
  private_constant :AsyncDelegator
366
356
 
@@ -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 ocurred"
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