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 <[email protected]>
+
+- 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
[](http://badge.fury.io/rb/concurrent-ruby)
-[](https://travis-ci.org/ruby-concurrency/concurrent-ruby)
-[](https://ci.appveyor.com/project/rubyconcurrency/concurrent-ruby)
[](http://opensource.org/licenses/MIT)
[-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).
[](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 && [email protected]
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 [email protected]? && (@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.