Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package rubygem-concurrent-ruby for 
openSUSE:Factory checked in at 2022-05-17 17:23:32
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/rubygem-concurrent-ruby (Old)
 and      /work/SRC/openSUSE:Factory/.rubygem-concurrent-ruby.new.1538 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "rubygem-concurrent-ruby"

Tue May 17 17:23:32 2022 rev:14 rq:977370 version:1.1.10

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/rubygem-concurrent-ruby/rubygem-concurrent-ruby.changes
  2021-07-04 22:10:25.989372797 +0200
+++ 
/work/SRC/openSUSE:Factory/.rubygem-concurrent-ruby.new.1538/rubygem-concurrent-ruby.changes
        2022-05-17 17:23:32.559122383 +0200
@@ -1,0 +2,15 @@
+Sun May 15 15:28:32 UTC 2022 - Manuel Schnitzer <mschnit...@suse.com>
+
+- updated to version 1.1.10
+
+  * (#951) Set the Ruby compatibility version at 2.2
+  * (#939, #933) The `caller_runs` fallback policy no longer blocks reads from 
the job queue by worker threads
+  * (#938, #761, #652) You can now explicitly `prune_pool` a thread pool 
(Sylvain Joyeux)
+  * (#937, #757, #670) We switched the Yahoo stock API for demos to Alpha 
Vantage (Gustavo Caso)
+  * (#932, #931) We changed how `SafeTaskExecutor` handles local jump errors 
(Aaron Jensen)
+  * (#927) You can use keyword arguments in your initialize when using `Async` 
(Matt Larraz)
+  * (#926, #639) We removed timeout from `TimerTask` because it wasn't sound, 
and now it's a no-op with a warning (Jacob Atzen)
+  * (#919) If you double-lock a re-entrant read-write lock, we promote to 
locked for writing (zp yuan)
+  * (#915) `monotonic_time` now accepts an optional unit parameter, as Ruby's 
`clock_gettime` (Jean Boussier)
+
+-------------------------------------------------------------------

Old:
----
  concurrent-ruby-1.1.9.gem

New:
----
  concurrent-ruby-1.1.10.gem

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ rubygem-concurrent-ruby.spec ++++++
--- /var/tmp/diff_new_pack.SrXacb/_old  2022-05-17 17:23:33.135122908 +0200
+++ /var/tmp/diff_new_pack.SrXacb/_new  2022-05-17 17:23:33.139122911 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package rubygem-concurrent-ruby
 #
-# Copyright (c) 2021 SUSE LLC
+# Copyright (c) 2022 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -24,12 +24,12 @@
 #
 
 Name:           rubygem-concurrent-ruby
-Version:        1.1.9
+Version:        1.1.10
 Release:        0
 %define mod_name concurrent-ruby
 %define mod_full_name %{mod_name}-%{version}
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
-BuildRequires:  %{ruby >= 1.9.3}
+BuildRequires:  %{ruby >= 2.2}
 BuildRequires:  %{rubygem gem2rpm}
 BuildRequires:  ruby-macros >= 5
 URL:            http://www.concurrent-ruby.com

++++++ concurrent-ruby-1.1.9.gem -> concurrent-ruby-1.1.10.gem ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CHANGELOG.md new/CHANGELOG.md
--- old/CHANGELOG.md    2021-06-05 14:47:58.000000000 +0200
+++ new/CHANGELOG.md    2022-03-22 01:03:48.000000000 +0100
@@ -1,5 +1,19 @@
 ## Current
 
+## Release v1.1.10
+
+concurrent-ruby:
+
+* (#951) Set the Ruby compatibility version at 2.2
+* (#939, #933) The `caller_runs` fallback policy no longer blocks reads from 
the job queue by worker threads
+* (#938, #761, #652) You can now explicitly `prune_pool` a thread pool 
(Sylvain Joyeux)
+* (#937, #757, #670) We switched the Yahoo stock API for demos to Alpha 
Vantage (Gustavo Caso)
+* (#932, #931) We changed how `SafeTaskExecutor` handles local jump errors 
(Aaron Jensen)
+* (#927) You can use keyword arguments in your initialize when using `Async` 
(Matt Larraz)
+* (#926, #639) We removed timeout from `TimerTask` because it wasn't sound, 
and now it's a no-op with a warning (Jacob Atzen)
+* (#919) If you double-lock a re-entrant read-write lock, we promote to locked 
for writing (zp yuan)
+* (#915) `monotonic_time` now accepts an optional unit parameter, as Ruby's 
`clock_gettime` (Jean Boussier)
+
 ## Release v1.1.9 (5 Jun 2021)
 
 concurrent-ruby:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Gemfile new/Gemfile
--- old/Gemfile 2021-06-05 14:47:58.000000000 +0200
+++ new/Gemfile 2022-03-22 01:03:48.000000000 +0100
@@ -12,7 +12,7 @@
 gem 'concurrent-ruby-ext', Concurrent::VERSION, options.merge(platform: :mri)
 
 group :development do
-  gem 'rake', (Concurrent.ruby_version :<, 2, 2, 0) ? '~> 12.0' : '~> 13.0'
+  gem 'rake', '~> 13.0'
   gem 'rake-compiler', '~> 1.0', '>= 1.0.7'
   gem 'rake-compiler-dock', '~> 1.0'
   gem 'pry', '~> 0.11', platforms: :mri
@@ -26,7 +26,7 @@
 
 group :testing do
   gem 'rspec', '~> 3.7'
-  gem 'timecop', '~> 0.7.4'
+  gem 'timecop', '~> 0.9'
   gem 'sigdump', require: false
 end
 
@@ -35,8 +35,3 @@
   gem 'simplecov', '~> 0.16.0', require: false
   gem 'coveralls', '~> 0.8.2', require: false
 end
-
-group :benchmarks, optional: true do
-  gem 'benchmark-ips', '~> 2.7'
-  gem 'bench9000'
-end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/README.md new/README.md
--- old/README.md       2021-06-05 14:47:58.000000000 +0200
+++ new/README.md       2022-03-22 01:03:48.000000000 +0100
@@ -1,8 +1,6 @@
 # Concurrent Ruby
 
 [![Gem 
Version](https://badge.fury.io/rb/concurrent-ruby.svg)](http://badge.fury.io/rb/concurrent-ruby)
-[![Build 
Status](https://travis-ci.org/ruby-concurrency/concurrent-ruby.svg?branch=master)](https://travis-ci.org/ruby-concurrency/concurrent-ruby)
-[![Build 
status](https://ci.appveyor.com/api/projects/status/iq8aboyuu3etad4w?svg=true)](https://ci.appveyor.com/project/rubyconcurrency/concurrent-ruby)
 
[![License](https://img.shields.io/badge/license-MIT-green.svg)](http://opensource.org/licenses/MIT)
 [![Gitter 
chat](https://img.shields.io/badge/IRC%20(gitter)-devs%20%26%20users-brightgreen.svg)](https://gitter.im/ruby-concurrency/concurrent-ruby)
 
@@ -39,6 +37,8 @@
 appreciate your help. Would you like to contribute? Great! Have a look at 
 [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.
 
+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)
+
 ## Thread Safety
 
 *Concurrent Ruby makes one of the strongest thread safety guarantees of any 
Ruby concurrency 
@@ -259,15 +259,11 @@
 
 ## Supported Ruby versions
 
-* MRI 2.0 and above
-* JRuby 9000
-* TruffleRuby are supported.
-* Any Ruby interpreter that is compliant with Ruby 2.0 or newer.
-
-Actually we still support mri 1.9.3 and jruby 1.7.27 but we are looking at 
ways how to drop the support.
-Java 8 is preferred for JRuby but every Java version on which JRuby 9000 runs 
is supported.
+* MRI 2.2 and above
+* Latest JRuby 9000
+* Latest TruffleRuby
 
-The legacy support for Rubinius is kept but it is no longer maintained, if you 
would like to help 
+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 
 please respond to 
[#739](https://github.com/ruby-concurrency/concurrent-ruby/issues/739).
 
 ## Usage
@@ -364,7 +360,7 @@
 
 ### Publishing the Gem
 
-* Update`version.rb`
+* Update `version.rb`
 * Update the CHANGELOG
 * Update the Yard documentation
     - Add the new version to `docs-source/signpost.md`. Needs to be done only 
if there are visible changes in the
@@ -378,22 +374,22 @@
 
 ## Maintainers
 
-*   [Petr Chalupa](https://github.com/pitr-ch) ??? Lead maintainer, 
point-of-contact.
-*   [Chris Seaton](https://github.com/chrisseaton) ???
-    If Petr is not available Chris can help or poke Petr to pay attention 
where it is needed.
+* [Chris Seaton](https://github.com/chrisseaton) ??? Lead maintainer, 
point-of-contact.
+* [Benoit Daloze](https://github.com/eregon) ??? If Chris is not available 
Benoit can help.
 
 ### Special Thanks to
 
-*   [Jerry D'Antonio](https://github.com/jdantonio) for creating the gem
-*   [Brian Durand](https://github.com/bdurand) for the `ref` gem
-*   [Charles Oliver Nutter](https://github.com/headius) for the `atomic` and 
`thread_safe` gems
-*   [thedarkone](https://github.com/thedarkone) for the `thread_safe` gem
+* [Jerry D'Antonio](https://github.com/jdantonio) for creating the gem
+* [Brian Durand](https://github.com/bdurand) for the `ref` gem
+* [Charles Oliver Nutter](https://github.com/headius) for the `atomic` and 
`thread_safe` gems
+* [thedarkone](https://github.com/thedarkone) for the `thread_safe` gem
 
 to the past maintainers
 
-*   [Michele Della Torre](https://github.com/mighe)
-*   [Pawe?? Obrok](https://github.com/obrok)
-*   [Lucas Allan](https://github.com/lucasallan)
+* [Petr Chalupa](https://github.com/pitr-ch)
+* [Michele Della Torre](https://github.com/mighe)
+* [Pawe?? Obrok](https://github.com/obrok)
+* [Lucas Allan](https://github.com/lucasallan)
 
 and to [Ruby Association](https://www.ruby.or.jp/en/) for sponsoring a project 
 ["Enhancing Ruby???s concurrency 
tooling"](https://www.ruby.or.jp/en/news/20181106) in 2018. 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Rakefile new/Rakefile
--- old/Rakefile        2021-06-05 14:47:58.000000000 +0200
+++ new/Rakefile        2022-03-22 01:03:48.000000000 +0100
@@ -2,15 +2,6 @@
 require_relative 'lib/concurrent-ruby-edge/concurrent/edge/version'
 require_relative 'lib/concurrent-ruby/concurrent/utility/engine'
 
-if Concurrent.ruby_version :<, 2, 0, 0
-  # @!visibility private
-  module Kernel
-    def __dir__
-      File.dirname __FILE__
-    end
-  end
-end
-
 core_gemspec = Gem::Specification.load File.join(__dir__, 
'concurrent-ruby.gemspec')
 ext_gemspec  = Gem::Specification.load File.join(__dir__, 
'concurrent-ruby-ext.gemspec')
 edge_gemspec = Gem::Specification.load File.join(__dir__, 
'concurrent-ruby-edge.gemspec')
@@ -24,7 +15,7 @@
   ext.lib_dir = 'lib/concurrent-ruby/concurrent'
 end
 
-unless Concurrent.on_jruby?
+unless Concurrent.on_jruby? || Concurrent.on_truffleruby?
   require 'rake/extensiontask'
 
   Rake::ExtensionTask.new('concurrent_ruby_ext', ext_gemspec) do |ext|
@@ -77,8 +68,7 @@
       options      = %w[ --color
                     --backtrace
                     --order defined
-                    --format documentation
-                    --tag ~notravis ]
+                    --format documentation ]
       t.rspec_opts = [*options].join(' ')
     end
 
Binary files old/checksums.yaml.gz and new/checksums.yaml.gz differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaSemaphoreLibrary.java 
new/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaSemaphoreLibrary.java
--- old/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaSemaphoreLibrary.java   
2021-06-05 14:47:58.000000000 +0200
+++ new/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaSemaphoreLibrary.java   
2022-03-22 01:03:48.000000000 +0100
@@ -10,6 +10,7 @@
 import org.jruby.RubyObject;
 import org.jruby.anno.JRubyClass;
 import org.jruby.anno.JRubyMethod;
+import org.jruby.runtime.Block;
 import org.jruby.runtime.ObjectAllocator;
 import org.jruby.runtime.ThreadContext;
 import org.jruby.runtime.builtin.IRubyObject;
@@ -45,9 +46,13 @@
         }
 
         @JRubyMethod
-        public IRubyObject acquire(ThreadContext context, IRubyObject value) 
throws InterruptedException {
-            this.semaphore.acquire(rubyFixnumToPositiveInt(value, "permits"));
-            return context.nil;
+        public IRubyObject acquire(ThreadContext context, final Block block) 
throws InterruptedException {
+            return this.acquire(context, 1, block);
+        }
+
+        @JRubyMethod
+        public IRubyObject acquire(ThreadContext context, IRubyObject permits, 
final Block block) throws InterruptedException {
+            return this.acquire(context, rubyFixnumToPositiveInt(permits, 
"permits"), block);
         }
 
         @JRubyMethod(name = "available_permits")
@@ -60,30 +65,32 @@
             return getRuntime().newFixnum(this.semaphore.drainPermits());
         }
 
-        @JRubyMethod
-        public IRubyObject acquire(ThreadContext context) throws 
InterruptedException {
-            this.semaphore.acquire(1);
-            return context.nil;
-        }
-
         @JRubyMethod(name = "try_acquire")
-        public IRubyObject tryAcquire(ThreadContext context) throws 
InterruptedException {
-           return getRuntime().newBoolean(semaphore.tryAcquire(1));
+        public IRubyObject tryAcquire(ThreadContext context, final Block 
block) throws InterruptedException {
+            int permitsInt = 1;
+            boolean acquired = semaphore.tryAcquire(permitsInt);
+
+            return triedAcquire(context, permitsInt, acquired, block);
         }
 
         @JRubyMethod(name = "try_acquire")
-        public IRubyObject tryAcquire(ThreadContext context, IRubyObject 
permits) throws InterruptedException {
-           return 
getRuntime().newBoolean(semaphore.tryAcquire(rubyFixnumToPositiveInt(permits, 
"permits")));
+        public IRubyObject tryAcquire(ThreadContext context, IRubyObject 
permits, final Block block) throws InterruptedException {
+            int permitsInt = rubyFixnumToPositiveInt(permits, "permits");
+            boolean acquired = semaphore.tryAcquire(permitsInt);
+
+            return triedAcquire(context, permitsInt, acquired, block);
         }
 
         @JRubyMethod(name = "try_acquire")
-        public IRubyObject tryAcquire(ThreadContext context, IRubyObject 
permits, IRubyObject timeout) throws InterruptedException {
-             return getRuntime().newBoolean(
-                        semaphore.tryAcquire(
-                                rubyFixnumToPositiveInt(permits, "permits"),
-                                rubyNumericToLong(timeout, "timeout"),
-                                java.util.concurrent.TimeUnit.SECONDS)
-                );
+        public IRubyObject tryAcquire(ThreadContext context, IRubyObject 
permits, IRubyObject timeout, final Block block) throws InterruptedException {
+            int permitsInt = rubyFixnumToPositiveInt(permits, "permits");
+            boolean acquired = semaphore.tryAcquire(
+                    permitsInt,
+                    rubyNumericToLong(timeout, "timeout"),
+                    java.util.concurrent.TimeUnit.SECONDS
+                    );
+
+            return triedAcquire(context, permitsInt, acquired, block);
         }
 
         @JRubyMethod
@@ -93,8 +100,8 @@
         }
 
         @JRubyMethod
-        public IRubyObject release(ThreadContext context, IRubyObject value) {
-            this.semaphore.release(rubyFixnumToPositiveInt(value, "permits"));
+        public IRubyObject release(ThreadContext context, IRubyObject permits) 
{
+            this.semaphore.release(rubyFixnumToPositiveInt(permits, 
"permits"));
             return getRuntime().newBoolean(true);
         }
 
@@ -104,6 +111,29 @@
             return context.nil;
         }
 
+        private IRubyObject acquire(ThreadContext context, int permits, final 
Block block) throws InterruptedException {
+            this.semaphore.acquire(permits);
+
+            if (!block.isGiven()) return context.nil;
+
+            try {
+                return block.yieldSpecific(context);
+            } finally {
+                this.semaphore.release(permits);
+            }
+        }
+
+        private IRubyObject triedAcquire(ThreadContext context, int permits, 
boolean acquired, final Block block) {
+            if (!block.isGiven()) return getRuntime().newBoolean(acquired);
+            if (!acquired) return context.nil;
+
+            try {
+                return block.yieldSpecific(context);
+            } finally {
+                this.semaphore.release(permits);
+            }
+        }
+
         private int rubyFixnumInt(IRubyObject value, String paramName) {
             if (value instanceof RubyFixnum) {
                 RubyFixnum fixNum = (RubyFixnum) value;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/concurrent-ruby/concurrent/async.rb 
new/lib/concurrent-ruby/concurrent/async.rb
--- old/lib/concurrent-ruby/concurrent/async.rb 2021-06-05 14:47:58.000000000 
+0200
+++ new/lib/concurrent-ruby/concurrent/async.rb 2022-03-22 01:03:48.000000000 
+0100
@@ -272,6 +272,7 @@
         obj.send(:init_synchronization)
         obj
       end
+      ruby2_keywords :new if respond_to?(:ruby2_keywords, true)
     end
     private_constant :ClassMethods
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb 
new/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb
--- old/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb       
2021-06-05 14:47:58.000000000 +0200
+++ new/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb       
2022-03-22 01:03:48.000000000 +0100
@@ -170,6 +170,7 @@
                                       alias_method :compare_and_swap, 
:compare_and_set
                                       alias_method :swap, :get_and_set
                                     end
+                                    TruffleRubyAtomicReference
                                   when Concurrent.on_rbx?
                                     # @note Extends 
`Rubinius::AtomicReference` version adding aliases
                                     #   and numeric logic.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/concurrent-ruby/concurrent/atomic/event.rb 
new/lib/concurrent-ruby/concurrent/atomic/event.rb
--- old/lib/concurrent-ruby/concurrent/atomic/event.rb  2021-06-05 
14:47:58.000000000 +0200
+++ new/lib/concurrent-ruby/concurrent/atomic/event.rb  2022-03-22 
01:03:48.000000000 +0100
@@ -19,7 +19,7 @@
   #   t1 = Thread.new do
   #     puts "t1 is waiting"
   #     event.wait(1)
-  #     puts "event ocurred"
+  #     puts "event occurred"
   #   end
   #
   #   t2 = Thread.new do
@@ -30,8 +30,8 @@
   #   [t1, t2].each(&:join)
   #
   #   # prints:
-  #   # t2 calling set
   #   # t1 is waiting
+  #   # t2 calling set
   #   # event occurred
   class Event < Synchronization::LockableObject
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb 
new/lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb
--- old/lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb        
2021-06-05 14:47:58.000000000 +0200
+++ new/lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb        
2022-03-22 01:03:48.000000000 +0100
@@ -23,7 +23,14 @@
 
       synchronize do
         try_acquire_timed(permits, nil)
-        nil
+      end
+
+      return unless block_given?
+
+      begin
+        yield
+      ensure
+        release(permits)
       end
     end
 
@@ -48,13 +55,22 @@
       Utility::NativeInteger.ensure_integer_and_bounds permits
       Utility::NativeInteger.ensure_positive permits
 
-      synchronize do
+      acquired = synchronize do
         if timeout.nil?
           try_acquire_now(permits)
         else
           try_acquire_timed(permits, timeout)
         end
       end
+
+      return acquired unless block_given?
+      return unless acquired
+
+      begin
+        yield
+      ensure
+        release(permits)
+      end
     end
 
     # @!macro semaphore_method_release
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb 
new/lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb
--- old/lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb      
2021-06-05 14:47:58.000000000 +0200
+++ new/lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb      
2022-03-22 01:03:48.000000000 +0100
@@ -267,12 +267,10 @@
         #   running right now, AND no writers who came before us still waiting 
to
         #   acquire the lock
         # Additionally, if any read locks have been taken, we must hold all of 
them
-        if c == held
-          # If we successfully swap the RUNNING_WRITER bit on, then we can go 
ahead
-          if @Counter.compare_and_set(c, c+RUNNING_WRITER)
-            @HeldCount.value = held + WRITE_LOCK_HELD
-            return true
-          end
+        if held > 0 && @Counter.compare_and_set(1, c+RUNNING_WRITER)
+          # If we are the only one reader and successfully swap the 
RUNNING_WRITER bit on, then we can go ahead
+          @HeldCount.value = held + WRITE_LOCK_HELD
+          return true
         elsif @Counter.compare_and_set(c, c+WAITING_WRITER)
           while true
             # Now we have successfully incremented, so no more readers will be 
able to increment
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/concurrent-ruby/concurrent/atomic/semaphore.rb 
new/lib/concurrent-ruby/concurrent/atomic/semaphore.rb
--- old/lib/concurrent-ruby/concurrent/atomic/semaphore.rb      2021-06-05 
14:47:58.000000000 +0200
+++ new/lib/concurrent-ruby/concurrent/atomic/semaphore.rb      2022-03-22 
01:03:48.000000000 +0100
@@ -16,14 +16,16 @@
   # @!macro semaphore_method_acquire
   #
   #   Acquires the given number of permits from this semaphore,
-  #     blocking until all are available.
+  #     blocking until all are available. If a block is given,
+  #     yields to it and releases the permits afterwards.
   #
   #   @param [Fixnum] permits Number of permits to acquire
   #
   #   @raise [ArgumentError] if `permits` is not an integer or is less than
   #     one
   #
-  #   @return [nil]
+  #   @return [nil, BasicObject] Without a block, `nil` is returned. If a block
+  #   is given, its return value is returned.
 
   # @!macro semaphore_method_available_permits
   #
@@ -41,7 +43,9 @@
   #
   #   Acquires the given number of permits from this semaphore,
   #     only if all are available at the time of invocation or within
-  #     `timeout` interval
+  #     `timeout` interval. If a block is given, yields to it if the permits
+  #     were successfully acquired, and releases them afterward, returning the
+  #     block's return value.
   #
   #   @param [Fixnum] permits the number of permits to acquire
   #
@@ -51,8 +55,10 @@
   #   @raise [ArgumentError] if `permits` is not an integer or is less than
   #     one
   #
-  #   @return [Boolean] `false` if no permits are available, `true` when
-  #     acquired a permit
+  #   @return [true, false, nil, BasicObject] `false` if no permits are
+  #     available, `true` when acquired a permit. If a block is given, the
+  #     block's return value is returned if the permits were acquired; if not,
+  #     `nil` is returned.
 
   # @!macro semaphore_method_release
   #
@@ -106,6 +112,8 @@
   #   releasing a blocking acquirer.
   #   However, no actual permit objects are used; the Semaphore just keeps a
   #   count of the number available and acts accordingly.
+  #   Alternatively, permits may be acquired within a block, and automatically
+  #   released after the block finishes executing.
   #
   # @!macro semaphore_public_api
   # @example
@@ -140,6 +148,19 @@
   #   # Thread 4 releasing semaphore
   #   # Thread 1 acquired semaphore
   #
+  # @example
+  #   semaphore = Concurrent::Semaphore.new(1)
+  #
+  #   puts semaphore.available_permits
+  #   semaphore.acquire do
+  #     puts semaphore.available_permits
+  #   end
+  #   puts semaphore.available_permits
+  #
+  #   # prints:
+  #   # 1
+  #   # 0
+  #   # 1
   class Semaphore < SemaphoreImplementation
   end
 end
Binary files old/lib/concurrent-ruby/concurrent/concurrent_ruby.jar and 
new/lib/concurrent-ruby/concurrent/concurrent_ruby.jar differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb 
new/lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb
--- old/lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb    
2021-06-05 14:47:58.000000000 +0200
+++ new/lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb    
2022-03-22 01:03:48.000000000 +0100
@@ -75,28 +75,31 @@
 
     private
 
-    # Handler which executes the `fallback_policy` once the queue size
-    # reaches `max_queue`.
+    # Returns an action which executes the `fallback_policy` once the queue
+    # size reaches `max_queue`. The reason for the indirection of an action
+    # is so that the work can be deferred outside of synchronization.
     #
     # @param [Array] args the arguments to the task which is being handled.
     #
     # @!visibility private
-    def handle_fallback(*args)
+    def fallback_action(*args)
       case fallback_policy
       when :abort
-        raise RejectedExecutionError
+        lambda { raise RejectedExecutionError }
       when :discard
-        false
+        lambda { false }
       when :caller_runs
-        begin
-          yield(*args)
-        rescue => ex
-          # let it fail
-          log DEBUG, ex
-        end
-        true
+        lambda {
+          begin
+            yield(*args)
+          rescue => ex
+            # let it fail
+            log DEBUG, ex
+          end
+          true
+        }
       else
-        fail "Unknown fallback policy #{fallback_policy}"
+        lambda { fail "Unknown fallback policy #{fallback_policy}" }
       end
     end
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb 
new/lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb
--- old/lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb    
2021-06-05 14:47:58.000000000 +0200
+++ new/lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb    
2022-03-22 01:03:48.000000000 +0100
@@ -71,9 +71,16 @@
   #   @return [Integer] Number of tasks that may be enqueued before reaching 
`max_queue` and rejecting
   #     new tasks. A value of -1 indicates that the queue may grow without 
bound.
 
-
-
-
+  # @!macro thread_pool_executor_method_prune_pool
+  #   Prune the thread pool of unneeded threads
+  #
+  #   What is being pruned is controlled by the min_threads and idletime
+  #   parameters passed at pool creation time
+  #
+  #   This is a no-op on some pool implementation (e.g. the Java one).  The 
Ruby
+  #   pool will auto-prune each time a new job is posted. You will need to call
+  #   this method explicitely in case your application post jobs in bursts (a
+  #   lot of jobs and then nothing for long periods)
 
   # @!macro thread_pool_executor_public_api
   #
@@ -111,6 +118,9 @@
   #
   #   @!method can_overflow?
   #     @!macro executor_service_method_can_overflow_question
+  #
+  #   @!method prune_pool
+  #     @!macro thread_pool_executor_method_prune_pool
 
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/lib/concurrent-ruby/concurrent/executor/java_executor_service.rb 
new/lib/concurrent-ruby/concurrent/executor/java_executor_service.rb
--- old/lib/concurrent-ruby/concurrent/executor/java_executor_service.rb        
2021-06-05 14:47:58.000000000 +0200
+++ new/lib/concurrent-ruby/concurrent/executor/java_executor_service.rb        
2022-03-22 01:03:48.000000000 +0100
@@ -20,7 +20,7 @@
 
       def post(*args, &task)
         raise ArgumentError.new('no block given') unless block_given?
-        return handle_fallback(*args, &task) unless running?
+        return fallback_action(*args, &task).call unless running?
         @executor.submit Job.new(args, task)
         true
       rescue Java::JavaUtilConcurrent::RejectedExecutionException
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/lib/concurrent-ruby/concurrent/executor/java_thread_pool_executor.rb 
new/lib/concurrent-ruby/concurrent/executor/java_thread_pool_executor.rb
--- old/lib/concurrent-ruby/concurrent/executor/java_thread_pool_executor.rb    
2021-06-05 14:47:58.000000000 +0200
+++ new/lib/concurrent-ruby/concurrent/executor/java_thread_pool_executor.rb    
2022-03-22 01:03:48.000000000 +0100
@@ -93,6 +93,10 @@
         super && !@executor.isTerminating
       end
 
+      # @!macro thread_pool_executor_method_prune_pool
+      def prune_pool
+      end
+
       private
 
       def ns_initialize(opts)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb 
new/lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb
--- old/lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb        
2021-06-05 14:47:58.000000000 +0200
+++ new/lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb        
2022-03-22 01:03:48.000000000 +0100
@@ -16,10 +16,16 @@
 
     def post(*args, &task)
       raise ArgumentError.new('no block given') unless block_given?
-      synchronize do
-        # If the executor is shut down, reject this task
-        return handle_fallback(*args, &task) unless running?
-        ns_execute(*args, &task)
+      deferred_action = synchronize {
+        if running?
+          ns_execute(*args, &task)
+        else
+          fallback_action(*args, &task)
+        end
+      }
+      if deferred_action
+        deferred_action.call
+      else
         true
       end
     end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb 
new/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb
--- old/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb    
2021-06-05 14:47:58.000000000 +0200
+++ new/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb    
2022-03-22 01:03:48.000000000 +0100
@@ -93,13 +93,8 @@
     end
 
     # @!visibility private
-    def ready_worker(worker)
-      synchronize { ns_ready_worker worker }
-    end
-
-    # @!visibility private
-    def worker_not_old_enough(worker)
-      synchronize { ns_worker_not_old_enough worker }
+    def ready_worker(worker, last_message)
+      synchronize { ns_ready_worker worker, last_message }
     end
 
     # @!visibility private
@@ -112,6 +107,11 @@
       synchronize { @completed_task_count += 1 }
     end
 
+    # @!macro thread_pool_executor_method_prune_pool
+    def prune_pool
+      synchronize { ns_prune_pool }
+    end
+
     private
 
     # @!visibility private
@@ -156,10 +156,11 @@
       if ns_assign_worker(*args, &task) || ns_enqueue(*args, &task)
         @scheduled_task_count += 1
       else
-        handle_fallback(*args, &task)
+        return fallback_action(*args, &task)
       end
 
       ns_prune_pool if @next_gc_time < Concurrent.monotonic_time
+      nil
     end
 
     # @!visibility private
@@ -192,7 +193,7 @@
     # @!visibility private
     def ns_assign_worker(*args, &task)
       # keep growing if the pool is not at the minimum yet
-      worker = (@ready.pop if @pool.size >= @min_length) || ns_add_busy_worker
+      worker, _ = (@ready.pop if @pool.size >= @min_length) || 
ns_add_busy_worker
       if worker
         worker << [task, args]
         true
@@ -223,7 +224,7 @@
     def ns_worker_died(worker)
       ns_remove_busy_worker worker
       replacement_worker = ns_add_busy_worker
-      ns_ready_worker replacement_worker, false if replacement_worker
+      ns_ready_worker replacement_worker, Concurrent.monotonic_time, false if 
replacement_worker
     end
 
     # creates new worker which has to receive work to do after it's added
@@ -242,29 +243,21 @@
     # handle ready worker, giving it new job or assigning back to @ready
     #
     # @!visibility private
-    def ns_ready_worker(worker, success = true)
+    def ns_ready_worker(worker, last_message, success = true)
       task_and_args = @queue.shift
       if task_and_args
         worker << task_and_args
       else
         # stop workers when !running?, do not return them to @ready
         if running?
-          @ready.push(worker)
+          raise unless last_message
+          @ready.push([worker, last_message])
         else
           worker.stop
         end
       end
     end
 
-    # returns back worker to @ready which was not idle for enough time
-    #
-    # @!visibility private
-    def ns_worker_not_old_enough(worker)
-      # let's put workers coming from idle_test back to the start (as the 
oldest worker)
-      @ready.unshift(worker)
-      true
-    end
-
     # removes a worker which is not in not tracked in @ready
     #
     # @!visibility private
@@ -278,10 +271,17 @@
     #
     # @!visibility private
     def ns_prune_pool
-      return if @pool.size <= @min_length
-
-      last_used = @ready.shift
-      last_used << :idle_test if last_used
+      now = Concurrent.monotonic_time
+      stopped_workers = 0
+      while !@ready.empty? && (@pool.size - stopped_workers > @min_length)
+        worker, last_message = @ready.first
+        if now - last_message > self.idletime
+          stopped_workers += 1
+          @ready.shift
+          worker << :stop
+        else break
+        end
+      end
 
       @next_gc_time = Concurrent.monotonic_time + @gc_interval
     end
@@ -330,19 +330,10 @@
 
       def create_worker(queue, pool, idletime)
         Thread.new(queue, pool, idletime) do |my_queue, my_pool, my_idletime|
-          last_message = Concurrent.monotonic_time
           catch(:stop) do
             loop do
 
               case message = my_queue.pop
-              when :idle_test
-                if (Concurrent.monotonic_time - last_message) > my_idletime
-                  my_pool.remove_busy_worker(self)
-                  throw :stop
-                else
-                  my_pool.worker_not_old_enough(self)
-                end
-
               when :stop
                 my_pool.remove_busy_worker(self)
                 throw :stop
@@ -350,9 +341,7 @@
               else
                 task, args = message
                 run_task my_pool, task, args
-                last_message = Concurrent.monotonic_time
-
-                my_pool.ready_worker(self)
+                my_pool.ready_worker(self, Concurrent.monotonic_time)
               end
             end
           end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb 
new/lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb
--- old/lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb   
2021-06-05 14:47:58.000000000 +0200
+++ new/lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb   
2022-03-22 01:03:48.000000000 +0100
@@ -16,10 +16,10 @@
 
     # @return [Array]
     def execute(*args)
-      synchronize do
-        success = false
-        value   = reason = nil
+      success = true
+      value   = reason = nil
 
+      synchronize do
         begin
           value   = @task.call(*args)
           success = true
@@ -27,9 +27,9 @@
           reason  = ex
           success = false
         end
-
-        [success, value, reason]
       end
+
+      [success, value, reason]
     end
   end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/concurrent-ruby/concurrent/map.rb 
new/lib/concurrent-ruby/concurrent/map.rb
--- old/lib/concurrent-ruby/concurrent/map.rb   2021-06-05 14:47:58.000000000 
+0200
+++ new/lib/concurrent-ruby/concurrent/map.rb   2022-03-22 01:03:48.000000000 
+0100
@@ -281,7 +281,6 @@
       each_pair { |k, v| return k if v == value }
       nil
     end unless method_defined?(:key)
-    alias_method :index, :key if RUBY_VERSION < '1.9'
 
     # Is map empty?
     # @return [true, false]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/concurrent-ruby/concurrent/scheduled_task.rb 
new/lib/concurrent-ruby/concurrent/scheduled_task.rb
--- old/lib/concurrent-ruby/concurrent/scheduled_task.rb        2021-06-05 
14:47:58.000000000 +0200
+++ new/lib/concurrent-ruby/concurrent/scheduled_task.rb        2022-03-22 
01:03:48.000000000 +0100
@@ -58,29 +58,42 @@
   # @example Basic usage
   #
   #   require 'concurrent'
-  #   require 'thread'   # for Queue
-  #   require 'open-uri' # for open(uri)
+  #   require 'csv'
+  #   require 'open-uri'
   #
   #   class Ticker
-  #     def get_year_end_closing(symbol, year)
-  #       uri = 
"http://ichart.finance.yahoo.com/table.csv?s=#{symbol}&a=11&b=01&c=#{year}&d=11&e=31&f=#{year}&g=m";
-  #       data = open(uri) {|f| f.collect{|line| line.strip } }
-  #       data[1].split(',')[4].to_f
-  #     end
+  #     def get_year_end_closing(symbol, year, api_key)
+  #      uri = 
"https://www.alphavantage.co/query?function=TIME_SERIES_MONTHLY&symbol=#{symbol}&apikey=#{api_key}&datatype=csv";
+  #      data = []
+  #      csv = URI.parse(uri).read
+  #      if csv.include?('call frequency')
+  #        return :rate_limit_exceeded
+  #      end
+  #      CSV.parse(csv, headers: true) do |row|
+  #        data << row['close'].to_f if row['timestamp'].include?(year.to_s)
+  #      end
+  #      year_end = data.first
+  #      year_end
+  #    rescue => e
+  #      p e
+  #    end
   #   end
   #
+  #   api_key = ENV['ALPHAVANTAGE_KEY']
+  #   abort(error_message) unless api_key
+  #
   #   # Future
-  #   price = Concurrent::Future.execute{ 
Ticker.new.get_year_end_closing('TWTR', 2013) }
+  #   price = Concurrent::Future.execute{ 
Ticker.new.get_year_end_closing('TWTR', 2013, api_key) }
   #   price.state #=> :pending
-  #   sleep(1)    # do other stuff
-  #   price.value #=> 63.65
-  #   price.state #=> :fulfilled
+  #   price.pending? #=> true
+  #   price.value(0) #=> nil (does not block)
   #
-  #   # ScheduledTask
-  #   task = Concurrent::ScheduledTask.execute(2){ 
Ticker.new.get_year_end_closing('INTC', 2013) }
-  #   task.state #=> :pending
-  #   sleep(3)   # do other stuff
-  #   task.value #=> 25.96
+  #    sleep(1)    # do other stuff
+  #
+  #   price.value #=> 63.65 (after blocking if necessary)
+  #   price.state #=> :fulfilled
+  #   price.fulfilled? #=> true
+  #   price.value #=> 63.65
   #
   # @example Successful task execution
   #
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/lib/concurrent-ruby/concurrent/synchronization/lockable_object.rb 
new/lib/concurrent-ruby/concurrent/synchronization/lockable_object.rb
--- old/lib/concurrent-ruby/concurrent/synchronization/lockable_object.rb       
2021-06-05 14:47:58.000000000 +0200
+++ new/lib/concurrent-ruby/concurrent/synchronization/lockable_object.rb       
2022-03-22 01:03:48.000000000 +0100
@@ -4,9 +4,7 @@
     # @!visibility private
     # @!macro internal_implementation_note
     LockableObjectImplementation = case
-                                   when Concurrent.on_cruby? && 
Concurrent.ruby_version(:<=, 1, 9, 3)
-                                     MonitorLockableObject
-                                   when Concurrent.on_cruby? && 
Concurrent.ruby_version(:>, 1, 9, 3)
+                                   when Concurrent.on_cruby?
                                      MutexLockableObject
                                    when Concurrent.on_jruby?
                                      JRubyLockableObject
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/concurrent-ruby/concurrent/timer_task.rb 
new/lib/concurrent-ruby/concurrent/timer_task.rb
--- old/lib/concurrent-ruby/concurrent/timer_task.rb    2021-06-05 
14:47:58.000000000 +0200
+++ new/lib/concurrent-ruby/concurrent/timer_task.rb    2022-03-22 
01:03:48.000000000 +0100
@@ -25,9 +25,7 @@
   # Should the task experience an unrecoverable crash only the task thread will
   # crash. This makes the `TimerTask` very fault tolerant. Additionally, the
   # `TimerTask` thread can respond to the success or failure of the task,
-  # performing logging or ancillary operations. `TimerTask` can also be
-  # configured with a timeout value allowing it to kill a task that runs too
-  # long.
+  # performing logging or ancillary operations.
   #
   # One other advantage of `TimerTask` is that it forces the business logic to
   # be completely decoupled from the concurrency logic. The business logic can
@@ -48,9 +46,7 @@
   # {http://ruby-doc.org/stdlib-2.0/libdoc/observer/rdoc/Observable.html
   # Observable} module. On execution the `TimerTask` will notify the observers
   # with three arguments: time of execution, the result of the block (or nil on
-  # failure), and any raised exceptions (or nil on success). If the timeout
-  # interval is exceeded the observer will receive a `Concurrent::TimeoutError`
-  # object as the third argument.
+  # failure), and any raised exceptions (or nil on success).
   #
   # @!macro copy_options
   #
@@ -59,20 +55,18 @@
   #   task.execute
   #
   #   task.execution_interval #=> 60 (default)
-  #   task.timeout_interval   #=> 30 (default)
   #
   #   # wait 60 seconds...
   #   #=> 'Boom!'
   #
   #   task.shutdown #=> true
   #
-  # @example Configuring `:execution_interval` and `:timeout_interval`
-  #   task = Concurrent::TimerTask.new(execution_interval: 5, 
timeout_interval: 5) do
+  # @example Configuring `:execution_interval`
+  #   task = Concurrent::TimerTask.new(execution_interval: 5) do
   #          puts 'Boom!'
   #        end
   #
   #   task.execution_interval #=> 5
-  #   task.timeout_interval   #=> 5
   #
   # @example Immediate execution with `:run_now`
   #   task = Concurrent::TimerTask.new(run_now: true){ puts 'Boom!' }
@@ -115,15 +109,13 @@
   #     def update(time, result, ex)
   #       if result
   #         print "(#{time}) Execution successfully returned #{result}\n"
-  #       elsif ex.is_a?(Concurrent::TimeoutError)
-  #         print "(#{time}) Execution timed out\n"
   #       else
   #         print "(#{time}) Execution failed with error #{ex}\n"
   #       end
   #     end
   #   end
   #
-  #   task = Concurrent::TimerTask.new(execution_interval: 1, 
timeout_interval: 1){ 42 }
+  #   task = Concurrent::TimerTask.new(execution_interval: 1){ 42 }
   #   task.add_observer(TaskObserver.new)
   #   task.execute
   #   sleep 4
@@ -133,7 +125,7 @@
   #   #=> (2013-10-13 19:09:00 -0400) Execution successfully returned 42
   #   task.shutdown
   #
-  #   task = Concurrent::TimerTask.new(execution_interval: 1, 
timeout_interval: 1){ sleep }
+  #   task = Concurrent::TimerTask.new(execution_interval: 1){ sleep }
   #   task.add_observer(TaskObserver.new)
   #   task.execute
   #
@@ -169,8 +161,6 @@
     #   @param [Hash] opts the options defining task execution.
     #   @option opts [Integer] :execution_interval number of seconds between
     #     task executions (default: EXECUTION_INTERVAL)
-    #   @option opts [Integer] :timeout_interval number of seconds a task can
-    #     run before it is considered to have failed (default: 
TIMEOUT_INTERVAL)
     #   @option opts [Boolean] :run_now Whether to run the task immediately
     #     upon instantiation or to wait until the first #  execution_interval
     #     has passed (default: false)
@@ -256,18 +246,14 @@
     # @return [Fixnum] Number of seconds the task can run before it is
     #   considered to have failed.
     def timeout_interval
-      synchronize { @timeout_interval }
+      warn 'TimerTask timeouts are now ignored as these were not able to be 
implemented correctly'
     end
 
     # @!attribute [rw] timeout_interval
     # @return [Fixnum] Number of seconds the task can run before it is
     #   considered to have failed.
     def timeout_interval=(value)
-      if (value = value.to_f) <= 0.0
-        raise ArgumentError.new('must be greater than zero')
-      else
-        synchronize { @timeout_interval = value }
-      end
+      warn 'TimerTask timeouts are now ignored as these were not able to be 
implemented correctly'
     end
 
     private :post, :<<
@@ -278,7 +264,9 @@
       set_deref_options(opts)
 
       self.execution_interval = opts[:execution] || opts[:execution_interval] 
|| EXECUTION_INTERVAL
-      self.timeout_interval = opts[:timeout] || opts[:timeout_interval] || 
TIMEOUT_INTERVAL
+      if opts[:timeout] || opts[:timeout_interval]
+        warn 'TimeTask timeouts are now ignored as these were not able to be 
implemented correctly'
+      end
       @run_now = opts[:now] || opts[:run_now]
       @executor = Concurrent::SafeTaskExecutor.new(task)
       @running = Concurrent::AtomicBoolean.new(false)
@@ -308,7 +296,6 @@
     # @!visibility private
     def execute_task(completion)
       return nil unless @running.true?
-      ScheduledTask.execute(timeout_interval, args: [completion], 
&method(:timeout_task))
       _success, value, reason = @executor.execute(self)
       if completion.try?
         self.value = value
@@ -320,14 +307,5 @@
       end
       nil
     end
-
-    # @!visibility private
-    def timeout_task(completion)
-      return unless @running.true?
-      if completion.try?
-        schedule_next_task
-        observers.notify_observers(Time.now, nil, Concurrent::TimeoutError.new)
-      end
-    end
   end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/concurrent-ruby/concurrent/tvar.rb 
new/lib/concurrent-ruby/concurrent/tvar.rb
--- old/lib/concurrent-ruby/concurrent/tvar.rb  2021-06-05 14:47:58.000000000 
+0200
+++ new/lib/concurrent-ruby/concurrent/tvar.rb  2022-03-22 01:03:48.000000000 
+0100
@@ -15,7 +15,6 @@
     # Create a new `TVar` with an initial value.
     def initialize(value)
       @value = value
-      @version = 0
       @lock = Mutex.new
     end
 
@@ -44,16 +43,6 @@
     end
 
     # @!visibility private
-    def unsafe_version # :nodoc:
-      @version
-    end
-
-    # @!visibility private
-    def unsafe_increment_version # :nodoc:
-      @version += 1
-    end
-
-    # @!visibility private
     def unsafe_lock # :nodoc:
       @lock
     end
@@ -164,53 +153,39 @@
 
     ABORTED = ::Object.new
 
-    ReadLogEntry = Struct.new(:tvar, :version)
+    OpenEntry = Struct.new(:value, :modified)
 
     AbortError = Class.new(StandardError)
     LeaveError = Class.new(StandardError)
 
     def initialize
-      @read_log  = []
-      @write_log = {}
+      @open_tvars = {}
     end
 
     def read(tvar)
-      Concurrent::abort_transaction unless valid?
-
-      if @write_log.has_key? tvar
-        @write_log[tvar]
-      else
-        @read_log.push(ReadLogEntry.new(tvar, tvar.unsafe_version))
-        tvar.unsafe_value
-      end
+      entry = open(tvar)
+      entry.value
     end
 
     def write(tvar, value)
-      # Have we already written to this TVar?
+      entry = open(tvar)
+      entry.modified = true
+      entry.value = value
+    end
 
-      if @write_log.has_key? tvar
-        # Record the value written
-        @write_log[tvar] = value
-      else
-        # Try to lock the TVar
+    def open(tvar)
+      entry = @open_tvars[tvar]
 
+      unless entry
         unless tvar.unsafe_lock.try_lock
-          # Someone else is writing to this TVar - abort
           Concurrent::abort_transaction
         end
 
-        # Record the value written
-  
-        @write_log[tvar] = value
-
-        # If we previously read from it, check the version hasn't changed
-
-        @read_log.each do |log_entry|
-          if log_entry.tvar == tvar and tvar.unsafe_version > log_entry.version
-            Concurrent::abort_transaction
-          end
-        end
+        entry = OpenEntry.new(tvar.unsafe_value, false)
+        @open_tvars[tvar] = entry
       end
+
+      entry
     end
 
     def abort
@@ -218,32 +193,17 @@
     end
 
     def commit
-      return false unless valid?
-
-      @write_log.each_pair do |tvar, value|
-        tvar.unsafe_value = value
-        tvar.unsafe_increment_version
-      end
-
-      unlock
-
-      true
-    end
-
-    def valid?
-      @read_log.each do |log_entry|
-        unless @write_log.has_key? log_entry.tvar
-          if log_entry.tvar.unsafe_version > log_entry.version
-            return false
-          end
+      @open_tvars.each do |tvar, entry|
+        if entry.modified
+          tvar.unsafe_value = entry.value
         end
       end
 
-      true
+      unlock
     end
 
     def unlock
-      @write_log.each_key do |tvar|
+      @open_tvars.each_key do |tvar|
         tvar.unsafe_lock.unlock
       end
     end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/lib/concurrent-ruby/concurrent/utility/monotonic_time.rb 
new/lib/concurrent-ruby/concurrent/utility/monotonic_time.rb
--- old/lib/concurrent-ruby/concurrent/utility/monotonic_time.rb        
2021-06-05 14:47:58.000000000 +0200
+++ new/lib/concurrent-ruby/concurrent/utility/monotonic_time.rb        
2022-03-22 01:03:48.000000000 +0100
@@ -2,26 +2,64 @@
 
 module Concurrent
 
-  class_definition = Class.new(Synchronization::LockableObject) do
-    def initialize
-      @last_time = Time.now.to_f
-      super()
+  # @!macro monotonic_get_time
+  #
+  #   Returns the current time a tracked by the application monotonic clock.
+  #
+  #   @param [Symbol] unit the time unit to be returned, can be either
+  #     :float_second, :float_millisecond, :float_microsecond, :second,
+  #     :millisecond, :microsecond, or :nanosecond default to :float_second.
+  #
+  #   @return [Float] The current monotonic time since some unspecified
+  #     starting point
+  #
+  #   @!macro monotonic_clock_warning
+  if defined?(Process::CLOCK_MONOTONIC)
+
+    def monotonic_time(unit = :float_second)
+      Process.clock_gettime(Process::CLOCK_MONOTONIC, unit)
     end
 
-    if defined?(Process::CLOCK_MONOTONIC)
-      # @!visibility private
-      def get_time
-        Process.clock_gettime(Process::CLOCK_MONOTONIC)
-      end
-    elsif Concurrent.on_jruby?
-      # @!visibility private
-      def get_time
-        java.lang.System.nanoTime() / 1_000_000_000.0
+  elsif Concurrent.on_jruby?
+
+    # @!visibility private
+    TIME_UNITS = Hash.new { |_hash, key| raise ArgumentError, "unexpected 
unit: #{key}" }.compare_by_identity
+    TIME_UNITS.merge!(
+      second: 1_000_000_000,
+      millisecond: 1_000_000,
+      microsecond: 1_000,
+      nanosecond: 1,
+      float_second: 1_000_000_000.0,
+      float_millisecond: 1_000_000.0,
+      float_microsecond: 1_000.0,
+    )
+    TIME_UNITS.freeze
+    private_constant :TIME_UNITS
+
+    def monotonic_time(unit = :float_second)
+      java.lang.System.nanoTime() / TIME_UNITS[unit]
+    end
+
+  else
+
+    class_definition = Class.new(Synchronization::LockableObject) do
+      def initialize
+        @last_time = Time.now.to_f
+        @time_units = Hash.new { |_hash, key| raise ArgumentError, "unexpected 
unit: #{key}" }.compare_by_identity
+        @time_units.merge!(
+          second: [nil, true],
+          millisecond: [1_000, true],
+          microsecond: [1_000_000, true],
+          nanosecond: [1_000_000_000, true],
+          float_second: [nil, false],
+          float_millisecond: [1_000.0, false],
+          float_microsecond: [1_000_000.0, false],
+        )
+        super()
       end
-    else
 
       # @!visibility private
-      def get_time
+      def get_time(unit)
         synchronize do
           now = Time.now.to_f
           if @last_time < now
@@ -29,30 +67,24 @@
           else # clock has moved back in time
             @last_time += 0.000_001
           end
+          scale, to_int = @time_units[unit]
+          now *= scale if scale
+          now = now.to_i if to_int
+          now
         end
       end
-
     end
-  end
 
-  # Clock that cannot be set and represents monotonic time since
-  # some unspecified starting point.
-  #
-  # @!visibility private
-  GLOBAL_MONOTONIC_CLOCK = class_definition.new
-  private_constant :GLOBAL_MONOTONIC_CLOCK
-
-  # @!macro monotonic_get_time
-  #
-  #   Returns the current time a tracked by the application monotonic clock.
-  #
-  #   @return [Float] The current monotonic time since some unspecified
-  #     starting point
-  #
-  #   @!macro monotonic_clock_warning
-  def monotonic_time
-    GLOBAL_MONOTONIC_CLOCK.get_time
+    # Clock that cannot be set and represents monotonic time since
+    # some unspecified starting point.
+    #
+    # @!visibility private
+    GLOBAL_MONOTONIC_CLOCK = class_definition.new
+    private_constant :GLOBAL_MONOTONIC_CLOCK
+    
+    def monotonic_time(unit = :float_second)
+      GLOBAL_MONOTONIC_CLOCK.get_time(unit)
+    end
   end
-
   module_function :monotonic_time
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/lib/concurrent-ruby/concurrent/utility/processor_counter.rb 
new/lib/concurrent-ruby/concurrent/utility/processor_counter.rb
--- old/lib/concurrent-ruby/concurrent/utility/processor_counter.rb     
2021-06-05 14:47:58.000000000 +0200
+++ new/lib/concurrent-ruby/concurrent/utility/processor_counter.rb     
2022-03-22 01:03:48.000000000 +0100
@@ -79,47 +79,14 @@
       def compute_processor_count
         if Concurrent.on_jruby?
           java.lang.Runtime.getRuntime.availableProcessors
-        elsif Etc.respond_to?(:nprocessors) && (nprocessor = Etc.nprocessors 
rescue nil)
-          nprocessor
         else
-          os_name = RbConfig::CONFIG["target_os"]
-          if os_name =~ /mingw|mswin/
-            require 'win32ole'
-            result = WIN32OLE.connect("winmgmts://").ExecQuery(
-              "select NumberOfLogicalProcessors from Win32_Processor")
-            result.to_enum.collect(&:NumberOfLogicalProcessors).reduce(:+)
-          elsif File.readable?("/proc/cpuinfo") && (cpuinfo_count = 
IO.read("/proc/cpuinfo").scan(/^processor/).size) > 0
-            cpuinfo_count
-          elsif File.executable?("/usr/bin/nproc")
-            IO.popen("/usr/bin/nproc --all", &:read).to_i
-          elsif File.executable?("/usr/bin/hwprefs")
-            IO.popen("/usr/bin/hwprefs thread_count", &:read).to_i
-          elsif File.executable?("/usr/sbin/psrinfo")
-            IO.popen("/usr/sbin/psrinfo", &:read).scan(/^.*on-*line/).size
-          elsif File.executable?("/usr/sbin/ioscan")
-            IO.popen("/usr/sbin/ioscan -kC processor", 
&:read).scan(/^.*processor/).size
-          elsif File.executable?("/usr/sbin/pmcycles")
-            IO.popen("/usr/sbin/pmcycles -m", &:read).count("\n")
-          elsif File.executable?("/usr/sbin/lsdev")
-            IO.popen("/usr/sbin/lsdev -Cc processor -S 1", &:read).count("\n")
-          elsif File.executable?("/usr/sbin/sysconf") and os_name =~ /irix/i
-            IO.popen("/usr/sbin/sysconf NPROC_ONLN", &:read).to_i
-          elsif File.executable?("/usr/sbin/sysctl")
-            IO.popen("/usr/sbin/sysctl -n hw.ncpu", &:read).to_i
-          elsif File.executable?("/sbin/sysctl")
-            IO.popen("/sbin/sysctl -n hw.ncpu", &:read).to_i
-          else
-            # TODO (pitr-ch 05-Nov-2016): warn about failures
-            1
-          end
+          Etc.nprocessors
         end
-      rescue
-        return 1
       end
 
       def compute_physical_processor_count
         ppc = case RbConfig::CONFIG["target_os"]
-              when /darwin1/
+              when /darwin\d\d/
                 IO.popen("/usr/sbin/sysctl -n hw.physicalcpu", &:read).to_i
               when /linux/
                 cores = {} # unique physical ID / core ID combinations
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/concurrent-ruby/concurrent/version.rb 
new/lib/concurrent-ruby/concurrent/version.rb
--- old/lib/concurrent-ruby/concurrent/version.rb       2021-06-05 
14:47:58.000000000 +0200
+++ new/lib/concurrent-ruby/concurrent/version.rb       2022-03-22 
01:03:48.000000000 +0100
@@ -1,3 +1,3 @@
 module Concurrent
-  VERSION = '1.1.9'
+  VERSION = '1.1.10'
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/concurrent-ruby/concurrent-ruby.rb 
new/lib/concurrent-ruby/concurrent-ruby.rb
--- old/lib/concurrent-ruby/concurrent-ruby.rb  2021-06-05 14:47:58.000000000 
+0200
+++ new/lib/concurrent-ruby/concurrent-ruby.rb  2022-03-22 01:03:48.000000000 
+0100
@@ -1 +1,5 @@
-require_relative "./concurrent"
+# This file is here so that there is a file with the same name as the gem that
+# can be required by Bundler.require. Applications should normally
+# require 'concurrent'.
+
+require_relative "concurrent"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/metadata new/metadata
--- old/metadata        2021-06-05 14:47:58.000000000 +0200
+++ new/metadata        2022-03-22 01:03:48.000000000 +0100
@@ -1,16 +1,16 @@
 --- !ruby/object:Gem::Specification
 name: concurrent-ruby
 version: !ruby/object:Gem::Version
-  version: 1.1.9
+  version: 1.1.10
 platform: ruby
 authors:
 - Jerry D'Antonio
 - Petr Chalupa
 - The Ruby Concurrency Team
-autorequire: 
+autorequire:
 bindir: bin
 cert_chain: []
-date: 2021-06-05 00:00:00.000000000 Z
+date: 2022-03-22 00:00:00.000000000 Z
 dependencies: []
 description: |
   Modern concurrency tools including agents, futures, promises, thread pools, 
actors, supervisors, and more.
@@ -170,7 +170,7 @@
 metadata:
   source_code_uri: https://github.com/ruby-concurrency/concurrent-ruby
   changelog_uri: 
https://github.com/ruby-concurrency/concurrent-ruby/blob/master/CHANGELOG.md
-post_install_message: 
+post_install_message:
 rdoc_options: []
 require_paths:
 - lib/concurrent-ruby
@@ -178,15 +178,15 @@
   requirements:
   - - ">="
     - !ruby/object:Gem::Version
-      version: 1.9.3
+      version: '2.2'
 required_rubygems_version: !ruby/object:Gem::Requirement
   requirements:
   - - ">="
     - !ruby/object:Gem::Version
       version: '0'
 requirements: []
-rubygems_version: 3.2.3
-signing_key: 
+rubygems_version: 3.3.4
+signing_key:
 specification_version: 4
 summary: Modern concurrency tools for Ruby. Inspired by Erlang, Clojure, 
Scala, Haskell,
   F#, C#, Java, and classic concurrency patterns.

Reply via email to