From 393ad72b9d537d6694fd8c9cd062e2cd52329e3e Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Thu, 6 Jun 2024 11:10:58 +0200 Subject: [PATCH 01/27] Remove dependency on `win32ole` This will become bundled in Ruby 3.5 Unfortunately there is no portable way of checking for this. The wmic command is deprecated, though I don't observe this myself on W11 (yet?) --- .../concurrent/utility/processor_counter.rb | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/lib/concurrent-ruby/concurrent/utility/processor_counter.rb b/lib/concurrent-ruby/concurrent/utility/processor_counter.rb index e31808722..d5274620e 100644 --- a/lib/concurrent-ruby/concurrent/utility/processor_counter.rb +++ b/lib/concurrent-ruby/concurrent/utility/processor_counter.rb @@ -68,10 +68,20 @@ def compute_physical_processor_count end cores.count when /mswin|mingw/ - require 'win32ole' - result_set = WIN32OLE.connect("winmgmts://").ExecQuery( - "select NumberOfCores from Win32_Processor") - result_set.to_enum.collect(&:NumberOfCores).reduce(:+) + # Get-CimInstance introduced in PowerShell 3 or earlier: https://learn.microsoft.com/en-us/previous-versions/powershell/module/cimcmdlets/get-ciminstance?view=powershell-3.0 + result = run('powershell -command "Get-CimInstance -ClassName Win32_Processor | Select-Object -Property NumberOfCores"') + if !result || $?.exitstatus != 0 + # fallback to deprecated wmic for older systems + result = run("wmic cpu get NumberOfCores") + end + if !result || $?.exitstatus != 0 + # Bail out if both commands returned something unexpected + processor_count + else + # powershell: "\nNumberOfCores\n-------------\n 4\n\n\n" + # wmic: "NumberOfCores \n\n4 \n\n\n\n" + result.scan(/\d+/).map(&:to_i).reduce(:+) + end else processor_count end @@ -81,6 +91,11 @@ def compute_physical_processor_count return 1 end + def run(command) + IO.popen(command, &:read) + rescue Errno::ENOENT + end + def compute_cpu_quota if RbConfig::CONFIG["target_os"].include?("linux") if File.exist?("/sys/fs/cgroup/cpu.max") From c672d6e1abfefe64396fa5f48e52c7fb43b9a5d3 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Thu, 6 Jun 2024 11:57:08 +0200 Subject: [PATCH 02/27] Add a windows job to CI --- .github/workflows/ci.yml | 8 ++++++-- spec/concurrent/channel/integration_spec.rb | 2 +- spec/concurrent/promises_spec.rb | 1 + 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bb118f400..ab1d23db8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,20 +6,24 @@ concurrency: jobs: build: - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }}-latest timeout-minutes: 10 strategy: fail-fast: false matrix: ruby: [2.3, 2.4, 2.5, 2.6, 2.7, '3.0', 3.1, 3.2, 3.3, jruby, truffleruby] + os: [ubuntu] + include: + - ruby: 3.3 + os: windows env: JAVA_OPTS: '-Xmx1024m' RUBYOPT: '-w' JRUBY_OPTS: '--dev' - name: "Tests: Ruby ${{ matrix.ruby }}" + name: "Tests: Ruby ${{ matrix.ruby }} - ${{ matrix.os }}" steps: - name: Clone Repo uses: actions/checkout@v4 diff --git a/spec/concurrent/channel/integration_spec.rb b/spec/concurrent/channel/integration_spec.rb index 01f490dc9..4d4c073ee 100644 --- a/spec/concurrent/channel/integration_spec.rb +++ b/spec/concurrent/channel/integration_spec.rb @@ -68,7 +68,7 @@ end specify 'default-selection.rb' do - skip('flaky') if Concurrent.on_jruby? || Concurrent.on_truffleruby? + skip('flaky') if Concurrent.on_jruby? || Concurrent.on_truffleruby? || Concurrent.on_windows? expected = <<-STDOUT . . diff --git a/spec/concurrent/promises_spec.rb b/spec/concurrent/promises_spec.rb index d89ce309f..2aa88fdfa 100644 --- a/spec/concurrent/promises_spec.rb +++ b/spec/concurrent/promises_spec.rb @@ -758,6 +758,7 @@ def behaves_as_delay(delay, value) describe 'value!' do %w[with without].each do |timeout| it "does not return spuriously #{timeout} timeout" do + skip "SIGHUP not supported" if Concurrent.on_windows? # https://github.com/ruby-concurrency/concurrent-ruby/issues/1015 trapped = false original_handler = Signal.trap(:SIGHUP) { trapped = true } From d1d29ac07ee48648f672e22a92d9bdc0160375c1 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Fri, 7 Jun 2024 22:05:42 +0200 Subject: [PATCH 03/27] 1.3.2 --- CHANGELOG.md | 6 +++++- lib/concurrent-ruby/concurrent/version.rb | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d0aef8e8..db8fd7964 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ ## Current -## Edge 0.7.1 (7 June 2024) +## Release v1.3.2, edge v0.7.1 (29 May 2024) + +concurrent-ruby: + +* (#1051) Remove dependency on `win32ole`. concurrent-ruby-edge: diff --git a/lib/concurrent-ruby/concurrent/version.rb b/lib/concurrent-ruby/concurrent/version.rb index afa6a4b04..e449c62bc 100644 --- a/lib/concurrent-ruby/concurrent/version.rb +++ b/lib/concurrent-ruby/concurrent/version.rb @@ -1,3 +1,3 @@ module Concurrent - VERSION = '1.3.1' + VERSION = '1.3.2' end From 4ea1fc51565354e2d0797f3ceae24e09548f4b51 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Sat, 8 Jun 2024 17:53:51 +0200 Subject: [PATCH 04/27] Improve speed for windows `Get-CimInstance` This only fetches a single property which is faster --- lib/concurrent-ruby/concurrent/utility/processor_counter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/concurrent-ruby/concurrent/utility/processor_counter.rb b/lib/concurrent-ruby/concurrent/utility/processor_counter.rb index d5274620e..6724457f1 100644 --- a/lib/concurrent-ruby/concurrent/utility/processor_counter.rb +++ b/lib/concurrent-ruby/concurrent/utility/processor_counter.rb @@ -69,7 +69,7 @@ def compute_physical_processor_count cores.count when /mswin|mingw/ # Get-CimInstance introduced in PowerShell 3 or earlier: https://learn.microsoft.com/en-us/previous-versions/powershell/module/cimcmdlets/get-ciminstance?view=powershell-3.0 - result = run('powershell -command "Get-CimInstance -ClassName Win32_Processor | Select-Object -Property NumberOfCores"') + result = run('powershell -command "Get-CimInstance -ClassName Win32_Processor -Property NumberOfCores | Select-Object -Property NumberOfCores"') if !result || $?.exitstatus != 0 # fallback to deprecated wmic for older systems result = run("wmic cpu get NumberOfCores") From b16af1e977c20e47bbab287ae92f2d397c7694b0 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Sun, 9 Jun 2024 16:33:25 +0200 Subject: [PATCH 05/27] 1.3.3 --- CHANGELOG.md | 6 +++++- lib/concurrent-ruby/concurrent/version.rb | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index db8fd7964..c117834d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ ## Current -## Release v1.3.2, edge v0.7.1 (29 May 2024) +## Release v1.3.3 (9 June 2024) + +* (#1053) Improve the speed of `Concurrent.physical_processor_count` on Windows. + +## Release v1.3.2, edge v0.7.1 (7 June 2024) concurrent-ruby: diff --git a/lib/concurrent-ruby/concurrent/version.rb b/lib/concurrent-ruby/concurrent/version.rb index e449c62bc..98e7f12b3 100644 --- a/lib/concurrent-ruby/concurrent/version.rb +++ b/lib/concurrent-ruby/concurrent/version.rb @@ -1,3 +1,3 @@ module Concurrent - VERSION = '1.3.2' + VERSION = '1.3.3' end From cadc8de0457a6f75bb7d343e6c21b92baea564c9 Mon Sep 17 00:00:00 2001 From: Holger Just Date: Tue, 9 Jul 2024 17:39:44 +0200 Subject: [PATCH 06/27] Update comment for JRuby variant of processor_count to reality --- lib/concurrent-ruby/concurrent/utility/processor_counter.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/concurrent-ruby/concurrent/utility/processor_counter.rb b/lib/concurrent-ruby/concurrent/utility/processor_counter.rb index 6724457f1..007668ae6 100644 --- a/lib/concurrent-ruby/concurrent/utility/processor_counter.rb +++ b/lib/concurrent-ruby/concurrent/utility/processor_counter.rb @@ -128,8 +128,8 @@ def compute_cpu_quota # `java.lang.Runtime.getRuntime.availableProcessors` will be used. According # to the Java documentation this "value may change during a particular # invocation of the virtual machine... [applications] should therefore - # occasionally poll this property." Subsequently the result will NOT be - # memoized under JRuby. + # occasionally poll this property." We still memoize this value once under + # JRuby. # # Otherwise Ruby's Etc.nprocessors will be used. # From 6f7c91ab5a4e99d850f69c958572a536426277e8 Mon Sep 17 00:00:00 2001 From: heka1024 Date: Wed, 31 Jul 2024 02:22:29 +0900 Subject: [PATCH 07/27] Add `Concurrent.cpu_shares` that is cgroups aware. --- .../concurrent/utility/processor_counter.rb | 27 +++++++++++++++++++ .../utility/processor_count_spec.rb | 22 +++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/lib/concurrent-ruby/concurrent/utility/processor_counter.rb b/lib/concurrent-ruby/concurrent/utility/processor_counter.rb index 007668ae6..2dd91b59a 100644 --- a/lib/concurrent-ruby/concurrent/utility/processor_counter.rb +++ b/lib/concurrent-ruby/concurrent/utility/processor_counter.rb @@ -12,6 +12,7 @@ def initialize @processor_count = Delay.new { compute_processor_count } @physical_processor_count = Delay.new { compute_physical_processor_count } @cpu_quota = Delay.new { compute_cpu_quota } + @cpu_shares = Delay.new { compute_cpu_shares } end def processor_count @@ -41,6 +42,10 @@ def cpu_quota @cpu_quota.value end + def cpu_shares + @cpu_shares.value + end + private def compute_processor_count @@ -113,6 +118,20 @@ def compute_cpu_quota end end end + + def compute_cpu_shares + if RbConfig::CONFIG["target_os"].include?("linux") + if File.exist?("/sys/fs/cgroup/cpu.weight") + # cgroups v2: https://docs.kernel.org/admin-guide/cgroup-v2.html#cpu-interface-files + # Ref: https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/2254-cgroup-v2#phase-1-convert-from-cgroups-v1-settings-to-v2 + weight = File.read("/sys/fs/cgroup/cpu.weight").to_f + ((((weight - 1) * 262142) / 9999) + 2) / 1024 + elsif File.exist?("/sys/fs/cgroup/cpu/cpu.shares") + # cgroups v1: https://kernel.googlesource.com/pub/scm/linux/kernel/git/glommer/memcg/+/cpu_stat/Documentation/cgroups/cpu.txt + File.read("/sys/fs/cgroup/cpu/cpu.shares").to_f / 1024 + end + end + end end end @@ -187,4 +206,12 @@ def self.available_processor_count def self.cpu_quota processor_counter.cpu_quota end + + # The CPU shares requested by the process. For performance reasons the calculated + # value will be memoized on the first call. + # + # @return [Float, nil] CPU shares requested by the process, or nil if not set + def self.cpu_shares + processor_counter.cpu_shares + end end diff --git a/spec/concurrent/utility/processor_count_spec.rb b/spec/concurrent/utility/processor_count_spec.rb index fdc44b0ae..7a636640c 100644 --- a/spec/concurrent/utility/processor_count_spec.rb +++ b/spec/concurrent/utility/processor_count_spec.rb @@ -92,4 +92,26 @@ module Concurrent end end + + RSpec.describe '#cpu_shares' do + let(:counter) { Concurrent::Utility::ProcessorCounter.new } + + it 'returns a float when cgroups v2 sets a cpu.weight' do + expect(RbConfig::CONFIG).to receive(:[]).with("target_os").and_return("linux") + expect(File).to receive(:exist?).with("/sys/fs/cgroup/cpu.weight").and_return(true) + + expect(File).to receive(:read).with("/sys/fs/cgroup/cpu.weight").and_return("10000\n") + expect(counter.cpu_shares).to be == 256.0 + end + + it 'returns a float if cgroups v1 sets a cpu.shares' do + expect(RbConfig::CONFIG).to receive(:[]).with("target_os").and_return("linux") + expect(File).to receive(:exist?).with("/sys/fs/cgroup/cpu.weight").and_return(false) + expect(File).to receive(:exist?).with("/sys/fs/cgroup/cpu/cpu.shares").and_return(true) + + expect(File).to receive(:read).with("/sys/fs/cgroup/cpu/cpu.shares").and_return("512\n") + expect(counter.cpu_shares).to be == 0.5 + end + + end end From cbee21568a80ec6fcce235b50adc69a9d6d0f63f Mon Sep 17 00:00:00 2001 From: Yuji Yaginuma Date: Wed, 7 Aug 2024 17:07:23 +0900 Subject: [PATCH 08/27] Fix the doc of `Concurrent.available_processor_count` Currently, the doc says that this methods returns `nil` if there is no cpu_quota, but actually not. https://github.com/ruby-concurrency/concurrent-ruby/blob/6f7c91ab5a4e99d850f69c958572a536426277e8/lib/concurrent-ruby/concurrent/utility/processor_counter.rb#L30 This PR fixes the doc to match the behavior. Co-authored-by: Benoit Daloze --- .../concurrent/utility/processor_counter.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/concurrent-ruby/concurrent/utility/processor_counter.rb b/lib/concurrent-ruby/concurrent/utility/processor_counter.rb index 2dd91b59a..5a2db24f3 100644 --- a/lib/concurrent-ruby/concurrent/utility/processor_counter.rb +++ b/lib/concurrent-ruby/concurrent/utility/processor_counter.rb @@ -83,7 +83,7 @@ def compute_physical_processor_count # Bail out if both commands returned something unexpected processor_count else - # powershell: "\nNumberOfCores\n-------------\n 4\n\n\n" + # powershell: "\nNumberOfCores\n-------------\n 4\n\n\n" # wmic: "NumberOfCores \n\n4 \n\n\n\n" result.scan(/\d+/).map(&:to_i).reduce(:+) end @@ -181,13 +181,14 @@ def self.physical_processor_count end # Number of processors cores available for process scheduling. - # Returns `nil` if there is no #cpu_quota, or a `Float` if the - # process is inside a cgroup with a dedicated CPU quota (typically Docker). + # This method takes in account the CPU quota if the process is inside a cgroup with a + # dedicated CPU quota (typically Docker). + # Otherwise it returns the same value as #processor_count but as a Float. # # For performance reasons the calculated value will be memoized on the first # call. # - # @return [nil, Float] number of available processors + # @return [Float] number of available processors def self.available_processor_count processor_counter.available_processor_count end From 98d0f168d4e4957d6629a1872f238fc9819bb896 Mon Sep 17 00:00:00 2001 From: Yuji Yaginuma Date: Fri, 9 Aug 2024 12:30:47 +0900 Subject: [PATCH 09/27] Fix the return value of `Concurrent.available_processor_count` when `cpu.cfs_quota_us` is -1 I tried to use `Concurrent.available_processor_count` in `parallel` gem, but we got some feedback `Concurrent.available_processor_count` returned a negative value. https://github.com/grosser/parallel/pull/348#issuecomment-2275859126 https://github.com/grosser/parallel/issues/349#issuecomment-2275953547 According to the https://docs.kernel.org/scheduler/sched-bwc.html#management, The default value of `cpu.cfs_quota_us` is -1. In that case, cgroup does not adhere to any CPU time restrictions. This PR adds the case of `cpu.cfs_quota_us` is -1 to `#cpu_quota` to return processor count from `Concurrent.available_processor_count` in that case. --- CHANGELOG.md | 2 ++ .../concurrent/utility/processor_counter.rb | 4 +++- spec/concurrent/utility/processor_count_spec.rb | 9 +++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c117834d4..32261d239 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ ## Current +* (#1060) Fix bug with return value of `Concurrent.available_processor_count` when `cpu.cfs_quota_us` is -1. + ## Release v1.3.3 (9 June 2024) * (#1053) Improve the speed of `Concurrent.physical_processor_count` on Windows. diff --git a/lib/concurrent-ruby/concurrent/utility/processor_counter.rb b/lib/concurrent-ruby/concurrent/utility/processor_counter.rb index 5a2db24f3..2489cbd76 100644 --- a/lib/concurrent-ruby/concurrent/utility/processor_counter.rb +++ b/lib/concurrent-ruby/concurrent/utility/processor_counter.rb @@ -112,7 +112,9 @@ def compute_cpu_quota elsif File.exist?("/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us") # cgroups v1: https://kernel.googlesource.com/pub/scm/linux/kernel/git/glommer/memcg/+/cpu_stat/Documentation/cgroups/cpu.txt max = File.read("/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us").to_i - return nil if max == 0 + # If the cpu.cfs_quota_us is -1, cgroup does not adhere to any CPU time restrictions + # https://docs.kernel.org/scheduler/sched-bwc.html#management + return nil if max <= 0 period = File.read("/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_period_us").to_f max / period end diff --git a/spec/concurrent/utility/processor_count_spec.rb b/spec/concurrent/utility/processor_count_spec.rb index 7a636640c..8de31e027 100644 --- a/spec/concurrent/utility/processor_count_spec.rb +++ b/spec/concurrent/utility/processor_count_spec.rb @@ -56,6 +56,15 @@ module Concurrent expect(counter.cpu_quota).to be_nil end + it 'returns nil if cgroups v1 and cpu.cfs_quota_us is -1' do + expect(RbConfig::CONFIG).to receive(:[]).with("target_os").and_return("linux") + expect(File).to receive(:exist?).with("/sys/fs/cgroup/cpu.max").and_return(false) + expect(File).to receive(:exist?).with("/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us").and_return(true) + + expect(File).to receive(:read).with("/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us").and_return("-1\n") + expect(counter.cpu_quota).to be_nil + end + it 'returns a float if cgroups v1 sets a limit' do expect(RbConfig::CONFIG).to receive(:[]).with("target_os").and_return("linux") expect(File).to receive(:exist?).with("/sys/fs/cgroup/cpu.max").and_return(false) From e671fec7cc0e5ecb7db6b72180e6903771ad6788 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Sat, 10 Aug 2024 13:11:02 +0200 Subject: [PATCH 10/27] Check early that $CONCURRENT_JRUBY_HOME is set --- Rakefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Rakefile b/Rakefile index 006fcb993..4b147970e 100644 --- a/Rakefile +++ b/Rakefile @@ -232,6 +232,8 @@ namespace :release do # Depends on environment of @pitr-ch task :checks do + raise '$CONCURRENT_JRUBY_HOME must be set' unless ENV['CONCURRENT_JRUBY_HOME'] + Dir.chdir(__dir__) do sh 'test -z "$(git status --porcelain)"' do |ok, res| unless ok @@ -262,6 +264,8 @@ namespace :release do desc '* test actual installed gems instead of cloned repository on MRI and JRuby' task :test do + raise '$CONCURRENT_JRUBY_HOME must be set' unless ENV['CONCURRENT_JRUBY_HOME'] + Dir.chdir(__dir__) do puts "Testing with the installed gem" From 8fefd59a7d124b332aaa1c1882e22d54d1322482 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Sat, 10 Aug 2024 13:12:47 +0200 Subject: [PATCH 11/27] 1.3.4 --- CHANGELOG.md | 3 +++ lib/concurrent-ruby/concurrent/version.rb | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32261d239..2c0375c7d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ ## Current +## Release v1.3.4 (10 August 2024) + * (#1060) Fix bug with return value of `Concurrent.available_processor_count` when `cpu.cfs_quota_us` is -1. +* (#1058) Add `Concurrent.cpu_shares` that is cgroups aware. ## Release v1.3.3 (9 June 2024) diff --git a/lib/concurrent-ruby/concurrent/version.rb b/lib/concurrent-ruby/concurrent/version.rb index 98e7f12b3..1b0c4c22f 100644 --- a/lib/concurrent-ruby/concurrent/version.rb +++ b/lib/concurrent-ruby/concurrent/version.rb @@ -1,3 +1,3 @@ module Concurrent - VERSION = '1.3.3' + VERSION = '1.3.4' end From 13badd0f0e41c2d75dba99233075d64be702c3be Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Sat, 10 Aug 2024 13:15:58 +0200 Subject: [PATCH 12/27] Update docs-source/signpost.md --- docs-source/signpost.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs-source/signpost.md b/docs-source/signpost.md index 161812a8f..e48a56a16 100644 --- a/docs-source/signpost.md +++ b/docs-source/signpost.md @@ -3,7 +3,7 @@ Pick a `concurrent-ruby` version: * [master](./master/index.html) -* [1.3.1 with edge 0.7.0](./1.3.1/index.html) +* [1.3.4 with edge 0.7.1](./1.3.4/index.html) * [1.1.10 with edge 0.6.0](./1.1.10/index.html) * [1.1.9 with edge 0.6.0](./1.1.9/index.html) * [1.1.8 with edge 0.6.0](./1.1.8/index.html) From f1312140264a4fba036bcd0ba1b8f7974c495499 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Sat, 10 Aug 2024 13:27:55 +0200 Subject: [PATCH 13/27] Avoid require in *.gemspec files to avoid redefined constant warnings * Like: concurrent-ruby/vendor/bundle/ruby/3.2.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/version.rb:2: warning: already initialized constant Concurrent::VERSION concurrent-ruby/lib/concurrent-ruby/concurrent/version.rb:2: warning: previous definition of VERSION was here --- concurrent-ruby-edge.gemspec | 8 ++++---- concurrent-ruby-ext.gemspec | 6 +++--- concurrent-ruby.gemspec | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/concurrent-ruby-edge.gemspec b/concurrent-ruby-edge.gemspec index 4eedb53f0..719548b95 100644 --- a/concurrent-ruby-edge.gemspec +++ b/concurrent-ruby-edge.gemspec @@ -1,11 +1,11 @@ -require File.join(File.dirname(__FILE__ ), 'lib/concurrent-ruby/concurrent/version') -require File.join(File.dirname(__FILE__ ), 'lib/concurrent-ruby-edge/concurrent/edge/version') +version = File.read("#{__dir__}/lib/concurrent-ruby/concurrent/version.rb")[/'(.+)'/, 1] or raise +edge_version = File.read("#{__dir__}/lib/concurrent-ruby-edge/concurrent/edge/version.rb")[/'(.+)'/, 1] or raise Gem::Specification.new do |s| git_files = `git ls-files`.split("\n") s.name = 'concurrent-ruby-edge' - s.version = Concurrent::EDGE_VERSION + s.version = edge_version s.platform = Gem::Platform::RUBY s.authors = ["Jerry D'Antonio", 'Petr Chalupa', 'The Ruby Concurrency Team'] s.email = 'concurrent-ruby@googlegroups.com' @@ -25,5 +25,5 @@ Please see http://concurrent-ruby.com for more information. s.required_ruby_version = '>= 2.3' - s.add_runtime_dependency 'concurrent-ruby', "~> #{Concurrent::VERSION.split('.')[0..1].join('.')}" + s.add_runtime_dependency 'concurrent-ruby', "~> #{version.split('.')[0..1].join('.')}" end diff --git a/concurrent-ruby-ext.gemspec b/concurrent-ruby-ext.gemspec index 534822de0..4bfafdd5b 100644 --- a/concurrent-ruby-ext.gemspec +++ b/concurrent-ruby-ext.gemspec @@ -1,8 +1,8 @@ -require File.join(File.dirname(__FILE__ ), 'lib/concurrent-ruby/concurrent/version') +version = File.read("#{__dir__}/lib/concurrent-ruby/concurrent/version.rb")[/'(.+)'/, 1] or raise Gem::Specification.new do |s| s.name = 'concurrent-ruby-ext' - s.version = Concurrent::VERSION + s.version = version s.platform = Gem::Platform::RUBY s.authors = ["Jerry D'Antonio", 'The Ruby Concurrency Team'] s.email = 'concurrent-ruby@googlegroups.com' @@ -23,5 +23,5 @@ Gem::Specification.new do |s| s.required_ruby_version = '>= 2.3' - s.add_runtime_dependency 'concurrent-ruby', "= #{Concurrent::VERSION}" + s.add_runtime_dependency 'concurrent-ruby', "= #{version}" end diff --git a/concurrent-ruby.gemspec b/concurrent-ruby.gemspec index 863201b54..1537d377d 100644 --- a/concurrent-ruby.gemspec +++ b/concurrent-ruby.gemspec @@ -1,10 +1,10 @@ -require File.join(File.dirname(__FILE__ ), 'lib/concurrent-ruby/concurrent/version') +version = File.read("#{__dir__}/lib/concurrent-ruby/concurrent/version.rb")[/'(.+)'/, 1] or raise Gem::Specification.new do |s| git_files = `git ls-files`.split("\n") s.name = 'concurrent-ruby' - s.version = Concurrent::VERSION + s.version = version s.platform = Gem::Platform::RUBY s.authors = ["Jerry D'Antonio", 'Petr Chalupa', 'The Ruby Concurrency Team'] s.email = 'concurrent-ruby@googlegroups.com' From 09bfcd02f375f85700e83281c5ef9b181d27342a Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Sat, 10 Aug 2024 13:34:39 +0200 Subject: [PATCH 14/27] Avoid require in Gemfile & Rakefile to avoid redefined constant warnings --- Gemfile | 10 +++++----- Rakefile | 30 +++++++++++++++--------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Gemfile b/Gemfile index f10dc8eba..1786c8b21 100644 --- a/Gemfile +++ b/Gemfile @@ -1,14 +1,14 @@ source 'https://rubygems.org' -require File.join(File.dirname(__FILE__), 'lib/concurrent-ruby/concurrent/version') -require File.join(File.dirname(__FILE__ ), 'lib/concurrent-ruby-edge/concurrent/edge/version') +version = File.read("#{__dir__}/lib/concurrent-ruby/concurrent/version.rb")[/'(.+)'/, 1] or raise +edge_version = File.read("#{__dir__}/lib/concurrent-ruby-edge/concurrent/edge/version.rb")[/'(.+)'/, 1] or raise no_path = ENV['NO_PATH'] options = no_path ? {} : { path: '.' } -gem 'concurrent-ruby', Concurrent::VERSION, options -gem 'concurrent-ruby-edge', Concurrent::EDGE_VERSION, options -gem 'concurrent-ruby-ext', Concurrent::VERSION, options.merge(platform: :mri) +gem 'concurrent-ruby', version, options +gem 'concurrent-ruby-edge', edge_version, options +gem 'concurrent-ruby-ext', version, options.merge(platform: :mri) group :development do gem 'rake', '~> 13.0' diff --git a/Rakefile b/Rakefile index 4b147970e..403acbdbf 100644 --- a/Rakefile +++ b/Rakefile @@ -1,5 +1,5 @@ -require_relative 'lib/concurrent-ruby/concurrent/version' -require_relative 'lib/concurrent-ruby-edge/concurrent/edge/version' +version = File.read("#{__dir__}/lib/concurrent-ruby/concurrent/version.rb")[/'(.+)'/, 1] or raise +edge_version = File.read("#{__dir__}/lib/concurrent-ruby-edge/concurrent/edge/version.rb")[/'(.+)'/, 1] or raise require_relative 'lib/concurrent-ruby/concurrent/utility/engine' core_gemspec = Gem::Specification.load File.join(__dir__, 'concurrent-ruby.gemspec') @@ -96,9 +96,9 @@ begin task :installed do Bundler.with_original_env do Dir.chdir(__dir__) do - sh "gem install pkg/concurrent-ruby-#{Concurrent::VERSION}.gem" - sh "gem install pkg/concurrent-ruby-ext-#{Concurrent::VERSION}.gem" if Concurrent.on_cruby? - sh "gem install pkg/concurrent-ruby-edge-#{Concurrent::EDGE_VERSION}.gem" + sh "gem install pkg/concurrent-ruby-#{version}.gem" + sh "gem install pkg/concurrent-ruby-ext-#{version}.gem" if Concurrent.on_cruby? + sh "gem install pkg/concurrent-ruby-edge-#{edge_version}.gem" ENV['NO_PATH'] = 'true' sh 'bundle update' sh 'bundle exec rake spec:ci' @@ -128,7 +128,7 @@ rescue LoadError => e puts 'RSpec is not installed, skipping test task definitions: ' + e.message end -current_yard_version_name = Concurrent::VERSION +current_yard_version_name = version begin require 'yard' @@ -314,21 +314,21 @@ namespace :release do desc '** tag HEAD with current version and push to github' task :tag => :ask do Dir.chdir(__dir__) do - sh "git tag v#{Concurrent::VERSION}" if publish_base - sh "git push origin v#{Concurrent::VERSION}" if publish_base - sh "git tag edge-v#{Concurrent::EDGE_VERSION}" if publish_edge - sh "git push origin edge-v#{Concurrent::EDGE_VERSION}" if publish_edge + sh "git tag v#{version}" if publish_base + sh "git push origin v#{version}" if publish_base + sh "git tag edge-v#{edge_version}" if publish_edge + sh "git push origin edge-v#{edge_version}" if publish_edge end end desc '** push all *.gem files to rubygems' task :rubygems => :ask do Dir.chdir(__dir__) do - sh "gem push pkg/concurrent-ruby-#{Concurrent::VERSION}.gem" if publish_base - sh "gem push pkg/concurrent-ruby-edge-#{Concurrent::EDGE_VERSION}.gem" if publish_edge - sh "gem push pkg/concurrent-ruby-ext-#{Concurrent::VERSION}.gem" if publish_base - sh "gem push pkg/concurrent-ruby-ext-#{Concurrent::VERSION}-x64-mingw32.gem" if publish_base - sh "gem push pkg/concurrent-ruby-ext-#{Concurrent::VERSION}-x86-mingw32.gem" if publish_base + sh "gem push pkg/concurrent-ruby-#{version}.gem" if publish_base + sh "gem push pkg/concurrent-ruby-edge-#{edge_version}.gem" if publish_edge + sh "gem push pkg/concurrent-ruby-ext-#{version}.gem" if publish_base + sh "gem push pkg/concurrent-ruby-ext-#{version}-x64-mingw32.gem" if publish_base + sh "gem push pkg/concurrent-ruby-ext-#{version}-x86-mingw32.gem" if publish_base end end From 044020f44b36930b863b930f3ee8fa1e9f750469 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Sat, 10 Aug 2024 13:37:57 +0200 Subject: [PATCH 15/27] Avoid requiring files of the gem in Rakefile to avoid redefined method warnings --- Rakefile | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Rakefile b/Rakefile index 403acbdbf..c52b5640e 100644 --- a/Rakefile +++ b/Rakefile @@ -1,6 +1,5 @@ version = File.read("#{__dir__}/lib/concurrent-ruby/concurrent/version.rb")[/'(.+)'/, 1] or raise edge_version = File.read("#{__dir__}/lib/concurrent-ruby-edge/concurrent/edge/version.rb")[/'(.+)'/, 1] or raise -require_relative 'lib/concurrent-ruby/concurrent/utility/engine' core_gemspec = Gem::Specification.load File.join(__dir__, 'concurrent-ruby.gemspec') ext_gemspec = Gem::Specification.load File.join(__dir__, 'concurrent-ruby-ext.gemspec') @@ -8,14 +7,14 @@ edge_gemspec = Gem::Specification.load File.join(__dir__, 'concurrent-ruby-edge. require 'rake/javaextensiontask' -ENV['JRUBY_HOME'] = ENV['CONCURRENT_JRUBY_HOME'] if ENV['CONCURRENT_JRUBY_HOME'] && !Concurrent.on_jruby? +ENV['JRUBY_HOME'] = ENV['CONCURRENT_JRUBY_HOME'] if ENV['CONCURRENT_JRUBY_HOME'] && RUBY_ENGINE != 'jruby' Rake::JavaExtensionTask.new('concurrent_ruby', core_gemspec) do |ext| ext.ext_dir = 'ext/concurrent-ruby' ext.lib_dir = 'lib/concurrent-ruby/concurrent' end -unless Concurrent.on_jruby? || Concurrent.on_truffleruby? +if RUBY_ENGINE == 'ruby' require 'rake/extensiontask' Rake::ExtensionTask.new('concurrent_ruby_ext', ext_gemspec) do |ext| @@ -68,7 +67,7 @@ require 'rubygems' require 'rubygems/package_task' Gem::PackageTask.new(core_gemspec) {} if core_gemspec -Gem::PackageTask.new(ext_gemspec) {} if ext_gemspec && !Concurrent.on_jruby? +Gem::PackageTask.new(ext_gemspec) {} if ext_gemspec && RUBY_ENGINE != 'jruby' Gem::PackageTask.new(edge_gemspec) {} if edge_gemspec CLEAN.include( @@ -97,7 +96,7 @@ begin Bundler.with_original_env do Dir.chdir(__dir__) do sh "gem install pkg/concurrent-ruby-#{version}.gem" - sh "gem install pkg/concurrent-ruby-ext-#{version}.gem" if Concurrent.on_cruby? + sh "gem install pkg/concurrent-ruby-ext-#{version}.gem" if RUBY_ENGINE == 'ruby' sh "gem install pkg/concurrent-ruby-edge-#{edge_version}.gem" ENV['NO_PATH'] = 'true' sh 'bundle update' From d7ce956dacd0b772273d39b8ed31a30cff7ecf38 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Wed, 4 Sep 2024 21:16:32 +0200 Subject: [PATCH 16/27] Remove dependency on logger * To fix the Ruby 3.3.5 warnings: https://github.com/ruby-concurrency/concurrent-ruby/issues/1061 * concurrent-ruby only uses 7 constants from Logger, so just copy those over. --- README.md | 2 +- docs-source/actor/celluloid_benchmark.rb | 6 +--- docs-source/actor/io.in.rb | 3 +- docs-source/actor/io.out.rb | 3 +- docs-source/actor/main.md | 8 ++--- examples/init.rb | 2 +- .../concurrent/actor/context.rb | 4 +-- .../concurrent/actor/internal_delegations.rb | 4 +-- .../concurrent/edge/erlang_actor.rb | 18 ++++++------ .../concurrent/concern/logging.rb | 29 +++++++++++-------- spec/spec_helper.rb | 2 +- 11 files changed, 40 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index 66a6983b0..63ee743c5 100644 --- a/README.md +++ b/README.md @@ -284,7 +284,7 @@ To use the tools in the Edge gem it must be required separately: require 'concurrent-edge' ``` -If the library does not behave as expected, `Concurrent.use_stdlib_logger(Logger::DEBUG)` could +If the library does not behave as expected, `Concurrent.use_simple_logger(:DEBUG)` could help to reveal the problem. ## Installation diff --git a/docs-source/actor/celluloid_benchmark.rb b/docs-source/actor/celluloid_benchmark.rb index dea20e553..30ca1e0d6 100644 --- a/docs-source/actor/celluloid_benchmark.rb +++ b/docs-source/actor/celluloid_benchmark.rb @@ -7,11 +7,7 @@ # require 'stackprof' # require 'profiler' -logger = Logger.new($stderr) -logger.level = Logger::INFO -Concurrent.configuration.logger = lambda do |level, progname, message = nil, &block| - logger.add level, message, progname, &block -end +Concurrent.use_simple_logger(:INFO) scale = 1 ADD_TO = (100 * scale).to_i diff --git a/docs-source/actor/io.in.rb b/docs-source/actor/io.in.rb index 6bbc1a07c..3c6a1bdb5 100644 --- a/docs-source/actor/io.in.rb +++ b/docs-source/actor/io.in.rb @@ -1,7 +1,6 @@ require 'concurrent' -# logger = Logger.new(STDOUT) -# Concurrent.configuration.logger = logger.method(:add) +# Concurrent.use_simple_logger(:WARN, STDOUT) # First option is to use operation pool diff --git a/docs-source/actor/io.out.rb b/docs-source/actor/io.out.rb index b96cfc72a..b879c4fb8 100644 --- a/docs-source/actor/io.out.rb +++ b/docs-source/actor/io.out.rb @@ -1,7 +1,6 @@ require 'concurrent' # => false -# logger = Logger.new(STDOUT) -# Concurrent.configuration.logger = logger.method(:add) +# Concurrent.use_simple_logger(:WARN, STDOUT) # First option is to use operation pool diff --git a/docs-source/actor/main.md b/docs-source/actor/main.md index 43cf72798..e3e67f62c 100644 --- a/docs-source/actor/main.md +++ b/docs-source/actor/main.md @@ -124,12 +124,12 @@ Spawned actor cannot be garbage-collected until it's terminated. There is a refe Actors are running on shared thread poll which allows user to create many actors cheaply. Downside is that these actors cannot be directly used to do IO or other blocking operations. -Blocking operations could starve the `default_task_pool`. However there are two options: +Blocking operations could starve the `global_fast_executor`. However there are two options: -- Create an regular actor which will schedule blocking operations in `global_operation_pool` +- Create an regular actor which will schedule blocking operations in `global_io_executor` (which is intended for blocking operations) sending results back to self in messages. -- Create an actor using `global_operation_pool` instead of `global_task_pool`, e.g. - `AnIOActor.spawn name: :blocking, executor: Concurrent.configuration.global_operation_pool`. +- Create an actor using `global_io_executor` instead of `global_fast_executor`, e.g. + `AnIOActor.spawn name: :blocking, executor: Concurrent.global_io_executor`. ### Example diff --git a/examples/init.rb b/examples/init.rb index 03c91f7c1..92d2c63af 100644 --- a/examples/init.rb +++ b/examples/init.rb @@ -4,4 +4,4 @@ def do_stuff(*args) :stuff end -Concurrent.use_simple_logger Logger::DEBUG +Concurrent.use_simple_logger :DEBUG diff --git a/lib/concurrent-ruby-edge/concurrent/actor/context.rb b/lib/concurrent-ruby-edge/concurrent/actor/context.rb index 19ee14ab7..96252901e 100644 --- a/lib/concurrent-ruby-edge/concurrent/actor/context.rb +++ b/lib/concurrent-ruby-edge/concurrent/actor/context.rb @@ -84,7 +84,7 @@ def default_reference_class Reference end - # override to se different default executor, e.g. to change it to global_operation_pool + # override to se different default executor, e.g. to change it to global_fast_executor # @return [Executor] def default_executor Concurrent.global_io_executor @@ -109,7 +109,7 @@ def ask(message) # @example by option hash # inc2 = AdHoc.spawn(name: 'increment by 2', # args: [2], - # executor: Concurrent.configuration.global_task_pool) do |increment_by| + # executor: Concurrent.global_fast_executor) do |increment_by| # lambda { |number| number + increment_by } # end # inc2.ask!(2) # => 4 diff --git a/lib/concurrent-ruby-edge/concurrent/actor/internal_delegations.rb b/lib/concurrent-ruby-edge/concurrent/actor/internal_delegations.rb index ddca34883..9ed051b5a 100644 --- a/lib/concurrent-ruby-edge/concurrent/actor/internal_delegations.rb +++ b/lib/concurrent-ruby-edge/concurrent/actor/internal_delegations.rb @@ -1,11 +1,11 @@ -require 'logger' +require 'concurrent/concern/logging' require 'concurrent/actor/public_delegations' module Concurrent module Actor module InternalDelegations include PublicDelegations - include Logger::Severity + include Concurrent::Concern::Logging # @see Core#children def children diff --git a/lib/concurrent-ruby-edge/concurrent/edge/erlang_actor.rb b/lib/concurrent-ruby-edge/concurrent/edge/erlang_actor.rb index 2277a977c..6690e9e26 100644 --- a/lib/concurrent-ruby-edge/concurrent/edge/erlang_actor.rb +++ b/lib/concurrent-ruby-edge/concurrent/edge/erlang_actor.rb @@ -674,7 +674,7 @@ def initialize(mailbox, environment, name, executor) end def tell_op(message) - log Logger::DEBUG, @Pid, told: message + log DEBUG, @Pid, told: message if (mailbox = @Mailbox) mailbox.push_op(message).then { @Pid } else @@ -683,7 +683,7 @@ def tell_op(message) end def tell(message, timeout = nil) - log Logger::DEBUG, @Pid, told: message + log DEBUG, @Pid, told: message if (mailbox = @Mailbox) timed_out = mailbox.push message, timeout timeout ? timed_out : @Pid @@ -693,7 +693,7 @@ def tell(message, timeout = nil) end def ask(message, timeout, timeout_value) - log Logger::DEBUG, @Pid, asked: message + log DEBUG, @Pid, asked: message if @Terminated.resolved? raise NoActor.new(@Pid) else @@ -724,7 +724,7 @@ def ask(message, timeout, timeout_value) end def ask_op(message, probe) - log Logger::DEBUG, @Pid, asked: message + log DEBUG, @Pid, asked: message if @Terminated.resolved? probe.reject NoActor.new(@Pid), false else @@ -1029,7 +1029,7 @@ def terminate_self(reason, value) end def after_termination(final_reason) - log Logger::DEBUG, @Pid, terminated: final_reason + log DEBUG, @Pid, terminated: final_reason clean_reply NoActor.new(@Pid) while true message = @Mailbox.try_pop NOTHING @@ -1071,7 +1071,7 @@ def run(*args, &body) inner_run(*args, &body). run(Run::TEST). then(&method(:after_termination)). - rescue { |e| log Logger::ERROR, e } + rescue { |e| log ERROR, e } end def receive(*rules, timeout: nil, timeout_value: nil, keep: false, &given_block) @@ -1163,7 +1163,7 @@ def internal_receive end message_future.then(start, self) do |message, s, _actor| - log Logger::DEBUG, pid, got: message + log DEBUG, pid, got: message catch(JUMP) do if (message = consume_signal(message)) == NOTHING @timeout = [@timeout + s - Concurrent.monotonic_time, 0].max if s @@ -1230,7 +1230,7 @@ def receive(*rules, timeout: nil, timeout_value: nil, &given_block) matcher = -> m { m.is_a?(Ask) ? rules_matcher === m.message : rules_matcher === m } while true message = @Mailbox.pop_matching(matcher, timeout, TIMEOUT) - log Logger::DEBUG, pid, got: message + log DEBUG, pid, got: message unless (message = consume_signal(message)) == NOTHING rules.each do |rule, job| return eval_task(message, job) if rule === message @@ -1535,7 +1535,7 @@ class NoReply < Error def self.create(type, channel, environment, name, executor) actor = KLASS_MAP.fetch(type).new(channel, environment, name, executor) ensure - log Logger::DEBUG, actor.pid, created: caller[1] if actor + log Concern::Logging::DEBUG, actor.pid, created: caller[1] if actor end KLASS_MAP = { diff --git a/lib/concurrent-ruby/concurrent/concern/logging.rb b/lib/concurrent-ruby/concurrent/concern/logging.rb index 568a539eb..d1aae81ae 100644 --- a/lib/concurrent-ruby/concurrent/concern/logging.rb +++ b/lib/concurrent-ruby/concurrent/concern/logging.rb @@ -1,4 +1,3 @@ -require 'logger' require 'concurrent/atomic/atomic_reference' module Concurrent @@ -8,10 +7,12 @@ module Concern # # @!visibility private module Logging - include Logger::Severity + # The same as Logger::Severity but we copy it here to avoid a dependency on the logger gem just for these 7 constants + DEBUG, INFO, WARN, ERROR, FATAL, UNKNOWN = 0, 1, 2, 3, 4, 5 + SEV_LABEL = %w[DEBUG INFO WARN ERROR FATAL ANY].freeze # Logs through {Concurrent.global_logger}, it can be overridden by setting @logger - # @param [Integer] level one of Logger::Severity constants + # @param [Integer] level one of Concurrent::Concern::Logging constants # @param [String] progname e.g. a path of an Actor # @param [String, nil] message when nil block is used to generate the message # @yieldreturn [String] a message @@ -23,7 +24,7 @@ def log(level, progname, message = nil, &block) end logger.call level, progname, message, &block rescue => error - $stderr.puts "`Concurrent.configuration.logger` failed to log #{[level, progname, message, block]}\n" + + $stderr.puts "`Concurrent.global_logger` failed to log #{[level, progname, message, block]}\n" + "#{error.message} (#{error.class})\n#{error.backtrace.join "\n"}" end end @@ -33,8 +34,10 @@ def log(level, progname, message = nil, &block) module Concurrent extend Concern::Logging - # @return [Logger] Logger with provided level and output. - def self.create_simple_logger(level = Logger::FATAL, output = $stderr) + # Create a simple logger with provided level and output. + def self.create_simple_logger(level = :FATAL, output = $stderr) + level = Concern::Logging.const_get(level) unless level.is_a?(Integer) + # TODO (pitr-ch 24-Dec-2016): figure out why it had to be replaced, stdlogger was deadlocking lambda do |severity, progname, message = nil, &block| return false if severity < level @@ -52,7 +55,7 @@ def self.create_simple_logger(level = Logger::FATAL, output = $stderr) output.print format "[%s] %5s -- %s: %s\n", Time.now.strftime('%Y-%m-%d %H:%M:%S.%L'), - Logger::SEV_LABEL[severity], + Concern::Logging::SEV_LABEL[severity], progname, formatted_message true @@ -60,13 +63,15 @@ def self.create_simple_logger(level = Logger::FATAL, output = $stderr) end # Use logger created by #create_simple_logger to log concurrent-ruby messages. - def self.use_simple_logger(level = Logger::FATAL, output = $stderr) + def self.use_simple_logger(level = :FATAL, output = $stderr) Concurrent.global_logger = create_simple_logger level, output end - # @return [Logger] Logger with provided level and output. + # Create a stdlib logger with provided level and output. + # If you use this deprecated method you might need to add logger to your Gemfile to avoid warnings from Ruby 3.3.5+. # @deprecated - def self.create_stdlib_logger(level = Logger::FATAL, output = $stderr) + def self.create_stdlib_logger(level = :FATAL, output = $stderr) + require 'logger' logger = Logger.new(output) logger.level = level logger.formatter = lambda do |severity, datetime, progname, msg| @@ -93,7 +98,7 @@ def self.create_stdlib_logger(level = Logger::FATAL, output = $stderr) # Use logger created by #create_stdlib_logger to log concurrent-ruby messages. # @deprecated - def self.use_stdlib_logger(level = Logger::FATAL, output = $stderr) + def self.use_stdlib_logger(level = :FATAL, output = $stderr) Concurrent.global_logger = create_stdlib_logger level, output end @@ -103,7 +108,7 @@ def self.use_stdlib_logger(level = Logger::FATAL, output = $stderr) NULL_LOGGER = lambda { |level, progname, message = nil, &block| } # @!visibility private - GLOBAL_LOGGER = AtomicReference.new(create_simple_logger(Logger::WARN)) + GLOBAL_LOGGER = AtomicReference.new(create_simple_logger(:WARN)) private_constant :GLOBAL_LOGGER def self.global_logger diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index d191183f6..1f0048647 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -42,7 +42,7 @@ def requires=(paths) config.before :all do # Only configure logging if it has been required, to make sure the necessary require's are in place if Concurrent.respond_to? :use_simple_logger - Concurrent.use_simple_logger Logger::FATAL + Concurrent.use_simple_logger :FATAL end end From 56fd2406e7ed96b91445dc273878e6984b45a547 Mon Sep 17 00:00:00 2001 From: Frances McMullin Date: Wed, 16 Oct 2024 16:28:55 +0100 Subject: [PATCH 17/27] Avoid error when member is present on ancestor class Niche case - when clearing class members for new definition, avoid trying to remove members present on ancestor classes. --- .../concurrent/synchronization/abstract_struct.rb | 2 +- spec/concurrent/struct_shared.rb | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb b/lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb index 1fe90c164..28816c518 100644 --- a/lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb +++ b/lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb @@ -157,7 +157,7 @@ def ns_initialize(*values) end end members.each_with_index do |member, index| - clazz.send :remove_method, member if clazz.instance_methods.include? member + clazz.send :remove_method, member if clazz.instance_methods(false).include? member clazz.send(:define_method, member) do @values[index] end diff --git a/spec/concurrent/struct_shared.rb b/spec/concurrent/struct_shared.rb index ae812f223..6dd91870d 100644 --- a/spec/concurrent/struct_shared.rb +++ b/spec/concurrent/struct_shared.rb @@ -26,6 +26,18 @@ expect(clazz.ancestors).to include described_class end + it 'ignores methods on ancestor classes' do + ancestor = described_class.ancestors.first + ancestor.class_eval { def foo; end } + + clazz = described_class.new(:foo) + expect{ described_class.const_get(clazz.to_s) }.to raise_error(NameError) + expect(clazz).to be_a Class + expect(clazz.ancestors).to include described_class + + ancestor.send :remove_method, :foo + end + it 'raises an exception when given an invalid class name' do expect{ described_class.new('lowercase') }.to raise_error(NameError) expect{ described_class.new('_') }.to raise_error(NameError) From 56227a4c3ebdd53b8b0976eb8296ceb7a093496f Mon Sep 17 00:00:00 2001 From: Frances McMullin Date: Wed, 16 Oct 2024 21:08:21 +0100 Subject: [PATCH 18/27] Improve ancestor classes spec --- spec/concurrent/struct_shared.rb | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/spec/concurrent/struct_shared.rb b/spec/concurrent/struct_shared.rb index 6dd91870d..4c73a9e40 100644 --- a/spec/concurrent/struct_shared.rb +++ b/spec/concurrent/struct_shared.rb @@ -27,13 +27,15 @@ end it 'ignores methods on ancestor classes' do - ancestor = described_class.ancestors.first - ancestor.class_eval { def foo; end } + ancestor = described_class.ancestors.last + ancestor.class_eval { def foo(bar); end } clazz = described_class.new(:foo) - expect{ described_class.const_get(clazz.to_s) }.to raise_error(NameError) - expect(clazz).to be_a Class - expect(clazz.ancestors).to include described_class + struct = clazz.new + + expect(struct).to respond_to :foo + method = struct.method(:foo) + expect(method.arity).to eq 0 ancestor.send :remove_method, :foo end From 957cf7d09aae59db7026e607ca42768aad644ebc Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Mon, 25 Nov 2024 13:55:21 -0600 Subject: [PATCH 19/27] Set rake-compiler source and target to Java 8 (#1071) This patch forces rake-compiler to emit bytecode for Java 8 level of JVM. rake-compiler currently defaults to Java 1.7 source and target, but that version is no longer supported by recent JDKs such as Java 21 (see https://github.com/rake-compiler/rake-compiler/pull/242 for a patch to update rake-compiler). This patch sets our minimum Java level to 8, bypassing the default in rake-compiler and allowing builds on Java 21+. --- Rakefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Rakefile b/Rakefile index c52b5640e..3d157d475 100644 --- a/Rakefile +++ b/Rakefile @@ -12,6 +12,8 @@ ENV['JRUBY_HOME'] = ENV['CONCURRENT_JRUBY_HOME'] if ENV['CONCURRENT_JRUBY_HOME'] Rake::JavaExtensionTask.new('concurrent_ruby', core_gemspec) do |ext| ext.ext_dir = 'ext/concurrent-ruby' ext.lib_dir = 'lib/concurrent-ruby/concurrent' + ext.source_version = '8' + ext.target_version = '8' end if RUBY_ENGINE == 'ruby' From 5d700c5f6afc6984bdd606012282ce90e0498d45 Mon Sep 17 00:00:00 2001 From: Rui Chen Date: Sat, 28 Dec 2024 15:53:04 -0500 Subject: [PATCH 20/27] chore: fix typos (#1076) Signed-off-by: Rui Chen --- CHANGELOG.md | 4 ++-- docs-source/erlang_actor.in.md | 2 +- docs-source/erlang_actor.out.md | 2 +- examples/benchmark_atomic_1.rb | 2 +- examples/graph_atomic_bench.rb | 2 +- .../com/concurrent_ruby/ext/jsr166e/ConcurrentHashMapV8.java | 2 +- .../ext/jsr166e/nounsafe/ConcurrentHashMapV8.java | 2 +- .../concurrent/edge/lock_free_linked_set/node.rb | 2 +- .../concurrent/edge/old_channel_integration.rb | 2 +- lib/concurrent-ruby/concurrent/agent.rb | 4 ++-- lib/concurrent-ruby/concurrent/async.rb | 2 +- lib/concurrent-ruby/concurrent/atom.rb | 2 +- lib/concurrent-ruby/concurrent/delay.rb | 2 +- lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb | 2 +- .../concurrent/executor/single_thread_executor.rb | 2 +- lib/concurrent-ruby/concurrent/map.rb | 2 +- lib/concurrent-ruby/concurrent/promise.rb | 2 +- lib/concurrent-ruby/concurrent/scheduled_task.rb | 2 +- lib/concurrent-ruby/concurrent/synchronization/object.rb | 2 +- lib/concurrent-ruby/concurrent/thread_safe/util/adder.rb | 2 +- .../concurrent/thread_safe/util/xor_shift_random.rb | 2 +- spec/concurrent/actor_spec.rb | 2 +- spec/concurrent/async_spec.rb | 4 ++-- spec/concurrent/executor/safe_task_executor_spec.rb | 2 +- spec/concurrent/executor/thread_pool_executor_shared.rb | 2 +- spec/concurrent/processing_actor_spec.rb | 2 +- spec/concurrent/utility/processor_count_spec.rb | 4 ++-- 27 files changed, 31 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c0375c7d..e95cf22e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -296,7 +296,7 @@ concurrent-ruby-edge: * Simplification of `RubySingleThreadExecutor` * `Async` improvements - Each object uses its own `SingleThreadExecutor` instead of the global thread pool. - - No longers supports executor injection + - No longer supports executor injection - Much better documentation * `Atom` updates - No longer `Dereferenceable` @@ -471,7 +471,7 @@ Please see the [roadmap](https://github.com/ruby-concurrency/concurrent-ruby/iss * Fixed bug with return value of `Concurrent::Actor::Utils::Pool#ask` * Fixed timing bug in `TimerTask` * Fixed bug when creating a `JavaThreadPoolExecutor` with minimum pool size of zero -* Removed confusing warning when not using native extenstions +* Removed confusing warning when not using native extensions * Improved documentation ## Release v0.7.0 (13 August 2014) diff --git a/docs-source/erlang_actor.in.md b/docs-source/erlang_actor.in.md index d8f7a6da0..ed0b94e3c 100644 --- a/docs-source/erlang_actor.in.md +++ b/docs-source/erlang_actor.in.md @@ -254,7 +254,7 @@ The one exception from the original Erlang naming is exit. To avoid clashing with `Kernel#exit` it's called `terminate`. Until there is more information available here, the chapters listed below from -a book [lern you some Erlang](https://learnyousomeerlang.com) +a book [learn you some Erlang](https://learnyousomeerlang.com) are excellent source of information. The Ruby ErlangActor implementation has same behaviour. diff --git a/docs-source/erlang_actor.out.md b/docs-source/erlang_actor.out.md index f062557a4..f94d1492c 100644 --- a/docs-source/erlang_actor.out.md +++ b/docs-source/erlang_actor.out.md @@ -276,7 +276,7 @@ The one exception from the original Erlang naming is exit. To avoid clashing with `Kernel#exit` it's called `terminate`. Until there is more information available here, the chapters listed below from -a book [lern you some Erlang](https://learnyousomeerlang.com) +a book [learn you some Erlang](https://learnyousomeerlang.com) are excellent source of information. The Ruby ErlangActor implementation has same behaviour. diff --git a/examples/benchmark_atomic_1.rb b/examples/benchmark_atomic_1.rb index f3f09b08e..d9deedf1b 100755 --- a/examples/benchmark_atomic_1.rb +++ b/examples/benchmark_atomic_1.rb @@ -133,7 +133,7 @@ def para_prepare(&block) # NOTE: It seems to me that this measurement method # is sensible to how the system dispatches his resources. # -# More precise caluclation could be done using +# More precise calculation could be done using # getrusage's times ret = Benchmark.measure do $go = true diff --git a/examples/graph_atomic_bench.rb b/examples/graph_atomic_bench.rb index c50da1737..b124f3b35 100755 --- a/examples/graph_atomic_bench.rb +++ b/examples/graph_atomic_bench.rb @@ -47,7 +47,7 @@ end elsif conf[:vary] == "speed" # Varies the execution time of the update block - # by using long calulation (MD5) + # by using long calculation (MD5) # # NOTE: Thread.pass and sleep() are not usable by the atomic # lock. It needs to run the whole block without hitting diff --git a/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMapV8.java b/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMapV8.java index 86aa4eb06..dc9901fb7 100644 --- a/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMapV8.java +++ b/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMapV8.java @@ -481,7 +481,7 @@ public static interface Spliterator extends Iterator { * * Maintaining API and serialization compatibility with previous * versions of this class introduces several oddities. Mainly: We - * leave untouched but unused constructor arguments refering to + * leave untouched but unused constructor arguments referring to * concurrencyLevel. We accept a loadFactor constructor argument, * but apply it only to initial table capacity (which is the only * time that we can guarantee to honor it.) We also declare an diff --git a/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/ConcurrentHashMapV8.java b/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/ConcurrentHashMapV8.java index b7fc5a937..a4e73ea14 100644 --- a/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/ConcurrentHashMapV8.java +++ b/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/ConcurrentHashMapV8.java @@ -484,7 +484,7 @@ public static interface Spliterator extends Iterator { * * Maintaining API and serialization compatibility with previous * versions of this class introduces several oddities. Mainly: We - * leave untouched but unused constructor arguments refering to + * leave untouched but unused constructor arguments referring to * concurrencyLevel. We accept a loadFactor constructor argument, * but apply it only to initial table capacity (which is the only * time that we can guarantee to honor it.) We also declare an diff --git a/lib/concurrent-ruby-edge/concurrent/edge/lock_free_linked_set/node.rb b/lib/concurrent-ruby-edge/concurrent/edge/lock_free_linked_set/node.rb index d7fafa370..f3682bbfc 100644 --- a/lib/concurrent-ruby-edge/concurrent/edge/lock_free_linked_set/node.rb +++ b/lib/concurrent-ruby-edge/concurrent/edge/lock_free_linked_set/node.rb @@ -38,7 +38,7 @@ def next_node @SuccessorReference.value end - # This method provides a unqiue key for the data which will be used for + # This method provides a unique key for the data which will be used for # ordering. This is configurable, and changes depending on how you wish # the nodes to be ordered. def key_for(data) diff --git a/lib/concurrent-ruby-edge/concurrent/edge/old_channel_integration.rb b/lib/concurrent-ruby-edge/concurrent/edge/old_channel_integration.rb index efb003eff..a215ad80c 100644 --- a/lib/concurrent-ruby-edge/concurrent/edge/old_channel_integration.rb +++ b/lib/concurrent-ruby-edge/concurrent/edge/old_channel_integration.rb @@ -36,7 +36,7 @@ module OldChannelIntegration # @!visibility private - # Zips with selected value form the suplied channels + # Zips with selected value form the supplied channels # @return [Future] def then_select(*channels) future = Concurrent::Promises.select(*channels) diff --git a/lib/concurrent-ruby/concurrent/agent.rb b/lib/concurrent-ruby/concurrent/agent.rb index 2d32926ba..dc8a26000 100644 --- a/lib/concurrent-ruby/concurrent/agent.rb +++ b/lib/concurrent-ruby/concurrent/agent.rb @@ -371,7 +371,7 @@ def await_for(timeout) # @param [Float] timeout the maximum number of seconds to wait # @return [Boolean] true if all actions complete before timeout # - # @raise [Concurrent::TimeoutError] when timout is reached + # @raise [Concurrent::TimeoutError] when timeout is reached # # @!macro agent_await_warning def await_for!(timeout) @@ -477,7 +477,7 @@ def await_for(timeout, *agents) # @param [Array] agents the Agents on which to wait # @return [Boolean] true if all actions complete before timeout # - # @raise [Concurrent::TimeoutError] when timout is reached + # @raise [Concurrent::TimeoutError] when timeout is reached # @!macro agent_await_warning def await_for!(timeout, *agents) raise Concurrent::TimeoutError unless await_for(timeout, *agents) diff --git a/lib/concurrent-ruby/concurrent/async.rb b/lib/concurrent-ruby/concurrent/async.rb index f9f8adf00..97c5a6b2d 100644 --- a/lib/concurrent-ruby/concurrent/async.rb +++ b/lib/concurrent-ruby/concurrent/async.rb @@ -218,7 +218,7 @@ module Async # @!method self.new(*args, &block) # - # Instanciate a new object and ensure proper initialization of the + # Instantiate a new object and ensure proper initialization of the # synchronization mechanisms. # # @param [Array] args Zero or more arguments to be passed to the diff --git a/lib/concurrent-ruby/concurrent/atom.rb b/lib/concurrent-ruby/concurrent/atom.rb index 1074006d7..f590a23d9 100644 --- a/lib/concurrent-ruby/concurrent/atom.rb +++ b/lib/concurrent-ruby/concurrent/atom.rb @@ -113,7 +113,7 @@ class Atom < Synchronization::Object # @option opts [Proc] :validator (nil) Optional proc used to validate new # values. It must accept one and only one argument which will be the # intended new value. The validator will return true if the new value - # is acceptable else return false (preferrably) or raise an exception. + # is acceptable else return false (preferably) or raise an exception. # # @!macro deref_options # diff --git a/lib/concurrent-ruby/concurrent/delay.rb b/lib/concurrent-ruby/concurrent/delay.rb index 923773cbc..0d6d91a57 100644 --- a/lib/concurrent-ruby/concurrent/delay.rb +++ b/lib/concurrent-ruby/concurrent/delay.rb @@ -19,7 +19,7 @@ module Concurrent # # When a `Delay` is created its state is set to `pending`. The value and # reason are both `nil`. The first time the `#value` method is called the - # enclosed opration will be run and the calling thread will block. Other + # enclosed operation will be run and the calling thread will block. Other # threads attempting to call `#value` will block as well. Once the operation # is complete the *value* will be set to the result of the operation or the # *reason* will be set to the raised exception, as appropriate. All threads diff --git a/lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb b/lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb index 993c3f1e3..8324c0673 100644 --- a/lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb +++ b/lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb @@ -83,7 +83,7 @@ module Concurrent # # 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 + # this method explicitly in case your application post jobs in bursts (a # lot of jobs and then nothing for long periods) # @!macro thread_pool_executor_public_api diff --git a/lib/concurrent-ruby/concurrent/executor/single_thread_executor.rb b/lib/concurrent-ruby/concurrent/executor/single_thread_executor.rb index f1474ea9f..220eb0ff6 100644 --- a/lib/concurrent-ruby/concurrent/executor/single_thread_executor.rb +++ b/lib/concurrent-ruby/concurrent/executor/single_thread_executor.rb @@ -27,7 +27,7 @@ module Concurrent # is received. This pattern has several issues. The thread itself is highly # susceptible to errors during processing. Also, the thread itself must be # constantly monitored and restarted should it die. `SingleThreadExecutor` - # encapsulates all these bahaviors. The task processor is highly resilient + # encapsulates all these behaviors. The task processor is highly resilient # to errors from within tasks. Also, should the thread die it will # automatically be restarted. # diff --git a/lib/concurrent-ruby/concurrent/map.rb b/lib/concurrent-ruby/concurrent/map.rb index 601e36504..b263f83d8 100644 --- a/lib/concurrent-ruby/concurrent/map.rb +++ b/lib/concurrent-ruby/concurrent/map.rb @@ -148,7 +148,7 @@ def [](key) if value = super # non-falsy value is an existing mapping, return it right away value # re-check is done with get_or_default(key, NULL) instead of a simple !key?(key) in order to avoid a race condition, whereby by the time the current thread gets to the key?(key) call - # a key => value mapping might have already been created by a different thread (key?(key) would then return true, this elsif branch wouldn't be taken and an incorrent +nil+ value + # a key => value mapping might have already been created by a different thread (key?(key) would then return true, this elsif branch wouldn't be taken and an incorrect +nil+ value # would be returned) # note: nil == value check is not technically necessary elsif @default_proc && nil == value && NULL == (value = get_or_default(key, NULL)) diff --git a/lib/concurrent-ruby/concurrent/promise.rb b/lib/concurrent-ruby/concurrent/promise.rb index ccc47dd62..c717f9b0d 100644 --- a/lib/concurrent-ruby/concurrent/promise.rb +++ b/lib/concurrent-ruby/concurrent/promise.rb @@ -103,7 +103,7 @@ module Concurrent # - if parent is *rejected* the child will be *pending* (but will ultimately be *rejected*) # # Promises are executed asynchronously from the main thread. By the time a - # child Promise finishes intialization it may be in a different state than its + # child Promise finishes initialization it may be in a different state than its # parent (by the time a child is created its parent may have completed # execution and changed state). Despite being asynchronous, however, the order # of execution of Promise objects in a chain (or tree) is strictly defined. diff --git a/lib/concurrent-ruby/concurrent/scheduled_task.rb b/lib/concurrent-ruby/concurrent/scheduled_task.rb index 429fc0683..efe9e193a 100644 --- a/lib/concurrent-ruby/concurrent/scheduled_task.rb +++ b/lib/concurrent-ruby/concurrent/scheduled_task.rb @@ -193,7 +193,7 @@ def initialize(delay, opts = {}, &task) end end - # The `delay` value given at instanciation. + # The `delay` value given at instantiation. # # @return [Float] the initial delay. def initial_delay diff --git a/lib/concurrent-ruby/concurrent/synchronization/object.rb b/lib/concurrent-ruby/concurrent/synchronization/object.rb index e839c9f18..592190708 100644 --- a/lib/concurrent-ruby/concurrent/synchronization/object.rb +++ b/lib/concurrent-ruby/concurrent/synchronization/object.rb @@ -58,7 +58,7 @@ def self.new(*args, &block) # Creates methods for reading and writing to a instance variable with # volatile (Java) semantic as {.attr_volatile} does. - # The instance variable should be accessed oly through generated methods. + # The instance variable should be accessed only through generated methods. # This method generates following methods: `value`, `value=(new_value) #=> new_value`, # `swap_value(new_value) #=> old_value`, # `compare_and_set_value(expected, value) #=> true || false`, `update_value(&block)`. diff --git a/lib/concurrent-ruby/concurrent/thread_safe/util/adder.rb b/lib/concurrent-ruby/concurrent/thread_safe/util/adder.rb index 7a6e8d5c0..852b403b8 100644 --- a/lib/concurrent-ruby/concurrent/thread_safe/util/adder.rb +++ b/lib/concurrent-ruby/concurrent/thread_safe/util/adder.rb @@ -9,7 +9,7 @@ module ThreadSafe # @!visibility private module Util - # A Ruby port of the Doug Lea's jsr166e.LondAdder class version 1.8 + # A Ruby port of the Doug Lea's jsr166e.LongAdder class version 1.8 # available in public domain. # # Original source code available here: diff --git a/lib/concurrent-ruby/concurrent/thread_safe/util/xor_shift_random.rb b/lib/concurrent-ruby/concurrent/thread_safe/util/xor_shift_random.rb index bdde2dd8b..c231d182c 100644 --- a/lib/concurrent-ruby/concurrent/thread_safe/util/xor_shift_random.rb +++ b/lib/concurrent-ruby/concurrent/thread_safe/util/xor_shift_random.rb @@ -15,7 +15,7 @@ module Util # Usage: # x = XorShiftRandom.get # uses Kernel.rand to generate an initial seed # while true - # if (x = XorShiftRandom.xorshift).odd? # thread-localy generate a next random number + # if (x = XorShiftRandom.xorshift).odd? # thread-locally generate a next random number # do_something_at_random # end # end diff --git a/spec/concurrent/actor_spec.rb b/spec/concurrent/actor_spec.rb index 5bb639fed..9f1e53b7c 100644 --- a/spec/concurrent/actor_spec.rb +++ b/spec/concurrent/actor_spec.rb @@ -160,7 +160,7 @@ def on_message(message) end describe 'dead letter routing' do - it 'logs by deafault' do + it 'logs by default' do ping = Ping.spawn! :ping, [] ping << :terminate! ping << 'asd' diff --git a/spec/concurrent/async_spec.rb b/spec/concurrent/async_spec.rb index c0ebfe8e6..aae2642db 100644 --- a/spec/concurrent/async_spec.rb +++ b/spec/concurrent/async_spec.rb @@ -153,7 +153,7 @@ def many(*args, &block) nil; end }.to raise_error(ArgumentError) end - it 'raises an error when pasing too many arguments (arity >= 0)' do + it 'raises an error when passing too many arguments (arity >= 0)' do expect { subject.async.echo(1, 2, 3, 4, 5) }.to raise_error(StandardError) @@ -224,7 +224,7 @@ def many(*args, &block) nil; end }.to raise_error(ArgumentError) end - it 'raises an error when pasing too many arguments (arity >= 0)' do + it 'raises an error when passing too many arguments (arity >= 0)' do expect { subject.await.echo(1, 2, 3, 4, 5) }.to raise_error(StandardError) diff --git a/spec/concurrent/executor/safe_task_executor_spec.rb b/spec/concurrent/executor/safe_task_executor_spec.rb index 5b4edf6a4..2907109e9 100644 --- a/spec/concurrent/executor/safe_task_executor_spec.rb +++ b/spec/concurrent/executor/safe_task_executor_spec.rb @@ -33,7 +33,7 @@ module Concurrent expect(expected).to eq [1, 2, 3] end - it 'protectes #execute with a mutex' do + it 'protects #execute with a mutex' do expect(subject).to receive(:synchronize).with(no_args) subject.execute end diff --git a/spec/concurrent/executor/thread_pool_executor_shared.rb b/spec/concurrent/executor/thread_pool_executor_shared.rb index 1fbf8de6d..147e2c5ca 100644 --- a/spec/concurrent/executor/thread_pool_executor_shared.rb +++ b/spec/concurrent/executor/thread_pool_executor_shared.rb @@ -411,7 +411,7 @@ subject << proc { all_tasks_posted.wait; initial_executed.increment; } end - # Inject 20 more tasks, which should throw an exeption + # Inject 20 more tasks, which should throw an exception 20.times do expect { subject << proc { subsequent_executed.increment; } diff --git a/spec/concurrent/processing_actor_spec.rb b/spec/concurrent/processing_actor_spec.rb index 36e3ac0e8..4632eaed8 100644 --- a/spec/concurrent/processing_actor_spec.rb +++ b/spec/concurrent/processing_actor_spec.rb @@ -29,7 +29,7 @@ def count(actor, count) # continue running count(actor, count) when Integer - # this will call count again to set up what to do on next message, based on new state `count + numer` + # this will call count again to set up what to do on next message, based on new state `count + number` count(actor, count + number_or_command) end end diff --git a/spec/concurrent/utility/processor_count_spec.rb b/spec/concurrent/utility/processor_count_spec.rb index 8de31e027..34d133f70 100644 --- a/spec/concurrent/utility/processor_count_spec.rb +++ b/spec/concurrent/utility/processor_count_spec.rb @@ -4,7 +4,7 @@ module Concurrent RSpec.describe '#processor_count' do - it 'retuns a positive integer' do + it 'returns a positive integer' do expect(Concurrent::processor_count).to be_a Integer expect(Concurrent::processor_count).to be >= 1 end @@ -12,7 +12,7 @@ module Concurrent RSpec.describe '#physical_processor_count' do - it 'retuns a positive integer' do + it 'returns a positive integer' do expect(Concurrent::physical_processor_count).to be_a Integer expect(Concurrent::physical_processor_count).to be >= 1 end From 33abefb6823a07699f4b8665abba9297ef5d2ccd Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Wed, 15 Jan 2025 22:08:02 +0100 Subject: [PATCH 21/27] Release concurrent-ruby 1.3.5 and concurrent-ruby-edge 0.7.2 --- CHANGELOG.md | 10 ++++++++++ docs-source/signpost.md | 2 +- lib/concurrent-ruby-edge/concurrent/edge/version.rb | 2 +- lib/concurrent-ruby/concurrent/version.rb | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e95cf22e8..30810b724 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ ## Current +## Release v1.3.5, edge v0.7.2 (15 January 2025) + +concurrent-ruby: + +* (#1062) Remove dependency on logger. + +concurrent-ruby-edge: + +* (#1062) Remove dependency on logger. + ## Release v1.3.4 (10 August 2024) * (#1060) Fix bug with return value of `Concurrent.available_processor_count` when `cpu.cfs_quota_us` is -1. diff --git a/docs-source/signpost.md b/docs-source/signpost.md index e48a56a16..7b52f16ac 100644 --- a/docs-source/signpost.md +++ b/docs-source/signpost.md @@ -3,7 +3,7 @@ Pick a `concurrent-ruby` version: * [master](./master/index.html) -* [1.3.4 with edge 0.7.1](./1.3.4/index.html) +* [1.3.5 with edge 0.7.2](./1.3.5/index.html) * [1.1.10 with edge 0.6.0](./1.1.10/index.html) * [1.1.9 with edge 0.6.0](./1.1.9/index.html) * [1.1.8 with edge 0.6.0](./1.1.8/index.html) diff --git a/lib/concurrent-ruby-edge/concurrent/edge/version.rb b/lib/concurrent-ruby-edge/concurrent/edge/version.rb index 26ae15ef6..e3dd82c4a 100644 --- a/lib/concurrent-ruby-edge/concurrent/edge/version.rb +++ b/lib/concurrent-ruby-edge/concurrent/edge/version.rb @@ -1,3 +1,3 @@ module Concurrent - EDGE_VERSION = '0.7.1' + EDGE_VERSION = '0.7.2' end diff --git a/lib/concurrent-ruby/concurrent/version.rb b/lib/concurrent-ruby/concurrent/version.rb index 1b0c4c22f..f773e44f1 100644 --- a/lib/concurrent-ruby/concurrent/version.rb +++ b/lib/concurrent-ruby/concurrent/version.rb @@ -1,3 +1,3 @@ module Concurrent - VERSION = '1.3.4' + VERSION = '1.3.5' end From dbfbc14097c16df30485bb295afe60c9b0282887 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Wed, 15 Jan 2025 22:39:01 +0100 Subject: [PATCH 22/27] Document Bundler workaround for releasing --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 63ee743c5..1ba61857c 100644 --- a/README.md +++ b/README.md @@ -358,7 +358,8 @@ best practice is to depend on `concurrent-ruby` and let users to decide if they * Recent CRuby * JRuby, `rbenv install jruby-9.2.17.0` * Set env variable `CONCURRENT_JRUBY_HOME` to point to it, e.g. `/usr/local/opt/rbenv/versions/jruby-9.2.17.0` -* Install Docker, required for Windows builds +* Install Docker or Podman, required for Windows builds +* If `bundle config get path` is set, use `bundle config set --local path.system true` otherwise the `gem name, path: '.'` gems won't be found (Bundler limitation). ### Publishing the Gem From 855a6dc19990bffab3406807928bb8a35ca1f7fe Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Mon, 27 Jan 2025 21:16:07 +0100 Subject: [PATCH 23/27] Fix guards in specs using C extension classes * Fixes https://github.com/ruby-concurrency/concurrent-ruby/issues/1080 --- spec/concurrent/atomic/atomic_boolean_spec.rb | 4 ++-- spec/concurrent/atomic/atomic_fixnum_spec.rb | 4 ++-- spec/concurrent/atomic/atomic_reference_spec.rb | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/spec/concurrent/atomic/atomic_boolean_spec.rb b/spec/concurrent/atomic/atomic_boolean_spec.rb index 133b7f2ce..76edd3e27 100644 --- a/spec/concurrent/atomic/atomic_boolean_spec.rb +++ b/spec/concurrent/atomic/atomic_boolean_spec.rb @@ -142,7 +142,7 @@ module Concurrent end end - if Concurrent.allow_c_extensions? + if Concurrent.c_extensions_loaded? RSpec.describe CAtomicBoolean do it_should_behave_like :atomic_boolean end @@ -165,7 +165,7 @@ module Concurrent it 'inherits from JavaAtomicBoolean' do expect(AtomicBoolean.ancestors).to include(JavaAtomicBoolean) end - elsif Concurrent.allow_c_extensions? + elsif Concurrent.c_extensions_loaded? it 'inherits from CAtomicBoolean' do expect(AtomicBoolean.ancestors).to include(CAtomicBoolean) end diff --git a/spec/concurrent/atomic/atomic_fixnum_spec.rb b/spec/concurrent/atomic/atomic_fixnum_spec.rb index 39259b13f..8222bf523 100644 --- a/spec/concurrent/atomic/atomic_fixnum_spec.rb +++ b/spec/concurrent/atomic/atomic_fixnum_spec.rb @@ -204,7 +204,7 @@ module Concurrent end end - if Concurrent.allow_c_extensions? + if Concurrent.c_extensions_loaded? RSpec.describe CAtomicFixnum do it_should_behave_like :atomic_fixnum end @@ -227,7 +227,7 @@ module Concurrent it 'inherits from JavaAtomicFixnum' do expect(AtomicFixnum.ancestors).to include(JavaAtomicFixnum) end - elsif Concurrent.allow_c_extensions? + elsif Concurrent.c_extensions_loaded? it 'inherits from CAtomicFixnum' do expect(AtomicFixnum.ancestors).to include(CAtomicFixnum) end diff --git a/spec/concurrent/atomic/atomic_reference_spec.rb b/spec/concurrent/atomic/atomic_reference_spec.rb index 2cc0caada..7eaf2e55e 100644 --- a/spec/concurrent/atomic/atomic_reference_spec.rb +++ b/spec/concurrent/atomic/atomic_reference_spec.rb @@ -163,7 +163,7 @@ module Concurrent it_should_behave_like :atomic_reference end - if Concurrent.allow_c_extensions? + if Concurrent.c_extensions_loaded? RSpec.describe CAtomicReference do it_should_behave_like :atomic_reference end @@ -190,7 +190,7 @@ module Concurrent it 'inherits from JavaAtomicReference' do expect(described_class.ancestors).to include(Concurrent::JavaAtomicReference) end - elsif Concurrent.allow_c_extensions? + elsif Concurrent.c_extensions_loaded? it 'inherits from CAtomicReference' do expect(described_class.ancestors).to include(Concurrent::CAtomicReference) end From 870abda1d4cff41cf2a269ad4f3d44e4d9dd1421 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Tue, 28 Jan 2025 10:27:41 +0100 Subject: [PATCH 24/27] Run tests without the C extension in CI --- .github/workflows/ci.yml | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ab1d23db8..07b5e6583 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,6 +6,7 @@ concurrency: jobs: build: + name: "Tests: Ruby ${{ matrix.ruby }} - ${{ matrix.os }}" runs-on: ${{ matrix.os }}-latest timeout-minutes: 10 @@ -23,7 +24,6 @@ jobs: RUBYOPT: '-w' JRUBY_OPTS: '--dev' - name: "Tests: Ruby ${{ matrix.ruby }} - ${{ matrix.os }}" steps: - name: Clone Repo uses: actions/checkout@v4 @@ -35,6 +35,21 @@ jobs: - name: Run tests run: bundle exec rake ci + no-extensions: + name: "Test without C extension" + runs-on: ubuntu-latest + timeout-minutes: 10 + env: + RUBYOPT: '-w' + steps: + - uses: actions/checkout@v4 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: ruby + bundler-cache: true + - name: Run tests + run: bundle exec rake spec:ci + isolated: name: "Test isolated" runs-on: ubuntu-latest From 6e2bd8a25878de59e5faedfb9632d4c5d76d7e7c Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Tue, 28 Jan 2025 10:33:06 +0100 Subject: [PATCH 25/27] Add 3.4 in CI --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 07b5e6583..093571fa6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,10 +13,10 @@ jobs: strategy: fail-fast: false matrix: - ruby: [2.3, 2.4, 2.5, 2.6, 2.7, '3.0', 3.1, 3.2, 3.3, jruby, truffleruby] + ruby: [2.3, 2.4, 2.5, 2.6, 2.7, '3.0', 3.1, 3.2, 3.3, 3.4, jruby, truffleruby] os: [ubuntu] include: - - ruby: 3.3 + - ruby: ruby os: windows env: From 2aa6f645ee25e9692ab655903139bcf7d57dd545 Mon Sep 17 00:00:00 2001 From: Daniel Diekmeier Date: Tue, 18 Feb 2025 18:20:31 +0100 Subject: [PATCH 26/27] Fix typo --- lib/concurrent-ruby/concurrent/promise.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/concurrent-ruby/concurrent/promise.rb b/lib/concurrent-ruby/concurrent/promise.rb index c717f9b0d..8df80b0c7 100644 --- a/lib/concurrent-ruby/concurrent/promise.rb +++ b/lib/concurrent-ruby/concurrent/promise.rb @@ -167,7 +167,7 @@ module Concurrent # c2 = p.then(-> reason { raise 'Boom!' }) # # c1.wait.state #=> :fulfilled - # c1.value #=> 45 + # c1.value #=> 42 # c2.wait.state #=> :rejected # c2.reason #=> # # ``` From c8f0bae98f1233dde681441b85dbc29a869267bd Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Sat, 22 Mar 2025 15:58:57 -0500 Subject: [PATCH 27/27] Correct word in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1ba61857c..6635e815a 100644 --- a/README.md +++ b/README.md @@ -207,7 +207,7 @@ Deprecated features are still available and bugs are being fixed, but new featur These are available in the `concurrent-ruby-edge` companion gem. These features are under active development and may change frequently. They are expected not to -keep backward compatibility (there may also lack tests and documentation). Semantic versions will +keep backward compatibility (they may also lack tests and documentation). Semantic versions will be obeyed though. Features developed in `concurrent-ruby-edge` are expected to move to `concurrent-ruby` when final.