diff --git a/Library/Homebrew/Gemfile b/Library/Homebrew/Gemfile index 03ca1d6111508..7849b80fc3fd5 100644 --- a/Library/Homebrew/Gemfile +++ b/Library/Homebrew/Gemfile @@ -78,6 +78,7 @@ end # vendored gems (no group) gem "addressable" +gem "concurrent-ruby" gem "patchelf" gem "plist" gem "ruby-macho" diff --git a/Library/Homebrew/Gemfile.lock b/Library/Homebrew/Gemfile.lock index 18b131f10ffdc..2154f3af2a585 100644 --- a/Library/Homebrew/Gemfile.lock +++ b/Library/Homebrew/Gemfile.lock @@ -9,6 +9,7 @@ GEM coderay (1.1.3) commander (5.0.0) highline (~> 3.0.0) + concurrent-ruby (1.3.4) diff-lcs (1.5.1) docile (1.4.1) elftools (1.3.1) @@ -161,6 +162,7 @@ PLATFORMS DEPENDENCIES addressable + concurrent-ruby json_schemer kramdown method_source diff --git a/Library/Homebrew/api/download.rb b/Library/Homebrew/api/download.rb index a13bfe73ca23b..e848daf328481 100644 --- a/Library/Homebrew/api/download.rb +++ b/Library/Homebrew/api/download.rb @@ -12,7 +12,9 @@ def symlink_location end end - class Download < Downloadable + class Download + include Downloadable + sig { params( url: String, @@ -29,6 +31,21 @@ def initialize(url, checksum, mirrors: [], cache: nil) @cache = cache end + sig { override.returns(API::DownloadStrategy) } + def downloader + T.cast(super, API::DownloadStrategy) + end + + sig { override.returns(String) } + def name + download_name + end + + sig { override.returns(String) } + def download_type + "API source" + end + sig { override.returns(Pathname) } def cache @cache || super @@ -36,7 +53,7 @@ def cache sig { returns(Pathname) } def symlink_location - T.cast(downloader, API::DownloadStrategy).symlink_location + downloader.symlink_location end end end diff --git a/Library/Homebrew/cask/download.rb b/Library/Homebrew/cask/download.rb index 075396a47e75c..eb1d9a7087139 100644 --- a/Library/Homebrew/cask/download.rb +++ b/Library/Homebrew/cask/download.rb @@ -8,7 +8,9 @@ module Cask # A download corresponding to a {Cask}. - class Download < ::Downloadable + class Download + include Downloadable + include Context attr_reader :cask @@ -20,6 +22,11 @@ def initialize(cask, quarantine: nil) @quarantine = quarantine end + sig { override.returns(String) } + def name + cask.token + end + sig { override.returns(T.nilable(::URL)) } def url return if cask.url.nil? @@ -88,6 +95,11 @@ def download_name cask.token end + sig { override.returns(String) } + def download_type + "cask" + end + private def quarantine(path) diff --git a/Library/Homebrew/cmd/fetch.rb b/Library/Homebrew/cmd/fetch.rb index 96eca371d3cbd..6bd826c48d25e 100644 --- a/Library/Homebrew/cmd/fetch.rb +++ b/Library/Homebrew/cmd/fetch.rb @@ -5,6 +5,7 @@ require "formula" require "fetch" require "cask/download" +require "retryable_download" module Homebrew module Cmd @@ -25,6 +26,7 @@ class FetchCmd < AbstractCommand "(Pass `all` to download for all architectures.)" flag "--bottle-tag=", description: "Download a bottle for given tag." + flag "--concurrency=", description: "Number of concurrent downloads.", hidden: true switch "--HEAD", description: "Fetch HEAD version instead of stable version." switch "-f", "--force", @@ -67,6 +69,49 @@ class FetchCmd < AbstractCommand named_args [:formula, :cask], min: 1 end + def concurrency + @concurrency ||= args.concurrency&.to_i || 1 + end + + def download_queue + @download_queue ||= begin + require "download_queue" + DownloadQueue.new(concurrency) + end + end + + class Spinner + FRAMES = [ + "⠋", + "⠙", + "⠚", + "⠞", + "⠖", + "⠦", + "⠴", + "⠲", + "⠳", + "⠓", + ].freeze + + sig { void } + def initialize + @start = Time.now + @i = 0 + end + + sig { returns(String) } + def to_s + now = Time.now + if @start + 0.1 < now + @start = now + @i = (@i + 1) % FRAMES.count + end + + FRAMES.fetch(@i) + end + end + sig { override.void } def run Formulary.enable_factory_cache! @@ -125,13 +170,10 @@ def run next end - begin - bottle.fetch_tab - rescue DownloadError - retry if retry_fetch?(bottle) - raise + if (manifest_resource = bottle.github_packages_manifest_resource) + fetch_downloadable(manifest_resource) end - fetch_formula(bottle) + fetch_downloadable(bottle) rescue Interrupt raise rescue => e @@ -147,14 +189,14 @@ def run next if fetched_bottle - fetch_formula(formula) + fetch_downloadable(formula.resource) formula.resources.each do |r| - fetch_resource(r) - r.patches.each { |p| fetch_patch(p) if p.external? } + fetch_downloadable(r) + r.patches.each { |patch| fetch_downloadable(patch.resource) if patch.external? } end - formula.patchlist.each { |p| fetch_patch(p) if p.external? } + formula.patchlist.each { |patch| fetch_downloadable(patch.resource) if patch.external? } end end else @@ -176,81 +218,119 @@ def run quarantine = true if quarantine.nil? download = Cask::Download.new(cask, quarantine:) - fetch_cask(download) + fetch_downloadable(download) end end end end - end - private + if concurrency == 1 + downloads.each do |downloadable, promise| + promise.wait! + rescue ChecksumMismatchError => e + opoo "#{downloadable.download_type.capitalize} reports different checksum: #{e.expected}" + Homebrew.failed = true if downloadable.is_a?(Resource::Patch) + end + else + spinner = Spinner.new + remaining_downloads = downloads.dup + previous_pending_line_count = 0 + + begin + $stdout.print Tty.hide_cursor + $stdout.flush + + output_message = lambda do |downloadable, future| + status = case future.state + when :fulfilled + "#{Tty.green}✔︎#{Tty.reset}" + when :rejected + "#{Tty.red}✘#{Tty.reset}" + when :pending, :processing + "#{Tty.blue}#{spinner}#{Tty.reset}" + else + raise future.state.to_s + end - def fetch_resource(resource) - puts "Resource: #{resource.name}" - fetch_fetchable resource - rescue ChecksumMismatchError => e - retry if retry_fetch?(resource) - opoo "Resource #{resource.name} reports different sha256: #{e.expected}" - end + message = "#{downloadable.download_type.capitalize} #{downloadable.name}" + $stdout.puts "#{status} #{message}" + $stdout.flush - def fetch_formula(formula) - fetch_fetchable(formula) - rescue ChecksumMismatchError => e - retry if retry_fetch?(formula) - opoo "Formula reports different sha256: #{e.expected}" - end + if future.rejected? && (e = future.reason).is_a?(ChecksumMismatchError) + opoo "#{downloadable.download_type.capitalize} reports different checksum: #{e.expected}" + Homebrew.failed = true if downloadable.is_a?(Resource::Patch) + next 2 + end - def fetch_cask(cask_download) - fetch_fetchable(cask_download) - rescue ChecksumMismatchError => e - retry if retry_fetch?(cask_download) - opoo "Cask reports different sha256: #{e.expected}" - end + 1 + end - def fetch_patch(patch) - fetch_fetchable(patch) - rescue ChecksumMismatchError => e - opoo "Patch reports different sha256: #{e.expected}" - Homebrew.failed = true - end + until remaining_downloads.empty? + begin + finished_states = [:fulfilled, :rejected] - def retry_fetch?(formula) - @fetch_tries ||= Hash.new { |h, k| h[k] = 1 } - if args.retry? && (@fetch_tries[formula] < FETCH_MAX_TRIES) - wait = 2 ** @fetch_tries[formula] - remaining = FETCH_MAX_TRIES - @fetch_tries[formula] - what = Utils.pluralize("tr", remaining, plural: "ies", singular: "y") + finished_downloads, remaining_downloads = remaining_downloads.partition do |_, future| + finished_states.include?(future.state) + end - ohai "Retrying download in #{wait}s... (#{remaining} #{what} left)" - sleep wait + finished_downloads.each do |downloadable, future| + previous_pending_line_count -= 1 + $stdout.print Tty.clear_to_end + $stdout.flush + output_message.call(downloadable, future) + end - formula.clear_cache - @fetch_tries[formula] += 1 - true - else - Homebrew.failed = true - false - end - end + previous_pending_line_count = 0 + remaining_downloads.each do |downloadable, future| + # FIXME: Allow printing full terminal height. + break if previous_pending_line_count >= [concurrency, (Tty.height - 1)].min - def fetch_fetchable(formula) - formula.clear_cache if args.force? + $stdout.print Tty.clear_to_end + $stdout.flush + previous_pending_line_count += output_message.call(downloadable, future) + end - already_fetched = formula.cached_download.exist? + if previous_pending_line_count.positive? + $stdout.print Tty.move_cursor_up_beginning(previous_pending_line_count) + $stdout.flush + end + + sleep 0.05 + rescue Interrupt + remaining_downloads.each do |_, future| + # FIXME: Implement cancellation of running downloads. + end - begin - download = formula.fetch(verify_download_integrity: false) - rescue DownloadError - retry if retry_fetch?(formula) - raise + download_queue.cancel + + if previous_pending_line_count.positive? + $stdout.print Tty.move_cursor_down(previous_pending_line_count - 1) + $stdout.flush + end + + raise + end + end + ensure + $stdout.print Tty.show_cursor + $stdout.flush + end end + ensure + download_queue.shutdown + end - return unless download.file? + private - puts "Downloaded to: #{download}" unless already_fetched - puts "SHA256: #{download.sha256}" + def downloads + @downloads ||= {} + end - formula.verify_download_integrity(download) + def fetch_downloadable(downloadable) + downloads[downloadable] ||= begin + tries = args.retry? ? {} : { tries: 1 } + download_queue.enqueue(RetryableDownload.new(downloadable, **tries), force: args.force?) + end end end end diff --git a/Library/Homebrew/cmd/install.rb b/Library/Homebrew/cmd/install.rb index 8a7c0fc80d6ed..fe9ac9869e7ad 100644 --- a/Library/Homebrew/cmd/install.rb +++ b/Library/Homebrew/cmd/install.rb @@ -207,7 +207,6 @@ def run end if casks.any? - if args.dry_run? if (casks_to_install = casks.reject(&:installed?).presence) ohai "Would install #{::Utils.pluralize("cask", casks_to_install.count, include_count: true)}:" diff --git a/Library/Homebrew/download_queue.rb b/Library/Homebrew/download_queue.rb new file mode 100644 index 0000000000000..e591c3f2ae5e5 --- /dev/null +++ b/Library/Homebrew/download_queue.rb @@ -0,0 +1,45 @@ +# typed: true # rubocop:todo Sorbet/StrictSigil +# frozen_string_literal: true + +require "downloadable" +require "concurrent/promises" +require "concurrent/executors" + +module Homebrew + class DownloadQueue + sig { returns(Concurrent::FixedThreadPool) } + attr_reader :pool + private :pool + + sig { params(size: Integer).void } + def initialize(size = 1) + @pool = Concurrent::FixedThreadPool.new(size) + end + + sig { params(downloadable: Downloadable, force: T::Boolean).returns(Concurrent::Promises::Future) } + def enqueue(downloadable, force: false) + quiet = pool.max_length > 1 + # Passing in arguments from outside into the future is a common `concurrent-ruby` pattern. + # rubocop:disable Lint/ShadowingOuterLocalVariable + Concurrent::Promises.future_on(pool, downloadable, force, quiet) do |downloadable, force, quiet| + downloadable.clear_cache if force + downloadable.fetch(quiet:) + end + # rubocop:enable Lint/ShadowingOuterLocalVariable + end + + sig { void } + def cancel + # FIXME: Implement graceful cancellaction of running downloads based on + # https://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Cancellation.html + # instead of killing the whole thread pool. + pool.kill + end + + sig { void } + def shutdown + pool.shutdown + pool.wait_for_termination + end + end +end diff --git a/Library/Homebrew/download_strategy.rb b/Library/Homebrew/download_strategy.rb index 39b81a10739a2..9a895611b8d3c 100644 --- a/Library/Homebrew/download_strategy.rb +++ b/Library/Homebrew/download_strategy.rb @@ -716,6 +716,10 @@ def initialize(path) # rubocop:disable Lint/MissingSuper @cached_location = path extend Pourable end + + def clear_cache + # Path is used directly and not cached. + end end # Strategy for downloading a Subversion repository. diff --git a/Library/Homebrew/downloadable.rb b/Library/Homebrew/downloadable.rb index 9a82d99f4ee5d..a39d5d7b48e8c 100644 --- a/Library/Homebrew/downloadable.rb +++ b/Library/Homebrew/downloadable.rb @@ -5,19 +5,19 @@ require "checksum" require "download_strategy" -class Downloadable +module Downloadable include Context extend T::Helpers abstract! - sig { returns(T.nilable(URL)) } + sig { overridable.returns(T.nilable(URL)) } attr_reader :url - sig { returns(T.nilable(Checksum)) } + sig { overridable.returns(T.nilable(Checksum)) } attr_reader :checksum - sig { returns(T::Array[String]) } + sig { overridable.returns(T::Array[String]) } attr_reader :mirrors sig { void } @@ -32,7 +32,7 @@ def initialize_dup(other) @version = @version.dup end - sig { override.returns(T.self_type) } + sig { overridable.returns(T.self_type) } def freeze @checksum.freeze @mirrors.freeze @@ -40,22 +40,30 @@ def freeze super end - sig { returns(T::Boolean) } + sig { abstract.returns(String) } + def name; end + + sig { returns(String) } + def download_type + T.must(self.class.name&.split("::")&.last).gsub(/([[:lower:]])([[:upper:]])/, '\1 \2').downcase + end + + sig(:final) { returns(T::Boolean) } def downloaded? cached_download.exist? end - sig { returns(Pathname) } + sig { overridable.returns(Pathname) } def cached_download downloader.cached_location end - sig { void } + sig { overridable.void } def clear_cache downloader.clear_cache end - sig { returns(T.nilable(Version)) } + sig { overridable.returns(T.nilable(Version)) } def version return @version if @version && !@version.null? @@ -63,27 +71,34 @@ def version version unless version&.null? end - sig { returns(T.class_of(AbstractDownloadStrategy)) } + sig { overridable.returns(T.class_of(AbstractDownloadStrategy)) } def download_strategy @download_strategy ||= determine_url&.download_strategy end - sig { returns(AbstractDownloadStrategy) } + sig { overridable.returns(AbstractDownloadStrategy) } def downloader @downloader ||= begin primary_url, *mirrors = determine_url_mirrors - raise ArgumentError, "attempted to use a Downloadable without a URL!" if primary_url.blank? + raise ArgumentError, "attempted to use a `Downloadable` without a URL!" if primary_url.blank? download_strategy.new(primary_url, download_name, version, mirrors:, cache:, **T.must(@url).specs) end end - sig { params(verify_download_integrity: T::Boolean, timeout: T.nilable(T.any(Integer, Float))).returns(Pathname) } - def fetch(verify_download_integrity: true, timeout: nil) + sig { + overridable.params( + verify_download_integrity: T::Boolean, + timeout: T.nilable(T.any(Integer, Float)), + quiet: T::Boolean, + ).returns(Pathname) + } + def fetch(verify_download_integrity: true, timeout: nil, quiet: false) cache.mkpath begin + downloader.quiet! if quiet downloader.fetch(timeout:) rescue ErrorDuringExecution, CurlDownloadStrategyError => e raise DownloadError.new(self, e) @@ -94,7 +109,7 @@ def fetch(verify_download_integrity: true, timeout: nil) download end - sig { params(filename: Pathname).void } + sig { overridable.params(filename: Pathname).void } def verify_download_integrity(filename) if filename.file? ohai "Verifying checksum for '#{filename.basename}'" if verbose? @@ -111,7 +126,7 @@ def verify_download_integrity(filename) sig { overridable.returns(String) } def download_name - File.basename(determine_url.to_s) + @download_name ||= File.basename(determine_url.to_s) end private diff --git a/Library/Homebrew/downloadable.rbi b/Library/Homebrew/downloadable.rbi new file mode 100644 index 0000000000000..2b50bad57667c --- /dev/null +++ b/Library/Homebrew/downloadable.rbi @@ -0,0 +1,5 @@ +# typed: strict + +module Downloadable + requires_ancestor { Kernel } +end diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index 75e1a2a06612d..b0cd72fcfb902 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -567,7 +567,13 @@ def synced_with_other_formulae? params(name: String, klass: T.class_of(Resource), block: T.nilable(T.proc.bind(Resource).void)) .returns(T.nilable(Resource)) } - def resource(name, klass = Resource, &block) = active_spec.resource(name, klass, &block) + def resource(name = T.unsafe(nil), klass = T.unsafe(nil), &block) + if klass.nil? + active_spec.resource(*name, &block) + else + active_spec.resource(name, klass, &block) + end + end # Old names for the formula. # @@ -2765,11 +2771,20 @@ def on_system_blocks_exist? self.class.on_system_blocks_exist? || @on_system_blocks_exist end - def fetch(verify_download_integrity: true) - active_spec.fetch(verify_download_integrity:) + sig { + params( + verify_download_integrity: T::Boolean, + timeout: T.nilable(T.any(Integer, Float)), + quiet: T::Boolean, + ).returns(Pathname) + } + def fetch(verify_download_integrity: true, timeout: nil, quiet: false) + # odeprecated "Formula#fetch", "Resource#fetch on Formula#resource" + active_spec.fetch(verify_download_integrity:, timeout:, quiet:) end def verify_download_integrity(filename) + # odeprecated "Formula#verify_download_integrity", "Resource#verify_download_integrity on Formula#resource" active_spec.verify_download_integrity(filename) end diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb index eeaaf127d74f8..50e15f4715ae8 100644 --- a/Library/Homebrew/formula_installer.rb +++ b/Library/Homebrew/formula_installer.rb @@ -1254,18 +1254,18 @@ def fetch formula.fetch_patches formula.resources.each(&:fetch) end - downloader.fetch + downloadable.downloader.fetch self.class.fetched << formula end - def downloader + def downloadable if (bottle_path = formula.local_bottle_path) - LocalBottleDownloadStrategy.new(bottle_path) + Resource::Local.new(bottle_path) elsif pour_bottle? formula.bottle else - formula + formula.resource end end @@ -1324,7 +1324,7 @@ def pour end HOMEBREW_CELLAR.cd do - downloader.stage + downloadable.downloader.stage end Tab.clear_cache diff --git a/Library/Homebrew/patch.rb b/Library/Homebrew/patch.rb index 6aacc0254b0cf..39e67b1d24031 100644 --- a/Library/Homebrew/patch.rb +++ b/Library/Homebrew/patch.rb @@ -106,7 +106,7 @@ class ExternalPatch def initialize(strip, &block) @strip = strip - @resource = Resource::PatchResource.new(&block) + @resource = Resource::Patch.new(&block) end sig { returns(T::Boolean) } diff --git a/Library/Homebrew/resource.rb b/Library/Homebrew/resource.rb index 61ce2eb408af1..d663ec3bab4b3 100644 --- a/Library/Homebrew/resource.rb +++ b/Library/Homebrew/resource.rb @@ -9,7 +9,8 @@ # Resource is the fundamental representation of an external resource. The # primary formula download, along with other declared resources, are instances # of this class. -class Resource < Downloadable +class Resource + include Downloadable include FileUtils include OnSystem::MacOSAndLinux @@ -140,7 +141,15 @@ def files(*files) Partial.new(self, files) end - def fetch(verify_download_integrity: true) + sig { + override + .params( + verify_download_integrity: T::Boolean, + timeout: T.nilable(T.any(Integer, Float)), + quiet: T::Boolean, + ).returns(Pathname) + } + def fetch(verify_download_integrity: true, timeout: nil, quiet: false) fetch_patches super @@ -194,7 +203,7 @@ def url(val = nil, **specs) @download_strategy = @url.download_strategy end - sig { params(val: T.nilable(T.any(String, Version))).returns(T.nilable(Version)) } + sig { override.params(val: T.nilable(T.any(String, Version))).returns(T.nilable(Version)) } def version(val = nil) return super() if val.nil? @@ -211,7 +220,7 @@ def mirror(val) end def patch(strip = :p1, src = nil, &block) - p = Patch.create(strip, src, &block) + p = ::Patch.create(strip, src, &block) patches << p end @@ -260,6 +269,27 @@ def determine_url_mirrors [*extra_urls, *super].uniq end + # A local resource that doesn't need to be downloaded. + class Local < Resource + def initialize(path) + super(File.basename(path)) + @downloader = LocalBottleDownloadStrategy.new(path) + end + end + + # A resource for a formula. + class Formula < Resource + sig { override.returns(String) } + def name + T.must(owner).name + end + + sig { override.returns(String) } + def download_name + name + end + end + # A resource containing a Go package. class Go < Resource def stage(target, &block) @@ -320,7 +350,7 @@ def tab end # A resource containing a patch. - class PatchResource < Resource + class Patch < Resource attr_reader :patch_files def initialize(&block) diff --git a/Library/Homebrew/retryable_download.rb b/Library/Homebrew/retryable_download.rb new file mode 100644 index 0000000000000..0f647b88358d3 --- /dev/null +++ b/Library/Homebrew/retryable_download.rb @@ -0,0 +1,96 @@ +# typed: true # rubocop:todo Sorbet/StrictSigil +# frozen_string_literal: true + +module Homebrew + class RetryableDownload + include Downloadable + + sig { returns(Downloadable) } + attr_reader :downloadable + private :downloadable + + sig { override.returns(T.nilable(URL)) } + def url = downloadable.url + + sig { override.returns(T.nilable(Checksum)) } + def checksum = downloadable.checksum + + sig { override.returns(T::Array[String]) } + def mirrors = downloadable.mirrors + + sig { params(downloadable: Downloadable, tries: Integer).void } + def initialize(downloadable, tries: 3) + super() + + @downloadable = downloadable + @try = 0 + @tries = tries + end + + sig { override.returns(String) } + def name = downloadable.name + + sig { override.returns(String) } + def download_type = downloadable.download_type + + sig { override.returns(Pathname) } + def cached_download = downloadable.cached_download + + sig { override.void } + def clear_cache = downloadable.clear_cache + + sig { override.returns(T.nilable(Version)) } + def version = downloadable.version + + sig { override.returns(T.class_of(AbstractDownloadStrategy)) } + def download_strategy = downloadable.download_strategy + + sig { override.returns(AbstractDownloadStrategy) } + def downloader = downloadable.downloader + + sig { + override.params( + verify_download_integrity: T::Boolean, + timeout: T.nilable(T.any(Integer, Float)), + quiet: T::Boolean, + ).returns(Pathname) + } + def fetch(verify_download_integrity: true, timeout: nil, quiet: false) + @try += 1 + + already_downloaded = downloadable.downloaded? + + download = downloadable.fetch(verify_download_integrity: false, timeout:, quiet:) + + return download unless download.file? + + unless quiet + puts "Downloaded to: #{download}" unless already_downloaded + puts "SHA256: #{download.sha256}" + end + + downloadable.verify_download_integrity(download) if verify_download_integrity + + download + rescue DownloadError, ChecksumMismatchError + tries_remaining = @tries - @try + raise if tries_remaining.zero? + + wait = 2 ** @try + unless quiet + what = Utils.pluralize("tr", tries_remaining, plural: "ies", singular: "y") + ohai "Retrying download in #{wait}s... (#{tries_remaining} #{what} left)" + end + sleep wait + + downloadable.clear_cache + retry + end + + sig { override.params(filename: Pathname).void } + def verify_download_integrity(filename) = downloadable.verify_download_integrity(filename) + + sig { override.returns(String) } + def download_name = downloadable.download_name + end +end diff --git a/Library/Homebrew/software_spec.rb b/Library/Homebrew/software_spec.rb index ebf7821dad9bb..2fd01ea0e4cfa 100644 --- a/Library/Homebrew/software_spec.rb +++ b/Library/Homebrew/software_spec.rb @@ -16,6 +16,8 @@ require "extend/on_system" class SoftwareSpec + include Downloadable + extend Forwardable include OnSystem::MacOSAndLinux @@ -34,8 +36,10 @@ class SoftwareSpec def_delegators :@resource, :sha256 def initialize(flags: []) + super() + # Ensure this is synced with `initialize_dup` and `freeze` (excluding simple objects like integers and booleans) - @resource = Resource.new + @resource = Resource::Formula.new @resources = {} @dependency_collector = DependencyCollector.new @bottle_specification = BottleSpecification.new @@ -78,6 +82,11 @@ def freeze super end + sig { override.returns(String) } + def download_type + "formula" + end + def owner=(owner) @name = owner.name @full_name = owner.full_name @@ -126,8 +135,9 @@ def resource_defined?(name) params(name: String, klass: T.class_of(Resource), block: T.nilable(T.proc.bind(Resource).void)) .returns(T.nilable(Resource)) } - def resource(name, klass = Resource, &block) + def resource(name = T.unsafe(nil), klass = Resource, &block) if block + raise ArgumentError, "Resource must have a name." if name.nil? raise DuplicateResourceError, name if resource_defined?(name) res = klass.new(name, &block) @@ -137,6 +147,8 @@ def resource(name, klass = Resource, &block) dependency_collector.add(res) res else + return @resource if name.nil? + resources.fetch(name) { raise ResourceMissingError.new(owner, name) } end end @@ -285,6 +297,8 @@ def verify_download_integrity(_filename) end class Bottle + include Downloadable + class Filename attr_reader :name, :version, :tag, :rebuild @@ -338,9 +352,11 @@ def extname attr_reader :name, :resource, :tag, :cellar, :rebuild def_delegators :resource, :url, :verify_download_integrity - def_delegators :resource, :cached_download + def_delegators :resource, :cached_download, :downloader def initialize(formula, spec, tag = nil) + super() + @name = formula.name @resource = Resource.new @resource.owner = formula @@ -360,8 +376,15 @@ def initialize(formula, spec, tag = nil) root_url(spec.root_url, spec.root_url_specs) end - def fetch(verify_download_integrity: true) - @resource.fetch(verify_download_integrity:) + sig { + override.params( + verify_download_integrity: T::Boolean, + timeout: T.nilable(T.any(Integer, Float)), + quiet: T.nilable(T::Boolean), + ).returns(Pathname) + } + def fetch(verify_download_integrity: true, timeout: nil, quiet: false) + resource.fetch(verify_download_integrity:, timeout:, quiet:) rescue DownloadError raise unless fallback_on_error @@ -369,6 +392,7 @@ def fetch(verify_download_integrity: true) retry end + sig { override.void } def clear_cache @resource.clear_cache github_packages_manifest_resource&.clear_cache @@ -384,30 +408,32 @@ def skip_relocation? @spec.skip_relocation?(tag: @tag) end - def stage - resource.downloader.stage - end + def stage = downloader.stage - def fetch_tab - return if github_packages_manifest_resource.blank? + def fetch_tab(timeout: nil, quiet: false) + return unless (resource = github_packages_manifest_resource) - github_packages_manifest_resource.fetch - rescue DownloadError - raise unless fallback_on_error + begin + resource.fetch(timeout:, quiet:) + rescue DownloadError + raise unless fallback_on_error - retry - rescue ArgumentError - raise if @fetch_tab_retried + retry + rescue ArgumentError + raise if @fetch_tab_retried - @fetch_tab_retried = true - github_packages_manifest_resource.clear_cache - retry + @fetch_tab_retried = true + resource.clear_cache + retry + end end def tab_attributes - return {} unless github_packages_manifest_resource&.downloaded? + if (resource = github_packages_manifest_resource) && resource.downloaded? + return resource.tab + end - github_packages_manifest_resource.tab + {} end sig { returns(Filename) } @@ -415,8 +441,7 @@ def filename Filename.create(resource.owner, @tag, @spec.rebuild) end - private - + sig { returns(T.nilable(Resource::BottleManifest)) } def github_packages_manifest_resource return if @resource.download_strategy != CurlGitHubPackagesDownloadStrategy @@ -439,6 +464,8 @@ def github_packages_manifest_resource end end + private + def select_download_strategy(specs) specs[:using] ||= DownloadStrategyDetector.detect(@root_url) specs[:bottle] = true diff --git a/Library/Homebrew/sorbet/rbi/dsl/homebrew/cmd/fetch_cmd.rbi b/Library/Homebrew/sorbet/rbi/dsl/homebrew/cmd/fetch_cmd.rbi index 9275df2ee4a4a..b90b857ce7bbf 100644 --- a/Library/Homebrew/sorbet/rbi/dsl/homebrew/cmd/fetch_cmd.rbi +++ b/Library/Homebrew/sorbet/rbi/dsl/homebrew/cmd/fetch_cmd.rbi @@ -32,6 +32,9 @@ class Homebrew::Cmd::FetchCmd::Args < Homebrew::CLI::Args sig { returns(T::Boolean) } def casks?; end + sig { returns(T.nilable(String)) } + def concurrency; end + sig { returns(T::Boolean) } def deps?; end diff --git a/Library/Homebrew/sorbet/rbi/gems/concurrent-ruby@1.3.4.rbi b/Library/Homebrew/sorbet/rbi/gems/concurrent-ruby@1.3.4.rbi new file mode 100644 index 0000000000000..7116a2c6d19e0 --- /dev/null +++ b/Library/Homebrew/sorbet/rbi/gems/concurrent-ruby@1.3.4.rbi @@ -0,0 +1,11645 @@ +# typed: true + +# DO NOT EDIT MANUALLY +# This is an autogenerated file for types exported from the `concurrent-ruby` gem. +# Please instead update this file by running `bin/tapioca gem concurrent-ruby`. + + +# {include:file:README.md} +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/version.rb#1 +module Concurrent + extend ::Concurrent::Utility::EngineDetector + extend ::Concurrent::Utility::NativeExtensionLoader + extend ::Logger::Severity + extend ::Concurrent::Concern::Logging + extend ::Concurrent::Concern::Deprecation + + private + + # Abort a currently running transaction - see `Concurrent::atomically`. + # + # @raise [Transaction::AbortError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#139 + def abort_transaction; end + + # Run a block that reads and writes `TVar`s as a single atomic transaction. + # With respect to the value of `TVar` objects, the transaction is atomic, in + # that it either happens or it does not, consistent, in that the `TVar` + # objects involved will never enter an illegal state, and isolated, in that + # transactions never interfere with each other. You may recognise these + # properties from database transactions. + # + # There are some very important and unusual semantics that you must be aware of: + # + # * Most importantly, the block that you pass to atomically may be executed + # more than once. In most cases your code should be free of + # side-effects, except for via TVar. + # + # * If an exception escapes an atomically block it will abort the transaction. + # + # * It is undefined behaviour to use callcc or Fiber with atomically. + # + # * If you create a new thread within an atomically, it will not be part of + # the transaction. Creating a thread counts as a side-effect. + # + # Transactions within transactions are flattened to a single transaction. + # + # @example + # a = new TVar(100_000) + # b = new TVar(100) + # + # Concurrent::atomically do + # a.value -= 10 + # b.value += 10 + # end + # @raise [ArgumentError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#82 + def atomically; end + + # @raise [ArgumentError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/dataflow.rb#56 + def call_dataflow(method, executor, *inputs, &block); end + + # Dataflow allows you to create a task that will be scheduled when all of its data dependencies are available. + # {include:file:docs-source/dataflow.md} + # + # @param inputs [Future] zero or more `Future` operations that this dataflow depends upon + # @raise [ArgumentError] if no block is given + # @raise [ArgumentError] if any of the inputs are not `IVar`s + # @return [Object] the result of all the operations + # @yield The operation to perform once all the dependencies are met + # @yieldparam inputs [Future] each of the `Future` inputs to the dataflow + # @yieldreturn [Object] the result of the block operation + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/dataflow.rb#34 + def dataflow(*inputs, &block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/dataflow.rb#44 + def dataflow!(*inputs, &block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/dataflow.rb#39 + def dataflow_with(executor, *inputs, &block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/dataflow.rb#49 + def dataflow_with!(executor, *inputs, &block); end + + # Leave a transaction without committing or aborting - see `Concurrent::atomically`. + # + # @raise [Transaction::LeaveError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#144 + def leave_transaction; end + + # Returns the current time as tracked by the application monotonic clock. + # + # @param unit [Symbol] 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 + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/monotonic_time.rb#15 + def monotonic_time(unit = T.unsafe(nil)); end + + class << self + # Abort a currently running transaction - see `Concurrent::atomically`. + # + # @raise [Transaction::AbortError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#139 + def abort_transaction; end + + # Run a block that reads and writes `TVar`s as a single atomic transaction. + # With respect to the value of `TVar` objects, the transaction is atomic, in + # that it either happens or it does not, consistent, in that the `TVar` + # objects involved will never enter an illegal state, and isolated, in that + # transactions never interfere with each other. You may recognise these + # properties from database transactions. + # + # There are some very important and unusual semantics that you must be aware of: + # + # * Most importantly, the block that you pass to atomically may be executed + # more than once. In most cases your code should be free of + # side-effects, except for via TVar. + # + # * If an exception escapes an atomically block it will abort the transaction. + # + # * It is undefined behaviour to use callcc or Fiber with atomically. + # + # * If you create a new thread within an atomically, it will not be part of + # the transaction. Creating a thread counts as a side-effect. + # + # Transactions within transactions are flattened to a single transaction. + # + # @example + # a = new TVar(100_000) + # b = new TVar(100) + # + # Concurrent::atomically do + # a.value -= 10 + # b.value += 10 + # end + # @raise [ArgumentError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#82 + def atomically; end + + # Number of processors cores available for process scheduling. + # 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 [Float] number of available processors + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#194 + def available_processor_count; end + + # @raise [ArgumentError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/dataflow.rb#56 + def call_dataflow(method, executor, *inputs, &block); end + + # The maximum number of processors cores available for process scheduling. + # Returns `nil` if there is no enforced limit, or a `Float` if the + # process is inside a cgroup with a dedicated CPU quota (typically Docker). + # + # Note that nothing prevents setting a CPU quota higher than the actual number of + # cores on the system. + # + # For performance reasons the calculated value will be memoized on the first + # call. + # + # @return [nil, Float] Maximum number of available processors as set by a cgroup CPU quota, or nil if none set + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#209 + def 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 + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#217 + def cpu_shares; end + + # @return [Logger] Logger with provided level and output. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/logging.rb#37 + def create_simple_logger(level = T.unsafe(nil), output = T.unsafe(nil)); end + + # @deprecated + # @return [Logger] Logger with provided level and output. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/logging.rb#69 + def create_stdlib_logger(level = T.unsafe(nil), output = T.unsafe(nil)); end + + # Dataflow allows you to create a task that will be scheduled when all of its data dependencies are available. + # {include:file:docs-source/dataflow.md} + # + # @param inputs [Future] zero or more `Future` operations that this dataflow depends upon + # @raise [ArgumentError] if no block is given + # @raise [ArgumentError] if any of the inputs are not `IVar`s + # @return [Object] the result of all the operations + # @yield The operation to perform once all the dependencies are met + # @yieldparam inputs [Future] each of the `Future` inputs to the dataflow + # @yieldreturn [Object] the result of the block operation + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/dataflow.rb#34 + def dataflow(*inputs, &block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/dataflow.rb#44 + def dataflow!(*inputs, &block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/dataflow.rb#39 + def dataflow_with(executor, *inputs, &block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/dataflow.rb#49 + def dataflow_with!(executor, *inputs, &block); end + + # Disables AtExit handlers including pool auto-termination handlers. + # When disabled it will be the application programmer's responsibility + # to ensure that the handlers are shutdown properly prior to application + # exit by calling `AtExit.run` method. + # + # @deprecated Has no effect since it is no longer needed, see https://github.com/ruby-concurrency/concurrent-ruby/pull/841. + # @note this option should be needed only because of `at_exit` ordering + # issues which may arise when running some of the testing frameworks. + # E.g. Minitest's test-suite runs itself in `at_exit` callback which + # executes after the pools are already terminated. Then auto termination + # needs to be disabled and called manually after test-suite ends. + # @note This method should *never* be called + # from within a gem. It should *only* be used from within the main + # application and even then it should be used only when necessary. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/configuration.rb#48 + def disable_at_exit_handlers!; end + + # General access point to global executors. + # + # @param executor_identifier [Symbol, Executor] symbols: + # - :fast - {Concurrent.global_fast_executor} + # - :io - {Concurrent.global_io_executor} + # - :immediate - {Concurrent.global_immediate_executor} + # @return [Executor] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/configuration.rb#83 + def executor(executor_identifier); end + + # Global thread pool optimized for short, fast *operations*. + # + # @return [ThreadPoolExecutor] the thread pool + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/configuration.rb#55 + def global_fast_executor; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/configuration.rb#66 + def global_immediate_executor; end + + # Global thread pool optimized for long, blocking (IO) *tasks*. + # + # @return [ThreadPoolExecutor] the thread pool + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/configuration.rb#62 + def global_io_executor; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/logging.rb#109 + def global_logger; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/logging.rb#113 + def global_logger=(value); end + + # Global thread pool user for global *timers*. + # + # @return [Concurrent::TimerSet] the thread pool + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/configuration.rb#73 + def global_timer_set; end + + # Leave a transaction without committing or aborting - see `Concurrent::atomically`. + # + # @raise [Transaction::LeaveError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#144 + def leave_transaction; end + + # Returns the current time as tracked by the application monotonic clock. + # + # @param unit [Symbol] 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 + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/monotonic_time.rb#15 + def monotonic_time(unit = T.unsafe(nil)); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/lock_local_var.rb#7 + def mutex_owned_per_thread?; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/configuration.rb#87 + def new_fast_executor(opts = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/configuration.rb#98 + def new_io_executor(opts = T.unsafe(nil)); end + + # Number of physical processor cores on the current system. For performance + # reasons the calculated value will be memoized on the first call. + # + # On Windows the Win32 API will be queried for the `NumberOfCores from + # Win32_Processor`. This will return the total number "of cores for the + # current instance of the processor." On Unix-like operating systems either + # the `hwprefs` or `sysctl` utility will be called in a subshell and the + # returned value will be used. In the rare case where none of these methods + # work or an exception is raised the function will simply return 1. + # + # @return [Integer] number physical processor cores on the current system + # @see https://github.com/grosser/parallel/blob/4fc8b89d08c7091fe0419ca8fba1ec3ce5a8d185/lib/parallel.rb + # @see http://msdn.microsoft.com/en-us/library/aa394373(v=vs.85).aspx + # @see http://www.unix.com/man-page/osx/1/HWPREFS/ + # @see http://linux.die.net/man/8/sysctl + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#181 + def physical_processor_count; end + + # Number of processors seen by the OS and used for process scheduling. For + # performance reasons the calculated value will be memoized on the first + # call. + # + # When running under JRuby the Java runtime call + # `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." We still memoize this value once under + # JRuby. + # + # Otherwise Ruby's Etc.nprocessors will be used. + # + # @return [Integer] number of processors seen by the OS or Java runtime + # @see http://docs.oracle.com/javase/6/docs/api/java/lang/Runtime.html#availableProcessors() + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#160 + def processor_count; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#142 + def processor_counter; end + + # Use logger created by #create_simple_logger to log concurrent-ruby messages. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/logging.rb#63 + def use_simple_logger(level = T.unsafe(nil), output = T.unsafe(nil)); end + + # Use logger created by #create_stdlib_logger to log concurrent-ruby messages. + # + # @deprecated + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/logging.rb#96 + def use_stdlib_logger(level = T.unsafe(nil), output = T.unsafe(nil)); end + end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#38 +class Concurrent::AbstractExchanger < ::Concurrent::Synchronization::Object + # @return [AbstractExchanger] a new instance of AbstractExchanger + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#44 + def initialize; end + + # Waits for another thread to arrive at this exchange point (unless the + # current thread is interrupted), and then transfers the given object to + # it, receiving its object in return. The timeout value indicates the + # approximate number of seconds the method should block while waiting + # for the exchange. When the timeout value is `nil` the method will + # block indefinitely. + # + # + # In some edge cases when a `timeout` is given a return value of `nil` may be + # ambiguous. Specifically, if `nil` is a valid value in the exchange it will + # be impossible to tell whether `nil` is the actual return value or if it + # signifies timeout. When `nil` is a valid value in the exchange consider + # using {#exchange!} or {#try_exchange} instead. + # + # @param value [Object] the value to exchange with another thread + # @param timeout [Numeric, nil] in seconds, `nil` blocks indefinitely + # @return [Object] the value exchanged by the other thread or `nil` on timeout + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#69 + def exchange(value, timeout = T.unsafe(nil)); end + + # Waits for another thread to arrive at this exchange point (unless the + # current thread is interrupted), and then transfers the given object to + # it, receiving its object in return. The timeout value indicates the + # approximate number of seconds the method should block while waiting + # for the exchange. When the timeout value is `nil` the method will + # block indefinitely. + # + # + # On timeout a {Concurrent::TimeoutError} exception will be raised. + # + # @param value [Object] the value to exchange with another thread + # @param timeout [Numeric, nil] in seconds, `nil` blocks indefinitely + # @raise [Concurrent::TimeoutError] on timeout + # @return [Object] the value exchanged by the other thread + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#80 + def exchange!(value, timeout = T.unsafe(nil)); end + + # Waits for another thread to arrive at this exchange point (unless the + # current thread is interrupted), and then transfers the given object to + # it, receiving its object in return. The timeout value indicates the + # approximate number of seconds the method should block while waiting + # for the exchange. When the timeout value is `nil` the method will + # block indefinitely. + # + # + # The return value will be a {Concurrent::Maybe} set to `Just` on success or + # `Nothing` on timeout. + # + # @example + # + # exchanger = Concurrent::Exchanger.new + # + # result = exchanger.exchange(:foo, 0.5) + # + # if result.just? + # puts result.value #=> :bar + # else + # puts 'timeout' + # end + # @param value [Object] the value to exchange with another thread + # @param timeout [Numeric, nil] in seconds, `nil` blocks indefinitely + # @return [Concurrent::Maybe] on success a `Just` maybe will be returned with + # the item exchanged by the other thread as `#value`; on timeout a + # `Nothing` maybe will be returned with {Concurrent::TimeoutError} as `#reason` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#109 + def try_exchange(value, timeout = T.unsafe(nil)); end + + private + + # Waits for another thread to arrive at this exchange point (unless the + # current thread is interrupted), and then transfers the given object to + # it, receiving its object in return. The timeout value indicates the + # approximate number of seconds the method should block while waiting + # for the exchange. When the timeout value is `nil` the method will + # block indefinitely. + # + # @param value [Object] the value to exchange with another thread + # @param timeout [Numeric, nil] in seconds, `nil` blocks indefinitely + # @raise [NotImplementedError] + # @return [Object, CANCEL] the value exchanged by the other thread; {CANCEL} on timeout + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#122 + def do_exchange(value, timeout); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#41 +Concurrent::AbstractExchanger::CANCEL = T.let(T.unsafe(nil), Object) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#10 +class Concurrent::AbstractExecutorService < ::Concurrent::Synchronization::LockableObject + include ::Logger::Severity + include ::Concurrent::Concern::Logging + include ::Concurrent::ExecutorService + include ::Concurrent::Concern::Deprecation + + # Create a new thread pool. + # + # @return [AbstractExecutorService] a new instance of AbstractExecutorService + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#23 + def initialize(opts = T.unsafe(nil), &block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#72 + def auto_terminate=(value); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#67 + def auto_terminate?; end + + # Returns the value of attribute fallback_policy. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#18 + def fallback_policy; end + + # @raise [NotImplementedError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#42 + def kill; end + + # Returns the value of attribute name. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#20 + def name; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#52 + def running?; end + + # @raise [NotImplementedError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#37 + def shutdown; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#62 + def shutdown?; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#57 + def shuttingdown?; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#32 + def to_s; end + + # @raise [NotImplementedError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#47 + def wait_for_termination(timeout = T.unsafe(nil)); end + + private + + # 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 args [Array] the arguments to the task which is being handled. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#85 + def fallback_action(*args); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#126 + def ns_auto_terminate?; end + + # @raise [NotImplementedError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#106 + def ns_execute(*args, &task); end + + # Callback method called when the executor has been killed. + # The default behavior is to do nothing. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#122 + def ns_kill_execution; end + + # Callback method called when an orderly shutdown has completed. + # The default behavior is to signal all waiting threads. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#114 + def ns_shutdown_execution; end +end + +# The set of possible fallback policies that may be set at thread pool creation. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#15 +Concurrent::AbstractExecutorService::FALLBACK_POLICIES = T.let(T.unsafe(nil), Array) + +# An abstract implementation of local storage, with sub-classes for +# per-thread and per-fiber locals. +# +# Each execution context (EC, thread or fiber) has a lazily initialized array +# of local variable values. Each time a new local variable is created, we +# allocate an "index" for it. +# +# For example, if the allocated index is 1, that means slot #1 in EVERY EC's +# locals array will be used for the value of that variable. +# +# The good thing about using a per-EC structure to hold values, rather than +# a global, is that no synchronization is needed when reading and writing +# those values (since the structure is only ever accessed by a single +# thread). +# +# Of course, when a local variable is GC'd, 1) we need to recover its index +# for use by other new local variables (otherwise the locals arrays could +# get bigger and bigger with time), and 2) we need to null out all the +# references held in the now-unused slots (both to avoid blocking GC of those +# objects, and also to prevent "stale" values from being passed on to a new +# local when the index is reused). +# +# Because we need to null out freed slots, we need to keep references to +# ALL the locals arrays, so we can null out the appropriate slots in all of +# them. This is why we need to use a finalizer to clean up the locals array +# when the EC goes out of scope. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#35 +class Concurrent::AbstractLocals + # @return [AbstractLocals] a new instance of AbstractLocals + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#36 + def initialize; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#89 + def fetch(index); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#71 + def free_index(index); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#55 + def next_index(local); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#102 + def set(index, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#43 + def synchronize; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#48 + def weak_synchronize; end + + private + + # When the local goes out of scope, clean up that slot across all locals currently assigned. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#112 + def local_finalizer(index); end + + # Returns the locals for the current scope, or nil if none exist. + # + # @raise [NotImplementedError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#128 + def locals; end + + # Returns the locals for the current scope, creating them if necessary. + # + # @raise [NotImplementedError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#133 + def locals!; end + + # When a thread/fiber goes out of scope, remove the array from @all_arrays. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#119 + def thread_fiber_finalizer(array_object_id); end +end + +# `Agent` is inspired by Clojure's [agent](http://clojure.org/agents) +# function. An agent is a shared, mutable variable providing independent, +# uncoordinated, *asynchronous* change of individual values. Best used when +# the value will undergo frequent, complex updates. Suitable when the result +# of an update does not need to be known immediately. `Agent` is (mostly) +# functionally equivalent to Clojure's agent, except where the runtime +# prevents parity. +# +# Agents are reactive, not autonomous - there is no imperative message loop +# and no blocking receive. The state of an Agent should be itself immutable +# and the `#value` of an Agent is always immediately available for reading by +# any thread without any messages, i.e. observation does not require +# cooperation or coordination. +# +# Agent action dispatches are made using the various `#send` methods. These +# methods always return immediately. At some point later, in another thread, +# the following will happen: +# +# 1. The given `action` will be applied to the state of the Agent and the +# `args`, if any were supplied. +# 2. The return value of `action` will be passed to the validator lambda, +# if one has been set on the Agent. +# 3. If the validator succeeds or if no validator was given, the return value +# of the given `action` will become the new `#value` of the Agent. See +# `#initialize` for details. +# 4. If any observers were added to the Agent, they will be notified. See +# `#add_observer` for details. +# 5. If during the `action` execution any other dispatches are made (directly +# or indirectly), they will be held until after the `#value` of the Agent +# has been changed. +# +# If any exceptions are thrown by an action function, no nested dispatches +# will occur, and the exception will be cached in the Agent itself. When an +# Agent has errors cached, any subsequent interactions will immediately throw +# an exception, until the agent's errors are cleared. Agent errors can be +# examined with `#error` and the agent restarted with `#restart`. +# +# The actions of all Agents get interleaved amongst threads in a thread pool. +# At any point in time, at most one action for each Agent is being executed. +# Actions dispatched to an agent from another single agent or thread will +# occur in the order they were sent, potentially interleaved with actions +# dispatched to the same agent from other sources. The `#send` method should +# be used for actions that are CPU limited, while the `#send_off` method is +# appropriate for actions that may block on IO. +# +# Unlike in Clojure, `Agent` cannot participate in `Concurrent::TVar` transactions. +# +# ## Example +# +# ``` +# def next_fibonacci(set = nil) +# return [0, 1] if set.nil? +# set + [set[-2..-1].reduce{|sum,x| sum + x }] +# end +# +# # create an agent with an initial value +# agent = Concurrent::Agent.new(next_fibonacci) +# +# # send a few update requests +# 5.times do +# agent.send{|set| next_fibonacci(set) } +# end +# +# # wait for them to complete +# agent.await +# +# # get the current value +# agent.value #=> [0, 1, 1, 2, 3, 5, 8] +# ``` +# +# ## Observation +# +# Agents support observers through the {Concurrent::Observable} mixin module. +# Notification of observers occurs every time an action dispatch returns and +# the new value is successfully validated. Observation will *not* occur if the +# action raises an exception, if validation fails, or when a {#restart} occurs. +# +# When notified the observer will receive three arguments: `time`, `old_value`, +# and `new_value`. The `time` argument is the time at which the value change +# occurred. The `old_value` is the value of the Agent when the action began +# processing. The `new_value` is the value to which the Agent was set when the +# action completed. Note that `old_value` and `new_value` may be the same. +# This is not an error. It simply means that the action returned the same +# value. +# +# ## Nested Actions +# +# It is possible for an Agent action to post further actions back to itself. +# The nested actions will be enqueued normally then processed *after* the +# outer action completes, in the order they were sent, possibly interleaved +# with action dispatches from other threads. Nested actions never deadlock +# with one another and a failure in a nested action will never affect the +# outer action. +# +# Nested actions can be called using the Agent reference from the enclosing +# scope or by passing the reference in as a "send" argument. Nested actions +# cannot be post using `self` from within the action block/proc/lambda; `self` +# in this context will not reference the Agent. The preferred method for +# dispatching nested actions is to pass the Agent as an argument. This allows +# Ruby to more effectively manage the closing scope. +# +# Prefer this: +# +# ``` +# agent = Concurrent::Agent.new(0) +# agent.send(agent) do |value, this| +# this.send {|v| v + 42 } +# 3.14 +# end +# agent.value #=> 45.14 +# ``` +# +# Over this: +# +# ``` +# agent = Concurrent::Agent.new(0) +# agent.send do |value| +# agent.send {|v| v + 42 } +# 3.14 +# end +# ``` +# +# +# **NOTE** Never, *under any circumstances*, call any of the "await" methods +# ({#await}, {#await_for}, {#await_for!}, and {#wait}) from within an action +# block/proc/lambda. The call will block the Agent and will always fail. +# Calling either {#await} or {#wait} (with a timeout of `nil`) will +# hopelessly deadlock the Agent with no possibility of recovery. +# +# @see http://clojure.org/Agents Clojure Agents +# @see http://clojure.org/state Values and Change - Clojure's approach to Identity and State +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#145 +class Concurrent::Agent < ::Concurrent::Synchronization::LockableObject + include ::Concurrent::Concern::Observable + + # Create a new `Agent` with the given initial value and options. + # + # The `:validator` option must be `nil` or a side-effect free proc/lambda + # which takes one argument. On any intended value change the validator, if + # provided, will be called. If the new value is invalid the validator should + # return `false` or raise an error. + # + # The `:error_handler` option must be `nil` or a proc/lambda which takes two + # arguments. When an action raises an error or validation fails, either by + # returning false or raising an error, the error handler will be called. The + # arguments to the error handler will be a reference to the agent itself and + # the error object which was raised. + # + # The `:error_mode` may be either `:continue` (the default if an error + # handler is given) or `:fail` (the default if error handler nil or not + # given). + # + # If an action being run by the agent throws an error or doesn't pass + # validation the error handler, if present, will be called. After the + # handler executes if the error mode is `:continue` the Agent will continue + # as if neither the action that caused the error nor the error itself ever + # happened. + # + # If the mode is `:fail` the Agent will become {#failed?} and will stop + # accepting new action dispatches. Any previously queued actions will be + # held until {#restart} is called. The {#value} method will still work, + # returning the value of the Agent before the error. + # + # @option opts + # @option opts + # @option opts + # @param initial [Object] the initial value + # @param opts [Hash] the configuration options + # @return [Agent] a new instance of Agent + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#220 + def initialize(initial, opts = T.unsafe(nil)); end + + # Dispatches an action to the Agent and returns immediately. Subsequently, + # in a thread from a thread pool, the {#value} will be set to the return + # value of the action. Appropriate for actions that may block on IO. + # + # @param action [Proc] the action dispatch to be enqueued + # @return [Concurrent::Agent] self + # @see #send_off + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#331 + def <<(action); end + + # Blocks the current thread (indefinitely!) until all actions dispatched + # thus far, from this thread or nested by the Agent, have occurred. Will + # block when {#failed?}. Will never return if a failed Agent is {#restart} + # with `:clear_actions` true. + # + # Returns a reference to `self` to support method chaining: + # + # ``` + # current_value = agent.await.value + # ``` + # + # + # **NOTE** Never, *under any circumstances*, call any of the "await" methods + # ({#await}, {#await_for}, {#await_for!}, and {#wait}) from within an action + # block/proc/lambda. The call will block the Agent and will always fail. + # Calling either {#await} or {#wait} (with a timeout of `nil`) will + # hopelessly deadlock the Agent with no possibility of recovery. + # + # @return [Boolean] self + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#350 + def await; end + + # Blocks the current thread until all actions dispatched thus far, from this + # thread or nested by the Agent, have occurred, or the timeout (in seconds) + # has elapsed. + # + # + # **NOTE** Never, *under any circumstances*, call any of the "await" methods + # ({#await}, {#await_for}, {#await_for!}, and {#wait}) from within an action + # block/proc/lambda. The call will block the Agent and will always fail. + # Calling either {#await} or {#wait} (with a timeout of `nil`) will + # hopelessly deadlock the Agent with no possibility of recovery. + # + # @param timeout [Float] the maximum number of seconds to wait + # @return [Boolean] true if all actions complete before timeout else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#363 + def await_for(timeout); end + + # Blocks the current thread until all actions dispatched thus far, from this + # thread or nested by the Agent, have occurred, or the timeout (in seconds) + # has elapsed. + # + # + # **NOTE** Never, *under any circumstances*, call any of the "await" methods + # ({#await}, {#await_for}, {#await_for!}, and {#wait}) from within an action + # block/proc/lambda. The call will block the Agent and will always fail. + # Calling either {#await} or {#wait} (with a timeout of `nil`) will + # hopelessly deadlock the Agent with no possibility of recovery. + # + # @param timeout [Float] the maximum number of seconds to wait + # @raise [Concurrent::TimeoutError] when timout is reached + # @return [Boolean] true if all actions complete before timeout + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#377 + def await_for!(timeout); end + + # The current value (state) of the Agent, irrespective of any pending or + # in-progress actions. The value is always available and is non-blocking. + # + # @return [Object] the current value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#229 + def deref; end + + # When {#failed?} and {#error_mode} is `:fail`, returns the error object + # which caused the failure, else `nil`. When {#error_mode} is `:continue` + # will *always* return `nil`. + # + # @return [nil, Error] the error which caused the failure when {#failed?} + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#240 + def error; end + + # The error mode this Agent is operating in. See {#initialize} for details. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#184 + def error_mode; end + + # Is the Agent in a failed state? + # + # @return [Boolean] + # @see #restart + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#402 + def failed?; end + + # Dispatches an action to the Agent and returns immediately. Subsequently, + # in a thread from a thread pool, the {#value} will be set to the return + # value of the action. Action dispatches are only allowed when the Agent + # is not {#failed?}. + # + # The action must be a block/proc/lambda which takes 1 or more arguments. + # The first argument is the current {#value} of the Agent. Any arguments + # passed to the send method via the `args` parameter will be passed to the + # action as the remaining arguments. The action must return the new value + # of the Agent. + # + # * {#send} and {#send!} should be used for actions that are CPU limited + # * {#send_off}, {#send_off!}, and {#<<} are appropriate for actions that + # may block on IO + # * {#send_via} and {#send_via!} are used when a specific executor is to + # be used for the action + # + # @param args [Array] zero or more arguments to be passed to + # the action + # @param action [Proc] the action dispatch to be enqueued + # @return [Boolean] true if the action is successfully enqueued, false if + # the Agent is {#failed?} + # @yield [agent, value, *args] process the old value and return the new + # @yieldparam value [Object] the current {#value} of the Agent + # @yieldparam args [Array] zero or more arguments to pass to the + # action + # @yieldreturn [Object] the new value of the Agent + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#294 + def post(*args, &action); end + + # When {#failed?} and {#error_mode} is `:fail`, returns the error object + # which caused the failure, else `nil`. When {#error_mode} is `:continue` + # will *always* return `nil`. + # + # @return [nil, Error] the error which caused the failure when {#failed?} + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#240 + def reason; end + + # When an Agent is {#failed?}, changes the Agent {#value} to `new_value` + # then un-fails the Agent so that action dispatches are allowed again. If + # the `:clear_actions` option is give and true, any actions queued on the + # Agent that were being held while it was failed will be discarded, + # otherwise those held actions will proceed. The `new_value` must pass the + # validator if any, or `restart` will raise an exception and the Agent will + # remain failed with its old {#value} and {#error}. Observers, if any, will + # not be notified of the new state. + # + # @option opts + # @param new_value [Object] the new value for the Agent once restarted + # @param opts [Hash] the configuration options + # @raise [Concurrent:AgentError] when not failed + # @return [Boolean] true + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#424 + def restart(new_value, opts = T.unsafe(nil)); end + + # Dispatches an action to the Agent and returns immediately. Subsequently, + # in a thread from a thread pool, the {#value} will be set to the return + # value of the action. Action dispatches are only allowed when the Agent + # is not {#failed?}. + # + # The action must be a block/proc/lambda which takes 1 or more arguments. + # The first argument is the current {#value} of the Agent. Any arguments + # passed to the send method via the `args` parameter will be passed to the + # action as the remaining arguments. The action must return the new value + # of the Agent. + # + # * {#send} and {#send!} should be used for actions that are CPU limited + # * {#send_off}, {#send_off!}, and {#<<} are appropriate for actions that + # may block on IO + # * {#send_via} and {#send_via!} are used when a specific executor is to + # be used for the action + # + # @param args [Array] zero or more arguments to be passed to + # the action + # @param action [Proc] the action dispatch to be enqueued + # @return [Boolean] true if the action is successfully enqueued, false if + # the Agent is {#failed?} + # @yield [agent, value, *args] process the old value and return the new + # @yieldparam value [Object] the current {#value} of the Agent + # @yieldparam args [Array] zero or more arguments to pass to the + # action + # @yieldreturn [Object] the new value of the Agent + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#278 + def send(*args, &action); end + + # Dispatches an action to the Agent and returns immediately. Subsequently, + # in a thread from a thread pool, the {#value} will be set to the return + # value of the action. Action dispatches are only allowed when the Agent + # is not {#failed?}. + # + # The action must be a block/proc/lambda which takes 1 or more arguments. + # The first argument is the current {#value} of the Agent. Any arguments + # passed to the send method via the `args` parameter will be passed to the + # action as the remaining arguments. The action must return the new value + # of the Agent. + # + # * {#send} and {#send!} should be used for actions that are CPU limited + # * {#send_off}, {#send_off!}, and {#<<} are appropriate for actions that + # may block on IO + # * {#send_via} and {#send_via!} are used when a specific executor is to + # be used for the action + # + # @param args [Array] zero or more arguments to be passed to + # the action + # @param action [Proc] the action dispatch to be enqueued + # @raise [Concurrent::Agent::Error] if the Agent is {#failed?} + # @return [Boolean] true if the action is successfully enqueued + # @yield [agent, value, *args] process the old value and return the new + # @yieldparam value [Object] the current {#value} of the Agent + # @yieldparam args [Array] zero or more arguments to pass to the + # action + # @yieldreturn [Object] the new value of the Agent + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#287 + def send!(*args, &action); end + + # Dispatches an action to the Agent and returns immediately. Subsequently, + # in a thread from a thread pool, the {#value} will be set to the return + # value of the action. Action dispatches are only allowed when the Agent + # is not {#failed?}. + # + # The action must be a block/proc/lambda which takes 1 or more arguments. + # The first argument is the current {#value} of the Agent. Any arguments + # passed to the send method via the `args` parameter will be passed to the + # action as the remaining arguments. The action must return the new value + # of the Agent. + # + # * {#send} and {#send!} should be used for actions that are CPU limited + # * {#send_off}, {#send_off!}, and {#<<} are appropriate for actions that + # may block on IO + # * {#send_via} and {#send_via!} are used when a specific executor is to + # be used for the action + # + # @param args [Array] zero or more arguments to be passed to + # the action + # @param action [Proc] the action dispatch to be enqueued + # @return [Boolean] true if the action is successfully enqueued, false if + # the Agent is {#failed?} + # @yield [agent, value, *args] process the old value and return the new + # @yieldparam value [Object] the current {#value} of the Agent + # @yieldparam args [Array] zero or more arguments to pass to the + # action + # @yieldreturn [Object] the new value of the Agent + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#294 + def send_off(*args, &action); end + + # Dispatches an action to the Agent and returns immediately. Subsequently, + # in a thread from a thread pool, the {#value} will be set to the return + # value of the action. Action dispatches are only allowed when the Agent + # is not {#failed?}. + # + # The action must be a block/proc/lambda which takes 1 or more arguments. + # The first argument is the current {#value} of the Agent. Any arguments + # passed to the send method via the `args` parameter will be passed to the + # action as the remaining arguments. The action must return the new value + # of the Agent. + # + # * {#send} and {#send!} should be used for actions that are CPU limited + # * {#send_off}, {#send_off!}, and {#<<} are appropriate for actions that + # may block on IO + # * {#send_via} and {#send_via!} are used when a specific executor is to + # be used for the action + # + # @param args [Array] zero or more arguments to be passed to + # the action + # @param action [Proc] the action dispatch to be enqueued + # @raise [Concurrent::Agent::Error] if the Agent is {#failed?} + # @return [Boolean] true if the action is successfully enqueued + # @yield [agent, value, *args] process the old value and return the new + # @yieldparam value [Object] the current {#value} of the Agent + # @yieldparam args [Array] zero or more arguments to pass to the + # action + # @yieldreturn [Object] the new value of the Agent + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#302 + def send_off!(*args, &action); end + + # Dispatches an action to the Agent and returns immediately. Subsequently, + # in a thread from a thread pool, the {#value} will be set to the return + # value of the action. Action dispatches are only allowed when the Agent + # is not {#failed?}. + # + # The action must be a block/proc/lambda which takes 1 or more arguments. + # The first argument is the current {#value} of the Agent. Any arguments + # passed to the send method via the `args` parameter will be passed to the + # action as the remaining arguments. The action must return the new value + # of the Agent. + # + # * {#send} and {#send!} should be used for actions that are CPU limited + # * {#send_off}, {#send_off!}, and {#<<} are appropriate for actions that + # may block on IO + # * {#send_via} and {#send_via!} are used when a specific executor is to + # be used for the action + # + # @param args [Array] zero or more arguments to be passed to + # the action + # @param action [Proc] the action dispatch to be enqueued + # @param executor [Concurrent::ExecutorService] the executor on which the + # action is to be dispatched + # @return [Boolean] true if the action is successfully enqueued, false if + # the Agent is {#failed?} + # @yield [agent, value, *args] process the old value and return the new + # @yieldparam value [Object] the current {#value} of the Agent + # @yieldparam args [Array] zero or more arguments to pass to the + # action + # @yieldreturn [Object] the new value of the Agent + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#311 + def send_via(executor, *args, &action); end + + # Dispatches an action to the Agent and returns immediately. Subsequently, + # in a thread from a thread pool, the {#value} will be set to the return + # value of the action. Action dispatches are only allowed when the Agent + # is not {#failed?}. + # + # The action must be a block/proc/lambda which takes 1 or more arguments. + # The first argument is the current {#value} of the Agent. Any arguments + # passed to the send method via the `args` parameter will be passed to the + # action as the remaining arguments. The action must return the new value + # of the Agent. + # + # * {#send} and {#send!} should be used for actions that are CPU limited + # * {#send_off}, {#send_off!}, and {#<<} are appropriate for actions that + # may block on IO + # * {#send_via} and {#send_via!} are used when a specific executor is to + # be used for the action + # + # @param args [Array] zero or more arguments to be passed to + # the action + # @param action [Proc] the action dispatch to be enqueued + # @param executor [Concurrent::ExecutorService] the executor on which the + # action is to be dispatched + # @raise [Concurrent::Agent::Error] if the Agent is {#failed?} + # @return [Boolean] true if the action is successfully enqueued + # @yield [agent, value, *args] process the old value and return the new + # @yieldparam value [Object] the current {#value} of the Agent + # @yieldparam args [Array] zero or more arguments to pass to the + # action + # @yieldreturn [Object] the new value of the Agent + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#319 + def send_via!(executor, *args, &action); end + + # Is the Agent in a failed state? + # + # @return [Boolean] + # @see #restart + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#402 + def stopped?; end + + # The current value (state) of the Agent, irrespective of any pending or + # in-progress actions. The value is always available and is non-blocking. + # + # @return [Object] the current value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#229 + def value; end + + # Blocks the current thread until all actions dispatched thus far, from this + # thread or nested by the Agent, have occurred, or the timeout (in seconds) + # has elapsed. Will block indefinitely when timeout is nil or not given. + # + # Provided mainly for consistency with other classes in this library. Prefer + # the various `await` methods instead. + # + # + # **NOTE** Never, *under any circumstances*, call any of the "await" methods + # ({#await}, {#await_for}, {#await_for!}, and {#wait}) from within an action + # block/proc/lambda. The call will block the Agent and will always fail. + # Calling either {#await} or {#wait} (with a timeout of `nil`) will + # hopelessly deadlock the Agent with no possibility of recovery. + # + # @param timeout [Float] the maximum number of seconds to wait + # @return [Boolean] true if all actions complete before timeout else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#393 + def wait(timeout = T.unsafe(nil)); end + + private + + # @raise [ArgumentError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#510 + def enqueue_action_job(action, args, executor); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#516 + def enqueue_await_job(latch); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#543 + def execute_next_job; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#576 + def handle_error(error); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#529 + def ns_enqueue_job(job, index = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#584 + def ns_find_last_job_for_thread; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#490 + def ns_initialize(initial, opts); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#539 + def ns_post_next_job; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#570 + def ns_validate(value); end + + class << self + # Blocks the current thread (indefinitely!) until all actions dispatched + # thus far to all the given Agents, from this thread or nested by the + # given Agents, have occurred. Will block when any of the agents are + # failed. Will never return if a failed Agent is restart with + # `:clear_actions` true. + # + # + # **NOTE** Never, *under any circumstances*, call any of the "await" methods + # ({#await}, {#await_for}, {#await_for!}, and {#wait}) from within an action + # block/proc/lambda. The call will block the Agent and will always fail. + # Calling either {#await} or {#wait} (with a timeout of `nil`) will + # hopelessly deadlock the Agent with no possibility of recovery. + # + # @param agents [Array] the Agents on which to wait + # @return [Boolean] true + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#449 + def await(*agents); end + + # Blocks the current thread until all actions dispatched thus far to all + # the given Agents, from this thread or nested by the given Agents, have + # occurred, or the timeout (in seconds) has elapsed. + # + # + # **NOTE** Never, *under any circumstances*, call any of the "await" methods + # ({#await}, {#await_for}, {#await_for!}, and {#wait}) from within an action + # block/proc/lambda. The call will block the Agent and will always fail. + # Calling either {#await} or {#wait} (with a timeout of `nil`) will + # hopelessly deadlock the Agent with no possibility of recovery. + # + # @param timeout [Float] the maximum number of seconds to wait + # @param agents [Array] the Agents on which to wait + # @return [Boolean] true if all actions complete before timeout else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#463 + def await_for(timeout, *agents); end + + # Blocks the current thread until all actions dispatched thus far to all + # the given Agents, from this thread or nested by the given Agents, have + # occurred, or the timeout (in seconds) has elapsed. + # + # + # **NOTE** Never, *under any circumstances*, call any of the "await" methods + # ({#await}, {#await_for}, {#await_for!}, and {#wait}) from within an action + # block/proc/lambda. The call will block the Agent and will always fail. + # Calling either {#await} or {#wait} (with a timeout of `nil`) will + # hopelessly deadlock the Agent with no possibility of recovery. + # + # @param timeout [Float] the maximum number of seconds to wait + # @param agents [Array] the Agents on which to wait + # @raise [Concurrent::TimeoutError] when timout is reached + # @return [Boolean] true if all actions complete before timeout + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#482 + def await_for!(timeout, *agents); end + end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#154 +Concurrent::Agent::AWAIT_ACTION = T.let(T.unsafe(nil), Proc) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#151 +Concurrent::Agent::AWAIT_FLAG = T.let(T.unsafe(nil), Object) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#157 +Concurrent::Agent::DEFAULT_ERROR_HANDLER = T.let(T.unsafe(nil), Proc) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#160 +Concurrent::Agent::DEFAULT_VALIDATOR = T.let(T.unsafe(nil), Proc) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#148 +Concurrent::Agent::ERROR_MODES = T.let(T.unsafe(nil), Array) + +# Raised during action processing or any other time in an Agent's lifecycle. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#167 +class Concurrent::Agent::Error < ::StandardError + # @return [Error] a new instance of Error + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#168 + def initialize(message = T.unsafe(nil)); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#163 +class Concurrent::Agent::Job < ::Struct + # Returns the value of attribute action + # + # @return [Object] the current value of action + def action; end + + # Sets the attribute action + # + # @param value [Object] the value to set the attribute action to. + # @return [Object] the newly set value + def action=(_); end + + # Returns the value of attribute args + # + # @return [Object] the current value of args + def args; end + + # Sets the attribute args + # + # @param value [Object] the value to set the attribute args to. + # @return [Object] the newly set value + def args=(_); end + + # Returns the value of attribute caller + # + # @return [Object] the current value of caller + def caller; end + + # Sets the attribute caller + # + # @param value [Object] the value to set the attribute caller to. + # @return [Object] the newly set value + def caller=(_); end + + # Returns the value of attribute executor + # + # @return [Object] the current value of executor + def executor; end + + # Sets the attribute executor + # + # @param value [Object] the value to set the attribute executor to. + # @return [Object] the newly set value + def executor=(_); end + + class << self + def [](*_arg0); end + def inspect; end + def keyword_init?; end + def members; end + def new(*_arg0); end + end +end + +# Raised when a new value obtained during action processing or at `#restart` +# fails validation. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#176 +class Concurrent::Agent::ValidationError < ::Concurrent::Agent::Error + # @return [ValidationError] a new instance of ValidationError + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#177 + def initialize(message = T.unsafe(nil)); end +end + +# A thread-safe subclass of Array. This version locks against the object +# itself for every method call, ensuring only one thread can be reading +# or writing at a time. This includes iteration methods like `#each`. +# +# @note `a += b` is **not** a **thread-safe** operation on +# `Concurrent::Array`. It reads array `a`, then it creates new `Concurrent::Array` +# which is concatenation of `a` and `b`, then it writes the concatenation to `a`. +# The read and write are independent operations they do not form a single atomic +# operation therefore when two `+=` operations are executed concurrently updates +# may be lost. Use `#concat` instead. +# @see http://ruby-doc.org/core/Array.html Ruby standard library `Array` +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/array.rb#53 +class Concurrent::Array < ::Array; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/array.rb#22 +Concurrent::ArrayImplementation = Array + +# A mixin module that provides simple asynchronous behavior to a class, +# turning it into a simple actor. Loosely based on Erlang's +# [gen_server](http://www.erlang.org/doc/man/gen_server.html), but without +# supervision or linking. +# +# A more feature-rich {Concurrent::Actor} is also available when the +# capabilities of `Async` are too limited. +# +# ```cucumber +# Feature: +# As a stateful, plain old Ruby class +# I want safe, asynchronous behavior +# So my long-running methods don't block the main thread +# ``` +# +# The `Async` module is a way to mix simple yet powerful asynchronous +# capabilities into any plain old Ruby object or class, turning each object +# into a simple Actor. Method calls are processed on a background thread. The +# caller is free to perform other actions while processing occurs in the +# background. +# +# Method calls to the asynchronous object are made via two proxy methods: +# `async` (alias `cast`) and `await` (alias `call`). These proxy methods post +# the method call to the object's background thread and return a "future" +# which will eventually contain the result of the method call. +# +# This behavior is loosely patterned after Erlang's `gen_server` behavior. +# When an Erlang module implements the `gen_server` behavior it becomes +# inherently asynchronous. The `start` or `start_link` function spawns a +# process (similar to a thread but much more lightweight and efficient) and +# returns the ID of the process. Using the process ID, other processes can +# send messages to the `gen_server` via the `cast` and `call` methods. Unlike +# Erlang's `gen_server`, however, `Async` classes do not support linking or +# supervision trees. +# +# ## Basic Usage +# +# When this module is mixed into a class, objects of the class become inherently +# asynchronous. Each object gets its own background thread on which to post +# asynchronous method calls. Asynchronous method calls are executed in the +# background one at a time in the order they are received. +# +# To create an asynchronous class, simply mix in the `Concurrent::Async` module: +# +# ``` +# class Hello +# include Concurrent::Async +# +# def hello(name) +# "Hello, #{name}!" +# end +# end +# ``` +# +# Mixing this module into a class provides each object two proxy methods: +# `async` and `await`. These methods are thread safe with respect to the +# enclosing object. The former proxy allows methods to be called +# asynchronously by posting to the object's internal thread. The latter proxy +# allows a method to be called synchronously but does so safely with respect +# to any pending asynchronous method calls and ensures proper ordering. Both +# methods return a {Concurrent::IVar} which can be inspected for the result +# of the proxied method call. Calling a method with `async` will return a +# `:pending` `IVar` whereas `await` will return a `:complete` `IVar`. +# +# ``` +# class Echo +# include Concurrent::Async +# +# def echo(msg) +# print "#{msg}\n" +# end +# end +# +# horn = Echo.new +# horn.echo('zero') # synchronous, not thread-safe +# # returns the actual return value of the method +# +# horn.async.echo('one') # asynchronous, non-blocking, thread-safe +# # returns an IVar in the :pending state +# +# horn.await.echo('two') # synchronous, blocking, thread-safe +# # returns an IVar in the :complete state +# ``` +# +# ## Let It Fail +# +# The `async` and `await` proxy methods have built-in error protection based +# on Erlang's famous "let it fail" philosophy. Instance methods should not be +# programmed defensively. When an exception is raised by a delegated method +# the proxy will rescue the exception, expose it to the caller as the `reason` +# attribute of the returned future, then process the next method call. +# +# ## Calling Methods Internally +# +# External method calls should *always* use the `async` and `await` proxy +# methods. When one method calls another method, the `async` proxy should +# rarely be used and the `await` proxy should *never* be used. +# +# When an object calls one of its own methods using the `await` proxy the +# second call will be enqueued *behind* the currently running method call. +# Any attempt to wait on the result will fail as the second call will never +# run until after the current call completes. +# +# Calling a method using the `await` proxy from within a method that was +# itself called using `async` or `await` will irreversibly deadlock the +# object. Do *not* do this, ever. +# +# ## Instance Variables and Attribute Accessors +# +# Instance variables do not need to be thread-safe so long as they are private. +# Asynchronous method calls are processed in the order they are received and +# are processed one at a time. Therefore private instance variables can only +# be accessed by one thread at a time. This is inherently thread-safe. +# +# When using private instance variables within asynchronous methods, the best +# practice is to read the instance variable into a local variable at the start +# of the method then update the instance variable at the *end* of the method. +# This way, should an exception be raised during method execution the internal +# state of the object will not have been changed. +# +# ### Reader Attributes +# +# The use of `attr_reader` is discouraged. Internal state exposed externally, +# when necessary, should be done through accessor methods. The instance +# variables exposed by these methods *must* be thread-safe, or they must be +# called using the `async` and `await` proxy methods. These two approaches are +# subtly different. +# +# When internal state is accessed via the `async` and `await` proxy methods, +# the returned value represents the object's state *at the time the call is +# processed*, which may *not* be the state of the object at the time the call +# is made. +# +# To get the state *at the current* time, irrespective of an enqueued method +# calls, a reader method must be called directly. This is inherently unsafe +# unless the instance variable is itself thread-safe, preferably using one +# of the thread-safe classes within this library. Because the thread-safe +# classes within this library are internally-locking or non-locking, they can +# be safely used from within asynchronous methods without causing deadlocks. +# +# Generally speaking, the best practice is to *not* expose internal state via +# reader methods. The best practice is to simply use the method's return value. +# +# ### Writer Attributes +# +# Writer attributes should never be used with asynchronous classes. Changing +# the state externally, even when done in the thread-safe way, is not logically +# consistent. Changes to state need to be timed with respect to all asynchronous +# method calls which my be in-process or enqueued. The only safe practice is to +# pass all necessary data to each method as arguments and let the method update +# the internal state as necessary. +# +# ## Class Constants, Variables, and Methods +# +# ### Class Constants +# +# Class constants do not need to be thread-safe. Since they are read-only and +# immutable they may be safely read both externally and from within +# asynchronous methods. +# +# ### Class Variables +# +# Class variables should be avoided. Class variables represent shared state. +# Shared state is anathema to concurrency. Should there be a need to share +# state using class variables they *must* be thread-safe, preferably +# using the thread-safe classes within this library. When updating class +# variables, never assign a new value/object to the variable itself. Assignment +# is not thread-safe in Ruby. Instead, use the thread-safe update functions +# of the variable itself to change the value. +# +# The best practice is to *never* use class variables with `Async` classes. +# +# ### Class Methods +# +# Class methods which are pure functions are safe. Class methods which modify +# class variables should be avoided, for all the reasons listed above. +# +# ## An Important Note About Thread Safe Guarantees +# +# > Thread safe guarantees can only be made when asynchronous method calls +# > are not mixed with direct method calls. Use only direct method calls +# > when the object is used exclusively on a single thread. Use only +# > `async` and `await` when the object is shared between threads. Once you +# > call a method using `async` or `await`, you should no longer call methods +# > directly on the object. Use `async` and `await` exclusively from then on. +# +# @example +# +# class Echo +# include Concurrent::Async +# +# def echo(msg) +# print "#{msg}\n" +# end +# end +# +# horn = Echo.new +# horn.echo('zero') # synchronous, not thread-safe +# # returns the actual return value of the method +# +# horn.async.echo('one') # asynchronous, non-blocking, thread-safe +# # returns an IVar in the :pending state +# +# horn.await.echo('two') # synchronous, blocking, thread-safe +# # returns an IVar in the :complete state +# @see Concurrent::Actor +# @see https://en.wikipedia.org/wiki/Actor_model "Actor Model" at Wikipedia +# @see http://www.erlang.org/doc/man/gen_server.html Erlang gen_server +# @see http://c2.com/cgi/wiki?LetItCrash "Let It Crash" at http://c2.com/ +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#217 +module Concurrent::Async + mixes_in_class_methods ::Concurrent::Async::ClassMethods + + # Causes the chained method call to be performed asynchronously on the + # object's thread. The delegated method will return a future in the + # `:pending` state and the method call will have been scheduled on the + # object's thread. The final disposition of the method call can be obtained + # by inspecting the returned future. + # + # @note The method call is guaranteed to be thread safe with respect to + # all other method calls against the same object that are called with + # either `async` or `await`. The mutable nature of Ruby references + # (and object orientation in general) prevent any other thread safety + # guarantees. Do NOT mix direct method calls with delegated method calls. + # Use *only* delegated method calls when sharing the object between threads. + # @raise [NameError] the object does not respond to the requested method + # @raise [ArgumentError] the given `args` do not match the arity of + # the requested method + # @return [Concurrent::IVar] the pending result of the asynchronous operation + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#412 + def async; end + + # Causes the chained method call to be performed synchronously on the + # current thread. The delegated will return a future in either the + # `:fulfilled` or `:rejected` state and the delegated method will have + # completed. The final disposition of the delegated method can be obtained + # by inspecting the returned future. + # + # @note The method call is guaranteed to be thread safe with respect to + # all other method calls against the same object that are called with + # either `async` or `await`. The mutable nature of Ruby references + # (and object orientation in general) prevent any other thread safety + # guarantees. Do NOT mix direct method calls with delegated method calls. + # Use *only* delegated method calls when sharing the object between threads. + # @raise [NameError] the object does not respond to the requested method + # @raise [ArgumentError] the given `args` do not match the arity of the + # requested method + # @return [Concurrent::IVar] the completed result of the synchronous operation + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#430 + def await; end + + # Causes the chained method call to be performed synchronously on the + # current thread. The delegated will return a future in either the + # `:fulfilled` or `:rejected` state and the delegated method will have + # completed. The final disposition of the delegated method can be obtained + # by inspecting the returned future. + # + # @note The method call is guaranteed to be thread safe with respect to + # all other method calls against the same object that are called with + # either `async` or `await`. The mutable nature of Ruby references + # (and object orientation in general) prevent any other thread safety + # guarantees. Do NOT mix direct method calls with delegated method calls. + # Use *only* delegated method calls when sharing the object between threads. + # @raise [NameError] the object does not respond to the requested method + # @raise [ArgumentError] the given `args` do not match the arity of the + # requested method + # @return [Concurrent::IVar] the completed result of the synchronous operation + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#430 + def call; end + + # Causes the chained method call to be performed asynchronously on the + # object's thread. The delegated method will return a future in the + # `:pending` state and the method call will have been scheduled on the + # object's thread. The final disposition of the method call can be obtained + # by inspecting the returned future. + # + # @note The method call is guaranteed to be thread safe with respect to + # all other method calls against the same object that are called with + # either `async` or `await`. The mutable nature of Ruby references + # (and object orientation in general) prevent any other thread safety + # guarantees. Do NOT mix direct method calls with delegated method calls. + # Use *only* delegated method calls when sharing the object between threads. + # @raise [NameError] the object does not respond to the requested method + # @raise [ArgumentError] the given `args` do not match the arity of + # the requested method + # @return [Concurrent::IVar] the pending result of the asynchronous operation + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#412 + def cast; end + + # Initialize the internal serializer and other stnchronization mechanisms. + # + # @note This method *must* be called immediately upon object construction. + # This is the only way thread-safe initialization can be guaranteed. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#441 + def init_synchronization; end + + class << self + # @private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#262 + def included(base); end + + # Check for the presence of a method on an object and determine if a given + # set of arguments matches the required arity. + # + # @note This check is imperfect because of the way Ruby reports the arity of + # methods with a variable number of arguments. It is possible to determine + # if too few arguments are given but impossible to determine if too many + # arguments are given. This check may also fail to recognize dynamic behavior + # of the object, such as methods simulated with `method_missing`. + # @param obj [Object] the object to check against + # @param method [Symbol] the method to check the object for + # @param args [Array] zero or more arguments for the arity check + # @raise [NameError] the object does not respond to `method` method + # @raise [ArgumentError] the given `args` do not match the arity of `method` + # @see http://www.ruby-doc.org/core-2.1.1/Method.html#method-i-arity Method#arity + # @see http://ruby-doc.org/core-2.1.0/Object.html#method-i-respond_to-3F Object#respond_to? + # @see http://www.ruby-doc.org/core-2.1.0/BasicObject.html#method-i-method_missing BasicObject#method_missing + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#250 + def validate_argc(obj, method, *args); end + end +end + +# Delegates asynchronous, thread-safe method calls to the wrapped object. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#282 +class Concurrent::Async::AsyncDelegator < ::Concurrent::Synchronization::LockableObject + # Create a new delegator object wrapping the given delegate. + # + # @param delegate [Object] the object to wrap and delegate method calls to + # @return [AsyncDelegator] a new instance of AsyncDelegator + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#288 + def initialize(delegate); end + + # Delegates method calls to the wrapped object. + # + # @param method [Symbol] the method being called + # @param args [Array] zero or more arguments to the method + # @raise [NameError] the object does not respond to `method` method + # @raise [ArgumentError] the given `args` do not match the arity of `method` + # @return [IVar] the result of the method call + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#305 + def method_missing(method, *args, &block); end + + # Perform all enqueued tasks. + # + # This method must be called from within the executor. It must not be + # called while already running. It will loop until the queue is empty. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#330 + def perform; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#348 + def reset_if_forked; end + + private + + # Check whether the method is responsive + # + # @param method [Symbol] the method being called + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#322 + def respond_to_missing?(method, include_private = T.unsafe(nil)); end +end + +# Delegates synchronous, thread-safe method calls to the wrapped object. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#360 +class Concurrent::Async::AwaitDelegator + # Create a new delegator object wrapping the given delegate. + # + # @param delegate [AsyncDelegator] the object to wrap and delegate method calls to + # @return [AwaitDelegator] a new instance of AwaitDelegator + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#365 + def initialize(delegate); end + + # Delegates method calls to the wrapped object. + # + # @param method [Symbol] the method being called + # @param args [Array] zero or more arguments to the method + # @raise [NameError] the object does not respond to `method` method + # @raise [ArgumentError] the given `args` do not match the arity of `method` + # @return [IVar] the result of the method call + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#378 + def method_missing(method, *args, &block); end + + private + + # Check whether the method is responsive + # + # @param method [Symbol] the method being called + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#387 + def respond_to_missing?(method, include_private = T.unsafe(nil)); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#269 +module Concurrent::Async::ClassMethods + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#270 + def new(*args, **_arg1, &block); end +end + +# Atoms provide a way to manage shared, synchronous, independent state. +# +# An atom is initialized with an initial value and an optional validation +# proc. At any time the value of the atom can be synchronously and safely +# changed. If a validator is given at construction then any new value +# will be checked against the validator and will be rejected if the +# validator returns false or raises an exception. +# +# There are two ways to change the value of an atom: {#compare_and_set} and +# {#swap}. The former will set the new value if and only if it validates and +# the current value matches the new value. The latter will atomically set the +# new value to the result of running the given block if and only if that +# value validates. +# +# ## Example +# +# ``` +# def next_fibonacci(set = nil) +# return [0, 1] if set.nil? +# set + [set[-2..-1].reduce{|sum,x| sum + x }] +# end +# +# # create an atom with an initial value +# atom = Concurrent::Atom.new(next_fibonacci) +# +# # send a few update requests +# 5.times do +# atom.swap{|set| next_fibonacci(set) } +# end +# +# # get the current value +# atom.value #=> [0, 1, 1, 2, 3, 5, 8] +# ``` +# +# ## Observation +# +# Atoms support observers through the {Concurrent::Observable} mixin module. +# Notification of observers occurs every time the value of the Atom changes. +# When notified the observer will receive three arguments: `time`, `old_value`, +# and `new_value`. The `time` argument is the time at which the value change +# occurred. The `old_value` is the value of the Atom when the change began +# The `new_value` is the value to which the Atom was set when the change +# completed. Note that `old_value` and `new_value` may be the same. This is +# not an error. It simply means that the change operation returned the same +# value. +# +# Unlike in Clojure, `Atom` cannot participate in {Concurrent::TVar} transactions. +# +# +# ## Thread-safe Variable Classes +# +# Each of the thread-safe variable classes is designed to solve a different +# problem. In general: +# +# * *{Concurrent::Agent}:* Shared, mutable variable providing independent, +# uncoordinated, *asynchronous* change of individual values. Best used when +# the value will undergo frequent, complex updates. Suitable when the result +# of an update does not need to be known immediately. +# * *{Concurrent::Atom}:* Shared, mutable variable providing independent, +# uncoordinated, *synchronous* change of individual values. Best used when +# the value will undergo frequent reads but only occasional, though complex, +# updates. Suitable when the result of an update must be known immediately. +# * *{Concurrent::AtomicReference}:* A simple object reference that can be updated +# atomically. Updates are synchronous but fast. Best used when updates a +# simple set operations. Not suitable when updates are complex. +# {Concurrent::AtomicBoolean} and {Concurrent::AtomicFixnum} are similar +# but optimized for the given data type. +# * *{Concurrent::Exchanger}:* Shared, stateless synchronization point. Used +# when two or more threads need to exchange data. The threads will pair then +# block on each other until the exchange is complete. +# * *{Concurrent::MVar}:* Shared synchronization point. Used when one thread +# must give a value to another, which must take the value. The threads will +# block on each other until the exchange is complete. +# * *{Concurrent::ThreadLocalVar}:* Shared, mutable, isolated variable which +# holds a different value for each thread which has access. Often used as +# an instance variable in objects which must maintain different state +# for different threads. +# * *{Concurrent::TVar}:* Shared, mutable variables which provide +# *coordinated*, *synchronous*, change of *many* stated. Used when multiple +# value must change together, in an all-or-nothing transaction. +# +# @see http://clojure.org/atoms Clojure Atoms +# @see http://clojure.org/state Values and Change - Clojure's approach to Identity and State +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atom.rb#95 +class Concurrent::Atom < ::Concurrent::Synchronization::Object + include ::Concurrent::Concern::Observable + extend ::Concurrent::Synchronization::SafeInitialization + + # Create a new atom with the given initial value. + # + # @option opts + # @param value [Object] The initial value + # @param opts [Hash] The options used to configure the atom + # @raise [ArgumentError] if the validator is not a `Proc` (when given) + # @return [Atom] a new instance of Atom + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atom.rb#121 + def initialize(value, opts = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#137 + def __initialize_atomic_fields__; end + + # Atomically sets the value of atom to the new value if and only if the + # current value of the atom is identical to the old value and the new + # value successfully validates against the (optional) validator given + # at construction. + # + # @param old_value [Object] The expected current value. + # @param new_value [Object] The intended new value. + # @return [Boolean] True if the value is changed else false. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atom.rb#181 + def compare_and_set(old_value, new_value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#93 + def deref; end + + # Atomically sets the value of atom to the new value without regard for the + # current value so long as the new value successfully validates against the + # (optional) validator given at construction. + # + # @param new_value [Object] The intended new value. + # @return [Object] The final value of the atom after all operations and + # validations are complete. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atom.rb#198 + def reset(new_value); end + + # Atomically swaps the value of atom using the given block. The current + # value will be passed to the block, as will any arguments passed as + # arguments to the function. The new value will be validated against the + # (optional) validator proc given at construction. If validation fails the + # value will not be changed. + # + # Internally, {#swap} reads the current value, applies the block to it, and + # attempts to compare-and-set it in. Since another thread may have changed + # the value in the intervening time, it may have to retry, and does so in a + # spin loop. The net effect is that the value will always be the result of + # the application of the supplied block to a current value, atomically. + # However, because the block might be called multiple times, it must be free + # of side effects. + # + # @note The given block may be called multiple times, and thus should be free + # of side effects. + # @param args [Object] Zero or more arguments passed to the block. + # @raise [ArgumentError] When no block is given. + # @return [Object] The final value of the atom after all operations and + # validations are complete. + # @yield [value, args] Calculates a new value for the atom based on the + # current value and any supplied arguments. + # @yieldparam value [Object] The current value of the atom. + # @yieldparam args [Object] All arguments passed to the function, in order. + # @yieldreturn [Object] The intended new value of the atom. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atom.rb#157 + def swap(*args); end + + # The current value of the atom. + # + # @return [Object] The current value. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#93 + def value; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#105 + def compare_and_set_value(expected, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#101 + def swap_value(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#109 + def update_value(&block); end + + # Is the new value valid? + # + # @param new_value [Object] The intended new value. + # @return [Boolean] false if the validator function returns false or raises + # an exception else true + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atom.rb#216 + def valid?(new_value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#97 + def value=(value); end +end + +# A boolean value that can be updated atomically. Reads and writes to an atomic +# boolean and thread-safe and guaranteed to succeed. Reads and writes may block +# briefly but no explicit locking is required. +# +# +# ## Thread-safe Variable Classes +# +# Each of the thread-safe variable classes is designed to solve a different +# problem. In general: +# +# * *{Concurrent::Agent}:* Shared, mutable variable providing independent, +# uncoordinated, *asynchronous* change of individual values. Best used when +# the value will undergo frequent, complex updates. Suitable when the result +# of an update does not need to be known immediately. +# * *{Concurrent::Atom}:* Shared, mutable variable providing independent, +# uncoordinated, *synchronous* change of individual values. Best used when +# the value will undergo frequent reads but only occasional, though complex, +# updates. Suitable when the result of an update must be known immediately. +# * *{Concurrent::AtomicReference}:* A simple object reference that can be updated +# atomically. Updates are synchronous but fast. Best used when updates a +# simple set operations. Not suitable when updates are complex. +# {Concurrent::AtomicBoolean} and {Concurrent::AtomicFixnum} are similar +# but optimized for the given data type. +# * *{Concurrent::Exchanger}:* Shared, stateless synchronization point. Used +# when two or more threads need to exchange data. The threads will pair then +# block on each other until the exchange is complete. +# * *{Concurrent::MVar}:* Shared synchronization point. Used when one thread +# must give a value to another, which must take the value. The threads will +# block on each other until the exchange is complete. +# * *{Concurrent::ThreadLocalVar}:* Shared, mutable, isolated variable which +# holds a different value for each thread which has access. Often used as +# an instance variable in objects which must maintain different state +# for different threads. +# * *{Concurrent::TVar}:* Shared, mutable variables which provide +# *coordinated*, *synchronous*, change of *many* stated. Used when multiple +# value must change together, in an all-or-nothing transaction. +# Performance: +# +# ``` +# Testing with ruby 2.1.2 +# Testing with Concurrent::MutexAtomicBoolean... +# 2.790000 0.000000 2.790000 ( 2.791454) +# Testing with Concurrent::CAtomicBoolean... +# 0.740000 0.000000 0.740000 ( 0.740206) +# +# Testing with jruby 1.9.3 +# Testing with Concurrent::MutexAtomicBoolean... +# 5.240000 2.520000 7.760000 ( 3.683000) +# Testing with Concurrent::JavaAtomicBoolean... +# 3.340000 0.010000 3.350000 ( 0.855000) +# ``` +# +# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicBoolean.html java.util.concurrent.atomic.AtomicBoolean +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_boolean.rb#119 +class Concurrent::AtomicBoolean < ::Concurrent::MutexAtomicBoolean + # @return [String] Short string representation. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_boolean.rb#121 + def inspect; end + + # @return [String] Short string representation. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_boolean.rb#121 + def to_s; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_boolean.rb#82 +Concurrent::AtomicBooleanImplementation = Concurrent::MutexAtomicBoolean + +# Define update methods that use direct paths +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/atomic_direct_update.rb#9 +module Concurrent::AtomicDirectUpdate + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/atomic_direct_update.rb#15 + def try_update; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/atomic_direct_update.rb#24 + def try_update!; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/atomic_direct_update.rb#10 + def update; end +end + +# A numeric value that can be updated atomically. Reads and writes to an atomic +# fixnum and thread-safe and guaranteed to succeed. Reads and writes may block +# briefly but no explicit locking is required. +# +# +# ## Thread-safe Variable Classes +# +# Each of the thread-safe variable classes is designed to solve a different +# problem. In general: +# +# * *{Concurrent::Agent}:* Shared, mutable variable providing independent, +# uncoordinated, *asynchronous* change of individual values. Best used when +# the value will undergo frequent, complex updates. Suitable when the result +# of an update does not need to be known immediately. +# * *{Concurrent::Atom}:* Shared, mutable variable providing independent, +# uncoordinated, *synchronous* change of individual values. Best used when +# the value will undergo frequent reads but only occasional, though complex, +# updates. Suitable when the result of an update must be known immediately. +# * *{Concurrent::AtomicReference}:* A simple object reference that can be updated +# atomically. Updates are synchronous but fast. Best used when updates a +# simple set operations. Not suitable when updates are complex. +# {Concurrent::AtomicBoolean} and {Concurrent::AtomicFixnum} are similar +# but optimized for the given data type. +# * *{Concurrent::Exchanger}:* Shared, stateless synchronization point. Used +# when two or more threads need to exchange data. The threads will pair then +# block on each other until the exchange is complete. +# * *{Concurrent::MVar}:* Shared synchronization point. Used when one thread +# must give a value to another, which must take the value. The threads will +# block on each other until the exchange is complete. +# * *{Concurrent::ThreadLocalVar}:* Shared, mutable, isolated variable which +# holds a different value for each thread which has access. Often used as +# an instance variable in objects which must maintain different state +# for different threads. +# * *{Concurrent::TVar}:* Shared, mutable variables which provide +# *coordinated*, *synchronous*, change of *many* stated. Used when multiple +# value must change together, in an all-or-nothing transaction. +# Performance: +# +# ``` +# Testing with ruby 2.1.2 +# Testing with Concurrent::MutexAtomicFixnum... +# 3.130000 0.000000 3.130000 ( 3.136505) +# Testing with Concurrent::CAtomicFixnum... +# 0.790000 0.000000 0.790000 ( 0.785550) +# +# Testing with jruby 1.9.3 +# Testing with Concurrent::MutexAtomicFixnum... +# 5.460000 2.460000 7.920000 ( 3.715000) +# Testing with Concurrent::JavaAtomicFixnum... +# 4.520000 0.030000 4.550000 ( 1.187000) +# ``` +# +# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicLong.html java.util.concurrent.atomic.AtomicLong +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_fixnum.rb#136 +class Concurrent::AtomicFixnum < ::Concurrent::MutexAtomicFixnum + # @return [String] Short string representation. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_fixnum.rb#138 + def inspect; end + + # @return [String] Short string representation. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_fixnum.rb#138 + def to_s; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_fixnum.rb#99 +Concurrent::AtomicFixnumImplementation = Concurrent::MutexAtomicFixnum + +# An atomic reference which maintains an object reference along with a mark bit +# that can be updated atomically. +# +# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicMarkableReference.html java.util.concurrent.atomic.AtomicMarkableReference +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb#10 +class Concurrent::AtomicMarkableReference < ::Concurrent::Synchronization::Object + extend ::Concurrent::Synchronization::SafeInitialization + + # @return [AtomicMarkableReference] a new instance of AtomicMarkableReference + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb#15 + def initialize(value = T.unsafe(nil), mark = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#137 + def __initialize_atomic_fields__; end + + # Atomically sets the value and mark to the given updated value and + # mark given both: + # - the current value == the expected value && + # - the current mark == the expected mark + # + # that the actual value was not equal to the expected value or the + # actual mark was not equal to the expected mark + # + # @param expected_val [Object] the expected value + # @param new_val [Object] the new value + # @param expected_mark [Boolean] the expected mark + # @param new_mark [Boolean] the new mark + # @return [Boolean] `true` if successful. A `false` return indicates + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb#33 + def compare_and_set(expected_val, new_val, expected_mark, new_mark); end + + # Atomically sets the value and mark to the given updated value and + # mark given both: + # - the current value == the expected value && + # - the current mark == the expected mark + # + # that the actual value was not equal to the expected value or the + # actual mark was not equal to the expected mark + # + # @param expected_val [Object] the expected value + # @param new_val [Object] the new value + # @param expected_mark [Boolean] the expected mark + # @param new_mark [Boolean] the new mark + # @return [Boolean] `true` if successful. A `false` return indicates + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb#33 + def compare_and_swap(expected_val, new_val, expected_mark, new_mark); end + + # Gets the current reference and marked values. + # + # @return [Array] the current reference and marked values + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb#64 + def get; end + + # Gets the current marked value + # + # @return [Boolean] the current marked value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb#78 + def mark; end + + # Gets the current marked value + # + # @return [Boolean] the current marked value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb#78 + def marked?; end + + # _Unconditionally_ sets to the given value of both the reference and + # the mark. + # + # @param new_val [Object] the new value + # @param new_mark [Boolean] the new mark + # @return [Array] both the new value and the new mark + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb#91 + def set(new_val, new_mark); end + + # Pass the current value to the given block, replacing it with the + # block's result. Simply return nil if update fails. + # + # the update failed + # + # @return [Array] the new value and marked state, or nil if + # @yield [Object] Calculate a new value and marked state for the atomic + # reference using given (old) value and (old) marked + # @yieldparam old_val [Object] the starting value of the atomic reference + # @yieldparam old_mark [Boolean] the starting state of marked + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb#152 + def try_update; end + + # Pass the current value to the given block, replacing it + # with the block's result. Raise an exception if the update + # fails. + # + # @raise [Concurrent::ConcurrentUpdateError] if the update fails + # @return [Array] the new value and marked state + # @yield [Object] Calculate a new value and marked state for the atomic + # reference using given (old) value and (old) marked + # @yieldparam old_val [Object] the starting value of the atomic reference + # @yieldparam old_mark [Boolean] the starting state of marked + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb#128 + def try_update!; end + + # Pass the current value and marked state to the given block, replacing it + # with the block's results. May retry if the value changes during the + # block's execution. + # + # @return [Array] the new value and new mark + # @yield [Object] Calculate a new value and marked state for the atomic + # reference using given (old) value and (old) marked + # @yieldparam old_val [Object] the starting value of the atomic reference + # @yieldparam old_mark [Boolean] the starting state of marked + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb#105 + def update; end + + # Gets the current value of the reference + # + # @return [Object] the current value of the reference + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb#71 + def value; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#105 + def compare_and_set_reference(expected, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb#163 + def immutable_array(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#93 + def reference; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#97 + def reference=(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#101 + def swap_reference(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#109 + def update_reference(&block); end +end + +# Special "compare and set" handling of numeric values. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/numeric_cas_wrapper.rb#7 +module Concurrent::AtomicNumericCompareAndSetWrapper + # Atomically sets the value to the given updated value if + # the current value == the expected value. + # + # that the actual value was not equal to the expected value. + # + # @param old_value [Object] the expected value + # @param new_value [Object] the new value + # @return [Boolean] `true` if successful. A `false` return indicates + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/numeric_cas_wrapper.rb#10 + def compare_and_set(old_value, new_value); end +end + +# An object reference that may be updated atomically. All read and write +# operations have java volatile semantic. +# +# +# ## Thread-safe Variable Classes +# +# Each of the thread-safe variable classes is designed to solve a different +# problem. In general: +# +# * *{Concurrent::Agent}:* Shared, mutable variable providing independent, +# uncoordinated, *asynchronous* change of individual values. Best used when +# the value will undergo frequent, complex updates. Suitable when the result +# of an update does not need to be known immediately. +# * *{Concurrent::Atom}:* Shared, mutable variable providing independent, +# uncoordinated, *synchronous* change of individual values. Best used when +# the value will undergo frequent reads but only occasional, though complex, +# updates. Suitable when the result of an update must be known immediately. +# * *{Concurrent::AtomicReference}:* A simple object reference that can be updated +# atomically. Updates are synchronous but fast. Best used when updates a +# simple set operations. Not suitable when updates are complex. +# {Concurrent::AtomicBoolean} and {Concurrent::AtomicFixnum} are similar +# but optimized for the given data type. +# * *{Concurrent::Exchanger}:* Shared, stateless synchronization point. Used +# when two or more threads need to exchange data. The threads will pair then +# block on each other until the exchange is complete. +# * *{Concurrent::MVar}:* Shared synchronization point. Used when one thread +# must give a value to another, which must take the value. The threads will +# block on each other until the exchange is complete. +# * *{Concurrent::ThreadLocalVar}:* Shared, mutable, isolated variable which +# holds a different value for each thread which has access. Often used as +# an instance variable in objects which must maintain different state +# for different threads. +# * *{Concurrent::TVar}:* Shared, mutable variables which provide +# *coordinated*, *synchronous*, change of *many* stated. Used when multiple +# value must change together, in an all-or-nothing transaction. +# +# @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicReference.html +# @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/package-summary.html +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb#126 +class Concurrent::AtomicReference < ::Concurrent::MutexAtomicReference + # @return [String] Short string representation. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb#129 + def inspect; end + + # @return [String] Short string representation. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb#129 + def to_s; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb#18 +Concurrent::AtomicReferenceImplementation = Concurrent::MutexAtomicReference + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/set.rb#30 +class Concurrent::CRubySet < ::Set + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#18 + def initialize(*args, &block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def &(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def +(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def -(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def <(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def <<(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def <=(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def <=>(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def ==(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def ===(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def >(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def >=(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def ^(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def add(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def add?(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def classify(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def clear(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def collect!(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def compare_by_identity(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def compare_by_identity?(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def delete(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def delete?(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def delete_if(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def difference(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def disjoint?(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def divide(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def each(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def empty?(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def eql?(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def filter!(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def flatten(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def flatten!(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def flatten_merge(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def freeze(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def hash(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def include?(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def inspect(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def intersect?(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def intersection(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def join(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def keep_if(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def length(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def map!(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def member?(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def merge(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def pretty_print(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def pretty_print_cycle(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def proper_subset?(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def proper_superset?(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def reject!(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def replace(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def reset(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def select!(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def size(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def subset?(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def subtract(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def superset?(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def to_a(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def to_s(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def to_set(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def union(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def |(*args); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#23 + def initialize_copy(other); end +end + +# A thread pool that dynamically grows and shrinks to fit the current workload. +# New threads are created as needed, existing threads are reused, and threads +# that remain idle for too long are killed and removed from the pool. These +# pools are particularly suited to applications that perform a high volume of +# short-lived tasks. +# +# On creation a `CachedThreadPool` has zero running threads. New threads are +# created on the pool as new operations are `#post`. The size of the pool +# will grow until `#max_length` threads are in the pool or until the number +# of threads exceeds the number of running and pending operations. When a new +# operation is post to the pool the first available idle thread will be tasked +# with the new operation. +# +# Should a thread crash for any reason the thread will immediately be removed +# from the pool. Similarly, threads which remain idle for an extended period +# of time will be killed and reclaimed. Thus these thread pools are very +# efficient at reclaiming unused resources. +# +# The API and behavior of this class are based on Java's `CachedThreadPool` +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/cached_thread_pool.rb#27 +class Concurrent::CachedThreadPool < ::Concurrent::ThreadPoolExecutor + # Create a new thread pool. + # + # @option opts + # @param opts [Hash] the options defining pool behavior. + # @raise [ArgumentError] if `fallback_policy` is not a known policy + # @return [CachedThreadPool] a new instance of CachedThreadPool + # @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executors.html#newCachedThreadPool-- + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/cached_thread_pool.rb#39 + def initialize(opts = T.unsafe(nil)); end + + private + + # Create a new thread pool. + # + # @option opts + # @param opts [Hash] the options defining pool behavior. + # @raise [ArgumentError] if `fallback_policy` is not a known policy + # @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executors.html#newCachedThreadPool-- + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/cached_thread_pool.rb#51 + def ns_initialize(opts); end +end + +# Raised when an asynchronous operation is cancelled before execution. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#9 +class Concurrent::CancelledOperationError < ::Concurrent::Error; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb#4 +module Concurrent::Collection; end + +# A thread safe observer set implemented using copy-on-read approach: +# observers are added and removed from a thread safe collection; every time +# a notification is required the internal data structure is copied to +# prevent concurrency issues +# +# @api private +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb#12 +class Concurrent::Collection::CopyOnNotifyObserverSet < ::Concurrent::Synchronization::LockableObject + # @api private + # @return [CopyOnNotifyObserverSet] a new instance of CopyOnNotifyObserverSet + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb#14 + def initialize; end + + # @api private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb#20 + def add_observer(observer = T.unsafe(nil), func = T.unsafe(nil), &block); end + + # @api private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb#55 + def count_observers; end + + # @api private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb#39 + def delete_observer(observer); end + + # @api private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb#47 + def delete_observers; end + + # Notifies all registered observers with optional args and deletes them. + # + # @api private + # @param args [Object] arguments to be passed to each observer + # @return [CopyOnWriteObserverSet] self + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb#72 + def notify_and_delete_observers(*args, &block); end + + # Notifies all registered observers with optional args + # + # @api private + # @param args [Object] arguments to be passed to each observer + # @return [CopyOnWriteObserverSet] self + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb#62 + def notify_observers(*args, &block); end + + protected + + # @api private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb#80 + def ns_initialize; end + + private + + # @api private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb#86 + def duplicate_and_clear_observers; end + + # @api private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb#94 + def duplicate_observers; end + + # @api private + # @raise [ArgumentError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb#98 + def notify_to(observers, *args); end +end + +# A thread safe observer set implemented using copy-on-write approach: +# every time an observer is added or removed the whole internal data structure is +# duplicated and replaced with a new one. +# +# @api private +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb#11 +class Concurrent::Collection::CopyOnWriteObserverSet < ::Concurrent::Synchronization::LockableObject + # @api private + # @return [CopyOnWriteObserverSet] a new instance of CopyOnWriteObserverSet + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb#13 + def initialize; end + + # @api private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb#19 + def add_observer(observer = T.unsafe(nil), func = T.unsafe(nil), &block); end + + # @api private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb#56 + def count_observers; end + + # @api private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb#40 + def delete_observer(observer); end + + # @api private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb#50 + def delete_observers; end + + # Notifies all registered observers with optional args and deletes them. + # + # @api private + # @param args [Object] arguments to be passed to each observer + # @return [CopyOnWriteObserverSet] self + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb#72 + def notify_and_delete_observers(*args, &block); end + + # Notifies all registered observers with optional args + # + # @api private + # @param args [Object] arguments to be passed to each observer + # @return [CopyOnWriteObserverSet] self + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb#63 + def notify_observers(*args, &block); end + + protected + + # @api private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb#80 + def ns_initialize; end + + private + + # @api private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb#102 + def clear_observers_and_return_old; end + + # @api private + # @raise [ArgumentError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb#86 + def notify_to(observers, *args); end + + # @api private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb#94 + def observers; end + + # @api private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb#98 + def observers=(new_set); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#10 +Concurrent::Collection::MapImplementation = Concurrent::Collection::MriMapBackend + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb#10 +class Concurrent::Collection::MriMapBackend < ::Concurrent::Collection::NonConcurrentMapBackend + # @return [MriMapBackend] a new instance of MriMapBackend + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb#12 + def initialize(options = T.unsafe(nil), &default_proc); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb#17 + def []=(key, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb#61 + def clear; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb#33 + def compute(key); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb#21 + def compute_if_absent(key); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb#29 + def compute_if_present(key); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb#53 + def delete(key); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb#57 + def delete_pair(key, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb#49 + def get_and_set(key, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb#37 + def merge_pair(key, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb#45 + def replace_if_exists(key, new_value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb#41 + def replace_pair(key, old_value, new_value); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#9 +class Concurrent::Collection::NonConcurrentMapBackend + # WARNING: all public methods of the class must operate on the @backend + # directly without calling each other. This is important because of the + # SynchronizedMapBackend which uses a non-reentrant mutex for performance + # reasons. + # + # @return [NonConcurrentMapBackend] a new instance of NonConcurrentMapBackend + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#15 + def initialize(options = T.unsafe(nil), &default_proc); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#21 + def [](key); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#25 + def []=(key, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#94 + def clear; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#59 + def compute(key); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#29 + def compute_if_absent(key); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#53 + def compute_if_present(key); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#81 + def delete(key); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#85 + def delete_pair(key, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#99 + def each_pair; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#71 + def get_and_set(key, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#110 + def get_or_default(key, default_value); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#77 + def key?(key); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#63 + def merge_pair(key, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#46 + def replace_if_exists(key, new_value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#37 + def replace_pair(key, old_value, new_value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#106 + def size; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#130 + def dupped_backend; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#124 + def initialize_copy(other); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#134 + def pair?(key, expected_value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#116 + def set_backend(default_proc); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#138 + def store_computed_value(key, new_value); end +end + +# A queue collection in which the elements are sorted based on their +# comparison (spaceship) operator `<=>`. Items are added to the queue +# at a position relative to their priority. On removal the element +# with the "highest" priority is removed. By default the sort order is +# from highest to lowest, but a lowest-to-highest sort order can be +# set on construction. +# +# The API is based on the `Queue` class from the Ruby standard library. +# +# The pure Ruby implementation, `RubyNonConcurrentPriorityQueue` uses a heap algorithm +# stored in an array. The algorithm is based on the work of Robert Sedgewick +# and Kevin Wayne. +# +# The JRuby native implementation is a thin wrapper around the standard +# library `java.util.NonConcurrentPriorityQueue`. +# +# When running under JRuby the class `NonConcurrentPriorityQueue` extends `JavaNonConcurrentPriorityQueue`. +# When running under all other interpreters it extends `RubyNonConcurrentPriorityQueue`. +# +# @note This implementation is *not* thread safe. +# @see http://en.wikipedia.org/wiki/Priority_queue +# @see http://ruby-doc.org/stdlib-2.0.0/libdoc/thread/rdoc/Queue.html +# @see http://algs4.cs.princeton.edu/24pq/index.php#2.6 +# @see http://algs4.cs.princeton.edu/24pq/MaxPQ.java.html +# @see http://docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/non_concurrent_priority_queue.rb#50 +class Concurrent::Collection::NonConcurrentPriorityQueue < ::Concurrent::Collection::RubyNonConcurrentPriorityQueue + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#78 + def <<(item); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#65 + def deq; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#78 + def enq(item); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#48 + def has_priority?(item); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#65 + def shift; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#54 + def size; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/non_concurrent_priority_queue.rb#10 +Concurrent::Collection::NonConcurrentPriorityQueueImplementation = Concurrent::Collection::RubyNonConcurrentPriorityQueue + +# A queue collection in which the elements are sorted based on their +# comparison (spaceship) operator `<=>`. Items are added to the queue +# at a position relative to their priority. On removal the element +# with the "highest" priority is removed. By default the sort order is +# from highest to lowest, but a lowest-to-highest sort order can be +# set on construction. +# +# The API is based on the `Queue` class from the Ruby standard library. +# +# The pure Ruby implementation, `RubyNonConcurrentPriorityQueue` uses a heap algorithm +# stored in an array. The algorithm is based on the work of Robert Sedgewick +# and Kevin Wayne. +# +# The JRuby native implementation is a thin wrapper around the standard +# library `java.util.NonConcurrentPriorityQueue`. +# +# When running under JRuby the class `NonConcurrentPriorityQueue` extends `JavaNonConcurrentPriorityQueue`. +# When running under all other interpreters it extends `RubyNonConcurrentPriorityQueue`. +# +# @note This implementation is *not* thread safe. +# @see http://en.wikipedia.org/wiki/Priority_queue +# @see http://ruby-doc.org/stdlib-2.0.0/libdoc/thread/rdoc/Queue.html +# @see http://algs4.cs.princeton.edu/24pq/index.php#2.6 +# @see http://algs4.cs.princeton.edu/24pq/MaxPQ.java.html +# @see http://docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#8 +class Concurrent::Collection::RubyNonConcurrentPriorityQueue + # Create a new priority queue with no items. + # + # @option opts + # @param opts [Hash] the options for creating the queue + # @return [RubyNonConcurrentPriorityQueue] a new instance of RubyNonConcurrentPriorityQueue + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#11 + def initialize(opts = T.unsafe(nil)); end + + # Inserts the specified element into this priority queue. + # + # @param item [Object] the item to insert onto the queue + # @raise [ArgumentError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#78 + def <<(item); end + + # Removes all of the elements from this priority queue. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#18 + def clear; end + + # Deletes all items from `self` that are equal to `item`. + # + # @param item [Object] the item to be removed from the queue + # @return [Object] true if the item is found else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#25 + def delete(item); end + + # Retrieves and removes the head of this queue, or returns `nil` if this + # queue is empty. + # + # @return [Object] the head of the queue or `nil` when empty + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#65 + def deq; end + + # Returns `true` if `self` contains no elements. + # + # @return [Boolean] true if there are no items in the queue else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#43 + def empty?; end + + # Inserts the specified element into this priority queue. + # + # @param item [Object] the item to insert onto the queue + # @raise [ArgumentError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#78 + def enq(item); end + + # Returns `true` if the given item is present in `self` (that is, if any + # element == `item`), otherwise returns false. + # + # @param item [Object] the item to search for + # @return [Boolean] true if the item is found else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#48 + def has_priority?(item); end + + # Returns `true` if the given item is present in `self` (that is, if any + # element == `item`), otherwise returns false. + # + # @param item [Object] the item to search for + # @return [Boolean] true if the item is found else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#48 + def include?(item); end + + # The current length of the queue. + # + # @return [Fixnum] the number of items in the queue + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#54 + def length; end + + # Retrieves, but does not remove, the head of this queue, or returns `nil` + # if this queue is empty. + # + # @return [Object] the head of the queue or `nil` when empty + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#60 + def peek; end + + # Retrieves and removes the head of this queue, or returns `nil` if this + # queue is empty. + # + # @return [Object] the head of the queue or `nil` when empty + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#65 + def pop; end + + # Inserts the specified element into this priority queue. + # + # @param item [Object] the item to insert onto the queue + # @raise [ArgumentError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#78 + def push(item); end + + # Retrieves and removes the head of this queue, or returns `nil` if this + # queue is empty. + # + # @return [Object] the head of the queue or `nil` when empty + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#65 + def shift; end + + # The current length of the queue. + # + # @return [Fixnum] the number of items in the queue + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#54 + def size; end + + private + + # Are the items at the given indexes ordered based on the priority + # order specified at construction? + # + # @param x [Integer] the first index from which to retrieve a comparable value + # @param y [Integer] the second index from which to retrieve a comparable value + # @return [Boolean] true if the two elements are in the correct priority order + # else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#119 + def ordered?(x, y); end + + # Percolate down to maintain heap invariant. + # + # @param k [Integer] the index at which to start the percolation + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#128 + def sink(k); end + + # Exchange the values at the given indexes within the internal array. + # + # @param x [Integer] the first index to swap + # @param y [Integer] the second index to swap + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#103 + def swap(x, y); end + + # Percolate up to maintain heap invariant. + # + # @param k [Integer] the index at which to start the percolation + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#147 + def swim(k); end + + class << self + # @!macro priority_queue_method_from_list + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#89 + def from_list(list, opts = T.unsafe(nil)); end + end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/dereferenceable.rb#2 +module Concurrent::Concern; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/deprecation.rb#8 +module Concurrent::Concern::Deprecation + include ::Logger::Severity + include ::Concurrent::Concern::Logging + extend ::Logger::Severity + extend ::Concurrent::Concern::Logging + extend ::Concurrent::Concern::Deprecation + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/deprecation.rb#12 + def deprecated(message, strip = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/deprecation.rb#27 + def deprecated_method(old_name, new_name); end +end + +# Object references in Ruby are mutable. This can lead to serious problems when +# the `#value` of a concurrent object is a mutable reference. Which is always the +# case unless the value is a `Fixnum`, `Symbol`, or similar "primitive" data type. +# Most classes in this library that expose a `#value` getter method do so using the +# `Dereferenceable` mixin module. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/dereferenceable.rb#11 +module Concurrent::Concern::Dereferenceable + # Return the value this object represents after applying the options specified + # by the `#set_deref_options` method. + # + # @return [Object] the current value of the object + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/dereferenceable.rb#21 + def deref; end + + # Return the value this object represents after applying the options specified + # by the `#set_deref_options` method. + # + # @return [Object] the current value of the object + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/dereferenceable.rb#21 + def value; end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/dereferenceable.rb#63 + def apply_deref_options(value); end + + # Set the options which define the operations #value performs before + # returning data to the caller (dereferencing). + # + # @note Most classes that include this module will call `#set_deref_options` + # from within the constructor, thus allowing these options to be set at + # object creation. + # @option opts + # @option opts + # @option opts + # @param opts [Hash] the options defining dereference behavior. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/dereferenceable.rb#54 + def ns_set_deref_options(opts); end + + # Set the options which define the operations #value performs before + # returning data to the caller (dereferencing). + # + # @note Most classes that include this module will call `#set_deref_options` + # from within the constructor, thus allowing these options to be set at + # object creation. + # @option opts + # @option opts + # @option opts + # @param opts [Hash] the options defining dereference behavior. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/dereferenceable.rb#48 + def set_deref_options(opts = T.unsafe(nil)); end + + # Set the internal value of this object + # + # @param value [Object] the new value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/dereferenceable.rb#31 + def value=(value); end +end + +# Include where logging is needed +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/logging.rb#10 +module Concurrent::Concern::Logging + include ::Logger::Severity + + # Logs through {Concurrent.global_logger}, it can be overridden by setting @logger + # + # @param level [Integer] one of Logger::Severity constants + # @param progname [String] e.g. a path of an Actor + # @param message [String, nil] when nil block is used to generate the message + # @yieldreturn [String] a message + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/logging.rb#18 + def log(level, progname, message = T.unsafe(nil), &block); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#10 +module Concurrent::Concern::Obligation + include ::Concurrent::Concern::Dereferenceable + + # Has the obligation completed processing? + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#49 + def complete?; end + + # @example allows Obligation to be risen + # rejected_ivar = Ivar.new.fail + # raise rejected_ivar + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#126 + def exception(*args); end + + # Has the obligation been fulfilled? + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#20 + def fulfilled?; end + + # Is the obligation still awaiting completion of processing? + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#56 + def incomplete?; end + + # Wait until obligation is complete or the timeout is reached. Will re-raise + # any exceptions raised during processing (but will not raise an exception + # on timeout). + # + # @param timeout [Numeric] the maximum time in seconds to wait. + # @raise [Exception] raises the reason when rejected + # @return [Obligation] self + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#86 + def no_error!(timeout = T.unsafe(nil)); end + + # Is obligation completion still pending? + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#35 + def pending?; end + + # Has the obligation been fulfilled? + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#20 + def realized?; end + + # If an exception was raised during processing this will return the + # exception object. Will return `nil` when the state is pending or if + # the obligation has been successfully fulfilled. + # + # @return [Exception] the exception raised during processing or `nil` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#119 + def reason; end + + # Has the obligation been rejected? + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#28 + def rejected?; end + + # The current state of the obligation. + # + # @return [Symbol] the current state + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#110 + def state; end + + # Is the obligation still unscheduled? + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#42 + def unscheduled?; end + + # The current value of the obligation. Will be `nil` while the state is + # pending or the operation has been rejected. + # + # @param timeout [Numeric] the maximum time in seconds to wait. + # @return [Object] see Dereferenceable#deref + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#65 + def value(timeout = T.unsafe(nil)); end + + # The current value of the obligation. Will be `nil` while the state is + # pending or the operation has been rejected. Will re-raise any exceptions + # raised during processing (but will not raise an exception on timeout). + # + # @param timeout [Numeric] the maximum time in seconds to wait. + # @raise [Exception] raises the reason when rejected + # @return [Object] see Dereferenceable#deref + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#98 + def value!(timeout = T.unsafe(nil)); end + + # Wait until obligation is complete or the timeout has been reached. + # + # @param timeout [Numeric] the maximum time in seconds to wait. + # @return [Obligation] self + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#74 + def wait(timeout = T.unsafe(nil)); end + + # Wait until obligation is complete or the timeout is reached. Will re-raise + # any exceptions raised during processing (but will not raise an exception + # on timeout). + # + # @param timeout [Numeric] the maximum time in seconds to wait. + # @raise [Exception] raises the reason when rejected + # @return [Obligation] self + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#86 + def wait!(timeout = T.unsafe(nil)); end + + protected + + # Atomic compare and set operation + # State is set to `next_state` only if `current state == expected_current`. + # + # @param next_state [Symbol] + # @param expected_current [Symbol] + # @return [Boolean] true is state is changed, false otherwise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#174 + def compare_and_set_state(next_state, *expected_current); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#145 + def event; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#134 + def get_arguments_from(opts = T.unsafe(nil)); end + + # Executes the block within mutex if current state is included in expected_states + # + # @return block value if executed, false otherwise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#190 + def if_state(*expected_states); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#139 + def init_obligation; end + + # Am I in the current state? + # + # @param expected [Symbol] The state to check against + # @return [Boolean] true if in the expected state else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#210 + def ns_check_state?(expected); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#215 + def ns_set_state(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#150 + def set_state(success, value, reason); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#161 + def state=(value); end +end + +# The [observer pattern](http://en.wikipedia.org/wiki/Observer_pattern) is one +# of the most useful design patterns. +# +# The workflow is very simple: +# - an `observer` can register itself to a `subject` via a callback +# - many `observers` can be registered to the same `subject` +# - the `subject` notifies all registered observers when its status changes +# - an `observer` can deregister itself when is no more interested to receive +# event notifications +# +# In a single threaded environment the whole pattern is very easy: the +# `subject` can use a simple data structure to manage all its subscribed +# `observer`s and every `observer` can react directly to every event without +# caring about synchronization. +# +# In a multi threaded environment things are more complex. The `subject` must +# synchronize the access to its data structure and to do so currently we're +# using two specialized ObserverSet: {Concurrent::Concern::CopyOnWriteObserverSet} +# and {Concurrent::Concern::CopyOnNotifyObserverSet}. +# +# When implementing and `observer` there's a very important rule to remember: +# **there are no guarantees about the thread that will execute the callback** +# +# Let's take this example +# ``` +# class Observer +# def initialize +# @count = 0 +# end +# +# def update +# @count += 1 +# end +# end +# +# obs = Observer.new +# [obj1, obj2, obj3, obj4].each { |o| o.add_observer(obs) } +# # execute [obj1, obj2, obj3, obj4] +# ``` +# +# `obs` is wrong because the variable `@count` can be accessed by different +# threads at the same time, so it should be synchronized (using either a Mutex +# or an AtomicFixum) +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/observable.rb#50 +module Concurrent::Concern::Observable + # Adds an observer to this set. If a block is passed, the observer will be + # created by this method and no other params should be passed. + # + # @param observer [Object] the observer to add + # @param func [Symbol] the function to call on the observer during notification. + # Default is :update + # @return [Object] the added observer + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/observable.rb#61 + def add_observer(observer = T.unsafe(nil), func = T.unsafe(nil), &block); end + + # Return the number of observers associated with this object. + # + # @return [Integer] the observers count + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/observable.rb#101 + def count_observers; end + + # Remove `observer` as an observer on this object so that it will no + # longer receive notifications. + # + # @param observer [Object] the observer to remove + # @return [Object] the deleted observer + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/observable.rb#82 + def delete_observer(observer); end + + # Remove all observers associated with this object. + # + # @return [Observable] self + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/observable.rb#91 + def delete_observers; end + + # As `#add_observer` but can be used for chaining. + # + # @param observer [Object] the observer to add + # @param func [Symbol] the function to call on the observer during notification. + # @return [Observable] self + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/observable.rb#70 + def with_observer(observer = T.unsafe(nil), func = T.unsafe(nil), &block); end + + protected + + # Returns the value of attribute observers. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/observable.rb#107 + def observers; end + + # Sets the attribute observers + # + # @param value the value to set the attribute observers to. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/observable.rb#107 + def observers=(_arg0); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#70 +class Concurrent::ConcurrentUpdateError < ::ThreadError; end + +# frozen pre-allocated backtrace to speed ConcurrentUpdateError +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#72 +Concurrent::ConcurrentUpdateError::CONC_UP_ERR_BACKTRACE = T.let(T.unsafe(nil), Array) + +# Raised when errors occur during configuration. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#6 +class Concurrent::ConfigurationError < ::Concurrent::Error; end + +# A synchronization object that allows one thread to wait on multiple other threads. +# The thread that will wait creates a `CountDownLatch` and sets the initial value +# (normally equal to the number of other threads). The initiating thread passes the +# latch to the other threads then waits for the other threads by calling the `#wait` +# method. Each of the other threads calls `#count_down` when done with its work. +# When the latch counter reaches zero the waiting thread is unblocked and continues +# with its work. A `CountDownLatch` can be used only once. Its value cannot be reset. +# +# @example Waiter and Decrementer +# latch = Concurrent::CountDownLatch.new(3) +# +# waiter = Thread.new do +# latch.wait() +# puts ("Waiter released") +# end +# +# decrementer = Thread.new do +# sleep(1) +# latch.count_down +# puts latch.count +# +# sleep(1) +# latch.count_down +# puts latch.count +# +# sleep(1) +# latch.count_down +# puts latch.count +# end +# +# [waiter, decrementer].each(&:join) +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/count_down_latch.rb#98 +class Concurrent::CountDownLatch < ::Concurrent::MutexCountDownLatch; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/count_down_latch.rb#56 +Concurrent::CountDownLatchImplementation = Concurrent::MutexCountDownLatch + +# A synchronization aid that allows a set of threads to all wait for each +# other to reach a common barrier point. +# +# @example +# barrier = Concurrent::CyclicBarrier.new(3) +# jobs = Array.new(3) { |i| -> { sleep i; p done: i } } +# process = -> (i) do +# # waiting to start at the same time +# barrier.wait +# # execute job +# jobs[i].call +# # wait for others to finish +# barrier.wait +# end +# threads = 2.times.map do |i| +# Thread.new(i, &process) +# end +# +# # use main as well +# process.call 2 +# +# # here we can be sure that all jobs are processed +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb#27 +class Concurrent::CyclicBarrier < ::Concurrent::Synchronization::LockableObject + # Create a new `CyclicBarrier` that waits for `parties` threads + # + # @param parties [Fixnum] the number of parties + # @raise [ArgumentError] if `parties` is not an integer or is less than zero + # @return [CyclicBarrier] a new instance of CyclicBarrier + # @yield an optional block that will be executed that will be executed after + # the last thread arrives and before the others are released + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb#40 + def initialize(parties, &block); end + + # A barrier can be broken when: + # - a thread called the `reset` method while at least one other thread was waiting + # - at least one thread timed out on `wait` method + # + # A broken barrier can be restored using `reset` it's safer to create a new one + # + # @return [Boolean] true if the barrier is broken otherwise false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb#105 + def broken?; end + + # @return [Fixnum] the number of threads currently waiting on the barrier + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb#54 + def number_waiting; end + + # @return [Fixnum] the number of threads needed to pass the barrier + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb#49 + def parties; end + + # resets the barrier to its initial state + # If there is at least one waiting thread, it will be woken up, the `wait` + # method will return false and the barrier will be broken + # If the barrier is broken, this method restores it to the original state + # + # @return [nil] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb#95 + def reset; end + + # Blocks on the barrier until the number of waiting threads is equal to + # `parties` or until `timeout` is reached or `reset` is called + # If a block has been passed to the constructor, it will be executed once by + # the last arrived thread before releasing the others + # + # @param timeout [Fixnum] the number of seconds to wait for the counter or + # `nil` to block indefinitely + # @return [Boolean] `true` if the `count` reaches zero else false on + # `timeout` or on `reset` or if the barrier is broken + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb#66 + def wait(timeout = T.unsafe(nil)); end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb#111 + def ns_generation_done(generation, status, continue = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb#122 + def ns_initialize(parties, &block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb#117 + def ns_next_generation; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb#30 +class Concurrent::CyclicBarrier::Generation < ::Struct + # Returns the value of attribute status + # + # @return [Object] the current value of status + def status; end + + # Sets the attribute status + # + # @param value [Object] the value to set the attribute status to. + # @return [Object] the newly set value + def status=(_); end + + class << self + def [](*_arg0); end + def inspect; end + def keyword_init?; end + def members; end + def new(*_arg0); end + end +end + +# Lazy evaluation of a block yielding an immutable result. Useful for +# expensive operations that may never be needed. It may be non-blocking, +# supports the `Concern::Obligation` interface, and accepts the injection of +# custom executor upon which to execute the block. Processing of +# block will be deferred until the first time `#value` is called. +# At that time the caller can choose to return immediately and let +# the block execute asynchronously, block indefinitely, or block +# with a timeout. +# +# 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 +# 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 +# blocked on `#value` will return. Subsequent calls to `#value` will immediately +# return the cached value. The operation will only be run once. This means that +# any side effects created by the operation will only happen once as well. +# +# `Delay` includes the `Concurrent::Concern::Dereferenceable` mixin to support thread +# safety of the reference returned by `#value`. +# +# @note The default behavior of `Delay` is to block indefinitely when +# calling either `value` or `wait`, executing the delayed operation on +# the current thread. This makes the `timeout` value completely +# irrelevant. To enable non-blocking behavior, use the `executor` +# constructor option. This will cause the delayed operation to be +# execute on the given executor, allowing the call to timeout. +# @see Concurrent::Concern::Dereferenceable +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/delay.rb#44 +class Concurrent::Delay < ::Concurrent::Synchronization::LockableObject + include ::Concurrent::Concern::Dereferenceable + include ::Concurrent::Concern::Obligation + + # Create a new `Delay` in the `:pending` state. + # + # @raise [ArgumentError] if no block is given + # @return [Delay] a new instance of Delay + # @yield the delayed operation to perform + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/delay.rb#62 + def initialize(opts = T.unsafe(nil), &block); end + + # Reconfigures the block returning the value if still `#incomplete?` + # + # @return [true, false] if success + # @yield the delayed operation to perform + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/delay.rb#146 + def reconfigure(&block); end + + # Return the value this object represents after applying the options + # specified by the `#set_deref_options` method. If the delayed operation + # raised an exception this method will return nil. The exception object + # can be accessed via the `#reason` method. + # + # @note The default behavior of `Delay` is to block indefinitely when + # calling either `value` or `wait`, executing the delayed operation on + # the current thread. This makes the `timeout` value completely + # irrelevant. To enable non-blocking behavior, use the `executor` + # constructor option. This will cause the delayed operation to be + # execute on the given executor, allowing the call to timeout. + # @param timeout [Numeric] the maximum number of seconds to wait + # @return [Object] the current value of the object + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/delay.rb#77 + def value(timeout = T.unsafe(nil)); end + + # Return the value this object represents after applying the options + # specified by the `#set_deref_options` method. If the delayed operation + # raised an exception, this method will raise that exception (even when) + # the operation has already been executed). + # + # @note The default behavior of `Delay` is to block indefinitely when + # calling either `value` or `wait`, executing the delayed operation on + # the current thread. This makes the `timeout` value completely + # irrelevant. To enable non-blocking behavior, use the `executor` + # constructor option. This will cause the delayed operation to be + # execute on the given executor, allowing the call to timeout. + # @param timeout [Numeric] the maximum number of seconds to wait + # @raise [Exception] when `#rejected?` raises `#reason` + # @return [Object] the current value of the object + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/delay.rb#113 + def value!(timeout = T.unsafe(nil)); end + + # Return the value this object represents after applying the options + # specified by the `#set_deref_options` method. + # + # @note The default behavior of `Delay` is to block indefinitely when + # calling either `value` or `wait`, executing the delayed operation on + # the current thread. This makes the `timeout` value completely + # irrelevant. To enable non-blocking behavior, use the `executor` + # constructor option. This will cause the delayed operation to be + # execute on the given executor, allowing the call to timeout. + # @param timeout [Integer] (nil) the maximum number of seconds to wait for + # the value to be computed. When `nil` the caller will block indefinitely. + # @return [Object] self + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/delay.rb#132 + def wait(timeout = T.unsafe(nil)); end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/delay.rb#160 + def ns_initialize(opts, &block); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/delay.rb#173 + def execute_task_once; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/dataflow.rb#7 +class Concurrent::DependencyCounter + # @return [DependencyCounter] a new instance of DependencyCounter + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/dataflow.rb#9 + def initialize(count, &block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/dataflow.rb#14 + def update(time, value, reason); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#3 +class Concurrent::Error < ::StandardError; end + +# Old school kernel-style event reminiscent of Win32 programming in C++. +# +# When an `Event` is created it is in the `unset` state. Threads can choose to +# `#wait` on the event, blocking until released by another thread. When one +# thread wants to alert all blocking threads it calls the `#set` method which +# will then wake up all listeners. Once an `Event` has been set it remains set. +# New threads calling `#wait` will return immediately. An `Event` may be +# `#reset` at any time once it has been set. +# +# @example +# event = Concurrent::Event.new +# +# t1 = Thread.new do +# puts "t1 is waiting" +# event.wait(1) +# puts "event occurred" +# end +# +# t2 = Thread.new do +# puts "t2 calling set" +# event.set +# end +# +# [t1, t2].each(&:join) +# +# # prints: +# # t1 is waiting +# # t2 calling set +# # event occurred +# @see http://msdn.microsoft.com/en-us/library/windows/desktop/ms682655.aspx +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/event.rb#36 +class Concurrent::Event < ::Concurrent::Synchronization::LockableObject + # Creates a new `Event` in the unset state. Threads calling `#wait` on the + # `Event` will block. + # + # @return [Event] a new instance of Event + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/event.rb#40 + def initialize; end + + # Reset a previously set event back to the `unset` state. + # Has no effect if the `Event` has not yet been set. + # + # @return [Boolean] should always return `true` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/event.rb#68 + def reset; end + + # Trigger the event, setting the state to `set` and releasing all threads + # waiting on the event. Has no effect if the `Event` has already been set. + # + # @return [Boolean] should always return `true` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/event.rb#56 + def set; end + + # Is the object in the set state? + # + # @return [Boolean] indicating whether or not the `Event` has been set + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/event.rb#48 + def set?; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/event.rb#60 + def try?; end + + # Wait a given number of seconds for the `Event` to be set by another + # thread. Will wait forever when no `timeout` value is given. Returns + # immediately if the `Event` has already been set. + # + # @return [Boolean] true if the `Event` was set before timeout else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/event.rb#83 + def wait(timeout = T.unsafe(nil)); end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/event.rb#104 + def ns_initialize; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/event.rb#96 + def ns_set; end +end + +# A synchronization point at which threads can pair and swap elements within +# pairs. Each thread presents some object on entry to the exchange method, +# matches with a partner thread, and receives its partner's object on return. +# +# +# ## Thread-safe Variable Classes +# +# Each of the thread-safe variable classes is designed to solve a different +# problem. In general: +# +# * *{Concurrent::Agent}:* Shared, mutable variable providing independent, +# uncoordinated, *asynchronous* change of individual values. Best used when +# the value will undergo frequent, complex updates. Suitable when the result +# of an update does not need to be known immediately. +# * *{Concurrent::Atom}:* Shared, mutable variable providing independent, +# uncoordinated, *synchronous* change of individual values. Best used when +# the value will undergo frequent reads but only occasional, though complex, +# updates. Suitable when the result of an update must be known immediately. +# * *{Concurrent::AtomicReference}:* A simple object reference that can be updated +# atomically. Updates are synchronous but fast. Best used when updates a +# simple set operations. Not suitable when updates are complex. +# {Concurrent::AtomicBoolean} and {Concurrent::AtomicFixnum} are similar +# but optimized for the given data type. +# * *{Concurrent::Exchanger}:* Shared, stateless synchronization point. Used +# when two or more threads need to exchange data. The threads will pair then +# block on each other until the exchange is complete. +# * *{Concurrent::MVar}:* Shared synchronization point. Used when one thread +# must give a value to another, which must take the value. The threads will +# block on each other until the exchange is complete. +# * *{Concurrent::ThreadLocalVar}:* Shared, mutable, isolated variable which +# holds a different value for each thread which has access. Often used as +# an instance variable in objects which must maintain different state +# for different threads. +# * *{Concurrent::TVar}:* Shared, mutable variables which provide +# *coordinated*, *synchronous*, change of *many* stated. Used when multiple +# value must change together, in an all-or-nothing transaction. +# This implementation is very simple, using only a single slot for each +# exchanger (unlike more advanced implementations which use an "arena"). +# This approach will work perfectly fine when there are only a few threads +# accessing a single `Exchanger`. Beyond a handful of threads the performance +# will degrade rapidly due to contention on the single slot, but the algorithm +# will remain correct. +# +# @example +# +# exchanger = Concurrent::Exchanger.new +# +# threads = [ +# Thread.new { puts "first: " << exchanger.exchange('foo', 1) }, #=> "first: bar" +# Thread.new { puts "second: " << exchanger.exchange('bar', 1) } #=> "second: foo" +# ] +# threads.each {|t| t.join(2) } +# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Exchanger.html java.util.concurrent.Exchanger +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#336 +class Concurrent::Exchanger < ::Concurrent::RubyExchanger; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#327 +Concurrent::ExchangerImplementation = Concurrent::RubyExchanger + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/executor_service.rb#157 +module Concurrent::ExecutorService + include ::Logger::Severity + include ::Concurrent::Concern::Logging + + # Submit a task to the executor for asynchronous processing. + # + # @param task [Proc] the asynchronous task to perform + # @return [self] returns itself + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/executor_service.rb#166 + def <<(task); end + + # Does the task queue have a maximum size? + # + # @note Always returns `false` + # @return [Boolean] True if the task queue has a maximum size else false. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/executor_service.rb#174 + def can_overflow?; end + + # Submit a task to the executor for asynchronous processing. + # + # @param args [Array] zero or more arguments to be passed to the task + # @raise [ArgumentError] if no task is given + # @return [Boolean] `true` if the task is queued, `false` if the executor + # is not running + # @yield the asynchronous task to perform + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/executor_service.rb#161 + def post(*args, &task); end + + # Does this executor guarantee serialization of its operations? + # + # @note Always returns `false` + # @return [Boolean] True if the executor guarantees that all operations + # will be post in the order they are received and no two operations may + # occur simultaneously. Else false. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/executor_service.rb#181 + def serialized?; end +end + +# A `FiberLocalVar` is a variable where the value is different for each fiber. +# Each variable may have a default value, but when you modify the variable only +# the current fiber will ever see that change. +# +# This is similar to Ruby's built-in fiber-local variables (`Thread.current[:name]`), +# but with these major advantages: +# * `FiberLocalVar` has its own identity, it doesn't need a Symbol. +# * Each Ruby's built-in fiber-local variable leaks some memory forever (it's a Symbol held forever on the fiber), +# so it's only OK to create a small amount of them. +# `FiberLocalVar` has no such issue and it is fine to create many of them. +# * Ruby's built-in fiber-local variables leak forever the value set on each fiber (unless set to nil explicitly). +# `FiberLocalVar` automatically removes the mapping for each fiber once the `FiberLocalVar` instance is GC'd. +# +# @example +# v = FiberLocalVar.new(14) +# v.value #=> 14 +# v.value = 2 +# v.value #=> 2 +# @example +# v = FiberLocalVar.new(14) +# +# Fiber.new do +# v.value #=> 14 +# v.value = 1 +# v.value #=> 1 +# end.resume +# +# Fiber.new do +# v.value #=> 14 +# v.value = 2 +# v.value #=> 2 +# end.resume +# +# v.value #=> 14 +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/fiber_local_var.rb#41 +class Concurrent::FiberLocalVar + # Creates a fiber local variable. + # + # @param default [Object] the default value when otherwise unset + # @param default_block [Proc] Optional block that gets called to obtain the + # default value for each fiber + # @return [FiberLocalVar] a new instance of FiberLocalVar + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/fiber_local_var.rb#49 + def initialize(default = T.unsafe(nil), &default_block); end + + # Bind the given value to fiber local storage during + # execution of the given block. + # + # @param value [Object] the value to bind + # @return [Object] the value + # @yield the operation to be performed with the bound variable + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/fiber_local_var.rb#86 + def bind(value); end + + # Returns the value in the current fiber's copy of this fiber-local variable. + # + # @return [Object] the current value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/fiber_local_var.rb#68 + def value; end + + # Sets the current fiber's copy of this fiber-local variable to the specified value. + # + # @param value [Object] the value to set + # @return [Object] the new value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/fiber_local_var.rb#76 + def value=(value); end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/fiber_local_var.rb#101 + def default; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/fiber_local_var.rb#42 +Concurrent::FiberLocalVar::LOCALS = T.let(T.unsafe(nil), Concurrent::FiberLocals) + +# An array-backed storage of indexed variables per fiber. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#166 +class Concurrent::FiberLocals < ::Concurrent::AbstractLocals + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#167 + def locals; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#171 + def locals!; end +end + +# A thread pool that reuses a fixed number of threads operating off an unbounded queue. +# At any point, at most `num_threads` will be active processing tasks. When all threads are busy new +# tasks `#post` to the thread pool are enqueued until a thread becomes available. +# Should a thread crash for any reason the thread will immediately be removed +# from the pool and replaced. +# +# The API and behavior of this class are based on Java's `FixedThreadPool` +# +# **Thread Pool Options** +# +# Thread pools support several configuration options: +# +# * `idletime`: The number of seconds that a thread may be idle before being reclaimed. +# * `name`: The name of the executor (optional). Printed in the executor's `#to_s` output and +# a `-worker-` name is given to its threads if supported by used Ruby +# implementation. `` is uniq for each thread. +# * `max_queue`: The maximum number of tasks that may be waiting in the work queue at +# any one time. When the queue size reaches `max_queue` and no new threads can be created, +# subsequent tasks will be rejected in accordance with the configured `fallback_policy`. +# * `auto_terminate`: When true (default), the threads started will be marked as daemon. +# * `fallback_policy`: The policy defining how rejected tasks are handled. +# +# Three fallback policies are supported: +# +# * `:abort`: Raise a `RejectedExecutionError` exception and discard the task. +# * `:discard`: Discard the task and return false. +# * `:caller_runs`: Execute the task on the calling thread. +# +# **Shutting Down Thread Pools** +# +# Killing a thread pool while tasks are still being processed, either by calling +# the `#kill` method or at application exit, will have unpredictable results. There +# is no way for the thread pool to know what resources are being used by the +# in-progress tasks. When those tasks are killed the impact on those resources +# cannot be predicted. The *best* practice is to explicitly shutdown all thread +# pools using the provided methods: +# +# * Call `#shutdown` to initiate an orderly termination of all in-progress tasks +# * Call `#wait_for_termination` with an appropriate timeout interval an allow +# the orderly shutdown to complete +# * Call `#kill` *only when* the thread pool fails to shutdown in the allotted time +# +# On some runtime platforms (most notably the JVM) the application will not +# exit until all thread pools have been shutdown. To prevent applications from +# "hanging" on exit, all threads can be marked as daemon according to the +# `:auto_terminate` option. +# +# ```ruby +# pool1 = Concurrent::FixedThreadPool.new(5) # threads will be marked as daemon +# pool2 = Concurrent::FixedThreadPool.new(5, auto_terminate: false) # mark threads as non-daemon +# ``` +# +# @note Failure to properly shutdown a thread pool can lead to unpredictable results. +# Please read *Shutting Down Thread Pools* for more information. +# @see http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html Java Tutorials: Thread Pools +# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html Java Executors class +# @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html Java ExecutorService interface +# @see https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setDaemon-boolean- +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb#201 +class Concurrent::FixedThreadPool < ::Concurrent::ThreadPoolExecutor + # Create a new thread pool. + # + # @option opts + # @param num_threads [Integer] the number of threads to allocate + # @param opts [Hash] the options defining pool behavior. + # @raise [ArgumentError] if `num_threads` is less than or equal to zero + # @raise [ArgumentError] if `fallback_policy` is not a known policy + # @return [FixedThreadPool] a new instance of FixedThreadPool + # @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executors.html#newFixedThreadPool-int- + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb#215 + def initialize(num_threads, opts = T.unsafe(nil)); end +end + +# {include:file:docs-source/future.md} +# +# @see http://ruby-doc.org/stdlib-2.1.1/libdoc/observer/rdoc/Observable.html Ruby Observable module +# @see http://clojuredocs.org/clojure_core/clojure.core/future Clojure's future function +# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html java.util.concurrent.Future +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/future.rb#21 +class Concurrent::Future < ::Concurrent::IVar + # Create a new `Future` in the `:unscheduled` state. + # + # @option opts + # @param opts [Hash] a customizable set of options + # @raise [ArgumentError] if no block is given + # @return [Future] a new instance of Future + # @yield the asynchronous operation to perform + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/future.rb#33 + def initialize(opts = T.unsafe(nil), &block); end + + # Attempt to cancel the operation if it has not already processed. + # The operation can only be cancelled while still `pending`. It cannot + # be cancelled once it has begun processing or has completed. + # + # @return [Boolean] was the operation successfully cancelled. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/future.rb#99 + def cancel; end + + # Has the operation been successfully cancelled? + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/future.rb#111 + def cancelled?; end + + # Execute an `:unscheduled` `Future`. Immediately sets the state to `:pending` and + # passes the block to a new thread/thread pool for eventual execution. + # Does nothing if the `Future` is in any state other than `:unscheduled`. + # + # @example Instance and execute in separate steps + # future = Concurrent::Future.new{ sleep(1); 42 } + # future.state #=> :unscheduled + # future.execute + # future.state #=> :pending + # @example Instance and execute in one line + # future = Concurrent::Future.new{ sleep(1); 42 }.execute + # future.state #=> :pending + # @return [Future] a reference to `self` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/future.rb#53 + def execute; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/future.rb#82 + def set(value = T.unsafe(nil), &block); end + + # Wait the given number of seconds for the operation to complete. + # On timeout attempt to cancel the operation. + # + # @param timeout [Numeric] the maximum time in seconds to wait. + # @return [Boolean] true if the operation completed before the timeout + # else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/future.rb#121 + def wait_or_cancel(timeout); end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/future.rb#133 + def ns_initialize(value, opts); end + + class << self + # Create a new `Future` object with the given block, execute it, and return the + # `:pending` object. + # + # @example + # future = Concurrent::Future.execute{ sleep(1); 42 } + # future.state #=> :pending + # @option opts + # @param opts [Hash] a customizable set of options + # @raise [ArgumentError] if no block is given + # @return [Future] the newly created `Future` in the `:pending` state + # @yield the asynchronous operation to perform + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/future.rb#77 + def execute(opts = T.unsafe(nil), &block); end + end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/configuration.rb#18 +Concurrent::GLOBAL_FAST_EXECUTOR = T.let(T.unsafe(nil), Concurrent::Delay) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/configuration.rb#30 +Concurrent::GLOBAL_IMMEDIATE_EXECUTOR = T.let(T.unsafe(nil), Concurrent::ImmediateExecutor) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/configuration.rb#22 +Concurrent::GLOBAL_IO_EXECUTOR = T.let(T.unsafe(nil), Concurrent::Delay) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/logging.rb#106 +Concurrent::GLOBAL_LOGGER = T.let(T.unsafe(nil), Concurrent::AtomicReference) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/configuration.rb#26 +Concurrent::GLOBAL_TIMER_SET = T.let(T.unsafe(nil), Concurrent::Delay) + +# A thread-safe subclass of Hash. This version locks against the object +# itself for every method call, ensuring only one thread can be reading +# or writing at a time. This includes iteration methods like `#each`, +# which takes the lock repeatedly when reading an item. +# +# @see http://ruby-doc.org/core/Hash.html Ruby standard library `Hash` +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/hash.rb#49 +class Concurrent::Hash < ::Hash; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/hash.rb#16 +Concurrent::HashImplementation = Hash + +# An `IVar` is like a future that you can assign. As a future is a value that +# is being computed that you can wait on, an `IVar` is a value that is waiting +# to be assigned, that you can wait on. `IVars` are single assignment and +# deterministic. +# +# Then, express futures as an asynchronous computation that assigns an `IVar`. +# The `IVar` becomes the primitive on which [futures](Future) and +# [dataflow](Dataflow) are built. +# +# An `IVar` is a single-element container that is normally created empty, and +# can only be set once. The I in `IVar` stands for immutable. Reading an +# `IVar` normally blocks until it is set. It is safe to set and read an `IVar` +# from different threads. +# +# If you want to have some parallel task set the value in an `IVar`, you want +# a `Future`. If you want to create a graph of parallel tasks all executed +# when the values they depend on are ready you want `dataflow`. `IVar` is +# generally a low-level primitive. +# +# ## Examples +# +# Create, set and get an `IVar` +# +# ```ruby +# ivar = Concurrent::IVar.new +# ivar.set 14 +# ivar.value #=> 14 +# ivar.set 2 # would now be an error +# ``` +# +# ## See Also +# +# 1. For the theory: Arvind, R. Nikhil, and K. Pingali. +# [I-Structures: Data structures for parallel computing](http://dl.acm.org/citation.cfm?id=69562). +# In Proceedings of Workshop on Graph Reduction, 1986. +# 2. For recent application: +# [DataDrivenFuture in Habanero Java from Rice](http://www.cs.rice.edu/~vs3/hjlib/doc/edu/rice/hj/api/HjDataDrivenFuture.html). +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#48 +class Concurrent::IVar < ::Concurrent::Synchronization::LockableObject + include ::Concurrent::Concern::Dereferenceable + include ::Concurrent::Concern::Obligation + include ::Concurrent::Concern::Observable + + # Create a new `IVar` in the `:pending` state with the (optional) initial value. + # + # @option opts + # @option opts + # @option opts + # @param value [Object] the initial value + # @param opts [Hash] the options to create a message with + # @return [IVar] a new instance of IVar + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#62 + def initialize(value = T.unsafe(nil), opts = T.unsafe(nil), &block); end + + # Add an observer on this object that will receive notification on update. + # + # Upon completion the `IVar` will notify all observers in a thread-safe way. + # The `func` method of the observer will be called with three arguments: the + # `Time` at which the `Future` completed the asynchronous operation, the + # final `value` (or `nil` on rejection), and the final `reason` (or `nil` on + # fulfillment). + # + # @param observer [Object] the object that will be notified of changes + # @param func [Symbol] symbol naming the method to call when this + # `Observable` has changes` + # @raise [ArgumentError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#81 + def add_observer(observer = T.unsafe(nil), func = T.unsafe(nil), &block); end + + # Set the `IVar` to failed due to some error and wake or notify all threads waiting on it. + # + # @param reason [Object] for the failure + # @raise [Concurrent::MultipleAssignmentError] if the `IVar` has already + # been set or otherwise completed + # @return [IVar] self + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#135 + def fail(reason = T.unsafe(nil)); end + + # Set the `IVar` to a value and wake or notify all threads waiting on it. + # + # @param value [Object] the value to store in the `IVar` + # @raise [ArgumentError] if both a value and a block are given + # @raise [Concurrent::MultipleAssignmentError] if the `IVar` has already + # been set or otherwise completed + # @return [IVar] self + # @yield A block operation to use for setting the value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#113 + def set(value = T.unsafe(nil)); end + + # Attempt to set the `IVar` with the given value or block. Return a + # boolean indicating the success or failure of the set operation. + # + # @param value [Object] the value to store in the `IVar` + # @raise [ArgumentError] if both a value and a block are given + # @raise [Concurrent::MultipleAssignmentError] if the `IVar` has already + # been set or otherwise completed + # @return [Boolean] true if the value was set else false + # @yield A block operation to use for setting the value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#145 + def try_set(value = T.unsafe(nil), &block); end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#202 + def check_for_block_or_value!(block_given, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#177 + def complete(success, value, reason); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#184 + def complete_without_notification(success, value, reason); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#190 + def notify_observers(value, reason); end + + # @raise [MultipleAssignmentError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#195 + def ns_complete_without_notification(success, value, reason); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#155 + def ns_initialize(value, opts); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#168 + def safe_execute(task, args = T.unsafe(nil)); end +end + +# Raised when an operation is attempted which is not legal given the +# receiver's current state +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#20 +class Concurrent::IllegalOperationError < ::Concurrent::Error; end + +# An executor service which runs all operations on the current thread, +# blocking as necessary. Operations are performed in the order they are +# received and no two operations can be performed simultaneously. +# +# This executor service exists mainly for testing an debugging. When used +# it immediately runs every `#post` operation on the current thread, blocking +# that thread until the operation is complete. This can be very beneficial +# during testing because it makes all operations deterministic. +# +# @note Intended for use primarily in testing and debugging. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/immediate_executor.rb#17 +class Concurrent::ImmediateExecutor < ::Concurrent::AbstractExecutorService + include ::Concurrent::SerialExecutorService + + # Creates a new executor + # + # @return [ImmediateExecutor] a new instance of ImmediateExecutor + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/immediate_executor.rb#21 + def initialize; end + + # Submit a task to the executor for asynchronous processing. + # + # @param task [Proc] the asynchronous task to perform + # @return [self] returns itself + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/immediate_executor.rb#34 + def <<(task); end + + # Begin an orderly shutdown. Tasks already in the queue will be executed, + # but no new tasks will be accepted. Has no additional effect if the + # thread pool is not running. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/immediate_executor.rb#55 + def kill; end + + # Submit a task to the executor for asynchronous processing. + # + # @param args [Array] zero or more arguments to be passed to the task + # @raise [ArgumentError] if no task is given + # @return [Boolean] `true` if the task is queued, `false` if the executor + # is not running + # @yield the asynchronous task to perform + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/immediate_executor.rb#26 + def post(*args, &task); end + + # Is the executor running? + # + # @return [Boolean] `true` when running, `false` when shutting down or shutdown + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/immediate_executor.rb#40 + def running?; end + + # Begin an orderly shutdown. Tasks already in the queue will be executed, + # but no new tasks will be accepted. Has no additional effect if the + # thread pool is not running. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/immediate_executor.rb#55 + def shutdown; end + + # Is the executor shutdown? + # + # @return [Boolean] `true` when shutdown, `false` when shutting down or running + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/immediate_executor.rb#50 + def shutdown?; end + + # Is the executor shuttingdown? + # + # @return [Boolean] `true` when not running and not shutdown, else `false` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/immediate_executor.rb#45 + def shuttingdown?; end + + # Block until executor shutdown is complete or until `timeout` seconds have + # passed. + # + # @note Does not initiate shutdown or termination. Either `shutdown` or `kill` + # must be called before this method (or on another thread). + # @param timeout [Integer] the maximum number of seconds to wait for shutdown to complete + # @return [Boolean] `true` if shutdown complete or false on `timeout` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/immediate_executor.rb#62 + def wait_for_termination(timeout = T.unsafe(nil)); end +end + +# Raised when an attempt is made to violate an immutability guarantee. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#16 +class Concurrent::ImmutabilityError < ::Concurrent::Error; end + +# A thread-safe, immutable variation of Ruby's standard `Struct`. +# +# @see http://ruby-doc.org/core/Struct.html Ruby standard library `Struct` +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#9 +module Concurrent::ImmutableStruct + include ::Concurrent::Synchronization::AbstractStruct + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#51 + def ==(other); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#46 + def [](member); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#56 + def each(&block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#62 + def each_pair(&block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#29 + def inspect; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#36 + def merge(other, &block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#68 + def select(&block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#17 + def to_a; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#41 + def to_h; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#29 + def to_s; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#17 + def values; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#24 + def values_at(*indexes); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#76 + def initialize_copy(original); end + + class << self + # @private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#12 + def included(base); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#82 + def new(*args, &block); end + end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#92 +Concurrent::ImmutableStruct::FACTORY = T.let(T.unsafe(nil), T.untyped) + +# An executor service which runs all operations on a new thread, blocking +# until it completes. Operations are performed in the order they are received +# and no two operations can be performed simultaneously. +# +# This executor service exists mainly for testing an debugging. When used it +# immediately runs every `#post` operation on a new thread, blocking the +# current thread until the operation is complete. This is similar to how the +# ImmediateExecutor works, but the operation has the full stack of the new +# thread at its disposal. This can be helpful when the operations will spawn +# more operations on the same executor and so on - such a situation might +# overflow the single stack in case of an ImmediateExecutor, which is +# inconsistent with how it would behave for a threaded executor. +# +# @note Intended for use primarily in testing and debugging. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/indirect_immediate_executor.rb#19 +class Concurrent::IndirectImmediateExecutor < ::Concurrent::ImmediateExecutor + # Creates a new executor + # + # @return [IndirectImmediateExecutor] a new instance of IndirectImmediateExecutor + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/indirect_immediate_executor.rb#21 + def initialize; end + + # Submit a task to the executor for asynchronous processing. + # + # @param args [Array] zero or more arguments to be passed to the task + # @raise [ArgumentError] if no task is given + # @return [Boolean] `true` if the task is queued, `false` if the executor + # is not running + # @yield the asynchronous task to perform + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/indirect_immediate_executor.rb#27 + def post(*args, &task); end +end + +# Raised when an object's methods are called when it has not been +# properly initialized. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#24 +class Concurrent::InitializationError < ::Concurrent::Error; end + +# Raised when a lifecycle method (such as `stop`) is called in an improper +# sequence or when the object is in an inappropriate state. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#13 +class Concurrent::LifecycleError < ::Concurrent::Error; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#6 +class Concurrent::LockFreeStack < ::Concurrent::Synchronization::Object + include ::Enumerable + extend ::Concurrent::Synchronization::SafeInitialization + + # @param head [Node] + # @return [LockFreeStack] a new instance of LockFreeStack + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#51 + def initialize(head = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#137 + def __initialize_atomic_fields__; end + + # @return [true, false] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#118 + def clear; end + + # @return [self] + # @yield over the cleared stack + # @yieldparam value [Object] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#142 + def clear_each(&block); end + + # @param head [Node] + # @return [true, false] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#128 + def clear_if(head); end + + # @param head [Node] + # @return [true, false] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#99 + def compare_and_clear(head); end + + # @param head [Node] + # @return [true, false] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#85 + def compare_and_pop(head); end + + # @param head [Node] + # @param value [Object] + # @return [true, false] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#65 + def compare_and_push(head, value); end + + # @param head [Node] + # @return [self] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#107 + def each(head = T.unsafe(nil)); end + + # @param head [Node] + # @return [true, false] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#58 + def empty?(head = T.unsafe(nil)); end + + # @return [String] Short string representation. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#154 + def inspect; end + + # @return [Node] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#79 + def peek; end + + # @return [Object] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#90 + def pop; end + + # @param value [Object] + # @return [self] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#71 + def push(value); end + + # @param head [Node] + # @param new_head [Node] + # @return [true, false] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#135 + def replace_if(head, new_head); end + + # @return [String] Short string representation. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#154 + def to_s; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#105 + def compare_and_set_head(expected, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#93 + def head; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#97 + def head=(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#101 + def swap_head(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#109 + def update_head(&block); end + + class << self + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#41 + def of1(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#46 + def of2(value1, value2); end + end +end + +# The singleton for empty node +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#32 +Concurrent::LockFreeStack::EMPTY = T.let(T.unsafe(nil), Concurrent::LockFreeStack::Node) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#10 +class Concurrent::LockFreeStack::Node + # @return [Node] a new instance of Node + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#23 + def initialize(value, next_node); end + + # @return [Node] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#14 + def next_node; end + + # @return [Object] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#17 + def value; end + + # allow to nil-ify to free GC when the entry is no longer relevant, not synchronised + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#21 + def value=(_arg0); end + + class << self + def [](*_arg0); end + end +end + +# Either {FiberLocalVar} or {ThreadLocalVar} depending on whether Mutex (and Monitor) +# are held, respectively, per Fiber or per Thread. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/lock_local_var.rb#21 +Concurrent::LockLocalVar = Concurrent::FiberLocalVar + +# An `MVar` is a synchronized single element container. They are empty or +# contain one item. Taking a value from an empty `MVar` blocks, as does +# putting a value into a full one. You can either think of them as blocking +# queue of length one, or a special kind of mutable variable. +# +# On top of the fundamental `#put` and `#take` operations, we also provide a +# `#mutate` that is atomic with respect to operations on the same instance. +# These operations all support timeouts. +# +# We also support non-blocking operations `#try_put!` and `#try_take!`, a +# `#set!` that ignores existing values, a `#value` that returns the value +# without removing it or returns `MVar::EMPTY`, and a `#modify!` that yields +# `MVar::EMPTY` if the `MVar` is empty and can be used to set `MVar::EMPTY`. +# You shouldn't use these operations in the first instance. +# +# `MVar` is a [Dereferenceable](Dereferenceable). +# +# `MVar` is related to M-structures in Id, `MVar` in Haskell and `SyncVar` in Scala. +# +# Note that unlike the original Haskell paper, our `#take` is blocking. This is how +# Haskell and Scala do it today. +# +# ## See Also +# +# 1. P. Barth, R. Nikhil, and Arvind. [M-Structures: Extending a parallel, non- strict, functional language with state](http://dl.acm.org/citation.cfm?id=652538). In Proceedings of the 5th +# ACM Conference on Functional Programming Languages and Computer Architecture (FPCA), 1991. +# +# 2. S. Peyton Jones, A. Gordon, and S. Finne. [Concurrent Haskell](http://dl.acm.org/citation.cfm?id=237794). +# In Proceedings of the 23rd Symposium on Principles of Programming Languages +# (PoPL), 1996. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#38 +class Concurrent::MVar < ::Concurrent::Synchronization::Object + include ::Concurrent::Concern::Dereferenceable + extend ::Concurrent::Synchronization::SafeInitialization + + # Create a new `MVar`, either empty or with an initial value. + # + # @param opts [Hash] the options controlling how the future will be processed + # @return [MVar] a new instance of MVar + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#54 + def initialize(value = T.unsafe(nil), opts = T.unsafe(nil)); end + + # acquires lock on the from an `MVAR`, yields the value to provided block, + # and release lock. A timeout can be set to limit the time spent blocked, + # in which case it returns `TIMEOUT` if the time is exceeded. + # + # @return [Object] the value returned by the block, or `TIMEOUT` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#86 + def borrow(timeout = T.unsafe(nil)); end + + # Returns if the `MVar` is currently empty. + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#195 + def empty?; end + + # Returns if the `MVar` currently contains a value. + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#200 + def full?; end + + # Atomically `take`, yield the value to a block for transformation, and then + # `put` the transformed value. Returns the transformed value. A timeout can + # be set to limit the time spent blocked, in which case it returns `TIMEOUT` + # if the time is exceeded. + # + # @raise [ArgumentError] + # @return [Object] the transformed value, or `TIMEOUT` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#123 + def modify(timeout = T.unsafe(nil)); end + + # Non-blocking version of `modify` that will yield with `EMPTY` if there is no value yet. + # + # @raise [ArgumentError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#179 + def modify!; end + + # Put a value into an `MVar`, blocking if there is already a value until + # it is empty. A timeout can be set to limit the time spent blocked, in + # which case it returns `TIMEOUT` if the time is exceeded. + # + # @return [Object] the value that was put, or `TIMEOUT` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#103 + def put(value, timeout = T.unsafe(nil)); end + + # Non-blocking version of `put` that will overwrite an existing value. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#169 + def set!(value); end + + # Remove the value from an `MVar`, leaving it empty, and blocking if there + # isn't a value. A timeout can be set to limit the time spent blocked, in + # which case it returns `TIMEOUT` if the time is exceeded. + # + # @return [Object] the value that was taken, or `TIMEOUT` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#66 + def take(timeout = T.unsafe(nil)); end + + # Non-blocking version of `put`, that returns whether or not it was successful. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#156 + def try_put!(value); end + + # Non-blocking version of `take`, that returns `EMPTY` instead of blocking. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#142 + def try_take!; end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#206 + def synchronize(&block); end + + private + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#212 + def unlocked_empty?; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#216 + def unlocked_full?; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#224 + def wait_for_empty(timeout); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#220 + def wait_for_full(timeout); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#228 + def wait_while(condition, timeout); end +end + +# Unique value that represents that an `MVar` was empty +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#43 +Concurrent::MVar::EMPTY = T.let(T.unsafe(nil), Object) + +# Unique value that represents that an `MVar` timed out before it was able +# to produce a value. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#47 +Concurrent::MVar::TIMEOUT = T.let(T.unsafe(nil), Object) + +# `Concurrent::Map` is a hash-like object and should have much better performance +# characteristics, especially under high concurrency, than `Concurrent::Hash`. +# However, `Concurrent::Map `is not strictly semantically equivalent to a ruby `Hash` +# -- for instance, it does not necessarily retain ordering by insertion time as `Hash` +# does. For most uses it should do fine though, and we recommend you consider +# `Concurrent::Map` instead of `Concurrent::Hash` for your concurrency-safe hash needs. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#39 +class Concurrent::Map < ::Concurrent::Collection::MriMapBackend + # Iterates over each key value pair. + # This method is atomic. + # + # @note Atomic methods taking a block do not allow the `self` instance + # to be used within the block. Doing so will cause a deadlock. + # @return [self] + # @yield for each key value pair in the map + # @yieldparam key [Object] + # @yieldparam value [Object] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#274 + def each; end + + # Iterates over each key. + # This method is atomic. + # + # @note Atomic methods taking a block do not allow the `self` instance + # to be used within the block. Doing so will cause a deadlock. + # @return [self] + # @yield for each key in the map + # @yieldparam key [Object] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#255 + def each_key; end + + # Iterates over each key value pair. + # This method is atomic. + # + # @note Atomic methods taking a block do not allow the `self` instance + # to be used within the block. Doing so will cause a deadlock. + # @return [self] + # @yield for each key value pair in the map + # @yieldparam key [Object] + # @yieldparam value [Object] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#274 + def each_pair; end + + # Iterates over each value. + # This method is atomic. + # + # @note Atomic methods taking a block do not allow the `self` instance + # to be used within the block. Doing so will cause a deadlock. + # @return [self] + # @yield for each value in the map + # @yieldparam value [Object] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#264 + def each_value; end + + # Is map empty? + # + # @return [true, false] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#291 + def empty?; end + + # Get a value with key, or default_value when key is absent, + # or fail when no default_value is given. + # + # @note The "fetch-then-act" methods of `Map` are not atomic. `Map` is intended + # to be use as a concurrency primitive with strong happens-before + # guarantees. It is not intended to be used as a high-level abstraction + # supporting complex operations. All read and write operations are + # thread safe, but no guarantees are made regarding race conditions + # between the fetch operation and yielding to the block. Additionally, + # this method does not support recursion. This is due to internal + # constraints that are very unlikely to change in the near future. + # @param key [Object] + # @param default_value [Object] + # @raise [KeyError] when key is missing and no default_value is provided + # @return [Object] the value or default value + # @yield default value for a key + # @yieldparam key [Object] + # @yieldreturn [Object] default value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#183 + def fetch(key, default_value = T.unsafe(nil)); end + + # Fetch value with key, or store default value when key is absent, + # or fail when no default_value is given. This is a two step operation, + # therefore not atomic. The store can overwrite other concurrently + # stored value. + # + # @param key [Object] + # @param default_value [Object] + # @return [Object] the value or default value + # @yield default value for a key + # @yieldparam key [Object] + # @yieldreturn [Object] default value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#205 + def fetch_or_store(key, default_value = T.unsafe(nil)); end + + # Get a value with key + # + # @param key [Object] + # @return [Object] the value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#21 + def get(key); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#321 + def inspect; end + + # Find key of a value. + # + # @param value [Object] + # @return [Object, nil] key or nil when not found + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#284 + def key(value); end + + # All keys + # + # @return [::Array] keys + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#236 + def keys; end + + # @raise [TypeError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#305 + def marshal_dump; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#313 + def marshal_load(hash); end + + # Set a value with key + # + # @param key [Object] + # @param value [Object] + # @return [Object] the new value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb#17 + def put(key, value); end + + # Insert value into map with key if key is absent in one atomic step. + # + # @param key [Object] + # @param value [Object] + # @return [Object, nil] the previous value when key was present or nil when there was no key + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#215 + def put_if_absent(key, value); end + + # Is the value stored in the map. Iterates over all values. + # + # @param value [Object] + # @return [true, false] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#227 + def value?(value); end + + # All values + # + # @return [::Array] values + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#244 + def values; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#331 + def initialize_copy(other); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#336 + def populate_from(hash); end + + # @raise [KeyError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#327 + def raise_fetch_no_key; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#341 + def validate_options_hash!(options); end +end + +# Raised when an object with a start/stop lifecycle has been started an +# excessive number of times. Often used in conjunction with a restart +# policy or strategy. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#29 +class Concurrent::MaxRestartFrequencyError < ::Concurrent::Error; end + +# A `Maybe` encapsulates an optional value. A `Maybe` either contains a value +# of (represented as `Just`), or it is empty (represented as `Nothing`). Using +# `Maybe` is a good way to deal with errors or exceptional cases without +# resorting to drastic measures such as exceptions. +# +# `Maybe` is a replacement for the use of `nil` with better type checking. +# +# For compatibility with {Concurrent::Concern::Obligation} the predicate and +# accessor methods are aliased as `fulfilled?`, `rejected?`, `value`, and +# `reason`. +# +# ## Motivation +# +# A common pattern in languages with pattern matching, such as Erlang and +# Haskell, is to return *either* a value *or* an error from a function +# Consider this Erlang code: +# +# ```erlang +# case file:consult("data.dat") of +# {ok, Terms} -> do_something_useful(Terms); +# {error, Reason} -> lager:error(Reason) +# end. +# ``` +# +# In this example the standard library function `file:consult` returns a +# [tuple](http://erlang.org/doc/reference_manual/data_types.html#id69044) +# with two elements: an [atom](http://erlang.org/doc/reference_manual/data_types.html#id64134) +# (similar to a ruby symbol) and a variable containing ancillary data. On +# success it returns the atom `ok` and the data from the file. On failure it +# returns `error` and a string with an explanation of the problem. With this +# pattern there is no ambiguity regarding success or failure. If the file is +# empty the return value cannot be misinterpreted as an error. And when an +# error occurs the return value provides useful information. +# +# In Ruby we tend to return `nil` when an error occurs or else we raise an +# exception. Both of these idioms are problematic. Returning `nil` is +# ambiguous because `nil` may also be a valid value. It also lacks +# information pertaining to the nature of the error. Raising an exception +# is both expensive and usurps the normal flow of control. All of these +# problems can be solved with the use of a `Maybe`. +# +# A `Maybe` is unambiguous with regard to whether or not it contains a value. +# When `Just` it contains a value, when `Nothing` it does not. When `Just` +# the value it contains may be `nil`, which is perfectly valid. When +# `Nothing` the reason for the lack of a value is contained as well. The +# previous Erlang example can be duplicated in Ruby in a principled way by +# having functions return `Maybe` objects: +# +# ```ruby +# result = MyFileUtils.consult("data.dat") # returns a Maybe +# if result.just? +# do_something_useful(result.value) # or result.just +# else +# logger.error(result.reason) # or result.nothing +# end +# ``` +# +# @example Returning a Maybe from a Function +# module MyFileUtils +# def self.consult(path) +# file = File.open(path, 'r') +# Concurrent::Maybe.just(file.read) +# rescue => ex +# return Concurrent::Maybe.nothing(ex) +# ensure +# file.close if file +# end +# end +# +# maybe = MyFileUtils.consult('bogus.file') +# maybe.just? #=> false +# maybe.nothing? #=> true +# maybe.reason #=> # +# +# maybe = MyFileUtils.consult('README.md') +# maybe.just? #=> true +# maybe.nothing? #=> false +# maybe.value #=> "# Concurrent Ruby\n[![Gem Version..." +# @example Using Maybe with a Block +# result = Concurrent::Maybe.from do +# Client.find(10) # Client is an ActiveRecord model +# end +# +# # -- if the record was found +# result.just? #=> true +# result.value #=> # +# +# # -- if the record was not found +# result.just? #=> false +# result.reason #=> ActiveRecord::RecordNotFound +# @example Using Maybe with the Null Object Pattern +# # In a Rails controller... +# result = ClientService.new(10).find # returns a Maybe +# render json: result.or(NullClient.new) +# @see https://hackage.haskell.org/package/base-4.2.0.1/docs/Data-Maybe.html Haskell Data.Maybe +# @see https://github.com/purescript/purescript-maybe/blob/master/docs/Data.Maybe.md PureScript Data.Maybe +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#104 +class Concurrent::Maybe < ::Concurrent::Synchronization::Object + include ::Comparable + extend ::Concurrent::Synchronization::SafeInitialization + + # Create a new `Maybe` with the given attributes. + # + # @param just [Object] The value when `Just` else `NONE`. + # @param nothing [Exception, Object] The exception when `Nothing` else `NONE`. + # @return [Maybe] The new `Maybe`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#224 + def initialize(just, nothing); end + + # Comparison operator. + # + # @return [Integer] 0 if self and other are both `Nothing`; + # -1 if self is `Nothing` and other is `Just`; + # 1 if self is `Just` and other is nothing; + # `self.just <=> other.just` if both self and other are `Just`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#199 + def <=>(other); end + + # Is this `Maybe` a `Just` (successfully fulfilled with a value)? + # + # @return [Boolean] True if `Just` or false if `Nothing`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#176 + def fulfilled?; end + + # The value of a `Maybe` when `Just`. Will be `NONE` when `Nothing`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#114 + def just; end + + # Is this `Maybe` a `Just` (successfully fulfilled with a value)? + # + # @return [Boolean] True if `Just` or false if `Nothing`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#176 + def just?; end + + # The reason for the `Maybe` when `Nothing`. Will be `NONE` when `Just`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#117 + def nothing; end + + # Is this `Maybe` a `nothing` (rejected with an exception upon fulfillment)? + # + # @return [Boolean] True if `Nothing` or false if `Just`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#184 + def nothing?; end + + # Return either the value of self or the given default value. + # + # @return [Object] The value of self when `Just`; else the given default. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#210 + def or(other); end + + # The reason for the `Maybe` when `Nothing`. Will be `NONE` when `Just`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#117 + def reason; end + + # Is this `Maybe` a `nothing` (rejected with an exception upon fulfillment)? + # + # @return [Boolean] True if `Nothing` or false if `Just`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#184 + def rejected?; end + + # The value of a `Maybe` when `Just`. Will be `NONE` when `Nothing`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#114 + def value; end + + class << self + # Create a new `Maybe` using the given block. + # + # Runs the given block passing all function arguments to the block as block + # arguments. If the block runs to completion without raising an exception + # a new `Just` is created with the value set to the return value of the + # block. If the block raises an exception a new `Nothing` is created with + # the reason being set to the raised exception. + # + # @param args [Array] Zero or more arguments to pass to the block. + # @raise [ArgumentError] when no block given. + # @return [Maybe] The newly created object. + # @yield The block from which to create a new `Maybe`. + # @yieldparam args [Array] Zero or more block arguments passed as + # arguments to the function. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#137 + def from(*args); end + + # Create a new `Just` with the given value. + # + # @param value [Object] The value to set for the new `Maybe` object. + # @return [Maybe] The newly created object. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#152 + def just(value); end + + # Create a new `Nothing` with the given (optional) reason. + # + # @param error [Exception] The reason to set for the new `Maybe` object. + # When given a string a new `StandardError` will be created with the + # argument as the message. When no argument is given a new + # `StandardError` with an empty message will be created. + # @return [Maybe] The newly created object. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#164 + def nothing(error = T.unsafe(nil)); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/safe_initialization.rb#29 + def new(*args, &block); end + end +end + +# Indicates that the given attribute has not been set. +# When `Just` the {#nothing} getter will return `NONE`. +# When `Nothing` the {#just} getter will return `NONE`. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#111 +Concurrent::Maybe::NONE = T.let(T.unsafe(nil), Object) + +# Raised when an attempt is made to modify an immutable object +# (such as an `IVar`) after its final state has been set. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#33 +class Concurrent::MultipleAssignmentError < ::Concurrent::Error + # @return [MultipleAssignmentError] a new instance of MultipleAssignmentError + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#36 + def initialize(message = T.unsafe(nil), inspection_data = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#41 + def inspect; end + + # Returns the value of attribute inspection_data. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#34 + def inspection_data; end +end + +# Aggregates multiple exceptions. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#58 +class Concurrent::MultipleErrors < ::Concurrent::Error + # @return [MultipleErrors] a new instance of MultipleErrors + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#61 + def initialize(errors, message = T.unsafe(nil)); end + + # Returns the value of attribute errors. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#59 + def errors; end +end + +# An thread-safe variation of Ruby's standard `Struct`. Values can be set at +# construction or safely changed at any time during the object's lifecycle. +# +# @see http://ruby-doc.org/core/Struct.html Ruby standard library `Struct` +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#10 +module Concurrent::MutableStruct + include ::Concurrent::Synchronization::AbstractStruct + + # Equality + # + # @return [Boolean] true if other has the same struct subclass and has + # equal member values (according to `Object#==`) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#128 + def ==(other); end + + # Attribute Reference + # + # @param member [Symbol, String, Integer] the string or symbol name of the member + # for which to obtain the value or the member's index + # @raise [NameError] if the member does not exist + # @raise [IndexError] if the index is out of range. + # @return [Object] the value of the given struct member or the member at the given index. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#118 + def [](member); end + + # Attribute Assignment + # + # Sets the value of the given struct member or the member at the given index. + # + # @param member [Symbol, String, Integer] the string or symbol name of the member + # for which to obtain the value or the member's index + # @raise [NameError] if the name does not exist + # @raise [IndexError] if the index is out of range. + # @return [Object] the value of the given struct member or the member at the given index. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#185 + def []=(member, value); end + + # Yields the value of each struct member in order. If no block is given + # an enumerator is returned. + # + # @yield the operation to be performed on each struct member + # @yieldparam value [Object] each struct value (in order) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#139 + def each(&block); end + + # Yields the name and value of each struct member in order. If no block is + # given an enumerator is returned. + # + # @yield the operation to be performed on each struct member/value pair + # @yieldparam member [Object] each struct member (in order) + # @yieldparam value [Object] each struct value (in order) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#152 + def each_pair(&block); end + + # Describe the contents of this struct in a string. + # + # @return [String] the contents of this struct in a string + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#72 + def inspect; end + + # Returns a new struct containing the contents of `other` and the contents + # of `self`. If no block is specified, the value for entries with duplicate + # keys will be that of `other`. Otherwise the value for each duplicate key + # is determined by calling the block with the key, its value in `self` and + # its value in `other`. + # + # @param other [Hash] the hash from which to set the new values + # @raise [ArgumentError] of given a member that is not defined in the struct + # @return [Synchronization::AbstractStruct] a new struct with the new values + # @yield an options block for resolving duplicate keys + # @yieldparam member [String, Symbol] the name of the member which is duplicated + # @yieldparam selfvalue [Object] the value of the member in `self` + # @yieldparam othervalue [Object] the value of the member in `other` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#94 + def merge(other, &block); end + + # Yields each member value from the struct to the block and returns an Array + # containing the member values from the struct for which the given block + # returns a true value (equivalent to `Enumerable#select`). + # + # @return [Array] an array containing each value for which the block returns true + # @yield the operation to be performed on each struct member + # @yieldparam value [Object] each struct value (in order) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#167 + def select(&block); end + + # Returns the values for this struct as an Array. + # + # @return [Array] the values for this struct + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#51 + def to_a; end + + # Returns a hash containing the names and values for the struct’s members. + # + # @return [Hash] the names and values for the struct’s members + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#103 + def to_h; end + + # Describe the contents of this struct in a string. + # + # @return [String] the contents of this struct in a string + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#72 + def to_s; end + + # Returns the values for this struct as an Array. + # + # @return [Array] the values for this struct + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#51 + def values; end + + # Returns the struct member values for each selector as an Array. + # + # A selector may be either an Integer offset or a Range of offsets (as in `Array#values_at`). + # + # @param indexes [Fixnum, Range] the index(es) from which to obatin the values (in order) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#63 + def values_at(*indexes); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#202 + def initialize_copy(original); end + + class << self + # Factory for creating new struct classes. + # + # ``` + # new([class_name] [, member_name]+>) -> StructClass click to toggle source + # new([class_name] [, member_name]+>) {|StructClass| block } -> StructClass + # new(value, ...) -> obj + # StructClass[value, ...] -> obj + # ``` + # + # The first two forms are used to create a new struct subclass `class_name` + # that can contain a value for each member_name . This subclass can be + # used to create instances of the structure like any other Class . + # + # If the `class_name` is omitted an anonymous struct class will be created. + # Otherwise, the name of this struct will appear as a constant in the struct class, + # so it must be unique for all structs under this base class and must start with a + # capital letter. Assigning a struct class to a constant also gives the class + # the name of the constant. + # + # If a block is given it will be evaluated in the context of `StructClass`, passing + # the created class as a parameter. This is the recommended way to customize a struct. + # Subclassing an anonymous struct creates an extra anonymous class that will never be used. + # + # The last two forms create a new instance of a struct subclass. The number of value + # parameters must be less than or equal to the number of attributes defined for the + # struct. Unset parameters default to nil. Passing more parameters than number of attributes + # will raise an `ArgumentError`. + # + # @see http://ruby-doc.org/core/Struct.html#method-c-new Ruby standard library `Struct#new` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#210 + def new(*args, &block); end + end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#220 +Concurrent::MutableStruct::FACTORY = T.let(T.unsafe(nil), T.untyped) + +# A boolean value that can be updated atomically. Reads and writes to an atomic +# boolean and thread-safe and guaranteed to succeed. Reads and writes may block +# briefly but no explicit locking is required. +# +# +# ## Thread-safe Variable Classes +# +# Each of the thread-safe variable classes is designed to solve a different +# problem. In general: +# +# * *{Concurrent::Agent}:* Shared, mutable variable providing independent, +# uncoordinated, *asynchronous* change of individual values. Best used when +# the value will undergo frequent, complex updates. Suitable when the result +# of an update does not need to be known immediately. +# * *{Concurrent::Atom}:* Shared, mutable variable providing independent, +# uncoordinated, *synchronous* change of individual values. Best used when +# the value will undergo frequent reads but only occasional, though complex, +# updates. Suitable when the result of an update must be known immediately. +# * *{Concurrent::AtomicReference}:* A simple object reference that can be updated +# atomically. Updates are synchronous but fast. Best used when updates a +# simple set operations. Not suitable when updates are complex. +# {Concurrent::AtomicBoolean} and {Concurrent::AtomicFixnum} are similar +# but optimized for the given data type. +# * *{Concurrent::Exchanger}:* Shared, stateless synchronization point. Used +# when two or more threads need to exchange data. The threads will pair then +# block on each other until the exchange is complete. +# * *{Concurrent::MVar}:* Shared synchronization point. Used when one thread +# must give a value to another, which must take the value. The threads will +# block on each other until the exchange is complete. +# * *{Concurrent::ThreadLocalVar}:* Shared, mutable, isolated variable which +# holds a different value for each thread which has access. Often used as +# an instance variable in objects which must maintain different state +# for different threads. +# * *{Concurrent::TVar}:* Shared, mutable variables which provide +# *coordinated*, *synchronous*, change of *many* stated. Used when multiple +# value must change together, in an all-or-nothing transaction. +# Performance: +# +# ``` +# Testing with ruby 2.1.2 +# Testing with Concurrent::MutexAtomicBoolean... +# 2.790000 0.000000 2.790000 ( 2.791454) +# Testing with Concurrent::CAtomicBoolean... +# 0.740000 0.000000 0.740000 ( 0.740206) +# +# Testing with jruby 1.9.3 +# Testing with Concurrent::MutexAtomicBoolean... +# 5.240000 2.520000 7.760000 ( 3.683000) +# Testing with Concurrent::JavaAtomicBoolean... +# 3.340000 0.010000 3.350000 ( 0.855000) +# ``` +# +# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicBoolean.html java.util.concurrent.atomic.AtomicBoolean +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb#8 +class Concurrent::MutexAtomicBoolean + extend ::Concurrent::Synchronization::SafeInitialization + + # Creates a new `AtomicBoolean` with the given initial value. + # + # @param initial [Boolean] the initial value + # @return [MutexAtomicBoolean] a new instance of MutexAtomicBoolean + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb#12 + def initialize(initial = T.unsafe(nil)); end + + # Is the current value `false` + # + # @return [Boolean] true if the current value is `false`, else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb#34 + def false?; end + + # Explicitly sets the value to false. + # + # @return [Boolean] true if value has changed, otherwise false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb#44 + def make_false; end + + # Explicitly sets the value to true. + # + # @return [Boolean] true if value has changed, otherwise false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb#39 + def make_true; end + + # Is the current value `true` + # + # @return [Boolean] true if the current value is `true`, else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb#29 + def true?; end + + # Retrieves the current `Boolean` value. + # + # @return [Boolean] the current value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb#19 + def value; end + + # Explicitly sets the value. + # + # @param value [Boolean] the new value to be set + # @return [Boolean] the current value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb#24 + def value=(value); end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb#51 + def synchronize; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb#62 + def ns_make_value(value); end +end + +# A numeric value that can be updated atomically. Reads and writes to an atomic +# fixnum and thread-safe and guaranteed to succeed. Reads and writes may block +# briefly but no explicit locking is required. +# +# +# ## Thread-safe Variable Classes +# +# Each of the thread-safe variable classes is designed to solve a different +# problem. In general: +# +# * *{Concurrent::Agent}:* Shared, mutable variable providing independent, +# uncoordinated, *asynchronous* change of individual values. Best used when +# the value will undergo frequent, complex updates. Suitable when the result +# of an update does not need to be known immediately. +# * *{Concurrent::Atom}:* Shared, mutable variable providing independent, +# uncoordinated, *synchronous* change of individual values. Best used when +# the value will undergo frequent reads but only occasional, though complex, +# updates. Suitable when the result of an update must be known immediately. +# * *{Concurrent::AtomicReference}:* A simple object reference that can be updated +# atomically. Updates are synchronous but fast. Best used when updates a +# simple set operations. Not suitable when updates are complex. +# {Concurrent::AtomicBoolean} and {Concurrent::AtomicFixnum} are similar +# but optimized for the given data type. +# * *{Concurrent::Exchanger}:* Shared, stateless synchronization point. Used +# when two or more threads need to exchange data. The threads will pair then +# block on each other until the exchange is complete. +# * *{Concurrent::MVar}:* Shared synchronization point. Used when one thread +# must give a value to another, which must take the value. The threads will +# block on each other until the exchange is complete. +# * *{Concurrent::ThreadLocalVar}:* Shared, mutable, isolated variable which +# holds a different value for each thread which has access. Often used as +# an instance variable in objects which must maintain different state +# for different threads. +# * *{Concurrent::TVar}:* Shared, mutable variables which provide +# *coordinated*, *synchronous*, change of *many* stated. Used when multiple +# value must change together, in an all-or-nothing transaction. +# Performance: +# +# ``` +# Testing with ruby 2.1.2 +# Testing with Concurrent::MutexAtomicFixnum... +# 3.130000 0.000000 3.130000 ( 3.136505) +# Testing with Concurrent::CAtomicFixnum... +# 0.790000 0.000000 0.790000 ( 0.785550) +# +# Testing with jruby 1.9.3 +# Testing with Concurrent::MutexAtomicFixnum... +# 5.460000 2.460000 7.920000 ( 3.715000) +# Testing with Concurrent::JavaAtomicFixnum... +# 4.520000 0.030000 4.550000 ( 1.187000) +# ``` +# +# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicLong.html java.util.concurrent.atomic.AtomicLong +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb#9 +class Concurrent::MutexAtomicFixnum + extend ::Concurrent::Synchronization::SafeInitialization + + # Creates a new `AtomicFixnum` with the given initial value. + # + # @param initial [Fixnum] the initial value + # @raise [ArgumentError] if the initial value is not a `Fixnum` + # @return [MutexAtomicFixnum] a new instance of MutexAtomicFixnum + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb#13 + def initialize(initial = T.unsafe(nil)); end + + # Atomically sets the value to the given updated value if the current + # value == the expected value. + # + # @param expect [Fixnum] the expected value + # @param update [Fixnum] the new value + # @return [Boolean] true if the value was updated else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb#44 + def compare_and_set(expect, update); end + + # Decreases the current value by the given amount (defaults to 1). + # + # @param delta [Fixnum] the amount by which to decrease the current value + # @return [Fixnum] the current value after decrementation + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb#37 + def decrement(delta = T.unsafe(nil)); end + + # Decreases the current value by the given amount (defaults to 1). + # + # @param delta [Fixnum] the amount by which to decrease the current value + # @return [Fixnum] the current value after decrementation + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb#37 + def down(delta = T.unsafe(nil)); end + + # Increases the current value by the given amount (defaults to 1). + # + # @param delta [Fixnum] the amount by which to increase the current value + # @return [Fixnum] the current value after incrementation + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb#30 + def increment(delta = T.unsafe(nil)); end + + # Increases the current value by the given amount (defaults to 1). + # + # @param delta [Fixnum] the amount by which to increase the current value + # @return [Fixnum] the current value after incrementation + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb#30 + def up(delta = T.unsafe(nil)); end + + # Pass the current value to the given block, replacing it + # with the block's result. May retry if the value changes + # during the block's execution. + # + # @return [Object] the new value + # @yield [Object] Calculate a new value for the atomic reference using + # given (old) value + # @yieldparam old_value [Object] the starting value of the atomic reference + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb#56 + def update; end + + # Retrieves the current `Fixnum` value. + # + # @return [Fixnum] the current value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb#20 + def value; end + + # Explicitly sets the value. + # + # @param value [Fixnum] the new value to be set + # @raise [ArgumentError] if the new value is not a `Fixnum` + # @return [Fixnum] the current value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb#25 + def value=(value); end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb#65 + def synchronize; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb#76 + def ns_set(value); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb#9 +class Concurrent::MutexAtomicReference + include ::Concurrent::AtomicDirectUpdate + include ::Concurrent::AtomicNumericCompareAndSetWrapper + extend ::Concurrent::Synchronization::SafeInitialization + + # @param value [Object] The initial value. + # @return [MutexAtomicReference] a new instance of MutexAtomicReference + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb#16 + def initialize(value = T.unsafe(nil)); end + + # Atomically sets the value to the given updated value if + # the current value == the expected value. + # + # that the actual value was not equal to the expected value. + # + # @param old_value [Object] the expected value + # @param new_value [Object] the new value + # @return [Boolean] `true` if successful. A `false` return indicates + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb#45 + def _compare_and_set(old_value, new_value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/numeric_cas_wrapper.rb#10 + def compare_and_swap(old_value, new_value); end + + # Gets the current value. + # + # @return [Object] the current value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb#23 + def get; end + + # Atomically sets to the given value and returns the old value. + # + # @param new_value [Object] the new value + # @return [Object] the old value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb#35 + def get_and_set(new_value); end + + # Sets to the given value. + # + # @param new_value [Object] the new value + # @return [Object] the new value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb#29 + def set(new_value); end + + # Atomically sets to the given value and returns the old value. + # + # @param new_value [Object] the new value + # @return [Object] the old value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb#35 + def swap(new_value); end + + # Gets the current value. + # + # @return [Object] the current value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb#23 + def value; end + + # Sets to the given value. + # + # @param new_value [Object] the new value + # @return [Object] the new value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb#29 + def value=(new_value); end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb#59 + def synchronize; end +end + +# A synchronization object that allows one thread to wait on multiple other threads. +# The thread that will wait creates a `CountDownLatch` and sets the initial value +# (normally equal to the number of other threads). The initiating thread passes the +# latch to the other threads then waits for the other threads by calling the `#wait` +# method. Each of the other threads calls `#count_down` when done with its work. +# When the latch counter reaches zero the waiting thread is unblocked and continues +# with its work. A `CountDownLatch` can be used only once. Its value cannot be reset. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_count_down_latch.rb#9 +class Concurrent::MutexCountDownLatch < ::Concurrent::Synchronization::LockableObject + # Create a new `CountDownLatch` with the initial `count`. + # + # @param count [new] the initial count + # @raise [ArgumentError] if `count` is not an integer or is less than zero + # @return [MutexCountDownLatch] a new instance of MutexCountDownLatch + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_count_down_latch.rb#12 + def initialize(count = T.unsafe(nil)); end + + # The current value of the counter. + # + # @return [Fixnum] the current value of the counter + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_count_down_latch.rb#34 + def count; end + + # Signal the latch to decrement the counter. Will signal all blocked threads when + # the `count` reaches zero. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_count_down_latch.rb#26 + def count_down; end + + # Block on the latch until the counter reaches zero or until `timeout` is reached. + # + # @param timeout [Fixnum] the number of seconds to wait for the counter or `nil` + # to block indefinitely + # @return [Boolean] `true` if the `count` reaches zero else false on `timeout` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_count_down_latch.rb#21 + def wait(timeout = T.unsafe(nil)); end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_count_down_latch.rb#40 + def ns_initialize(count); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb#9 +class Concurrent::MutexSemaphore < ::Concurrent::Synchronization::LockableObject + # @return [MutexSemaphore] a new instance of MutexSemaphore + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb#12 + def initialize(count); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb#20 + def acquire(permits = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb#38 + def available_permits; end + + # Acquires and returns all permits that are immediately available. + # + # @return [Integer] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb#47 + def drain_permits; end + + # Shrinks the number of available permits by the indicated reduction. + # + # @param reduction [Fixnum] Number of permits to remove. + # @raise [ArgumentError] if `reduction` is not an integer or is negative + # @raise [ArgumentError] if `@free` - `@reduction` is less than zero + # @return [nil] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb#99 + def reduce_permits(reduction); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb#77 + def release(permits = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb#54 + def try_acquire(permits = T.unsafe(nil), timeout = T.unsafe(nil)); end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb#110 + def ns_initialize(count); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb#117 + def try_acquire_now(permits); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb#127 + def try_acquire_timed(permits, timeout); end +end + +# Various classes within allows for +nil+ values to be stored, +# so a special +NULL+ token is required to indicate the "nil-ness". +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/constants.rb#6 +Concurrent::NULL = T.let(T.unsafe(nil), Object) + +# Suppresses all output when used for logging. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/logging.rb#103 +Concurrent::NULL_LOGGER = T.let(T.unsafe(nil), Proc) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/options.rb#6 +module Concurrent::Options + class << self + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/options.rb#27 + def executor(executor_identifier); end + + # Get the requested `Executor` based on the values set in the options hash. + # + # @option opts + # @param opts [Hash] the options defining the requested executor + # @return [Executor, nil] the requested thread pool, or nil when no option specified + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/options.rb#19 + def executor_from_options(opts = T.unsafe(nil)); end + end +end + +# Promises are inspired by the JavaScript [Promises/A](http://wiki.commonjs.org/wiki/Promises/A) +# and [Promises/A+](http://promises-aplus.github.io/promises-spec/) specifications. +# +# > A promise represents the eventual value returned from the single +# > completion of an operation. +# +# Promises are similar to futures and share many of the same behaviours. +# Promises are far more robust, however. Promises can be chained in a tree +# structure where each promise may have zero or more children. Promises are +# chained using the `then` method. The result of a call to `then` is always +# another promise. Promises are resolved asynchronously (with respect to the +# main thread) but in a strict order: parents are guaranteed to be resolved +# before their children, children before their younger siblings. The `then` +# method takes two parameters: an optional block to be executed upon parent +# resolution and an optional callable to be executed upon parent failure. The +# result of each promise is passed to each of its children upon resolution. +# When a promise is rejected all its children will be summarily rejected and +# will receive the reason. +# +# Promises have several possible states: *:unscheduled*, *:pending*, +# *:processing*, *:rejected*, or *:fulfilled*. These are also aggregated as +# `#incomplete?` and `#complete?`. When a Promise is created it is set to +# *:unscheduled*. Once the `#execute` method is called the state becomes +# *:pending*. Once a job is pulled from the thread pool's queue and is given +# to a thread for processing (often immediately upon `#post`) the state +# becomes *:processing*. The future will remain in this state until processing +# is complete. A future that is in the *:unscheduled*, *:pending*, or +# *:processing* is considered `#incomplete?`. A `#complete?` Promise is either +# *:rejected*, indicating that an exception was thrown during processing, or +# *:fulfilled*, indicating success. If a Promise is *:fulfilled* its `#value` +# will be updated to reflect the result of the operation. If *:rejected* the +# `reason` will be updated with a reference to the thrown exception. The +# predicate methods `#unscheduled?`, `#pending?`, `#rejected?`, and +# `#fulfilled?` can be called at any time to obtain the state of the Promise, +# as can the `#state` method, which returns a symbol. +# +# Retrieving the value of a promise is done through the `value` (alias: +# `deref`) method. Obtaining the value of a promise is a potentially blocking +# operation. When a promise is *rejected* a call to `value` will return `nil` +# immediately. When a promise is *fulfilled* a call to `value` will +# immediately return the current value. When a promise is *pending* a call to +# `value` will block until the promise is either *rejected* or *fulfilled*. A +# *timeout* value can be passed to `value` to limit how long the call will +# block. If `nil` the call will block indefinitely. If `0` the call will not +# block. Any other integer or float value will indicate the maximum number of +# seconds to block. +# +# Promises run on the global thread pool. +# +# ### Examples +# +# Start by requiring promises +# +# ```ruby +# require 'concurrent/promise' +# ``` +# +# Then create one +# +# ```ruby +# p = Concurrent::Promise.execute do +# # do something +# 42 +# end +# ``` +# +# Promises can be chained using the `then` method. The `then` method accepts a +# block and an executor, to be executed on fulfillment, and a callable argument to be executed +# on rejection. The result of the each promise is passed as the block argument +# to chained promises. +# +# ```ruby +# p = Concurrent::Promise.new{10}.then{|x| x * 2}.then{|result| result - 10 }.execute +# ``` +# +# And so on, and so on, and so on... +# +# ```ruby +# p = Concurrent::Promise.fulfill(20). +# then{|result| result - 10 }. +# then{|result| result * 3 }. +# then(executor: different_executor){|result| result % 5 }.execute +# ``` +# +# The initial state of a newly created Promise depends on the state of its parent: +# - if parent is *unscheduled* the child will be *unscheduled* +# - if parent is *pending* the child will be *pending* +# - if parent is *fulfilled* the child will be *pending* +# - 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 +# 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. +# +# There are multiple ways to create and execute a new `Promise`. Both ways +# provide identical behavior: +# +# ```ruby +# # create, operate, then execute +# p1 = Concurrent::Promise.new{ "Hello World!" } +# p1.state #=> :unscheduled +# p1.execute +# +# # create and immediately execute +# p2 = Concurrent::Promise.new{ "Hello World!" }.execute +# +# # execute during creation +# p3 = Concurrent::Promise.execute{ "Hello World!" } +# ``` +# +# Once the `execute` method is called a `Promise` becomes `pending`: +# +# ```ruby +# p = Concurrent::Promise.execute{ "Hello, world!" } +# p.state #=> :pending +# p.pending? #=> true +# ``` +# +# Wait a little bit, and the promise will resolve and provide a value: +# +# ```ruby +# p = Concurrent::Promise.execute{ "Hello, world!" } +# sleep(0.1) +# +# p.state #=> :fulfilled +# p.fulfilled? #=> true +# p.value #=> "Hello, world!" +# ``` +# +# If an exception occurs, the promise will be rejected and will provide +# a reason for the rejection: +# +# ```ruby +# p = Concurrent::Promise.execute{ raise StandardError.new("Here comes the Boom!") } +# sleep(0.1) +# +# p.state #=> :rejected +# p.rejected? #=> true +# p.reason #=> "#" +# ``` +# +# #### Rejection +# +# When a promise is rejected all its children will be rejected and will +# receive the rejection `reason` as the rejection callable parameter: +# +# ```ruby +# p = Concurrent::Promise.execute { Thread.pass; raise StandardError } +# +# c1 = p.then(-> reason { 42 }) +# c2 = p.then(-> reason { raise 'Boom!' }) +# +# c1.wait.state #=> :fulfilled +# c1.value #=> 45 +# c2.wait.state #=> :rejected +# c2.reason #=> # +# ``` +# +# Once a promise is rejected it will continue to accept children that will +# receive immediately rejection (they will be executed asynchronously). +# +# #### Aliases +# +# The `then` method is the most generic alias: it accepts a block to be +# executed upon parent fulfillment and a callable to be executed upon parent +# rejection. At least one of them should be passed. The default block is `{ +# |result| result }` that fulfills the child with the parent value. The +# default callable is `{ |reason| raise reason }` that rejects the child with +# the parent reason. +# +# - `on_success { |result| ... }` is the same as `then {|result| ... }` +# - `rescue { |reason| ... }` is the same as `then(Proc.new { |reason| ... } )` +# - `rescue` is aliased by `catch` and `on_error` +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#190 +class Concurrent::Promise < ::Concurrent::IVar + # Initialize a new Promise with the provided options. + # + # @option opts + # @option opts + # @option opts + # @option opts + # @param opts [Hash] a customizable set of options + # @raise [ArgumentError] if no block is given + # @return [Promise] a new instance of Promise + # @see http://wiki.commonjs.org/wiki/Promises/A + # @see http://promises-aplus.github.io/promises-spec/ + # @yield The block operation to be performed asynchronously. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#210 + def initialize(opts = T.unsafe(nil), &block); end + + # Chain onto this promise an action to be undertaken on failure + # (rejection). + # + # @return [Promise] self + # @yield The block to execute + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#360 + def catch(&block); end + + # Execute an `:unscheduled` `Promise`. Immediately sets the state to `:pending` and + # passes the block to a new thread/thread pool for eventual execution. + # Does nothing if the `Promise` is in any state other than `:unscheduled`. + # + # @return [Promise] a reference to `self` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#246 + def execute; end + + # Set the `IVar` to failed due to some error and wake or notify all threads waiting on it. + # + # @param reason [Object] for the failure + # @raise [Concurrent::MultipleAssignmentError] if the `IVar` has already + # been set or otherwise completed + # @raise [Concurrent::PromiseExecutionError] if not the root promise + # @return [IVar] self + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#278 + def fail(reason = T.unsafe(nil)); end + + # Yield the successful result to the block that returns a promise. If that + # promise is also successful the result is the result of the yielded promise. + # If either part fails the whole also fails. + # + # @example + # Promise.execute { 1 }.flat_map { |v| Promise.execute { v + 2 } }.value! #=> 3 + # @return [Promise] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#375 + def flat_map(&block); end + + # Chain onto this promise an action to be undertaken on failure + # (rejection). + # + # @return [Promise] self + # @yield The block to execute + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#360 + def on_error(&block); end + + # Chain onto this promise an action to be undertaken on success + # (fulfillment). + # + # @raise [ArgumentError] + # @return [Promise] self + # @yield The block to execute + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#349 + def on_success(&block); end + + # Chain onto this promise an action to be undertaken on failure + # (rejection). + # + # @return [Promise] self + # @yield The block to execute + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#360 + def rescue(&block); end + + # Set the `IVar` to a value and wake or notify all threads waiting on it. + # + # @param value [Object] the value to store in the `IVar` + # @raise [ArgumentError] if both a value and a block are given + # @raise [Concurrent::MultipleAssignmentError] if the `IVar` has already + # been set or otherwise completed + # @raise [Concurrent::PromiseExecutionError] if not the root promise + # @return [IVar] self + # @yield A block operation to use for setting the value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#262 + def set(value = T.unsafe(nil), &block); end + + # Chain a new promise off the current promise. + # + # @overload then + # @overload then + # @raise [ArgumentError] + # @return [Promise] the new promise + # @yield The block operation to be performed asynchronously. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#314 + def then(*args, &block); end + + # Builds a promise that produces the result of self and others in an Array + # and fails if any of them fails. + # + # @overload zip + # @overload zip + # @return [Promise] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#440 + def zip(*others); end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#551 + def complete(success, value, reason); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#545 + def notify_child(child); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#481 + def ns_initialize(value, opts); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#533 + def on_fulfill(result); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#539 + def on_reject(reason); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#562 + def realize(task); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#528 + def root?; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#520 + def set_pending; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#570 + def set_state!(success, value, reason); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#576 + def synchronized_set_state!(success, value, reason); end + + class << self + # Aggregate a collection of zero or more promises under a composite promise, + # execute the aggregated promises and collect them into a standard Ruby array, + # call the given Ruby `Ennnumerable` predicate (such as `any?`, `all?`, `none?`, + # or `one?`) on the collection checking for the success or failure of each, + # then executing the composite's `#then` handlers if the predicate returns + # `true` or executing the composite's `#rescue` handlers if the predicate + # returns false. + # + # + # The returned promise will not yet have been executed. Additional `#then` + # and `#rescue` handlers may still be provided. Once the returned promise + # is execute the aggregate promises will be also be executed (if they have + # not been executed already). The results of the aggregate promises will + # be checked upon completion. The necessary `#then` and `#rescue` blocks + # on the aggregating promise will then be executed as appropriate. If the + # `#rescue` handlers are executed the raises exception will be + # `Concurrent::PromiseExecutionError`. + # + # @param promises [Array] Zero or more promises to aggregate + # @return [Promise] an unscheduled (not executed) promise that aggregates + # the promises given as arguments + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#505 + def aggregate(method, *promises); end + + # Aggregates a collection of promises and executes the `then` condition + # if all aggregated promises succeed. Executes the `rescue` handler with + # a `Concurrent::PromiseExecutionError` if any of the aggregated promises + # fail. Upon execution will execute any of the aggregate promises that + # were not already executed. + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#464 + def all?(*promises); end + + # Aggregates a collection of promises and executes the `then` condition + # if any aggregated promises succeed. Executes the `rescue` handler with + # a `Concurrent::PromiseExecutionError` if any of the aggregated promises + # fail. Upon execution will execute any of the aggregate promises that + # were not already executed. + # + # + # The returned promise will not yet have been executed. Additional `#then` + # and `#rescue` handlers may still be provided. Once the returned promise + # is execute the aggregate promises will be also be executed (if they have + # not been executed already). The results of the aggregate promises will + # be checked upon completion. The necessary `#then` and `#rescue` blocks + # on the aggregating promise will then be executed as appropriate. If the + # `#rescue` handlers are executed the raises exception will be + # `Concurrent::PromiseExecutionError`. + # + # @param promises [Array] Zero or more promises to aggregate + # @return [Promise] an unscheduled (not executed) promise that aggregates + # the promises given as arguments + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#475 + def any?(*promises); end + + # Create a new `Promise` object with the given block, execute it, and return the + # `:pending` object. + # + # @example + # promise = Concurrent::Promise.execute{ sleep(1); 42 } + # promise.state #=> :pending + # @option opts + # @option opts + # @option opts + # @option opts + # @param opts [Hash] a customizable set of options + # @raise [ArgumentError] if no block is given + # @return [Promise] the newly created `Promise` in the `:pending` state + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#296 + def execute(opts = T.unsafe(nil), &block); end + + # Create a new `Promise` and fulfill it immediately. + # + # @option opts + # @option opts + # @option opts + # @option opts + # @param opts [Hash] a customizable set of options + # @raise [ArgumentError] if no block is given + # @return [Promise] the newly created `Promise` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#224 + def fulfill(value, opts = T.unsafe(nil)); end + + # Create a new `Promise` and reject it immediately. + # + # @option opts + # @option opts + # @option opts + # @option opts + # @param opts [Hash] a customizable set of options + # @raise [ArgumentError] if no block is given + # @return [Promise] the newly created `Promise` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#237 + def reject(reason, opts = T.unsafe(nil)); end + + # Builds a promise that produces the result of promises in an Array + # and fails if any of them fails. + # + # @overload zip + # @overload zip + # @return [Promise] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#409 + def zip(*promises); end + end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#11 +class Concurrent::PromiseExecutionError < ::StandardError; end + +# {include:file:docs-source/promises-main.md} +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#13 +module Concurrent::Promises + extend ::Concurrent::Promises::FactoryMethods::Configuration + extend ::Concurrent::Promises::FactoryMethods +end + +# @abstract +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2047 +class Concurrent::Promises::AbstractAnyPromise < ::Concurrent::Promises::BlockedPromise; end + +# Common ancestor of {Event} and {Future} classes, many shared methods are defined here. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#513 +class Concurrent::Promises::AbstractEventFuture < ::Concurrent::Synchronization::Object + include ::Concurrent::Promises::InternalStates + extend ::Concurrent::Synchronization::SafeInitialization + + # @return [AbstractEventFuture] a new instance of AbstractEventFuture + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#522 + def initialize(promise, default_executor); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#137 + def __initialize_atomic_fields__; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#738 + def add_callback_clear_delayed_node(node); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#733 + def add_callback_notify_blocked(promise, index); end + + # For inspection. + # + # @return [Array] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#702 + def blocks; end + + # For inspection. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#710 + def callbacks; end + + # Shortcut of {#chain_on} with default `:io` executor supplied. + # + # @return [Future] + # @see #chain_on + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#596 + def chain(*args, &task); end + + # Chains the task to be executed asynchronously on executor after it is resolved. + # + # @overload an_event.chain_on + # @overload a_future.chain_on + # @param executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. The task is executed on it, default executor remains unchanged. + # @param args [Object] arguments which are passed to the task when it's executed. + # (It might be prepended with other arguments, see the @yield section). + # @return [Future] + # @yieldreturn will become result of the returned Future. + # Its returned value becomes {Future#value} fulfilling it, + # raised exception becomes {Future#reason} rejecting it. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#614 + def chain_on(executor, *args, &task); end + + # Resolves the resolvable when receiver is resolved. + # + # @param resolvable [Resolvable] + # @return [self] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#629 + def chain_resolvable(resolvable); end + + # Returns default executor. + # + # @return [Executor] default executor + # @see #with_default_executor + # @see FactoryMethods#future_on + # @see FactoryMethods#resolvable_future + # @see FactoryMethods#any_fulfilled_future_on + # @see similar + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#590 + def default_executor; end + + # @return [String] Short string representation. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#619 + def inspect; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#93 + def internal_state; end + + # Shortcut of {#on_resolution_using} with default `:io` executor supplied. + # + # @return [self] + # @see #on_resolution_using + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#637 + def on_resolution(*args, &callback); end + + # Stores the callback to be executed synchronously on resolving thread after it is + # resolved. + # + # @overload an_event.on_resolution! + # @overload a_future.on_resolution! + # @param args [Object] arguments which are passed to the task when it's executed. + # (It might be prepended with other arguments, see the @yield section). + # @return [self] + # @yieldreturn is forgotten. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#655 + def on_resolution!(*args, &callback); end + + # Stores the callback to be executed asynchronously on executor after it is resolved. + # + # @overload an_event.on_resolution_using + # @overload a_future.on_resolution_using + # @param executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. The task is executed on it, default executor remains unchanged. + # @param args [Object] arguments which are passed to the task when it's executed. + # (It might be prepended with other arguments, see the @yield section). + # @return [self] + # @yieldreturn is forgotten. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#673 + def on_resolution_using(executor, *args, &callback); end + + # Is it in pending state? + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#549 + def pending?; end + + # For inspection. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#716 + def promise; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#688 + def resolve_with(state, raise_on_reassign = T.unsafe(nil), reserved = T.unsafe(nil)); end + + # Is it in resolved state? + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#555 + def resolved?; end + + # Returns its state. + # + # @overload an_event.state + # @overload a_future.state + # @return [Symbol] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#543 + def state; end + + # Resolves the resolvable when receiver is resolved. + # + # @param resolvable [Resolvable] + # @return [self] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#629 + def tangle(resolvable); end + + # @return [String] Short string representation. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#619 + def to_s; end + + # Propagates touch. Requests all the delayed futures, which it depends on, to be + # executed. This method is called by any other method requiring resolved state, like {#wait}. + # + # @return [self] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#562 + def touch; end + + # For inspection. + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#722 + def touched?; end + + # Wait (block the Thread) until receiver is {#resolved?}. + # Calls {Concurrent::AbstractEventFuture#touch}. + # + # @note This function potentially blocks current thread until the Future is resolved. + # Be careful it can deadlock. Try to chain instead. + # @param timeout [Numeric] the maximum time in second to wait. + # @return [self, true, false] self implies timeout was not used, true implies timeout was used + # and it was resolved, false implies it was not resolved within timeout. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#578 + def wait(timeout = T.unsafe(nil)); end + + # For inspection. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#728 + def waiting_threads; end + + # Crates new object with same class with the executor set as its new default executor. + # Any futures depending on it will use the new default executor. + # + # @abstract + # @raise [NotImplementedError] + # @return [AbstractEventFuture] + # @see Event#with_default_executor + # @see Future#with_default_executor + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#683 + def with_default_executor(executor); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#743 + def with_hidden_resolvable; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#750 + def add_callback(method, *args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#812 + def async_callback_on_resolution(state, executor, args, callback); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#796 + def call_callback(method, state, args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#800 + def call_callbacks(state); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#763 + def callback_clear_delayed_node(state, node); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#818 + def callback_notify_blocked(state, promise, index); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#105 + def compare_and_set_internal_state(expected, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#97 + def internal_state=(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#101 + def swap_internal_state(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#109 + def update_internal_state(&block); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#768 + def wait_until_resolved(timeout); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#808 + def with_async(executor, *args, &block); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1796 +class Concurrent::Promises::AbstractFlatPromise < ::Concurrent::Promises::BlockedPromise + # @return [AbstractFlatPromise] a new instance of AbstractFlatPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1798 + def initialize(delayed_because, blockers_count, event_or_future); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1808 + def touch; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1828 + def add_delayed_of(future); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1820 + def on_resolvable(resolved_future, index); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1824 + def resolvable?(countdown, future, index); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1816 + def touched?; end +end + +# @abstract +# @private +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1549 +class Concurrent::Promises::AbstractPromise < ::Concurrent::Synchronization::Object + include ::Concurrent::Promises::InternalStates + extend ::Concurrent::Synchronization::SafeInitialization + + # @return [AbstractPromise] a new instance of AbstractPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1553 + def initialize(future); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1564 + def default_executor; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1581 + def delayed_because; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1558 + def event; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1558 + def future; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1575 + def inspect; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1568 + def state; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1575 + def to_s; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1572 + def touch; end + + private + + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1592 + def evaluate_to(*args, block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1587 + def resolve_with(new_state, raise_on_reassign = T.unsafe(nil)); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2084 +class Concurrent::Promises::AnyFulfilledFuturePromise < ::Concurrent::Promises::AnyResolvedFuturePromise + private + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2088 + def resolvable?(countdown, event_or_future, index); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2050 +class Concurrent::Promises::AnyResolvedEventPromise < ::Concurrent::Promises::AbstractAnyPromise + # @return [AnyResolvedEventPromise] a new instance of AnyResolvedEventPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2054 + def initialize(delayed, blockers_count, default_executor); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2062 + def on_resolvable(resolved_future, index); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2058 + def resolvable?(countdown, future, index); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2067 +class Concurrent::Promises::AnyResolvedFuturePromise < ::Concurrent::Promises::AbstractAnyPromise + # @return [AnyResolvedFuturePromise] a new instance of AnyResolvedFuturePromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2071 + def initialize(delayed, blockers_count, default_executor); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2079 + def on_resolvable(resolved_future, index); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2075 + def resolvable?(countdown, future, index); end +end + +# @abstract +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1619 +class Concurrent::Promises::BlockedPromise < ::Concurrent::Promises::InnerPromise + # @return [BlockedPromise] a new instance of BlockedPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1661 + def initialize(delayed, blockers_count, future); end + + # for inspection only + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1683 + def blocked_by; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1674 + def delayed_because; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1667 + def on_blocker_resolution(future, index); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1678 + def touch; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1691 + def clear_and_propagate_touch(stack_or_element = T.unsafe(nil)); end + + # @raise [NotImplementedError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1710 + def on_resolvable(resolved_future, index); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1706 + def process_on_blocker_resolution(future, index); end + + # @return [true, false] if resolvable + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1702 + def resolvable?(countdown, future, index); end + + class << self + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1652 + def add_delayed(delayed1, delayed2); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1645 + def new_blocked_by(blockers, *args, &block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1623 + def new_blocked_by1(blocker, *args, &block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1630 + def new_blocked_by2(blocker1, blocker2, *args, &block); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/safe_initialization.rb#29 + def new(*args, &block); end + end +end + +# @abstract +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1716 +class Concurrent::Promises::BlockedTaskPromise < ::Concurrent::Promises::BlockedPromise + # @raise [ArgumentError] + # @return [BlockedTaskPromise] a new instance of BlockedTaskPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1717 + def initialize(delayed, blockers_count, default_executor, executor, args, &task); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1725 + def executor; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1766 +class Concurrent::Promises::ChainPromise < ::Concurrent::Promises::BlockedTaskPromise + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1769 + def on_resolvable(resolved_future, index); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2095 +class Concurrent::Promises::DelayPromise < ::Concurrent::Promises::InnerPromise + # @return [DelayPromise] a new instance of DelayPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2097 + def initialize(default_executor); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2108 + def delayed_because; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2104 + def touch; end +end + +# Represents an event which will happen in future (will be resolved). The event is either +# pending or resolved. It should be always resolved. Use {Future} to communicate rejections and +# cancellation. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#826 +class Concurrent::Promises::Event < ::Concurrent::Promises::AbstractEventFuture + # Creates a new event or a future which will be resolved when receiver and other are. + # Returns an event if receiver and other are events, otherwise returns a future. + # If just one of the parties is Future then the result + # of the returned future is equal to the result of the supplied future. If both are futures + # then the result is as described in {FactoryMethods#zip_futures_on}. + # + # @return [Future, Event] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#839 + def &(other); end + + # Creates a new event which will be resolved when the first of receiver, `event_or_future` + # resolves. + # + # @return [Event] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#853 + def any(event_or_future); end + + # Creates new event dependent on receiver which will not evaluate until touched, see {#touch}. + # In other words, it inserts delay into the chain of Futures making rest of it lazy evaluated. + # + # @return [Event] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#863 + def delay; end + + # Creates new event dependent on receiver scheduled to execute on/in intended_time. + # In time is interpreted from the moment the receiver is resolved, therefore it inserts + # delay into the chain. + # + # @param intended_time [Numeric, Time] `Numeric` means to run in `intended_time` seconds. + # `Time` means to run on `intended_time`. + # @return [Event] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#875 + def schedule(intended_time); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#596 + def then(*args, &task); end + + # Returns self, since this is event + # + # @return [Event] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#893 + def to_event; end + + # Converts event to a future. The future is fulfilled when the event is resolved, the future may never fail. + # + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#885 + def to_future; end + + # Crates new object with same class with the executor set as its new default executor. + # Any futures depending on it will use the new default executor. + # + # @return [Event] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#899 + def with_default_executor(executor); end + + # Creates a new event or a future which will be resolved when receiver and other are. + # Returns an event if receiver and other are events, otherwise returns a future. + # If just one of the parties is Future then the result + # of the returned future is equal to the result of the supplied future. If both are futures + # then the result is as described in {FactoryMethods#zip_futures_on}. + # + # @return [Future, Event] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#839 + def zip(other); end + + # Creates a new event which will be resolved when the first of receiver, `event_or_future` + # resolves. + # + # @return [Event] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#853 + def |(event_or_future); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#910 + def callback_on_resolution(state, args, callback); end + + # @raise [Concurrent::MultipleAssignmentError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#905 + def rejected_resolution(raise_on_reassign, state); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1972 +class Concurrent::Promises::EventWrapperPromise < ::Concurrent::Promises::BlockedPromise + # @return [EventWrapperPromise] a new instance of EventWrapperPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1973 + def initialize(delayed, blockers_count, default_executor); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1979 + def on_resolvable(resolved_future, index); end +end + +# Container of all {Future}, {Event} factory methods. They are never constructed directly with +# new. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#46 +module Concurrent::Promises::FactoryMethods + include ::Concurrent::Promises::FactoryMethods::Configuration + extend ::Concurrent::ReInclude + extend ::Concurrent::Promises::FactoryMethods::Configuration + extend ::Concurrent::Promises::FactoryMethods + + # Shortcut of {#any_resolved_future_on} with default `:io` executor supplied. + # + # @return [Future] + # @see #any_resolved_future_on + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#278 + def any(*futures_and_or_events); end + + # Shortcut of {#any_event_on} with default `:io` executor supplied. + # + # @return [Event] + # @see #any_event_on + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#319 + def any_event(*futures_and_or_events); end + + # Creates a new event which becomes resolved after the first futures_and_or_events resolves. + # If resolved it does not propagate {Concurrent::AbstractEventFuture#touch}, leaving delayed + # futures un-executed if they are not required any more. + # + # @param default_executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # @param futures_and_or_events [AbstractEventFuture] + # @return [Event] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#329 + def any_event_on(default_executor, *futures_and_or_events); end + + # Shortcut of {#any_fulfilled_future_on} with default `:io` executor supplied. + # + # @return [Future] + # @see #any_fulfilled_future_on + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#300 + def any_fulfilled_future(*futures_and_or_events); end + + # Creates a new future which is resolved after the first futures_and_or_events is fulfilled. + # Its result equals the result of the first resolved future or if all futures_and_or_events reject, + # it has reason of the last rejected future. + # If resolved it does not propagate {Concurrent::AbstractEventFuture#touch}, leaving delayed + # futures un-executed if they are not required any more. + # If event is supplied, which does not have value and can be only resolved, it's + # represented as `:fulfilled` with value `nil`. + # + # @param default_executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # @param futures_and_or_events [AbstractEventFuture] + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#313 + def any_fulfilled_future_on(default_executor, *futures_and_or_events); end + + # Shortcut of {#any_resolved_future_on} with default `:io` executor supplied. + # + # @return [Future] + # @see #any_resolved_future_on + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#278 + def any_resolved_future(*futures_and_or_events); end + + # Creates a new future which is resolved after the first futures_and_or_events is resolved. + # Its result equals the result of the first resolved future. + # If resolved it does not propagate {Concurrent::AbstractEventFuture#touch}, leaving delayed + # futures un-executed if they are not required any more. + # If event is supplied, which does not have value and can be only resolved, it's + # represented as `:fulfilled` with value `nil`. + # + # @param default_executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # @param futures_and_or_events [AbstractEventFuture] + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#294 + def any_resolved_future_on(default_executor, *futures_and_or_events); end + + # Shortcut of {#delay_on} with default `:io` executor supplied. + # + # @return [Future, Event] + # @see #delay_on + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#190 + def delay(*args, &task); end + + # Creates a new event or future which is resolved only after it is touched, + # see {Concurrent::AbstractEventFuture#touch}. + # + # @overload delay_on + # @overload delay_on + # @param default_executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#207 + def delay_on(default_executor, *args, &task); end + + # Creates a resolved future which will be fulfilled with the given value. + # + # @param default_executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # @param value [Object] + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#127 + def fulfilled_future(value, default_executor = T.unsafe(nil)); end + + # Shortcut of {#future_on} with default `:io` executor supplied. + # + # @return [Future] + # @see #future_on + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#94 + def future(*args, &task); end + + # Constructs a new Future which will be resolved after block is evaluated on default executor. + # Evaluation begins immediately. + # + # @param default_executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # @param args [Object] arguments which are passed to the task when it's executed. + # (It might be prepended with other arguments, see the @yield section). + # @return [Future] + # @yield [*args] to the task. + # @yieldreturn will become result of the returned Future. + # Its returned value becomes {Future#value} fulfilling it, + # raised exception becomes {Future#reason} rejecting it. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#106 + def future_on(default_executor, *args, &task); end + + # General constructor. Behaves differently based on the argument's type. It's provided for convenience + # but it's better to be explicit. + # + # @overload make_future + # @overload make_future + # @overload make_future + # @overload make_future + # @overload make_future + # @param default_executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # @return [Event, Future] + # @see rejected_future, resolved_event, fulfilled_future + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#174 + def make_future(argument = T.unsafe(nil), default_executor = T.unsafe(nil)); end + + # Creates a resolved future which will be rejected with the given reason. + # + # @param default_executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # @param reason [Object] + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#136 + def rejected_future(reason, default_executor = T.unsafe(nil)); end + + # Shortcut of {#resolvable_event_on} with default `:io` executor supplied. + # + # @return [ResolvableEvent] + # @see #resolvable_event_on + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#63 + def resolvable_event; end + + # Creates a resolvable event, user is responsible for resolving the event once + # by calling {Promises::ResolvableEvent#resolve}. + # + # @param default_executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # @return [ResolvableEvent] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#72 + def resolvable_event_on(default_executor = T.unsafe(nil)); end + + # Shortcut of {#resolvable_future_on} with default `:io` executor supplied. + # + # @return [ResolvableFuture] + # @see #resolvable_future_on + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#78 + def resolvable_future; end + + # Creates resolvable future, user is responsible for resolving the future once by + # {Promises::ResolvableFuture#resolve}, {Promises::ResolvableFuture#fulfill}, + # or {Promises::ResolvableFuture#reject} + # + # @param default_executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # @return [ResolvableFuture] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#88 + def resolvable_future_on(default_executor = T.unsafe(nil)); end + + # Creates resolved event. + # + # @param default_executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # @return [Event] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#144 + def resolved_event(default_executor = T.unsafe(nil)); end + + # Creates a resolved future with will be either fulfilled with the given value or rejected with + # the given reason. + # + # @param fulfilled [true, false] + # @param value [Object] + # @param reason [Object] + # @param default_executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#118 + def resolved_future(fulfilled, value, reason, default_executor = T.unsafe(nil)); end + + # Shortcut of {#schedule_on} with default `:io` executor supplied. + # + # @return [Future, Event] + # @see #schedule_on + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#214 + def schedule(intended_time, *args, &task); end + + # Creates a new event or future which is resolved in intended_time. + # + # @overload schedule_on + # @overload schedule_on + # @param default_executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # @param intended_time [Numeric, Time] `Numeric` means to run in `intended_time` seconds. + # `Time` means to run on `intended_time`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#233 + def schedule_on(default_executor, intended_time, *args, &task); end + + # Shortcut of {#zip_futures_on} with default `:io` executor supplied. + # + # @return [Future] + # @see #zip_futures_on + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#240 + def zip(*futures_and_or_events); end + + # Shortcut of {#zip_events_on} with default `:io` executor supplied. + # + # @return [Event] + # @see #zip_events_on + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#262 + def zip_events(*futures_and_or_events); end + + # Creates a new event which is resolved after all futures_and_or_events are resolved. + # (Future is resolved when fulfilled or rejected.) + # + # @param default_executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # @param futures_and_or_events [AbstractEventFuture] + # @return [Event] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#272 + def zip_events_on(default_executor, *futures_and_or_events); end + + # Shortcut of {#zip_futures_on} with default `:io` executor supplied. + # + # @return [Future] + # @see #zip_futures_on + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#240 + def zip_futures(*futures_and_or_events); end + + # Creates a new future which is resolved after all futures_and_or_events are resolved. + # Its value is an array of zipped future values. Its reason is an array of reasons for rejection. + # If there is an error it rejects. + # If event is supplied, which does not have value and can be only resolved, it's + # represented as `:fulfilled` with value `nil`. + # + # @param default_executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # @param futures_and_or_events [AbstractEventFuture] + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#254 + def zip_futures_on(default_executor, *futures_and_or_events); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#50 +module Concurrent::Promises::FactoryMethods::Configuration + # @return [Executor, :io, :fast] the executor which is used when none is supplied + # to a factory method. The method can be overridden in the receivers of + # `include FactoryMethod` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#54 + def default_executor; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1840 +class Concurrent::Promises::FlatEventPromise < ::Concurrent::Promises::AbstractFlatPromise + # @return [FlatEventPromise] a new instance of FlatEventPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1844 + def initialize(delayed, blockers_count, default_executor); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1848 + def process_on_blocker_resolution(future, index); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1873 +class Concurrent::Promises::FlatFuturePromise < ::Concurrent::Promises::AbstractFlatPromise + # @raise [ArgumentError] + # @return [FlatFuturePromise] a new instance of FlatFuturePromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1877 + def initialize(delayed, blockers_count, levels, default_executor); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1884 + def process_on_blocker_resolution(future, index); end +end + +# Represents a value which will become available in future. May reject with a reason instead, +# e.g. when the tasks raises an exception. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#917 +class Concurrent::Promises::Future < ::Concurrent::Promises::AbstractEventFuture + # Creates a new event or a future which will be resolved when receiver and other are. + # Returns an event if receiver and other are events, otherwise returns a future. + # If just one of the parties is Future then the result + # of the returned future is equal to the result of the supplied future. If both are futures + # then the result is as described in {FactoryMethods#zip_futures_on}. + # + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1070 + def &(other); end + + # Creates a new event which will be resolved when the first of receiver, `event_or_future` + # resolves. Returning future will have value nil if event_or_future is event and resolves + # first. + # + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1085 + def any(event_or_future); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1215 + def apply(args, block); end + + # Creates new future dependent on receiver which will not evaluate until touched, see {#touch}. + # In other words, it inserts delay into the chain of Futures making rest of it lazy evaluated. + # + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1095 + def delay; end + + # Allows rejected Future to be risen with `raise` method. + # If the reason is not an exception `Runtime.new(reason)` is returned. + # + # @example + # raise Promises.rejected_future(StandardError.new("boom")) + # raise Promises.rejected_future("or just boom") + # @raise [Concurrent::Error] when raising not rejected future + # @return [Exception] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1013 + def exception(*args); end + + # Creates new future which will have result of the future returned by receiver. If receiver + # rejects it will have its rejection. + # + # @param level [Integer] how many levels of futures should flatten + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1120 + def flat(level = T.unsafe(nil)); end + + # Creates new event which will be resolved when the returned event by receiver is. + # Be careful if the receiver rejects it will just resolve since Event does not hold reason. + # + # @return [Event] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1130 + def flat_event; end + + # Creates new future which will have result of the future returned by receiver. If receiver + # rejects it will have its rejection. + # + # @param level [Integer] how many levels of futures should flatten + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1120 + def flat_future(level = T.unsafe(nil)); end + + # Is it in fulfilled state? + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#921 + def fulfilled?; end + + # @return [String] Short string representation. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1235 + def inspect; end + + # Shortcut of {#on_fulfillment_using} with default `:io` executor supplied. + # + # @return [self] + # @see #on_fulfillment_using + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1136 + def on_fulfillment(*args, &callback); end + + # Stores the callback to be executed synchronously on resolving thread after it is + # fulfilled. Does nothing on rejection. + # + # @param args [Object] arguments which are passed to the task when it's executed. + # (It might be prepended with other arguments, see the @yield section). + # @return [self] + # @yield [value, *args] to the callback. + # @yieldreturn is forgotten. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1147 + def on_fulfillment!(*args, &callback); end + + # Stores the callback to be executed asynchronously on executor after it is + # fulfilled. Does nothing on rejection. + # + # @param executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. The task is executed on it, default executor remains unchanged. + # @param args [Object] arguments which are passed to the task when it's executed. + # (It might be prepended with other arguments, see the @yield section). + # @return [self] + # @yield [value, *args] to the callback. + # @yieldreturn is forgotten. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1159 + def on_fulfillment_using(executor, *args, &callback); end + + # Shortcut of {#on_rejection_using} with default `:io` executor supplied. + # + # @return [self] + # @see #on_rejection_using + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1165 + def on_rejection(*args, &callback); end + + # Stores the callback to be executed synchronously on resolving thread after it is + # rejected. Does nothing on fulfillment. + # + # @param args [Object] arguments which are passed to the task when it's executed. + # (It might be prepended with other arguments, see the @yield section). + # @return [self] + # @yield [reason, *args] to the callback. + # @yieldreturn is forgotten. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1176 + def on_rejection!(*args, &callback); end + + # Stores the callback to be executed asynchronously on executor after it is + # rejected. Does nothing on fulfillment. + # + # @param executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. The task is executed on it, default executor remains unchanged. + # @param args [Object] arguments which are passed to the task when it's executed. + # (It might be prepended with other arguments, see the @yield section). + # @return [self] + # @yield [reason, *args] to the callback. + # @yieldreturn is forgotten. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1188 + def on_rejection_using(executor, *args, &callback); end + + # Returns reason of future's rejection. + # Calls {Concurrent::AbstractEventFuture#touch}. + # + # @note This function potentially blocks current thread until the Future is resolved. + # Be careful it can deadlock. Try to chain instead. + # @note Make sure returned `nil` is not confused with timeout, no value when rejected, + # no reason when fulfilled, etc. + # Use more exact methods if needed, like {#wait}, {#value!}, {#result}, etc. + # @param timeout [Numeric] the maximum time in second to wait. + # @param timeout_value [Object] a value returned by the method when it times out + # @return [Object, timeout_value] the reason, or timeout_value on timeout, or nil on fulfillment. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#966 + def reason(timeout = T.unsafe(nil), timeout_value = T.unsafe(nil)); end + + # Is it in rejected state? + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#928 + def rejected?; end + + # Shortcut of {#rescue_on} with default `:io` executor supplied. + # + # @return [Future] + # @see #rescue_on + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1052 + def rescue(*args, &task); end + + # Chains the task to be executed asynchronously on executor after it rejects. Does not run + # the task if it fulfills. It will resolve though, triggering any dependent futures. + # + # @param executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. The task is executed on it, default executor remains unchanged. + # @param args [Object] arguments which are passed to the task when it's executed. + # (It might be prepended with other arguments, see the @yield section). + # @return [Future] + # @yield [reason, *args] to the task. + # @yieldreturn will become result of the returned Future. + # Its returned value becomes {Future#value} fulfilling it, + # raised exception becomes {Future#reason} rejecting it. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1064 + def rescue_on(executor, *args, &task); end + + # Returns triplet fulfilled?, value, reason. + # Calls {Concurrent::AbstractEventFuture#touch}. + # + # @note This function potentially blocks current thread until the Future is resolved. + # Be careful it can deadlock. Try to chain instead. + # @param timeout [Numeric] the maximum time in second to wait. + # @return [Array(Boolean, Object, Object), nil] triplet of fulfilled?, value, reason, or nil + # on timeout. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#981 + def result(timeout = T.unsafe(nil)); end + + # Allows to use futures as green threads. The receiver has to evaluate to a future which + # represents what should be done next. It basically flattens indefinitely until non Future + # values is returned which becomes result of the returned future. Any encountered exception + # will become reason of the returned future. + # + # @example + # body = lambda do |v| + # v += 1 + # v < 5 ? Promises.future(v, &body) : v + # end + # Promises.future(0, &body).run.value! # => 5 + # @param run_test [#call(value)] an object which when called returns either Future to keep running with + # or nil, then the run completes with the value. + # The run_test can be used to extract the Future from deeper structure, + # or to distinguish Future which is a resulting value from a future + # which is suppose to continue running. + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1210 + def run(run_test = T.unsafe(nil)); end + + # Creates new event dependent on receiver scheduled to execute on/in intended_time. + # In time is interpreted from the moment the receiver is resolved, therefore it inserts + # delay into the chain. + # + # @param intended_time [Numeric, Time] `Numeric` means to run in `intended_time` seconds. + # `Time` means to run on `intended_time`. + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1102 + def schedule(intended_time); end + + # Shortcut of {#then_on} with default `:io` executor supplied. + # + # @return [Future] + # @see #then_on + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1034 + def then(*args, &task); end + + # Chains the task to be executed asynchronously on executor after it fulfills. Does not run + # the task if it rejects. It will resolve though, triggering any dependent futures. + # + # @param executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. The task is executed on it, default executor remains unchanged. + # @param args [Object] arguments which are passed to the task when it's executed. + # (It might be prepended with other arguments, see the @yield section). + # @return [Future] + # @yield [value, *args] to the task. + # @yieldreturn will become result of the returned Future. + # Its returned value becomes {Future#value} fulfilling it, + # raised exception becomes {Future#reason} rejecting it. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1046 + def then_on(executor, *args, &task); end + + # Converts future to event which is resolved when future is resolved by fulfillment or rejection. + # + # @return [Event] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1222 + def to_event; end + + # Returns self, since this is a future + # + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1230 + def to_future; end + + # @return [String] Short string representation. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1235 + def to_s; end + + # Return value of the future. + # Calls {Concurrent::AbstractEventFuture#touch}. + # + # @note This function potentially blocks current thread until the Future is resolved. + # Be careful it can deadlock. Try to chain instead. + # @note Make sure returned `nil` is not confused with timeout, no value when rejected, + # no reason when fulfilled, etc. + # Use more exact methods if needed, like {#wait}, {#value!}, {#result}, etc. + # @param timeout [Numeric] the maximum time in second to wait. + # @param timeout_value [Object] a value returned by the method when it times out + # @return [Object, nil, timeout_value] the value of the Future when fulfilled, + # timeout_value on timeout, + # nil on rejection. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#950 + def value(timeout = T.unsafe(nil), timeout_value = T.unsafe(nil)); end + + # Return value of the future. + # Calls {Concurrent::AbstractEventFuture#touch}. + # + # @note This function potentially blocks current thread until the Future is resolved. + # Be careful it can deadlock. Try to chain instead. + # @note Make sure returned `nil` is not confused with timeout, no value when rejected, + # no reason when fulfilled, etc. + # Use more exact methods if needed, like {#wait}, {#value!}, {#result}, etc. + # @param timeout [Numeric] the maximum time in second to wait. + # @param timeout_value [Object] a value returned by the method when it times out + # @raise [Exception] {#reason} on rejection + # @return [Object, nil, timeout_value] the value of the Future when fulfilled, + # or nil on rejection, + # or timeout_value on timeout. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#997 + def value!(timeout = T.unsafe(nil), timeout_value = T.unsafe(nil)); end + + # Wait (block the Thread) until receiver is {#resolved?}. + # Calls {Concurrent::AbstractEventFuture#touch}. + # + # @note This function potentially blocks current thread until the Future is resolved. + # Be careful it can deadlock. Try to chain instead. + # @param timeout [Numeric] the maximum time in second to wait. + # @raise [Exception] {#reason} on rejection + # @return [self, true, false] self implies timeout was not used, true implies timeout was used + # and it was resolved, false implies it was not resolved within timeout. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#987 + def wait!(timeout = T.unsafe(nil)); end + + # Crates new object with same class with the executor set as its new default executor. + # Any futures depending on it will use the new default executor. + # + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1111 + def with_default_executor(executor); end + + # Creates a new event or a future which will be resolved when receiver and other are. + # Returns an event if receiver and other are events, otherwise returns a future. + # If just one of the parties is Future then the result + # of the returned future is equal to the result of the supplied future. If both are futures + # then the result is as described in {FactoryMethods#zip_futures_on}. + # + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1070 + def zip(other); end + + # Creates a new event which will be resolved when the first of receiver, `event_or_future` + # resolves. Returning future will have value nil if event_or_future is event and resolves + # first. + # + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1085 + def |(event_or_future); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1272 + def async_callback_on_fulfillment(state, executor, args, callback); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1278 + def async_callback_on_rejection(state, executor, args, callback); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1284 + def callback_on_fulfillment(state, args, callback); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1288 + def callback_on_rejection(state, args, callback); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1292 + def callback_on_resolution(state, args, callback); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1251 + def rejected_resolution(raise_on_reassign, state); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1247 + def run_test(v); end + + # @raise [self] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1266 + def wait_until_resolved!(timeout = T.unsafe(nil)); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1984 +class Concurrent::Promises::FutureWrapperPromise < ::Concurrent::Promises::BlockedPromise + # @return [FutureWrapperPromise] a new instance of FutureWrapperPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1985 + def initialize(delayed, blockers_count, default_executor); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1991 + def on_resolvable(resolved_future, index); end +end + +# will be immediately resolved +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1783 +class Concurrent::Promises::ImmediateEventPromise < ::Concurrent::Promises::InnerPromise + # @return [ImmediateEventPromise] a new instance of ImmediateEventPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1784 + def initialize(default_executor); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1789 +class Concurrent::Promises::ImmediateFuturePromise < ::Concurrent::Promises::InnerPromise + # @return [ImmediateFuturePromise] a new instance of ImmediateFuturePromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1790 + def initialize(default_executor, fulfilled, value, reason); end +end + +# @abstract +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1615 +class Concurrent::Promises::InnerPromise < ::Concurrent::Promises::AbstractPromise; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#338 +module Concurrent::Promises::InternalStates; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#397 +class Concurrent::Promises::InternalStates::Fulfilled < ::Concurrent::Promises::InternalStates::ResolvedWithResult + # @return [Fulfilled] a new instance of Fulfilled + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#399 + def initialize(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#407 + def apply(args, block); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#403 + def fulfilled?; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#415 + def reason; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#419 + def to_sym; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#411 + def value; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#425 +class Concurrent::Promises::InternalStates::FulfilledArray < ::Concurrent::Promises::InternalStates::Fulfilled + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#426 + def apply(args, block); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#488 +Concurrent::Promises::InternalStates::PENDING = T.let(T.unsafe(nil), Concurrent::Promises::InternalStates::Pending) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#459 +class Concurrent::Promises::InternalStates::PartiallyRejected < ::Concurrent::Promises::InternalStates::ResolvedWithResult + # @return [PartiallyRejected] a new instance of PartiallyRejected + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#460 + def initialize(value, reason); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#482 + def apply(args, block); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#466 + def fulfilled?; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#478 + def reason; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#470 + def to_sym; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#474 + def value; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#351 +class Concurrent::Promises::InternalStates::Pending < ::Concurrent::Promises::InternalStates::State + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#352 + def resolved?; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#356 + def to_sym; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#490 +Concurrent::Promises::InternalStates::RESERVED = T.let(T.unsafe(nil), Concurrent::Promises::InternalStates::Reserved) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#492 +Concurrent::Promises::InternalStates::RESOLVED = T.let(T.unsafe(nil), Concurrent::Promises::InternalStates::Fulfilled) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#432 +class Concurrent::Promises::InternalStates::Rejected < ::Concurrent::Promises::InternalStates::ResolvedWithResult + # @return [Rejected] a new instance of Rejected + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#433 + def initialize(reason); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#453 + def apply(args, block); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#437 + def fulfilled?; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#445 + def reason; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#449 + def to_sym; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#441 + def value; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#362 +class Concurrent::Promises::InternalStates::Reserved < ::Concurrent::Promises::InternalStates::Pending; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#366 +class Concurrent::Promises::InternalStates::ResolvedWithResult < ::Concurrent::Promises::InternalStates::State + # @raise [NotImplementedError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#391 + def apply; end + + # @raise [NotImplementedError] + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#379 + def fulfilled?; end + + # @raise [NotImplementedError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#387 + def reason; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#367 + def resolved?; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#375 + def result; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#371 + def to_sym; end + + # @raise [NotImplementedError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#383 + def value; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#340 +class Concurrent::Promises::InternalStates::State + # @raise [NotImplementedError] + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#341 + def resolved?; end + + # @raise [NotImplementedError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#345 + def to_sym; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1748 +class Concurrent::Promises::RescuePromise < ::Concurrent::Promises::BlockedTaskPromise + # @return [RescuePromise] a new instance of RescuePromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1751 + def initialize(delayed, blockers_count, default_executor, executor, args, &task); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1755 + def on_resolvable(resolved_future, index); end +end + +# Marker module of Future, Event resolved manually. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1299 +module Concurrent::Promises::Resolvable + include ::Concurrent::Promises::InternalStates +end + +# A Event which can be resolved by user. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1304 +class Concurrent::Promises::ResolvableEvent < ::Concurrent::Promises::Event + include ::Concurrent::Promises::Resolvable + + # Makes the event resolved, which triggers all dependent futures. + # + # @param raise_on_reassign [Boolean] should method raise exception if already resolved + # @param reserved [true, false] Set to true if the resolvable is {#reserve}d by you, + # marks resolution of reserved resolvable events and futures explicitly. + # Advanced feature, ignore unless you use {Resolvable#reserve} from edge. + # @return [self, false] false is returned when raise_on_reassign is false and the receiver + # is already resolved. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1324 + def resolve(raise_on_reassign = T.unsafe(nil), reserved = T.unsafe(nil)); end + + # Behaves as {AbstractEventFuture#wait} but has one additional optional argument + # resolve_on_timeout. + # + # @param resolve_on_timeout [true, false] If it times out and the argument is true it will also resolve the event. + # @return [self, true, false] + # @see AbstractEventFuture#wait + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1342 + def wait(timeout = T.unsafe(nil), resolve_on_timeout = T.unsafe(nil)); end + + # Creates new event wrapping receiver, effectively hiding the resolve method. + # + # @return [Event] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1331 + def with_hidden_resolvable; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1600 +class Concurrent::Promises::ResolvableEventPromise < ::Concurrent::Promises::AbstractPromise + # @return [ResolvableEventPromise] a new instance of ResolvableEventPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1601 + def initialize(default_executor); end +end + +# A Future which can be resolved by user. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1354 +class Concurrent::Promises::ResolvableFuture < ::Concurrent::Promises::Future + include ::Concurrent::Promises::Resolvable + + # Evaluates the block and sets its result as future's value fulfilling, if the block raises + # an exception the future rejects with it. + # + # @return [self] + # @yield [*args] to the block. + # @yieldreturn [Object] value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1395 + def evaluate_to(*args, &block); end + + # Evaluates the block and sets its result as future's value fulfilling, if the block raises + # an exception the future rejects with it. + # + # @raise [Exception] also raise reason on rejection. + # @return [self] + # @yield [*args] to the block. + # @yieldreturn [Object] value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1406 + def evaluate_to!(*args, &block); end + + # Makes the future fulfilled with `value`, + # which triggers all dependent futures. + # + # @param value [Object] + # @param raise_on_reassign [Boolean] should method raise exception if already resolved + # @param reserved [true, false] Set to true if the resolvable is {#reserve}d by you, + # marks resolution of reserved resolvable events and futures explicitly. + # Advanced feature, ignore unless you use {Resolvable#reserve} from edge. + # @return [self, false] false is returned when raise_on_reassign is false and the receiver + # is already resolved. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1375 + def fulfill(value, raise_on_reassign = T.unsafe(nil), reserved = T.unsafe(nil)); end + + # Behaves as {Future#reason} but has one additional optional argument + # resolve_on_timeout. + # + # @param resolve_on_timeout [::Array(true, Object, nil), ::Array(false, nil, Exception), nil] If it times out and the argument is not nil it will also resolve the future + # to the provided resolution. + # @return [Exception, timeout_value, nil] + # @see Future#reason + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1503 + def reason(timeout = T.unsafe(nil), timeout_value = T.unsafe(nil), resolve_on_timeout = T.unsafe(nil)); end + + # Makes the future rejected with `reason`, + # which triggers all dependent futures. + # + # @param reason [Object] + # @param raise_on_reassign [Boolean] should method raise exception if already resolved + # @param reserved [true, false] Set to true if the resolvable is {#reserve}d by you, + # marks resolution of reserved resolvable events and futures explicitly. + # Advanced feature, ignore unless you use {Resolvable#reserve} from edge. + # @return [self, false] false is returned when raise_on_reassign is false and the receiver + # is already resolved. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1385 + def reject(reason, raise_on_reassign = T.unsafe(nil), reserved = T.unsafe(nil)); end + + # Makes the future resolved with result of triplet `fulfilled?`, `value`, `reason`, + # which triggers all dependent futures. + # + # @param fulfilled [true, false] + # @param value [Object] + # @param reason [Object] + # @param raise_on_reassign [Boolean] should method raise exception if already resolved + # @param reserved [true, false] Set to true if the resolvable is {#reserve}d by you, + # marks resolution of reserved resolvable events and futures explicitly. + # Advanced feature, ignore unless you use {Resolvable#reserve} from edge. + # @return [self, false] false is returned when raise_on_reassign is false and the receiver + # is already resolved. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1365 + def resolve(fulfilled = T.unsafe(nil), value = T.unsafe(nil), reason = T.unsafe(nil), raise_on_reassign = T.unsafe(nil), reserved = T.unsafe(nil)); end + + # Behaves as {Future#result} but has one additional optional argument + # resolve_on_timeout. + # + # @param resolve_on_timeout [::Array(true, Object, nil), ::Array(false, nil, Exception), nil] If it times out and the argument is not nil it will also resolve the future + # to the provided resolution. + # @return [::Array(Boolean, Object, Exception), nil] + # @see Future#result + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1524 + def result(timeout = T.unsafe(nil), resolve_on_timeout = T.unsafe(nil)); end + + # Behaves as {Future#value} but has one additional optional argument + # resolve_on_timeout. + # + # @param resolve_on_timeout [::Array(true, Object, nil), ::Array(false, nil, Exception), nil] If it times out and the argument is not nil it will also resolve the future + # to the provided resolution. + # @return [Object, timeout_value, nil] + # @see Future#value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1459 + def value(timeout = T.unsafe(nil), timeout_value = T.unsafe(nil), resolve_on_timeout = T.unsafe(nil)); end + + # Behaves as {Future#value!} but has one additional optional argument + # resolve_on_timeout. + # + # @param resolve_on_timeout [::Array(true, Object, nil), ::Array(false, nil, Exception), nil] If it times out and the argument is not nil it will also resolve the future + # to the provided resolution. + # @raise [Exception] {#reason} on rejection + # @return [Object, timeout_value, nil] + # @see Future#value! + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1481 + def value!(timeout = T.unsafe(nil), timeout_value = T.unsafe(nil), resolve_on_timeout = T.unsafe(nil)); end + + # Behaves as {AbstractEventFuture#wait} but has one additional optional argument + # resolve_on_timeout. + # + # @param resolve_on_timeout [::Array(true, Object, nil), ::Array(false, nil, Exception), nil] If it times out and the argument is not nil it will also resolve the future + # to the provided resolution. + # @return [self, true, false] + # @see AbstractEventFuture#wait + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1421 + def wait(timeout = T.unsafe(nil), resolve_on_timeout = T.unsafe(nil)); end + + # Behaves as {Future#wait!} but has one additional optional argument + # resolve_on_timeout. + # + # @param resolve_on_timeout [::Array(true, Object, nil), ::Array(false, nil, Exception), nil] If it times out and the argument is not nil it will also resolve the future + # to the provided resolution. + # @raise [Exception] {#reason} on rejection + # @return [self, true, false] + # @see Future#wait! + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1438 + def wait!(timeout = T.unsafe(nil), resolve_on_timeout = T.unsafe(nil)); end + + # Creates new future wrapping receiver, effectively hiding the resolve method and similar. + # + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1542 + def with_hidden_resolvable; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1606 +class Concurrent::Promises::ResolvableFuturePromise < ::Concurrent::Promises::AbstractPromise + # @return [ResolvableFuturePromise] a new instance of ResolvableFuturePromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1607 + def initialize(default_executor); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1592 + def evaluate_to(*args, block); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1909 +class Concurrent::Promises::RunFuturePromise < ::Concurrent::Promises::AbstractFlatPromise + # @return [RunFuturePromise] a new instance of RunFuturePromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1913 + def initialize(delayed, blockers_count, default_executor, run_test); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1918 + def process_on_blocker_resolution(future, index); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2114 +class Concurrent::Promises::ScheduledPromise < ::Concurrent::Promises::InnerPromise + # @return [ScheduledPromise] a new instance of ScheduledPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2125 + def initialize(default_executor, intended_time); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2119 + def inspect; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2115 + def intended_time; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1730 +class Concurrent::Promises::ThenPromise < ::Concurrent::Promises::BlockedTaskPromise + # @return [ThenPromise] a new instance of ThenPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1733 + def initialize(delayed, blockers_count, default_executor, executor, args, &task); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1737 + def on_resolvable(resolved_future, index); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1940 +class Concurrent::Promises::ZipEventEventPromise < ::Concurrent::Promises::BlockedPromise + # @return [ZipEventEventPromise] a new instance of ZipEventEventPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1941 + def initialize(delayed, blockers_count, default_executor); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1947 + def on_resolvable(resolved_future, index); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2031 +class Concurrent::Promises::ZipEventsPromise < ::Concurrent::Promises::BlockedPromise + # @return [ZipEventsPromise] a new instance of ZipEventsPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2035 + def initialize(delayed, blockers_count, default_executor); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2041 + def on_resolvable(resolved_future, index); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1952 +class Concurrent::Promises::ZipFutureEventPromise < ::Concurrent::Promises::BlockedPromise + # @return [ZipFutureEventPromise] a new instance of ZipFutureEventPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1953 + def initialize(delayed, blockers_count, default_executor); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1967 + def on_resolvable(resolved_future, index); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1960 + def process_on_blocker_resolution(future, index); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1996 +class Concurrent::Promises::ZipFuturesPromise < ::Concurrent::Promises::BlockedPromise + # @return [ZipFuturesPromise] a new instance of ZipFuturesPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2000 + def initialize(delayed, blockers_count, default_executor); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2013 + def on_resolvable(resolved_future, index); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2007 + def process_on_blocker_resolution(future, index); end +end + +# Methods form module A included to a module B, which is already included into class C, +# will not be visible in the C class. If this module is extended to B then A's methods +# are correctly made visible to C. +# +# @example +# module A +# def a +# :a +# end +# end +# +# module B1 +# end +# +# class C1 +# include B1 +# end +# +# module B2 +# extend Concurrent::ReInclude +# end +# +# class C2 +# include B2 +# end +# +# B1.send :include, A +# B2.send :include, A +# +# C1.new.respond_to? :a # => false +# C2.new.respond_to? :a # => true +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/re_include.rb#36 +module Concurrent::ReInclude + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/re_include.rb#44 + def extended(base); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/re_include.rb#50 + def include(*modules); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/re_include.rb#38 + def included(base); end +end + +# Ruby read-write lock implementation +# +# Allows any number of concurrent readers, but only one concurrent writer +# (And if the "write" lock is taken, any readers who come along will have to wait) +# +# If readers are already active when a writer comes along, the writer will wait for +# all the readers to finish before going ahead. +# Any additional readers that come when the writer is already waiting, will also +# wait (so writers are not starved). +# +# This implementation is based on `java.util.concurrent.ReentrantReadWriteLock`. +# +# @example +# lock = Concurrent::ReadWriteLock.new +# lock.with_read_lock { data.retrieve } +# lock.with_write_lock { data.modify! } +# @note Do **not** try to acquire the write lock while already holding a read lock +# **or** try to acquire the write lock while you already have it. +# This will lead to deadlock +# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.html java.util.concurrent.ReentrantReadWriteLock +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#31 +class Concurrent::ReadWriteLock < ::Concurrent::Synchronization::Object + extend ::Concurrent::Synchronization::SafeInitialization + + # Create a new `ReadWriteLock` in the unlocked state. + # + # @return [ReadWriteLock] a new instance of ReadWriteLock + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#59 + def initialize; end + + # Acquire a read lock. If a write lock has been acquired will block until + # it is released. Will not block if other read locks have been acquired. + # + # @raise [Concurrent::ResourceLimitError] if the maximum number of readers + # is exceeded. + # @return [Boolean] true if the lock is successfully acquired + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#111 + def acquire_read_lock; end + + # Acquire a write lock. Will block and wait for all active readers and writers. + # + # @raise [Concurrent::ResourceLimitError] if the maximum number of writers + # is exceeded. + # @return [Boolean] true if the lock is successfully acquired + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#160 + def acquire_write_lock; end + + # Queries whether any threads are waiting to acquire the read or write lock. + # + # @return [Boolean] true if any threads are waiting for a lock else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#214 + def has_waiters?; end + + # Release a previously acquired read lock. + # + # @return [Boolean] true if the lock is successfully released + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#140 + def release_read_lock; end + + # Release a previously acquired write lock. + # + # @return [Boolean] true if the lock is successfully released + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#196 + def release_write_lock; end + + # Execute a block operation within a read lock. + # + # @raise [ArgumentError] when no block is given. + # @raise [Concurrent::ResourceLimitError] if the maximum number of readers + # is exceeded. + # @return [Object] the result of the block operation. + # @yield the task to be performed within the lock. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#75 + def with_read_lock; end + + # Execute a block operation within a write lock. + # + # @raise [ArgumentError] when no block is given. + # @raise [Concurrent::ResourceLimitError] if the maximum number of readers + # is exceeded. + # @return [Object] the result of the block operation. + # @yield the task to be performed within the lock. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#94 + def with_write_lock; end + + # Queries if the write lock is held by any thread. + # + # @return [Boolean] true if the write lock is held else false` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#207 + def write_locked?; end + + private + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#246 + def max_readers?(c = T.unsafe(nil)); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#251 + def max_writers?(c = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#221 + def running_readers(c = T.unsafe(nil)); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#226 + def running_readers?(c = T.unsafe(nil)); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#231 + def running_writer?(c = T.unsafe(nil)); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#241 + def waiting_writer?(c = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#236 + def waiting_writers(c = T.unsafe(nil)); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#40 +Concurrent::ReadWriteLock::MAX_READERS = T.let(T.unsafe(nil), Integer) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#43 +Concurrent::ReadWriteLock::MAX_WRITERS = T.let(T.unsafe(nil), Integer) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#37 +Concurrent::ReadWriteLock::RUNNING_WRITER = T.let(T.unsafe(nil), Integer) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#34 +Concurrent::ReadWriteLock::WAITING_WRITER = T.let(T.unsafe(nil), Integer) + +# Re-entrant read-write lock implementation +# +# Allows any number of concurrent readers, but only one concurrent writer +# (And while the "write" lock is taken, no read locks can be obtained either. +# Hence, the write lock can also be called an "exclusive" lock.) +# +# If another thread has taken a read lock, any thread which wants a write lock +# will block until all the readers release their locks. However, once a thread +# starts waiting to obtain a write lock, any additional readers that come along +# will also wait (so writers are not starved). +# +# A thread can acquire both a read and write lock at the same time. A thread can +# also acquire a read lock OR a write lock more than once. Only when the read (or +# write) lock is released as many times as it was acquired, will the thread +# actually let it go, allowing other threads which might have been waiting +# to proceed. Therefore the lock can be upgraded by first acquiring +# read lock and then write lock and that the lock can be downgraded by first +# having both read and write lock a releasing just the write lock. +# +# If both read and write locks are acquired by the same thread, it is not strictly +# necessary to release them in the same order they were acquired. In other words, +# the following code is legal: +# +# This implementation was inspired by `java.util.concurrent.ReentrantReadWriteLock`. +# +# @example +# lock = Concurrent::ReentrantReadWriteLock.new +# lock.acquire_write_lock +# lock.acquire_read_lock +# lock.release_write_lock +# # At this point, the current thread is holding only a read lock, not a write +# # lock. So other threads can take read locks, but not a write lock. +# lock.release_read_lock +# # Now the current thread is not holding either a read or write lock, so +# # another thread could potentially acquire a write lock. +# @example +# lock = Concurrent::ReentrantReadWriteLock.new +# lock.with_read_lock { data.retrieve } +# lock.with_write_lock { data.modify! } +# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.html java.util.concurrent.ReentrantReadWriteLock +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#53 +class Concurrent::ReentrantReadWriteLock < ::Concurrent::Synchronization::Object + extend ::Concurrent::Synchronization::SafeInitialization + + # Create a new `ReentrantReadWriteLock` in the unlocked state. + # + # @return [ReentrantReadWriteLock] a new instance of ReentrantReadWriteLock + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#109 + def initialize; end + + # Acquire a read lock. If a write lock is held by another thread, will block + # until it is released. + # + # @raise [Concurrent::ResourceLimitError] if the maximum number of readers + # is exceeded. + # @return [Boolean] true if the lock is successfully acquired + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#162 + def acquire_read_lock; end + + # Acquire a write lock. Will block and wait for all active readers and writers. + # + # @raise [Concurrent::ResourceLimitError] if the maximum number of writers + # is exceeded. + # @return [Boolean] true if the lock is successfully acquired + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#257 + def acquire_write_lock; end + + # Release a previously acquired read lock. + # + # @return [Boolean] true if the lock is successfully released + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#236 + def release_read_lock; end + + # Release a previously acquired write lock. + # + # @return [Boolean] true if the lock is successfully released + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#329 + def release_write_lock; end + + # Try to acquire a read lock and return true if we succeed. If it cannot be + # acquired immediately, return false. + # + # @return [Boolean] true if the lock is successfully acquired + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#215 + def try_read_lock; end + + # Try to acquire a write lock and return true if we succeed. If it cannot be + # acquired immediately, return false. + # + # @return [Boolean] true if the lock is successfully acquired + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#310 + def try_write_lock; end + + # Execute a block operation within a read lock. + # + # @raise [ArgumentError] when no block is given. + # @raise [Concurrent::ResourceLimitError] if the maximum number of readers + # is exceeded. + # @return [Object] the result of the block operation. + # @yield the task to be performed within the lock. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#126 + def with_read_lock; end + + # Execute a block operation within a write lock. + # + # @raise [ArgumentError] when no block is given. + # @raise [Concurrent::ResourceLimitError] if the maximum number of readers + # is exceeded. + # @return [Object] the result of the block operation. + # @yield the task to be performed within the lock. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#145 + def with_write_lock; end + + private + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#370 + def max_readers?(c = T.unsafe(nil)); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#375 + def max_writers?(c = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#345 + def running_readers(c = T.unsafe(nil)); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#350 + def running_readers?(c = T.unsafe(nil)); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#355 + def running_writer?(c = T.unsafe(nil)); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#365 + def waiting_or_running_writer?(c = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#360 + def waiting_writers(c = T.unsafe(nil)); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#94 +Concurrent::ReentrantReadWriteLock::MAX_READERS = T.let(T.unsafe(nil), Integer) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#96 +Concurrent::ReentrantReadWriteLock::MAX_WRITERS = T.let(T.unsafe(nil), Integer) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#84 +Concurrent::ReentrantReadWriteLock::READER_BITS = T.let(T.unsafe(nil), Integer) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#102 +Concurrent::ReentrantReadWriteLock::READ_LOCK_MASK = T.let(T.unsafe(nil), Integer) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#92 +Concurrent::ReentrantReadWriteLock::RUNNING_WRITER = T.let(T.unsafe(nil), Integer) + +# Used with @Counter: +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#90 +Concurrent::ReentrantReadWriteLock::WAITING_WRITER = T.let(T.unsafe(nil), Integer) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#86 +Concurrent::ReentrantReadWriteLock::WRITER_BITS = T.let(T.unsafe(nil), Integer) + +# Used with @HeldCount: +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#100 +Concurrent::ReentrantReadWriteLock::WRITE_LOCK_HELD = T.let(T.unsafe(nil), Integer) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#104 +Concurrent::ReentrantReadWriteLock::WRITE_LOCK_MASK = T.let(T.unsafe(nil), Integer) + +# Raised by an `Executor` when it is unable to process a given task, +# possibly because of a reject policy or other internal error. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#48 +class Concurrent::RejectedExecutionError < ::Concurrent::Error; end + +# Raised when any finite resource, such as a lock counter, exceeds its +# maximum limit/threshold. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#52 +class Concurrent::ResourceLimitError < ::Concurrent::Error; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#129 +class Concurrent::RubyExchanger < ::Concurrent::AbstractExchanger + extend ::Concurrent::Synchronization::SafeInitialization + + # @return [RubyExchanger] a new instance of RubyExchanger + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#159 + def initialize; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#137 + def __initialize_atomic_fields__; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#105 + def compare_and_set_slot(expected, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#93 + def slot; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#97 + def slot=(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#101 + def swap_slot(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#109 + def update_slot(&block); end + + private + + # Waits for another thread to arrive at this exchange point (unless the + # current thread is interrupted), and then transfers the given object to + # it, receiving its object in return. The timeout value indicates the + # approximate number of seconds the method should block while waiting + # for the exchange. When the timeout value is `nil` the method will + # block indefinitely. + # + # @param value [Object] the value to exchange with another thread + # @param timeout [Numeric, nil] in seconds, `nil` blocks indefinitely + # @return [Object, CANCEL] the value exchanged by the other thread; {CANCEL} on timeout + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#170 + def do_exchange(value, timeout); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#138 +class Concurrent::RubyExchanger::Node < ::Concurrent::Synchronization::Object + extend ::Concurrent::Synchronization::SafeInitialization + + # @return [Node] a new instance of Node + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#142 + def initialize(item); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#137 + def __initialize_atomic_fields__; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#105 + def compare_and_set_value(expected, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#153 + def item; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#149 + def latch; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#101 + def swap_value(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#109 + def update_value(&block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#93 + def value; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#97 + def value=(value); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb#8 +class Concurrent::RubyExecutorService < ::Concurrent::AbstractExecutorService + # @return [RubyExecutorService] a new instance of RubyExecutorService + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb#11 + def initialize(*args, &block); end + + # Begin an immediate shutdown. In-progress tasks will be allowed to + # complete but enqueued tasks will be dismissed and no new tasks + # will be accepted. Has no additional effect if the thread pool is + # not running. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb#42 + def kill; end + + # Submit a task to the executor for asynchronous processing. + # + # @param args [Array] zero or more arguments to be passed to the task + # @raise [ArgumentError] if no task is given + # @return [Boolean] `true` if the task is queued, `false` if the executor + # is not running + # @yield the asynchronous task to perform + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb#17 + def post(*args, &task); end + + # Begin an orderly shutdown. Tasks already in the queue will be executed, + # but no new tasks will be accepted. Has no additional effect if the + # thread pool is not running. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb#33 + def shutdown; end + + # Block until executor shutdown is complete or until `timeout` seconds have + # passed. + # + # @note Does not initiate shutdown or termination. Either `shutdown` or `kill` + # must be called before this method (or on another thread). + # @param timeout [Integer] the maximum number of seconds to wait for shutdown to complete + # @return [Boolean] `true` if shutdown complete or false on `timeout` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb#52 + def wait_for_termination(timeout = T.unsafe(nil)); end + + private + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb#70 + def ns_running?; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb#78 + def ns_shutdown?; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb#66 + def ns_shutdown_execution; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb#74 + def ns_shuttingdown?; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb#58 + def stop_event; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb#62 + def stopped_event; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_single_thread_executor.rb#8 +class Concurrent::RubySingleThreadExecutor < ::Concurrent::RubyThreadPoolExecutor + # @return [RubySingleThreadExecutor] a new instance of RubySingleThreadExecutor + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_single_thread_executor.rb#11 + def initialize(opts = T.unsafe(nil)); end +end + +# **Thread Pool Options** +# +# Thread pools support several configuration options: +# +# * `idletime`: The number of seconds that a thread may be idle before being reclaimed. +# * `name`: The name of the executor (optional). Printed in the executor's `#to_s` output and +# a `-worker-` name is given to its threads if supported by used Ruby +# implementation. `` is uniq for each thread. +# * `max_queue`: The maximum number of tasks that may be waiting in the work queue at +# any one time. When the queue size reaches `max_queue` and no new threads can be created, +# subsequent tasks will be rejected in accordance with the configured `fallback_policy`. +# * `auto_terminate`: When true (default), the threads started will be marked as daemon. +# * `fallback_policy`: The policy defining how rejected tasks are handled. +# +# Three fallback policies are supported: +# +# * `:abort`: Raise a `RejectedExecutionError` exception and discard the task. +# * `:discard`: Discard the task and return false. +# * `:caller_runs`: Execute the task on the calling thread. +# +# **Shutting Down Thread Pools** +# +# Killing a thread pool while tasks are still being processed, either by calling +# the `#kill` method or at application exit, will have unpredictable results. There +# is no way for the thread pool to know what resources are being used by the +# in-progress tasks. When those tasks are killed the impact on those resources +# cannot be predicted. The *best* practice is to explicitly shutdown all thread +# pools using the provided methods: +# +# * Call `#shutdown` to initiate an orderly termination of all in-progress tasks +# * Call `#wait_for_termination` with an appropriate timeout interval an allow +# the orderly shutdown to complete +# * Call `#kill` *only when* the thread pool fails to shutdown in the allotted time +# +# On some runtime platforms (most notably the JVM) the application will not +# exit until all thread pools have been shutdown. To prevent applications from +# "hanging" on exit, all threads can be marked as daemon according to the +# `:auto_terminate` option. +# +# ```ruby +# pool1 = Concurrent::FixedThreadPool.new(5) # threads will be marked as daemon +# pool2 = Concurrent::FixedThreadPool.new(5, auto_terminate: false) # mark threads as non-daemon +# ``` +# +# @note Failure to properly shutdown a thread pool can lead to unpredictable results. +# Please read *Shutting Down Thread Pools* for more information. +# @see http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html Java Tutorials: Thread Pools +# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html Java Executors class +# @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html Java ExecutorService interface +# @see https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setDaemon-boolean- +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#12 +class Concurrent::RubyThreadPoolExecutor < ::Concurrent::RubyExecutorService + # @return [RubyThreadPoolExecutor] a new instance of RubyThreadPoolExecutor + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#45 + def initialize(opts = T.unsafe(nil)); end + + # The number of threads that are actively executing tasks. + # + # @return [Integer] The number of threads that are actively executing tasks. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#65 + def active_count; end + + # Does the task queue have a maximum size? + # + # @return [Boolean] True if the task queue has a maximum size else false. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#72 + def can_overflow?; end + + # The number of tasks that have been completed by the pool since construction. + # + # @return [Integer] The number of tasks that have been completed by the pool since construction. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#60 + def completed_task_count; end + + # The number of seconds that a thread may be idle before being reclaimed. + # + # @return [Integer] The number of seconds that a thread may be idle before being reclaimed. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#36 + def idletime; end + + # The largest number of threads that have been created in the pool since construction. + # + # @return [Integer] The largest number of threads that have been created in the pool since construction. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#50 + def largest_length; end + + # The number of threads currently in the pool. + # + # @return [Integer] The number of threads currently in the pool. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#77 + def length; end + + # The maximum number of threads that may be created in the pool. + # + # @return [Integer] The maximum number of threads that may be created in the pool. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#30 + def max_length; end + + # The maximum number of tasks that may be waiting in the work queue at any one time. + # When the queue size reaches `max_queue` subsequent tasks will be rejected in + # accordance with the configured `fallback_policy`. + # + # @return [Integer] The maximum number of tasks that may be waiting in the work queue at any one time. + # When the queue size reaches `max_queue` subsequent tasks will be rejected in + # accordance with the configured `fallback_policy`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#39 + def max_queue; end + + # The minimum number of threads that may be retained in the pool. + # + # @return [Integer] The minimum number of threads that may be retained in the pool. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#33 + def min_length; end + + # 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) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#118 + def prune_pool; end + + # The number of tasks in the queue awaiting execution. + # + # @return [Integer] The number of tasks in the queue awaiting execution. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#82 + def queue_length; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#103 + def ready_worker(worker, last_message); end + + # 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. + # + # @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. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#87 + def remaining_capacity; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#98 + def remove_busy_worker(worker); end + + # The number of tasks that have been scheduled for execution on the pool since construction. + # + # @return [Integer] The number of tasks that have been scheduled for execution on the pool since construction. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#55 + def scheduled_task_count; end + + # Whether or not a value of 0 for :max_queue option means the queue must perform direct hand-off or rather unbounded queue. + # + # @return [true, false] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#42 + def synchronous; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#108 + def worker_died(worker); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#113 + def worker_task_completed; end + + private + + # creates new worker which has to receive work to do after it's added + # + # @return [nil, Worker] nil of max capacity is reached + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#241 + def ns_add_busy_worker; end + + # tries to assign task to a worker, tries to get one from @ready or to create new one + # + # @return [true, false] if task is assigned to a worker + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#201 + def ns_assign_worker(*args, &task); end + + # tries to enqueue task + # + # @return [true, false] if enqueued + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#219 + def ns_enqueue(*args, &task); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#160 + def ns_execute(*args, &task); end + + # @raise [ArgumentError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#125 + def ns_initialize(opts); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#189 + def ns_kill_execution; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#155 + def ns_limited_queue?; end + + # try oldest worker if it is idle for enough time, it's returned back at the start + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#280 + def ns_prune_pool; end + + # handle ready worker, giving it new job or assigning back to @ready + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#253 + def ns_ready_worker(worker, last_message, success = T.unsafe(nil)); end + + # removes a worker which is not in not tracked in @ready + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#271 + def ns_remove_busy_worker(worker); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#296 + def ns_reset_if_forked; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#174 + def ns_shutdown_execution; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#231 + def ns_worker_died(worker); end +end + +# Default maximum number of threads that will be created in the pool. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#15 +Concurrent::RubyThreadPoolExecutor::DEFAULT_MAX_POOL_SIZE = T.let(T.unsafe(nil), Integer) + +# Default maximum number of tasks that may be added to the task queue. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#21 +Concurrent::RubyThreadPoolExecutor::DEFAULT_MAX_QUEUE_SIZE = T.let(T.unsafe(nil), Integer) + +# Default minimum number of threads that will be retained in the pool. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#18 +Concurrent::RubyThreadPoolExecutor::DEFAULT_MIN_POOL_SIZE = T.let(T.unsafe(nil), Integer) + +# Default value of the :synchronous option. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#27 +Concurrent::RubyThreadPoolExecutor::DEFAULT_SYNCHRONOUS = T.let(T.unsafe(nil), FalseClass) + +# Default maximum number of seconds a thread in the pool may remain idle +# before being reclaimed. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#24 +Concurrent::RubyThreadPoolExecutor::DEFAULT_THREAD_IDLETIMEOUT = T.let(T.unsafe(nil), Integer) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#310 +class Concurrent::RubyThreadPoolExecutor::Worker + include ::Logger::Severity + include ::Concurrent::Concern::Logging + + # @return [Worker] a new instance of Worker + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#313 + def initialize(pool, id); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#324 + def <<(message); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#332 + def kill; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#328 + def stop; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#338 + def create_worker(queue, pool, idletime); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#358 + def run_task(pool, task, args); end +end + +# A simple utility class that executes a callable and returns and array of three elements: +# success - indicating if the callable has been executed without errors +# value - filled by the callable result if it has been executed without errors, nil otherwise +# reason - the error risen by the callable if it has been executed with errors, nil otherwise +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb#9 +class Concurrent::SafeTaskExecutor < ::Concurrent::Synchronization::LockableObject + # @return [SafeTaskExecutor] a new instance of SafeTaskExecutor + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb#11 + def initialize(task, opts = T.unsafe(nil)); end + + # @return [Array] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb#18 + def execute(*args); end +end + +# `ScheduledTask` is a close relative of `Concurrent::Future` but with one +# important difference: A `Future` is set to execute as soon as possible +# whereas a `ScheduledTask` is set to execute after a specified delay. This +# implementation is loosely based on Java's +# [ScheduledExecutorService](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html). +# It is a more feature-rich variant of {Concurrent.timer}. +# +# The *intended* schedule time of task execution is set on object construction +# with the `delay` argument. The delay is a numeric (floating point or integer) +# representing a number of seconds in the future. Any other value or a numeric +# equal to or less than zero will result in an exception. The *actual* schedule +# time of task execution is set when the `execute` method is called. +# +# The constructor can also be given zero or more processing options. Currently +# the only supported options are those recognized by the +# [Dereferenceable](Dereferenceable) module. +# +# The final constructor argument is a block representing the task to be performed. +# If no block is given an `ArgumentError` will be raised. +# +# **States** +# +# `ScheduledTask` mixes in the [Obligation](Obligation) module thus giving it +# "future" behavior. This includes the expected lifecycle states. `ScheduledTask` +# has one additional state, however. While the task (block) is being executed the +# state of the object will be `:processing`. This additional state is necessary +# because it has implications for task cancellation. +# +# **Cancellation** +# +# A `:pending` task can be cancelled using the `#cancel` method. A task in any +# other state, including `:processing`, cannot be cancelled. The `#cancel` +# method returns a boolean indicating the success of the cancellation attempt. +# A cancelled `ScheduledTask` cannot be restarted. It is immutable. +# +# **Obligation and Observation** +# +# The result of a `ScheduledTask` can be obtained either synchronously or +# asynchronously. `ScheduledTask` mixes in both the [Obligation](Obligation) +# module and the +# [Observable](http://ruby-doc.org/stdlib-2.0/libdoc/observer/rdoc/Observable.html) +# module from the Ruby standard library. With one exception `ScheduledTask` +# behaves identically to [Future](Observable) with regard to these modules. +# +# @example Basic usage +# +# require 'concurrent/scheduled_task' +# require 'csv' +# require 'open-uri' +# +# class Ticker +# 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, api_key) } +# price.state #=> :pending +# price.pending? #=> true +# price.value(0) #=> nil (does not block) +# +# 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 +# +# task = Concurrent::ScheduledTask.new(2){ 'What does the fox say?' } +# task.state #=> :unscheduled +# task.execute +# task.state #=> pending +# +# # wait for it... +# sleep(3) +# +# task.unscheduled? #=> false +# task.pending? #=> false +# task.fulfilled? #=> true +# task.rejected? #=> false +# task.value #=> 'What does the fox say?' +# @example One line creation and execution +# +# task = Concurrent::ScheduledTask.new(2){ 'What does the fox say?' }.execute +# task.state #=> pending +# +# task = Concurrent::ScheduledTask.execute(2){ 'What do you get when you multiply 6 by 9?' } +# task.state #=> pending +# @example Failed task execution +# +# task = Concurrent::ScheduledTask.execute(2){ raise StandardError.new('Call me maybe?') } +# task.pending? #=> true +# +# # wait for it... +# sleep(3) +# +# task.unscheduled? #=> false +# task.pending? #=> false +# task.fulfilled? #=> false +# task.rejected? #=> true +# task.value #=> nil +# task.reason #=> # +# @example Task execution with observation +# +# observer = Class.new{ +# def update(time, value, reason) +# puts "The task completed at #{time} with value '#{value}'" +# end +# }.new +# +# task = Concurrent::ScheduledTask.new(2){ 'What does the fox say?' } +# task.add_observer(observer) +# task.execute +# task.pending? #=> true +# +# # wait for it... +# sleep(3) +# +# #>> The task completed at 2013-11-07 12:26:09 -0500 with value 'What does the fox say?' +# @see Concurrent.timer +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#158 +class Concurrent::ScheduledTask < ::Concurrent::IVar + include ::Comparable + + # Schedule a task for execution at a specified future time. + # + # @option opts + # @param delay [Float] the number of seconds to wait for before executing the task + # @param opts [Hash] a customizable set of options + # @raise [ArgumentError] When no block is given + # @raise [ArgumentError] When given a time that is in the past + # @return [ScheduledTask] a new instance of ScheduledTask + # @yield the task to be performed + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#178 + def initialize(delay, opts = T.unsafe(nil), &task); end + + # Comparator which orders by schedule time. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#213 + def <=>(other); end + + # Cancel this task and prevent it from executing. A task can only be + # cancelled if it is pending or unscheduled. + # + # @return [Boolean] true if successfully cancelled else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#235 + def cancel; end + + # Has the task been cancelled? + # + # @return [Boolean] true if the task is in the given state else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#220 + def cancelled?; end + + # Execute an `:unscheduled` `ScheduledTask`. Immediately sets the state to `:pending` + # and starts counting down toward execution. Does nothing if the `ScheduledTask` is + # in any state other than `:unscheduled`. + # + # @return [ScheduledTask] a reference to `self` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#273 + def execute; end + + # The executor on which to execute the task. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#163 + def executor; end + + # The `delay` value given at instanciation. + # + # @return [Float] the initial delay. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#199 + def initial_delay; end + + # Execute the task. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#297 + def process_task; end + + # In the task execution in progress? + # + # @return [Boolean] true if the task is in the given state else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#227 + def processing?; end + + # Reschedule the task using the given delay and the current time. + # A task can only be reset while it is `:pending`. + # + # @param delay [Float] the number of seconds to wait for before executing the task + # @raise [ArgumentError] When given a time that is in the past + # @return [Boolean] true if successfully rescheduled else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#262 + def reschedule(delay); end + + # Reschedule the task using the original delay and the current time. + # A task can only be reset while it is `:pending`. + # + # @return [Boolean] true if successfully rescheduled else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#250 + def reset; end + + # The monotonic time at which the the task is scheduled to be executed. + # + # @return [Float] the schedule time or nil if `unscheduled` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#206 + def schedule_time; end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#135 + def fail(reason = T.unsafe(nil)); end + + # Reschedule the task using the given delay and the current time. + # A task can only be reset while it is `:pending`. + # + # @param delay [Float] the number of seconds to wait for before executing the task + # @return [Boolean] true if successfully rescheduled else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#326 + def ns_reschedule(delay); end + + # Schedule the task using the given delay and the current time. + # + # @param delay [Float] the number of seconds to wait for before executing the task + # @return [Boolean] true if successfully rescheduled else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#312 + def ns_schedule(delay); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#113 + def set(value = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#145 + def try_set(value = T.unsafe(nil), &block); end + + class << self + # Create a new `ScheduledTask` object with the given block, execute it, and return the + # `:pending` object. + # + # @param delay [Float] the number of seconds to wait for before executing the task + # @raise [ArgumentError] if no block is given + # @return [ScheduledTask] the newly created `ScheduledTask` in the `:pending` state + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#290 + def execute(delay, opts = T.unsafe(nil), &task); end + end +end + +# A counting semaphore. Conceptually, a semaphore maintains a set of +# permits. Each {#acquire} blocks if necessary until a permit is +# available, and then takes it. Each {#release} adds a permit, potentially +# 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. +# +# @example +# semaphore = Concurrent::Semaphore.new(2) +# +# t1 = Thread.new do +# semaphore.acquire +# puts "Thread 1 acquired semaphore" +# end +# +# t2 = Thread.new do +# semaphore.acquire +# puts "Thread 2 acquired semaphore" +# end +# +# t3 = Thread.new do +# semaphore.acquire +# puts "Thread 3 acquired semaphore" +# end +# +# t4 = Thread.new do +# sleep(2) +# puts "Thread 4 releasing semaphore" +# semaphore.release +# end +# +# [t1, t2, t3, t4].each(&:join) +# +# # prints: +# # Thread 3 acquired semaphore +# # Thread 2 acquired semaphore +# # 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 +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/semaphore.rb#161 +class Concurrent::Semaphore < ::Concurrent::MutexSemaphore; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/semaphore.rb#96 +Concurrent::SemaphoreImplementation = Concurrent::MutexSemaphore + +# Indicates that the including `ExecutorService` guarantees +# that all operations will occur in the order they are post and that no +# two operations may occur simultaneously. This module provides no +# functionality and provides no guarantees. That is the responsibility +# of the including class. This module exists solely to allow the including +# object to be interrogated for its serialization status. +# +# @example +# class Foo +# include Concurrent::SerialExecutor +# end +# +# foo = Foo.new +# +# foo.is_a? Concurrent::ExecutorService #=> true +# foo.is_a? Concurrent::SerialExecutor #=> true +# foo.serialized? #=> true +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/serial_executor_service.rb#24 +module Concurrent::SerialExecutorService + include ::Logger::Severity + include ::Concurrent::Concern::Logging + include ::Concurrent::ExecutorService + + # Does this executor guarantee serialization of its operations? + # + # @note Always returns `true` + # @return [Boolean] True if the executor guarantees that all operations + # will be post in the order they are received and no two operations may + # occur simultaneously. Else false. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/serial_executor_service.rb#30 + def serialized?; end +end + +# Ensures passed jobs in a serialized order never running at the same time. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/serialized_execution.rb#8 +class Concurrent::SerializedExecution < ::Concurrent::Synchronization::LockableObject + include ::Logger::Severity + include ::Concurrent::Concern::Logging + + # @return [SerializedExecution] a new instance of SerializedExecution + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/serialized_execution.rb#11 + def initialize; end + + # Submit a task to the executor for asynchronous processing. + # + # @param executor [Executor] to be used for this job + # @param args [Array] zero or more arguments to be passed to the task + # @raise [ArgumentError] if no task is given + # @return [Boolean] `true` if the task is queued, `false` if the executor + # is not running + # @yield the asynchronous task to perform + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/serialized_execution.rb#34 + def post(executor, *args, &task); end + + # As {#post} but allows to submit multiple tasks at once, it's guaranteed that they will not + # be interleaved by other tasks. + # + # @param posts [Array, Proc)>] array of triplets where + # first is a {ExecutorService}, second is array of args for task, third is a task (Proc) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/serialized_execution.rb#44 + def posts(posts); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/serialized_execution.rb#75 + def call_job(job); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/serialized_execution.rb#70 + def ns_initialize; end + + # ensures next job is executed if any is stashed + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/serialized_execution.rb#95 + def work(job); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/serialized_execution.rb#16 +class Concurrent::SerializedExecution::Job < ::Struct + # Returns the value of attribute args + # + # @return [Object] the current value of args + def args; end + + # Sets the attribute args + # + # @param value [Object] the value to set the attribute args to. + # @return [Object] the newly set value + def args=(_); end + + # Returns the value of attribute block + # + # @return [Object] the current value of block + def block; end + + # Sets the attribute block + # + # @param value [Object] the value to set the attribute block to. + # @return [Object] the newly set value + def block=(_); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/serialized_execution.rb#17 + def call; end + + # Returns the value of attribute executor + # + # @return [Object] the current value of executor + def executor; end + + # Sets the attribute executor + # + # @param value [Object] the value to set the attribute executor to. + # @return [Object] the newly set value + def executor=(_); end + + class << self + def [](*_arg0); end + def inspect; end + def keyword_init?; end + def members; end + def new(*_arg0); end + end +end + +# A wrapper/delegator for any `ExecutorService` that +# guarantees serialized execution of tasks. +# +# @see [SimpleDelegator](http://www.ruby-doc.org/stdlib-2.1.2/libdoc/delegate/rdoc/SimpleDelegator.html) +# @see Concurrent::SerializedExecution +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/serialized_execution_delegator.rb#12 +class Concurrent::SerializedExecutionDelegator < ::SimpleDelegator + include ::Logger::Severity + include ::Concurrent::Concern::Logging + include ::Concurrent::ExecutorService + include ::Concurrent::SerialExecutorService + + # @return [SerializedExecutionDelegator] a new instance of SerializedExecutionDelegator + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/serialized_execution_delegator.rb#15 + def initialize(executor); end + + # Submit a task to the executor for asynchronous processing. + # + # @param args [Array] zero or more arguments to be passed to the task + # @raise [ArgumentError] if no task is given + # @return [Boolean] `true` if the task is queued, `false` if the executor + # is not running + # @yield the asynchronous task to perform + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/serialized_execution_delegator.rb#22 + def post(*args, &task); end +end + +# A thread-safe subclass of Set. This version locks against the object +# itself for every method call, ensuring only one thread can be reading +# or writing at a time. This includes iteration methods like `#each`. +# +# @note `a += b` is **not** a **thread-safe** operation on +# `Concurrent::Set`. It reads Set `a`, then it creates new `Concurrent::Set` +# which is union of `a` and `b`, then it writes the union to `a`. +# The read and write are independent operations they do not form a single atomic +# operation therefore when two `+=` operations are executed concurrently updates +# may be lost. Use `#merge` instead. +# @see http://ruby-doc.org/stdlib-2.4.0/libdoc/set/rdoc/Set.html Ruby standard library `Set` +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/set.rb#61 +class Concurrent::Set < ::Concurrent::CRubySet; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/set.rb#23 +Concurrent::SetImplementation = Concurrent::CRubySet + +# An thread-safe, write-once variation of Ruby's standard `Struct`. +# Each member can have its value set at most once, either at construction +# or any time thereafter. Attempting to assign a value to a member +# that has already been set will result in a `Concurrent::ImmutabilityError`. +# +# @see http://ruby-doc.org/core/Struct.html Ruby standard library `Struct` +# @see http://en.wikipedia.org/wiki/Final_(Java) Java `final` keyword +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#14 +module Concurrent::SettableStruct + include ::Concurrent::Synchronization::AbstractStruct + + # Equality + # + # @return [Boolean] true if other has the same struct subclass and has + # equal member values (according to `Object#==`) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#50 + def ==(other); end + + # Attribute Reference + # + # @param member [Symbol, String, Integer] the string or symbol name of the member + # for which to obtain the value or the member's index + # @raise [NameError] if the member does not exist + # @raise [IndexError] if the index is out of range. + # @return [Object] the value of the given struct member or the member at the given index. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#45 + def [](member); end + + # Attribute Assignment + # + # Sets the value of the given struct member or the member at the given index. + # + # @param member [Symbol, String, Integer] the string or symbol name of the member + # for which to obtain the value or the member's index + # @raise [NameError] if the name does not exist + # @raise [IndexError] if the index is out of range. + # @raise [Concurrent::ImmutabilityError] if the given member has already been set + # @return [Object] the value of the given struct member or the member at the given index. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#75 + def []=(member, value); end + + # Yields the value of each struct member in order. If no block is given + # an enumerator is returned. + # + # @yield the operation to be performed on each struct member + # @yieldparam value [Object] each struct value (in order) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#55 + def each(&block); end + + # Yields the name and value of each struct member in order. If no block is + # given an enumerator is returned. + # + # @yield the operation to be performed on each struct member/value pair + # @yieldparam member [Object] each struct member (in order) + # @yieldparam value [Object] each struct value (in order) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#61 + def each_pair(&block); end + + # Describe the contents of this struct in a string. + # + # @return [String] the contents of this struct in a string + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#29 + def inspect; end + + # Returns a new struct containing the contents of `other` and the contents + # of `self`. If no block is specified, the value for entries with duplicate + # keys will be that of `other`. Otherwise the value for each duplicate key + # is determined by calling the block with the key, its value in `self` and + # its value in `other`. + # + # @param other [Hash] the hash from which to set the new values + # @raise [ArgumentError] of given a member that is not defined in the struct + # @return [Synchronization::AbstractStruct] a new struct with the new values + # @yield an options block for resolving duplicate keys + # @yieldparam member [String, Symbol] the name of the member which is duplicated + # @yieldparam selfvalue [Object] the value of the member in `self` + # @yieldparam othervalue [Object] the value of the member in `other` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#35 + def merge(other, &block); end + + # Yields each member value from the struct to the block and returns an Array + # containing the member values from the struct for which the given block + # returns a true value (equivalent to `Enumerable#select`). + # + # @return [Array] an array containing each value for which the block returns true + # @yield the operation to be performed on each struct member + # @yieldparam value [Object] each struct value (in order) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#67 + def select(&block); end + + # Returns the values for this struct as an Array. + # + # @return [Array] the values for this struct + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#18 + def to_a; end + + # Returns a hash containing the names and values for the struct’s members. + # + # @return [Hash] the names and values for the struct’s members + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#40 + def to_h; end + + # Describe the contents of this struct in a string. + # + # @return [String] the contents of this struct in a string + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#29 + def to_s; end + + # Returns the values for this struct as an Array. + # + # @return [Array] the values for this struct + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#18 + def values; end + + # Returns the struct member values for each selector as an Array. + # + # A selector may be either an Integer offset or a Range of offsets (as in `Array#values_at`). + # + # @param indexes [Fixnum, Range] the index(es) from which to obatin the values (in order) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#24 + def values_at(*indexes); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#97 + def initialize_copy(original); end + + class << self + # Factory for creating new struct classes. + # + # ``` + # new([class_name] [, member_name]+>) -> StructClass click to toggle source + # new([class_name] [, member_name]+>) {|StructClass| block } -> StructClass + # new(value, ...) -> obj + # StructClass[value, ...] -> obj + # ``` + # + # The first two forms are used to create a new struct subclass `class_name` + # that can contain a value for each member_name . This subclass can be + # used to create instances of the structure like any other Class . + # + # If the `class_name` is omitted an anonymous struct class will be created. + # Otherwise, the name of this struct will appear as a constant in the struct class, + # so it must be unique for all structs under this base class and must start with a + # capital letter. Assigning a struct class to a constant also gives the class + # the name of the constant. + # + # If a block is given it will be evaluated in the context of `StructClass`, passing + # the created class as a parameter. This is the recommended way to customize a struct. + # Subclassing an anonymous struct creates an extra anonymous class that will never be used. + # + # The last two forms create a new instance of a struct subclass. The number of value + # parameters must be less than or equal to the number of attributes defined for the + # struct. Unset parameters default to nil. Passing more parameters than number of attributes + # will raise an `ArgumentError`. + # + # @see http://ruby-doc.org/core/Struct.html#method-c-new Ruby standard library `Struct#new` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#105 + def new(*args, &block); end + end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#115 +Concurrent::SettableStruct::FACTORY = T.let(T.unsafe(nil), T.untyped) + +# An executor service in which every operation spawns a new, +# independently operating thread. +# +# This is perhaps the most inefficient executor service in this +# library. It exists mainly for testing an debugging. Thread creation +# and management is expensive in Ruby and this executor performs no +# resource pooling. This can be very beneficial during testing and +# debugging because it decouples the using code from the underlying +# executor implementation. In production this executor will likely +# lead to suboptimal performance. +# +# @note Intended for use primarily in testing and debugging. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb#21 +class Concurrent::SimpleExecutorService < ::Concurrent::RubyExecutorService + # Submit a task to the executor for asynchronous processing. + # + # @param task [Proc] the asynchronous task to perform + # @return [self] returns itself + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb#56 + def <<(task); end + + # Begin an immediate shutdown. In-progress tasks will be allowed to + # complete but enqueued tasks will be dismissed and no new tasks + # will be accepted. Has no additional effect if the thread pool is + # not running. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb#84 + def kill; end + + # Submit a task to the executor for asynchronous processing. + # + # @param args [Array] zero or more arguments to be passed to the task + # @raise [ArgumentError] if no task is given + # @return [Boolean] `true` if the task is queued, `false` if the executor + # is not running + # @yield the asynchronous task to perform + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb#40 + def post(*args, &task); end + + # Is the executor running? + # + # @return [Boolean] `true` when running, `false` when shutting down or shutdown + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb#62 + def running?; end + + # Begin an orderly shutdown. Tasks already in the queue will be executed, + # but no new tasks will be accepted. Has no additional effect if the + # thread pool is not running. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb#77 + def shutdown; end + + # Is the executor shutdown? + # + # @return [Boolean] `true` when shutdown, `false` when shutting down or running + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb#72 + def shutdown?; end + + # Is the executor shuttingdown? + # + # @return [Boolean] `true` when not running and not shutdown, else `false` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb#67 + def shuttingdown?; end + + # Block until executor shutdown is complete or until `timeout` seconds have + # passed. + # + # @note Does not initiate shutdown or termination. Either `shutdown` or `kill` + # must be called before this method (or on another thread). + # @param timeout [Integer] the maximum number of seconds to wait for shutdown to complete + # @return [Boolean] `true` if shutdown complete or false on `timeout` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb#91 + def wait_for_termination(timeout = T.unsafe(nil)); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb#97 + def ns_initialize(*args); end + + class << self + # Submit a task to the executor for asynchronous processing. + # + # @param task [Proc] the asynchronous task to perform + # @return [self] returns itself + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb#34 + def <<(task); end + + # Submit a task to the executor for asynchronous processing. + # + # @param args [Array] zero or more arguments to be passed to the task + # @raise [ArgumentError] if no task is given + # @return [Boolean] `true` if the task is queued, `false` if the executor + # is not running + # @yield the asynchronous task to perform + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb#24 + def post(*args); end + end +end + +# A thread pool with a single thread an unlimited queue. Should the thread +# die for any reason it will be removed and replaced, thus ensuring that +# the executor will always remain viable and available to process jobs. +# +# A common pattern for background processing is to create a single thread +# on which an infinite loop is run. The thread's loop blocks on an input +# source (perhaps blocking I/O or a queue) and processes each input as it +# 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 +# to errors from within tasks. Also, should the thread die it will +# automatically be restarted. +# +# The API and behavior of this class are based on Java's `SingleThreadExecutor`. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/single_thread_executor.rb#37 +class Concurrent::SingleThreadExecutor < ::Concurrent::RubySingleThreadExecutor; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/single_thread_executor.rb#10 +Concurrent::SingleThreadExecutorImplementation = Concurrent::RubySingleThreadExecutor + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_object.rb#2 +module Concurrent::Synchronization + class << self + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/full_memory_barrier.rb#7 + def full_memory_barrier; end + end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb#9 +class Concurrent::Synchronization::AbstractLockableObject < ::Concurrent::Synchronization::Object + protected + + # Broadcast to all waiting threads. + # + # @note only to be used inside synchronized block + # @note to provide direct access to this method in a descendant add method + # ``` + # def broadcast + # synchronize { ns_broadcast } + # end + # ``` + # @raise [NotImplementedError] + # @return [self] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb#96 + def ns_broadcast; end + + # Signal one waiting thread. + # + # @note only to be used inside synchronized block + # @note to provide direct access to this method in a descendant add method + # ``` + # def signal + # synchronize { ns_signal } + # end + # ``` + # @raise [NotImplementedError] + # @return [self] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb#81 + def ns_signal; end + + # Wait until another thread calls #signal or #broadcast, + # spurious wake-ups can happen. + # + # @note only to be used inside synchronized block + # @note to provide direct access to this method in a descendant add method + # ``` + # def wait(timeout = nil) + # synchronize { ns_wait(timeout) } + # end + # ``` + # @param timeout [Numeric, nil] in seconds, `nil` means no timeout + # @raise [NotImplementedError] + # @return [self] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb#66 + def ns_wait(timeout = T.unsafe(nil)); end + + # Wait until condition is met or timeout passes, + # protects against spurious wake-ups. + # + # @note only to be used inside synchronized block + # @note to provide direct access to this method in a descendant add method + # ``` + # def wait_until(timeout = nil, &condition) + # synchronize { ns_wait_until(timeout, &condition) } + # end + # ``` + # @param timeout [Numeric, nil] in seconds, `nil` means no timeout + # @return [true, false] if condition met + # @yield condition to be met + # @yieldreturn [true, false] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb#37 + def ns_wait_until(timeout = T.unsafe(nil), &condition); end + + # @note can by made public in descendants if required by `public :synchronize` + # @raise [NotImplementedError] + # @yield runs the block synchronized against this object, + # equivalent of java's `synchronize(this) {}` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb#18 + def synchronize; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_object.rb#6 +class Concurrent::Synchronization::AbstractObject + # @return [AbstractObject] a new instance of AbstractObject + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_object.rb#7 + def initialize; end + + # @abstract + # @raise [NotImplementedError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_object.rb#13 + def full_memory_barrier; end + + class << self + # @raise [NotImplementedError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_object.rb#17 + def attr_volatile(*names); end + end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#6 +module Concurrent::Synchronization::AbstractStruct + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#9 + def initialize(*values); end + + # Returns the number of struct members. + # + # @return [Fixnum] the number of struct members + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#19 + def length; end + + # Returns the struct members as an array of symbols. + # + # @return [Array] the struct members as an array of symbols + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#29 + def members; end + + # Returns the number of struct members. + # + # @return [Fixnum] the number of struct members + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#19 + def size; end + + protected + + # Yields the value of each struct member in order. If no block is given + # an enumerator is returned. + # + # @yield the operation to be performed on each struct member + # @yieldparam value [Object] each struct value (in order) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#82 + def ns_each; end + + # Yields the name and value of each struct member in order. If no block is + # given an enumerator is returned. + # + # @yield the operation to be performed on each struct member/value pair + # @yieldparam member [Object] each struct member (in order) + # @yieldparam value [Object] each struct value (in order) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#89 + def ns_each_pair; end + + # Equality + # + # @return [Boolean] true if other has the same struct subclass and has + # equal member values (according to `Object#==`) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#75 + def ns_equality(other); end + + # Attribute Reference + # + # @param member [Symbol, String, Integer] the string or symbol name of the member + # for which to obtain the value or the member's index + # @raise [NameError] if the member does not exist + # @raise [IndexError] if the index is out of range. + # @return [Object] the value of the given struct member or the member at the given index. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#59 + def ns_get(member); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#119 + def ns_initialize_copy; end + + # Describe the contents of this struct in a string. + # + # @return [String] the contents of this struct in a string + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#105 + def ns_inspect; end + + # Returns a new struct containing the contents of `other` and the contents + # of `self`. If no block is specified, the value for entries with duplicate + # keys will be that of `other`. Otherwise the value for each duplicate key + # is determined by calling the block with the key, its value in `self` and + # its value in `other`. + # + # @param other [Hash] the hash from which to set the new values + # @raise [ArgumentError] of given a member that is not defined in the struct + # @return [Synchronization::AbstractStruct] a new struct with the new values + # @yield an options block for resolving duplicate keys + # @yieldparam member [String, Symbol] the name of the member which is duplicated + # @yieldparam selfvalue [Object] the value of the member in `self` + # @yieldparam othervalue [Object] the value of the member in `other` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#114 + def ns_merge(other, &block); end + + # Yields each member value from the struct to the block and returns an Array + # containing the member values from the struct for which the given block + # returns a true value (equivalent to `Enumerable#select`). + # + # @return [Array] an array containing each value for which the block returns true + # @yield the operation to be performed on each struct member + # @yieldparam value [Object] each struct value (in order) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#98 + def ns_select; end + + # Returns a hash containing the names and values for the struct’s members. + # + # @return [Hash] the names and values for the struct’s members + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#52 + def ns_to_h; end + + # Returns the values for this struct as an Array. + # + # @return [Array] the values for this struct + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#38 + def ns_values; end + + # Returns the struct member values for each selector as an Array. + # + # A selector may be either an Integer offset or a Range of offsets (as in `Array#values_at`). + # + # @param indexes [Fixnum, Range] the index(es) from which to obatin the values (in order) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#45 + def ns_values_at(indexes); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#130 + def pr_underscore(clazz); end + + class << self + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#141 + def define_struct_class(parent, base, name, members, &block); end + end +end + +# TODO (pitr-ch 04-Dec-2016): should be in edge +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/condition.rb#8 +class Concurrent::Synchronization::Condition < ::Concurrent::Synchronization::LockableObject + # @return [Condition] a new instance of Condition + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/condition.rb#18 + def initialize(lock); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/condition.rb#47 + def broadcast; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/condition.rb#51 + def ns_broadcast; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/condition.rb#43 + def ns_signal; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/condition.rb#27 + def ns_wait(timeout = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/condition.rb#35 + def ns_wait_until(timeout = T.unsafe(nil), &condition); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/condition.rb#39 + def signal; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/condition.rb#23 + def wait(timeout = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/condition.rb#31 + def wait_until(timeout = T.unsafe(nil), &condition); end + + class << self + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/safe_initialization.rb#29 + def private_new(*args, &block); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/safe_initialization.rb#29 + def new(*args, &block); end + end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#8 +module Concurrent::Synchronization::ConditionSignalling + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#16 + def ns_broadcast; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#11 + def ns_signal; end +end + +# TODO (pitr-ch 04-Dec-2016): should be in edge +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/lock.rb#8 +class Concurrent::Synchronization::Lock < ::Concurrent::Synchronization::LockableObject + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/lock.rb#31 + def broadcast; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#16 + def ns_broadcast; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#11 + def ns_signal; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#52 + def ns_wait(timeout = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb#37 + def ns_wait_until(timeout = T.unsafe(nil), &condition); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/lock.rb#25 + def signal; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#44 + def synchronize; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/lock.rb#13 + def wait(timeout = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/lock.rb#19 + def wait_until(timeout = T.unsafe(nil), &condition); end +end + +# Safe synchronization under any Ruby implementation. +# It provides methods like {#synchronize}, {#wait}, {#signal} and {#broadcast}. +# Provides a single layer which can improve its implementation over time without changes needed to +# the classes using it. Use {Synchronization::Object} not this abstract class. +# +# @note this object does not support usage together with +# [`Thread#wakeup`](http://ruby-doc.org/core/Thread.html#method-i-wakeup) +# and [`Thread#raise`](http://ruby-doc.org/core/Thread.html#method-i-raise). +# `Thread#sleep` and `Thread#wakeup` will work as expected but mixing `Synchronization::Object#wait` and +# `Thread#wakeup` will not work on all platforms. +# +# @see Event implementation as an example of this class use +# +# @example simple +# class AnClass < Synchronization::Object +# def initialize +# super +# synchronize { @value = 'asd' } +# end +# +# def value +# synchronize { @value } +# end +# end +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/lockable_object.rb#50 +class Concurrent::Synchronization::LockableObject < ::Concurrent::Synchronization::MutexLockableObject + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/condition.rb#57 + def new_condition; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/lockable_object.rb#11 +Concurrent::Synchronization::LockableObjectImplementation = Concurrent::Synchronization::MutexLockableObject + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#60 +class Concurrent::Synchronization::MonitorLockableObject < ::Concurrent::Synchronization::AbstractLockableObject + include ::Concurrent::Synchronization::ConditionSignalling + extend ::Concurrent::Synchronization::SafeInitialization + + # @return [MonitorLockableObject] a new instance of MonitorLockableObject + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#65 + def initialize; end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#83 + def ns_wait(timeout = T.unsafe(nil)); end + + # TODO may be a problem with lock.synchronize { lock.wait } + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#79 + def synchronize; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#71 + def initialize_copy(other); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#25 +class Concurrent::Synchronization::MutexLockableObject < ::Concurrent::Synchronization::AbstractLockableObject + include ::Concurrent::Synchronization::ConditionSignalling + extend ::Concurrent::Synchronization::SafeInitialization + + # @return [MutexLockableObject] a new instance of MutexLockableObject + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#30 + def initialize; end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#52 + def ns_wait(timeout = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#44 + def synchronize; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#36 + def initialize_copy(other); end +end + +# Abstract object providing final, volatile, ans CAS extensions to build other concurrent abstractions. +# - final instance variables see {Object.safe_initialization!} +# - volatile instance variables see {Object.attr_volatile} +# - volatile instance variables see {Object.attr_atomic} +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#15 +class Concurrent::Synchronization::Object < ::Concurrent::Synchronization::AbstractObject + include ::Concurrent::Synchronization::Volatile + extend ::Concurrent::Synchronization::Volatile::ClassMethods + + # Has to be called by children. + # + # @return [Object] a new instance of Object + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#28 + def initialize; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#146 + def __initialize_atomic_fields__; end + + class << self + # @return [true, false] is the attribute with name atomic? + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#125 + def atomic_attribute?(name); end + + # @param inherited [true, false] should inherited volatile with CAS fields be returned? + # @return [::Array] Returns defined volatile with CAS fields on this class. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#119 + def atomic_attributes(inherited = T.unsafe(nil)); end + + # 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. + # 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)`. + # + # @param names [::Array] of the instance variables to be volatile with CAS. + # @return [::Array] names of defined method names. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#84 + def attr_atomic(*names); end + + # For testing purposes, quite slow. Injects assert code to new method which will raise if class instance contains + # any instance variables with CamelCase names and isn't {.safe_initialization?}. + # + # @raise when offend found + # @return [true] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#45 + def ensure_safe_initialization_when_final_fields_are_present; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#33 + def safe_initialization!; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#37 + def safe_initialization?; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#131 + def define_initialize_atomic_fields; end + end +end + +# By extending this module, a class and all its children are marked to be constructed safely. Meaning that +# all writes (ivar initializations) are made visible to all readers of newly constructed object. It ensures +# same behaviour as Java's final fields. +# +# Due to using Kernel#extend, the module is not included again if already present in the ancestors, +# which avoids extra overhead. +# +# @example +# class AClass < Concurrent::Synchronization::Object +# extend Concurrent::Synchronization::SafeInitialization +# +# def initialize +# @AFinalValue = 'value' # published safely, #foo will never return nil +# end +# +# def foo +# @AFinalValue +# end +# end +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/safe_initialization.rb#28 +module Concurrent::Synchronization::SafeInitialization + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/safe_initialization.rb#29 + def new(*args, &block); end +end + +# Volatile adds the attr_volatile class method when included. +# +# foo = Foo.new +# foo.bar +# => 1 +# foo.bar = 2 +# => 2 +# +# @example +# class Foo +# include Concurrent::Synchronization::Volatile +# +# attr_volatile :bar +# +# def initialize +# self.bar = 1 +# end +# end +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/volatile.rb#28 +module Concurrent::Synchronization::Volatile + mixes_in_class_methods ::Concurrent::Synchronization::Volatile::ClassMethods + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/volatile.rb#33 + def full_memory_barrier; end + + class << self + # @private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/volatile.rb#29 + def included(base); end + end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/volatile.rb#37 +module Concurrent::Synchronization::Volatile::ClassMethods + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/volatile.rb#39 + def attr_volatile(*names); end +end + +# This class provides a trivial way to synchronize all calls to a given object +# by wrapping it with a `Delegator` that performs `Monitor#enter/exit` calls +# around the delegated `#send`. Example: +# +# array = [] # not thread-safe on many impls +# array = SynchronizedDelegator.new([]) # thread-safe +# +# A simple `Monitor` provides a very coarse-grained way to synchronize a given +# object, in that it will cause synchronization for methods that have no need +# for it, but this is a trivial way to get thread-safety where none may exist +# currently on some implementations. +# +# This class is currently being considered for inclusion into stdlib, via +# https://bugs.ruby-lang.org/issues/8556 +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb#21 +class Concurrent::SynchronizedDelegator < ::SimpleDelegator + # @return [SynchronizedDelegator] a new instance of SynchronizedDelegator + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb#31 + def initialize(obj); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb#36 + def method_missing(method, *args, &block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb#22 + def setup; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb#27 + def teardown; end +end + +# A `TVar` is a transactional variable - a single-element container that +# is used as part of a transaction - see `Concurrent::atomically`. +# +# +# ## Thread-safe Variable Classes +# +# Each of the thread-safe variable classes is designed to solve a different +# problem. In general: +# +# * *{Concurrent::Agent}:* Shared, mutable variable providing independent, +# uncoordinated, *asynchronous* change of individual values. Best used when +# the value will undergo frequent, complex updates. Suitable when the result +# of an update does not need to be known immediately. +# * *{Concurrent::Atom}:* Shared, mutable variable providing independent, +# uncoordinated, *synchronous* change of individual values. Best used when +# the value will undergo frequent reads but only occasional, though complex, +# updates. Suitable when the result of an update must be known immediately. +# * *{Concurrent::AtomicReference}:* A simple object reference that can be updated +# atomically. Updates are synchronous but fast. Best used when updates a +# simple set operations. Not suitable when updates are complex. +# {Concurrent::AtomicBoolean} and {Concurrent::AtomicFixnum} are similar +# but optimized for the given data type. +# * *{Concurrent::Exchanger}:* Shared, stateless synchronization point. Used +# when two or more threads need to exchange data. The threads will pair then +# block on each other until the exchange is complete. +# * *{Concurrent::MVar}:* Shared synchronization point. Used when one thread +# must give a value to another, which must take the value. The threads will +# block on each other until the exchange is complete. +# * *{Concurrent::ThreadLocalVar}:* Shared, mutable, isolated variable which +# holds a different value for each thread which has access. Often used as +# an instance variable in objects which must maintain different state +# for different threads. +# * *{Concurrent::TVar}:* Shared, mutable variables which provide +# *coordinated*, *synchronous*, change of *many* stated. Used when multiple +# value must change together, in an all-or-nothing transaction. +# {include:file:docs-source/tvar.md} +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#12 +class Concurrent::TVar < ::Concurrent::Synchronization::Object + extend ::Concurrent::Synchronization::SafeInitialization + + # Create a new `TVar` with an initial value. + # + # @return [TVar] a new instance of TVar + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#16 + def initialize(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#46 + def unsafe_lock; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#36 + def unsafe_value; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#41 + def unsafe_value=(value); end + + # Get the value of a `TVar`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#22 + def value; end + + # Set the value of a `TVar`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#29 + def value=(value); end +end + +# A `ThreadLocalVar` is a variable where the value is different for each thread. +# Each variable may have a default value, but when you modify the variable only +# the current thread will ever see that change. +# +# This is similar to Ruby's built-in thread-local variables (`Thread#thread_variable_get`), +# but with these major advantages: +# * `ThreadLocalVar` has its own identity, it doesn't need a Symbol. +# * Each Ruby's built-in thread-local variable leaks some memory forever (it's a Symbol held forever on the thread), +# so it's only OK to create a small amount of them. +# `ThreadLocalVar` has no such issue and it is fine to create many of them. +# * Ruby's built-in thread-local variables leak forever the value set on each thread (unless set to nil explicitly). +# `ThreadLocalVar` automatically removes the mapping for each thread once the `ThreadLocalVar` instance is GC'd. +# +# +# ## Thread-safe Variable Classes +# +# Each of the thread-safe variable classes is designed to solve a different +# problem. In general: +# +# * *{Concurrent::Agent}:* Shared, mutable variable providing independent, +# uncoordinated, *asynchronous* change of individual values. Best used when +# the value will undergo frequent, complex updates. Suitable when the result +# of an update does not need to be known immediately. +# * *{Concurrent::Atom}:* Shared, mutable variable providing independent, +# uncoordinated, *synchronous* change of individual values. Best used when +# the value will undergo frequent reads but only occasional, though complex, +# updates. Suitable when the result of an update must be known immediately. +# * *{Concurrent::AtomicReference}:* A simple object reference that can be updated +# atomically. Updates are synchronous but fast. Best used when updates a +# simple set operations. Not suitable when updates are complex. +# {Concurrent::AtomicBoolean} and {Concurrent::AtomicFixnum} are similar +# but optimized for the given data type. +# * *{Concurrent::Exchanger}:* Shared, stateless synchronization point. Used +# when two or more threads need to exchange data. The threads will pair then +# block on each other until the exchange is complete. +# * *{Concurrent::MVar}:* Shared synchronization point. Used when one thread +# must give a value to another, which must take the value. The threads will +# block on each other until the exchange is complete. +# * *{Concurrent::ThreadLocalVar}:* Shared, mutable, isolated variable which +# holds a different value for each thread which has access. Often used as +# an instance variable in objects which must maintain different state +# for different threads. +# * *{Concurrent::TVar}:* Shared, mutable variables which provide +# *coordinated*, *synchronous*, change of *many* stated. Used when multiple +# value must change together, in an all-or-nothing transaction. +# +# @example +# v = ThreadLocalVar.new(14) +# v.value #=> 14 +# v.value = 2 +# v.value #=> 2 +# @example +# v = ThreadLocalVar.new(14) +# +# t1 = Thread.new do +# v.value #=> 14 +# v.value = 1 +# v.value #=> 1 +# end +# +# t2 = Thread.new do +# v.value #=> 14 +# v.value = 2 +# v.value #=> 2 +# end +# +# v.value #=> 14 +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb#43 +class Concurrent::ThreadLocalVar + # Creates a thread local variable. + # + # @param default [Object] the default value when otherwise unset + # @param default_block [Proc] Optional block that gets called to obtain the + # default value for each thread + # @return [ThreadLocalVar] a new instance of ThreadLocalVar + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb#51 + def initialize(default = T.unsafe(nil), &default_block); end + + # Bind the given value to thread local storage during + # execution of the given block. + # + # @param value [Object] the value to bind + # @return [Object] the value + # @yield the operation to be performed with the bound variable + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb#88 + def bind(value); end + + # Returns the value in the current thread's copy of this thread-local variable. + # + # @return [Object] the current value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb#70 + def value; end + + # Sets the current thread's copy of this thread-local variable to the specified value. + # + # @param value [Object] the value to set + # @return [Object] the new value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb#78 + def value=(value); end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb#103 + def default; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb#44 +Concurrent::ThreadLocalVar::LOCALS = T.let(T.unsafe(nil), Concurrent::ThreadLocals) + +# An array-backed storage of indexed variables per thread. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#141 +class Concurrent::ThreadLocals < ::Concurrent::AbstractLocals + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#142 + def locals; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#146 + def locals!; end +end + +# An abstraction composed of one or more threads and a task queue. Tasks +# (blocks or `proc` objects) are submitted to the pool and added to the queue. +# The threads in the pool remove the tasks and execute them in the order +# they were received. +# +# A `ThreadPoolExecutor` will automatically adjust the pool size according +# to the bounds set by `min-threads` and `max-threads`. When a new task is +# submitted and fewer than `min-threads` threads are running, a new thread +# is created to handle the request, even if other worker threads are idle. +# If there are more than `min-threads` but less than `max-threads` threads +# running, a new thread will be created only if the queue is full. +# +# Threads that are idle for too long will be garbage collected, down to the +# configured minimum options. Should a thread crash it, too, will be garbage collected. +# +# `ThreadPoolExecutor` is based on the Java class of the same name. From +# the official Java documentation; +# +# > Thread pools address two different problems: they usually provide +# > improved performance when executing large numbers of asynchronous tasks, +# > due to reduced per-task invocation overhead, and they provide a means +# > of bounding and managing the resources, including threads, consumed +# > when executing a collection of tasks. Each ThreadPoolExecutor also +# > maintains some basic statistics, such as the number of completed tasks. +# > +# > To be useful across a wide range of contexts, this class provides many +# > adjustable parameters and extensibility hooks. However, programmers are +# > urged to use the more convenient Executors factory methods +# > [CachedThreadPool] (unbounded thread pool, with automatic thread reclamation), +# > [FixedThreadPool] (fixed size thread pool) and [SingleThreadExecutor] (single +# > background thread), that preconfigure settings for the most common usage +# > scenarios. +# +# **Thread Pool Options** +# +# Thread pools support several configuration options: +# +# * `idletime`: The number of seconds that a thread may be idle before being reclaimed. +# * `name`: The name of the executor (optional). Printed in the executor's `#to_s` output and +# a `-worker-` name is given to its threads if supported by used Ruby +# implementation. `` is uniq for each thread. +# * `max_queue`: The maximum number of tasks that may be waiting in the work queue at +# any one time. When the queue size reaches `max_queue` and no new threads can be created, +# subsequent tasks will be rejected in accordance with the configured `fallback_policy`. +# * `auto_terminate`: When true (default), the threads started will be marked as daemon. +# * `fallback_policy`: The policy defining how rejected tasks are handled. +# +# Three fallback policies are supported: +# +# * `:abort`: Raise a `RejectedExecutionError` exception and discard the task. +# * `:discard`: Discard the task and return false. +# * `:caller_runs`: Execute the task on the calling thread. +# +# **Shutting Down Thread Pools** +# +# Killing a thread pool while tasks are still being processed, either by calling +# the `#kill` method or at application exit, will have unpredictable results. There +# is no way for the thread pool to know what resources are being used by the +# in-progress tasks. When those tasks are killed the impact on those resources +# cannot be predicted. The *best* practice is to explicitly shutdown all thread +# pools using the provided methods: +# +# * Call `#shutdown` to initiate an orderly termination of all in-progress tasks +# * Call `#wait_for_termination` with an appropriate timeout interval an allow +# the orderly shutdown to complete +# * Call `#kill` *only when* the thread pool fails to shutdown in the allotted time +# +# On some runtime platforms (most notably the JVM) the application will not +# exit until all thread pools have been shutdown. To prevent applications from +# "hanging" on exit, all threads can be marked as daemon according to the +# `:auto_terminate` option. +# +# ```ruby +# pool1 = Concurrent::FixedThreadPool.new(5) # threads will be marked as daemon +# pool2 = Concurrent::FixedThreadPool.new(5, auto_terminate: false) # mark threads as non-daemon +# ``` +# +# @note Failure to properly shutdown a thread pool can lead to unpredictable results. +# Please read *Shutting Down Thread Pools* for more information. +# @see http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html Java Tutorials: Thread Pools +# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html Java Executors class +# @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html Java ExecutorService interface +# @see https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setDaemon-boolean- +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/thread_pool_executor.rb#56 +class Concurrent::ThreadPoolExecutor < ::Concurrent::RubyThreadPoolExecutor; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/thread_pool_executor.rb#10 +Concurrent::ThreadPoolExecutorImplementation = Concurrent::RubyThreadPoolExecutor + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util.rb#4 +module Concurrent::ThreadSafe; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util.rb#7 +module Concurrent::ThreadSafe::Util + class << self + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#16 + def make_synchronized_on_cruby(klass); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#41 + def make_synchronized_on_truffleruby(klass); end + end +end + +# TODO (pitr-ch 15-Oct-2016): migrate to Utility::ProcessorCounter +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util.rb#13 +Concurrent::ThreadSafe::Util::CPU_COUNT = T.let(T.unsafe(nil), Integer) + +# TODO (pitr-ch 15-Oct-2016): migrate to Utility::NativeInteger +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util.rb#10 +Concurrent::ThreadSafe::Util::FIXNUM_BIT_SIZE = T.let(T.unsafe(nil), Integer) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util.rb#11 +Concurrent::ThreadSafe::Util::MAX_INT = T.let(T.unsafe(nil), Integer) + +# Raised when an operation times out. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#55 +class Concurrent::TimeoutError < ::Concurrent::Error; end + +# Executes a collection of tasks, each after a given delay. A master task +# monitors the set and schedules each task for execution at the appropriate +# time. Tasks are run on the global thread pool or on the supplied executor. +# Each task is represented as a `ScheduledTask`. +# +# @see Concurrent::ScheduledTask +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/timer_set.rb#19 +class Concurrent::TimerSet < ::Concurrent::RubyExecutorService + # Create a new set of timed tasks. + # + # @option opts + # @param opts [Hash] the options used to specify the executor on which to perform actions + # @return [TimerSet] a new instance of TimerSet + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/timer_set.rb#30 + def initialize(opts = T.unsafe(nil)); end + + # Begin an immediate shutdown. In-progress tasks will be allowed to + # complete but enqueued tasks will be dismissed and no new tasks + # will be accepted. Has no additional effect if the thread pool is + # not running. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/timer_set.rb#62 + def kill; end + + # Post a task to be execute run after a given delay (in seconds). If the + # delay is less than 1/100th of a second the task will be immediately post + # to the executor. + # + # @param delay [Float] the number of seconds to wait for before executing the task. + # @param args [Array] the arguments passed to the task on execution. + # @raise [ArgumentError] if the intended execution time is not in the future. + # @raise [ArgumentError] if no block is given. + # @return [Concurrent::ScheduledTask, false] IVar representing the task if the post + # is successful; false after shutdown. + # @yield the task to be performed. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/timer_set.rb#48 + def post(delay, *args, &task); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/executor_service.rb#166 + def <<(task); end + + # Initialize the object. + # + # @param opts [Hash] the options to create the object with. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/timer_set.rb#74 + def ns_initialize(opts); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/timer_set.rb#94 + def ns_post_task(task); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/timer_set.rb#129 + def ns_reset_if_forked; end + + # `ExecutorService` callback called during shutdown. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/timer_set.rb#122 + def ns_shutdown_execution; end + + # Post the task to the internal queue. + # + # @note This is intended as a callback method from ScheduledTask + # only. It is not intended to be used directly. Post a task + # by using the `SchedulesTask#execute` method. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/timer_set.rb#89 + def post_task(task); end + + # Run a loop and execute tasks in the scheduled order and at the approximate + # scheduled time. If no tasks remain the thread will exit gracefully so that + # garbage collection can occur. If there are no ready tasks it will sleep + # for up to 60 seconds waiting for the next scheduled task. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/timer_set.rb#143 + def process_tasks; end + + # Remove the given task from the queue. + # + # @note This is intended as a callback method from `ScheduledTask` + # only. It is not intended to be used directly. Cancel a task + # by using the `ScheduledTask#cancel` method. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/timer_set.rb#115 + def remove_task(task); end +end + +# A very common concurrency pattern is to run a thread that performs a task at +# regular intervals. The thread that performs the task sleeps for the given +# interval then wakes up and performs the task. Lather, rinse, repeat... This +# pattern causes two problems. First, it is difficult to test the business +# logic of the task because the task itself is tightly coupled with the +# concurrency logic. Second, an exception raised while performing the task can +# cause the entire thread to abend. In a long-running application where the +# task thread is intended to run for days/weeks/years a crashed task thread +# can pose a significant problem. `TimerTask` alleviates both problems. +# +# When a `TimerTask` is launched it starts a thread for monitoring the +# execution interval. The `TimerTask` thread does not perform the task, +# however. Instead, the TimerTask launches the task on a separate thread. +# 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. +# +# One other advantage of `TimerTask` is that it forces the business logic to +# be completely decoupled from the concurrency logic. The business logic can +# be tested separately then passed to the `TimerTask` for scheduling and +# running. +# +# A `TimerTask` supports two different types of interval calculations. +# A fixed delay will always wait the same amount of time between the +# completion of one task and the start of the next. A fixed rate will +# attempt to maintain a constant rate of execution regardless of the +# duration of the task. For example, if a fixed rate task is scheduled +# to run every 60 seconds but the task itself takes 10 seconds to +# complete, the next task will be scheduled to run 50 seconds after +# the start of the previous task. If the task takes 70 seconds to +# complete, the next task will be start immediately after the previous +# task completes. Tasks will not be executed concurrently. +# +# In some cases it may be necessary for a `TimerTask` to affect its own +# execution cycle. To facilitate this, a reference to the TimerTask instance +# is passed as an argument to the provided block every time the task is +# executed. +# +# The `TimerTask` class includes the `Dereferenceable` mixin module so the +# result of the last execution is always available via the `#value` method. +# Dereferencing options can be passed to the `TimerTask` during construction or +# at any later time using the `#set_deref_options` method. +# +# `TimerTask` supports notification through the Ruby standard library +# {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). +# +# @example Basic usage +# task = Concurrent::TimerTask.new{ puts 'Boom!' } +# task.execute +# +# task.execution_interval #=> 60 (default) +# +# # wait 60 seconds... +# #=> 'Boom!' +# +# task.shutdown #=> true +# @example Configuring `:execution_interval` +# task = Concurrent::TimerTask.new(execution_interval: 5) do +# puts 'Boom!' +# end +# +# task.execution_interval #=> 5 +# @example Immediate execution with `:run_now` +# task = Concurrent::TimerTask.new(run_now: true){ puts 'Boom!' } +# task.execute +# +# #=> 'Boom!' +# @example Configuring `:interval_type` with either :fixed_delay or :fixed_rate, default is :fixed_delay +# task = Concurrent::TimerTask.new(execution_interval: 5, interval_type: :fixed_rate) do +# puts 'Boom!' +# end +# task.interval_type #=> :fixed_rate +# @example Last `#value` and `Dereferenceable` mixin +# task = Concurrent::TimerTask.new( +# dup_on_deref: true, +# execution_interval: 5 +# ){ Time.now } +# +# task.execute +# Time.now #=> 2013-11-07 18:06:50 -0500 +# sleep(10) +# task.value #=> 2013-11-07 18:06:55 -0500 +# @example Controlling execution from within the block +# timer_task = Concurrent::TimerTask.new(execution_interval: 1) do |task| +# task.execution_interval.to_i.times{ print 'Boom! ' } +# print "\n" +# task.execution_interval += 1 +# if task.execution_interval > 5 +# puts 'Stopping...' +# task.shutdown +# end +# end +# +# timer_task.execute +# #=> Boom! +# #=> Boom! Boom! +# #=> Boom! Boom! Boom! +# #=> Boom! Boom! Boom! Boom! +# #=> Boom! Boom! Boom! Boom! Boom! +# #=> Stopping... +# @example Observation +# class TaskObserver +# def update(time, result, ex) +# if result +# print "(#{time}) Execution successfully returned #{result}\n" +# else +# print "(#{time}) Execution failed with error #{ex}\n" +# end +# end +# end +# +# task = Concurrent::TimerTask.new(execution_interval: 1){ 42 } +# task.add_observer(TaskObserver.new) +# task.execute +# sleep 4 +# +# #=> (2013-10-13 19:08:58 -0400) Execution successfully returned 42 +# #=> (2013-10-13 19:08:59 -0400) Execution successfully returned 42 +# #=> (2013-10-13 19:09:00 -0400) Execution successfully returned 42 +# task.shutdown +# +# task = Concurrent::TimerTask.new(execution_interval: 1){ sleep } +# task.add_observer(TaskObserver.new) +# task.execute +# +# #=> (2013-10-13 19:07:25 -0400) Execution timed out +# #=> (2013-10-13 19:07:27 -0400) Execution timed out +# #=> (2013-10-13 19:07:29 -0400) Execution timed out +# task.shutdown +# +# task = Concurrent::TimerTask.new(execution_interval: 1){ raise StandardError } +# task.add_observer(TaskObserver.new) +# task.execute +# +# #=> (2013-10-13 19:09:37 -0400) Execution failed with error StandardError +# #=> (2013-10-13 19:09:38 -0400) Execution failed with error StandardError +# #=> (2013-10-13 19:09:39 -0400) Execution failed with error StandardError +# task.shutdown +# @see http://ruby-doc.org/stdlib-2.0/libdoc/observer/rdoc/Observable.html +# @see http://docs.oracle.com/javase/7/docs/api/java/util/TimerTask.html +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#165 +class Concurrent::TimerTask < ::Concurrent::RubyExecutorService + include ::Concurrent::Concern::Dereferenceable + include ::Concurrent::Concern::Observable + + # Create a new TimerTask with the given task and configuration. + # + # @option opts + # @option opts + # @option opts + # @param opts [Hash] the options defining task execution. + # @raise ArgumentError when no block is given. + # @return [TimerTask] the new `TimerTask` + # @yield to the block after :execution_interval seconds have passed since + # the last yield + # @yieldparam task a reference to the `TimerTask` instance so that the + # block can control its own lifecycle. Necessary since `self` will + # refer to the execution context of the block rather than the running + # `TimerTask`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#209 + def initialize(opts = T.unsafe(nil), &task); end + + # Execute a previously created `TimerTask`. + # + # @example Instance and execute in separate steps + # task = Concurrent::TimerTask.new(execution_interval: 10){ print "Hello World\n" } + # task.running? #=> false + # task.execute + # task.running? #=> true + # @example Instance and execute in one line + # task = Concurrent::TimerTask.new(execution_interval: 10){ print "Hello World\n" }.execute + # task.running? #=> true + # @return [TimerTask] a reference to `self` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#235 + def execute; end + + # @return [Fixnum] Number of seconds after the task completes before the + # task is performed again. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#259 + def execution_interval; end + + # @return [Fixnum] Number of seconds after the task completes before the + # task is performed again. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#266 + def execution_interval=(value); end + + # @return [Symbol] method to calculate the interval between executions + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#276 + def interval_type; end + + # Is the executor running? + # + # @return [Boolean] `true` when running, `false` when shutting down or shutdown + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#218 + def running?; end + + # @return [Fixnum] Number of seconds the task can run before it is + # considered to have failed. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#281 + def timeout_interval; end + + # @return [Fixnum] Number of seconds the task can run before it is + # considered to have failed. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#288 + def timeout_interval=(value); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/executor_service.rb#166 + def <<(task); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#352 + def calculate_next_interval(start_time); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#336 + def execute_task(completion); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#296 + def ns_initialize(opts, &task); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#324 + def ns_kill_execution; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#318 + def ns_shutdown_execution; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb#17 + def post(*args, &task); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#330 + def schedule_next_task(interval = T.unsafe(nil)); end + + class << self + # Create and execute a new `TimerTask`. + # + # @example + # task = Concurrent::TimerTask.execute(execution_interval: 10){ print "Hello World\n" } + # task.running? #=> true + # @option opts + # @option opts + # @option opts + # @param opts [Hash] the options defining task execution. + # @raise ArgumentError when no block is given. + # @return [TimerTask] the new `TimerTask` + # @yield to the block after :execution_interval seconds have passed since + # the last yield + # @yieldparam task a reference to the `TimerTask` instance so that the + # block can control its own lifecycle. Necessary since `self` will + # refer to the execution context of the block rather than the running + # `TimerTask`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#252 + def execute(opts = T.unsafe(nil), &task); end + end +end + +# Default `:interval_type` +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#181 +Concurrent::TimerTask::DEFAULT_INTERVAL_TYPE = T.let(T.unsafe(nil), Symbol) + +# Default `:execution_interval` in seconds. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#170 +Concurrent::TimerTask::EXECUTION_INTERVAL = T.let(T.unsafe(nil), Integer) + +# Maintain the interval between the end of one execution and the start of the next execution. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#173 +Concurrent::TimerTask::FIXED_DELAY = T.let(T.unsafe(nil), Symbol) + +# Maintain the interval between the start of one execution and the start of the next. +# If execution time exceeds the interval, the next execution will start immediately +# after the previous execution finishes. Executions will not run concurrently. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#178 +Concurrent::TimerTask::FIXED_RATE = T.let(T.unsafe(nil), Symbol) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#153 +class Concurrent::Transaction + # @return [Transaction] a new instance of Transaction + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#162 + def initialize; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#192 + def abort; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#196 + def commit; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#177 + def open(tvar); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#166 + def read(tvar); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#206 + def unlock; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#171 + def write(tvar, value); end + + class << self + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#212 + def current; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#216 + def current=(transaction); end + end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#155 +Concurrent::Transaction::ABORTED = T.let(T.unsafe(nil), Object) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#159 +class Concurrent::Transaction::AbortError < ::StandardError; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#160 +class Concurrent::Transaction::LeaveError < ::StandardError; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#157 +class Concurrent::Transaction::OpenEntry < ::Struct + # Returns the value of attribute modified + # + # @return [Object] the current value of modified + def modified; end + + # Sets the attribute modified + # + # @param value [Object] the value to set the attribute modified to. + # @return [Object] the newly set value + def modified=(_); end + + # Returns the value of attribute value + # + # @return [Object] the current value of value + def value; end + + # Sets the attribute value + # + # @param value [Object] the value to set the attribute value to. + # @return [Object] the newly set value + def value=(_); end + + class << self + def [](*_arg0); end + def inspect; end + def keyword_init?; end + def members; end + def new(*_arg0); end + end +end + +# A fixed size array with volatile (synchronized, thread safe) getters/setters. +# Mixes in Ruby's `Enumerable` module for enhanced search, sort, and traversal. +# +# @example +# tuple = Concurrent::Tuple.new(16) +# +# tuple.set(0, :foo) #=> :foo | volatile write +# tuple.get(0) #=> :foo | volatile read +# tuple.compare_and_set(0, :foo, :bar) #=> true | strong CAS +# tuple.cas(0, :foo, :baz) #=> false | strong CAS +# tuple.get(0) #=> :bar | volatile read +# @see https://en.wikipedia.org/wiki/Tuple Tuple entry at Wikipedia +# @see http://www.erlang.org/doc/reference_manual/data_types.html#id70396 Erlang Tuple +# @see http://ruby-doc.org/core-2.2.2/Enumerable.html Enumerable +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/tuple.rb#20 +class Concurrent::Tuple + include ::Enumerable + + # Create a new tuple of the given size. + # + # @param size [Integer] the number of elements in the tuple + # @return [Tuple] a new instance of Tuple + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tuple.rb#29 + def initialize(size); end + + # Set the value at the given index to the new value if and only if the current + # value matches the given old value. + # + # @param i [Integer] the index for the element to set + # @param old_value [Object] the value to compare against the current value + # @param new_value [Object] the value to set at the given index + # @return [Boolean] true if the value at the given element was set else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tuple.rb#69 + def cas(i, old_value, new_value); end + + # Set the value at the given index to the new value if and only if the current + # value matches the given old value. + # + # @param i [Integer] the index for the element to set + # @param old_value [Object] the value to compare against the current value + # @param new_value [Object] the value to set at the given index + # @return [Boolean] true if the value at the given element was set else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tuple.rb#69 + def compare_and_set(i, old_value, new_value); end + + # Calls the given block once for each element in self, passing that element as a parameter. + # + # @yieldparam ref [Object] the `Concurrent::AtomicReference` object at the current index + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tuple.rb#78 + def each; end + + # Get the value of the element at the given index. + # + # @param i [Integer] the index from which to retrieve the value + # @return [Object] the value at the given index or nil if the index is out of bounds + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tuple.rb#43 + def get(i); end + + # Set the element at the given index to the given value + # + # @param i [Integer] the index for the element to set + # @param value [Object] the value to set at the given index + # @return [Object] the new value of the element at the given index or nil if the index is out of bounds + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tuple.rb#55 + def set(i, value); end + + # The (fixed) size of the tuple. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tuple.rb#24 + def size; end + + # Get the value of the element at the given index. + # + # @param i [Integer] the index from which to retrieve the value + # @return [Object] the value at the given index or nil if the index is out of bounds + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tuple.rb#43 + def volatile_get(i); end + + # Set the element at the given index to the given value + # + # @param i [Integer] the index for the element to set + # @param value [Object] the value to set at the given index + # @return [Object] the new value of the element at the given index or nil if the index is out of bounds + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tuple.rb#55 + def volatile_set(i, value); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/engine.rb#3 +module Concurrent::Utility; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/engine.rb#6 +module Concurrent::Utility::EngineDetector + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/engine.rb#7 + def on_cruby?; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/engine.rb#11 + def on_jruby?; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/engine.rb#27 + def on_linux?; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/engine.rb#23 + def on_osx?; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/engine.rb#15 + def on_truffleruby?; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/engine.rb#19 + def on_windows?; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/engine.rb#31 + def ruby_version(version = T.unsafe(nil), comparison, major, minor, patch); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb#9 +module Concurrent::Utility::NativeExtensionLoader + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb#11 + def allow_c_extensions?; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb#15 + def c_extensions_loaded?; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb#19 + def load_native_extensions; end + + private + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb#50 + def java_extensions_loaded?; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb#38 + def load_error_path(error); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb#46 + def set_c_extensions_loaded; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb#54 + def set_java_extensions_loaded; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb#58 + def try_load_c_extension(path); end +end + +# @private +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_integer.rb#5 +module Concurrent::Utility::NativeInteger + extend ::Concurrent::Utility::NativeInteger + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_integer.rb#24 + def ensure_integer(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_integer.rb#31 + def ensure_integer_and_bounds(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_integer.rb#17 + def ensure_lower_bound(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_integer.rb#37 + def ensure_positive(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_integer.rb#44 + def ensure_positive_and_no_zero(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_integer.rb#10 + def ensure_upper_bound(value); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_integer.rb#8 +Concurrent::Utility::NativeInteger::MAX_VALUE = T.let(T.unsafe(nil), Integer) + +# http://stackoverflow.com/questions/535721/ruby-max-integer +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_integer.rb#7 +Concurrent::Utility::NativeInteger::MIN_VALUE = T.let(T.unsafe(nil), Integer) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#10 +class Concurrent::Utility::ProcessorCounter + # @return [ProcessorCounter] a new instance of ProcessorCounter + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#11 + def initialize; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#26 + def available_processor_count; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#41 + def cpu_quota; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#45 + def cpu_shares; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#22 + def physical_processor_count; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#18 + def processor_count; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#104 + def compute_cpu_quota; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#124 + def compute_cpu_shares; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#59 + def compute_physical_processor_count; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#51 + def compute_processor_count; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#99 + def run(command); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/version.rb#2 +Concurrent::VERSION = T.let(T.unsafe(nil), String) diff --git a/Library/Homebrew/test/patch_spec.rb b/Library/Homebrew/test/patch_spec.rb index f9c7b5c5818ee..c546f520a1e80 100644 --- a/Library/Homebrew/test/patch_spec.rb +++ b/Library/Homebrew/test/patch_spec.rb @@ -55,7 +55,7 @@ subject(:patch) { described_class.create(:p2, nil) } context "when the patch is empty" do - it(:resource) { expect(patch.resource).to be_a Resource::PatchResource } + it(:resource) { expect(patch.resource).to be_a Resource::Patch } it { expect(patch.patch_files).to eq(patch.resource.patch_files) } it { expect(patch.patch_files).to eq([]) } end diff --git a/Library/Homebrew/utils/tty.rb b/Library/Homebrew/utils/tty.rb index f1ebba8a89615..a539e37b5b13b 100644 --- a/Library/Homebrew/utils/tty.rb +++ b/Library/Homebrew/utils/tty.rb @@ -51,14 +51,54 @@ def strip_ansi(string) string.gsub(/\033\[\d+(;\d+)*m/, "") end + sig { params(line_count: Integer).returns(String) } + def move_cursor_up(line_count) + "\033[#{line_count}A" + end + + sig { params(line_count: Integer).returns(String) } + def move_cursor_up_beginning(line_count) + "\033[#{line_count}F" + end + + sig { params(line_count: Integer).returns(String) } + def move_cursor_down(line_count) + "\033[#{line_count}B" + end + + sig { returns(String) } + def clear_to_end + "\033[K" + end + + sig { returns(String) } + def hide_cursor + "\033[?25l" + end + + sig { returns(String) } + def show_cursor + "\033[?25h" + end + + sig { returns(T.nilable([Integer, Integer])) } + def size + return @size if defined?(@size) + + height, width = `/bin/stty size 2>/dev/null`.presence&.split&.map(&:to_i) + return if height.nil? || width.nil? + + @size = [height, width] + end + + sig { returns(Integer) } + def height + @height ||= size&.first || `/usr/bin/tput lines 2>/dev/null`.presence&.to_i || 40 + end + sig { returns(Integer) } def width - @width ||= begin - _, width = `/bin/stty size 2>/dev/null`.split - width, = `/usr/bin/tput cols 2>/dev/null`.split if width.to_i.zero? - width ||= 80 - width.to_i - end + @width ||= size&.second || `/usr/bin/tput cols 2>/dev/null`.presence&.to_i || 80 end sig { params(string: String).returns(String) } diff --git a/Library/Homebrew/vendor/bundle/bundler/setup.rb b/Library/Homebrew/vendor/bundle/bundler/setup.rb index 6d51885d702a9..d1fc474ed35a8 100644 --- a/Library/Homebrew/vendor/bundle/bundler/setup.rb +++ b/Library/Homebrew/vendor/bundle/bundler/setup.rb @@ -43,6 +43,7 @@ def self.extension_api_version $:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/coderay-1.1.3/lib") $:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/highline-3.0.1/lib") $:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/commander-5.0.0/lib") +$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby") $:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/diff-lcs-1.5.1/lib") $:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/docile-1.4.1/lib") $:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/elftools-1.3.1/lib") diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/LICENSE.txt b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/LICENSE.txt new file mode 100644 index 0000000000000..1026f28d0be92 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/LICENSE.txt @@ -0,0 +1,21 @@ +Copyright (c) Jerry D'Antonio -- released under the MIT license. + +http://www.opensource.org/licenses/mit-license.php + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent-ruby.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent-ruby.rb new file mode 100644 index 0000000000000..e9a3dea4ab40d --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent-ruby.rb @@ -0,0 +1,5 @@ +# 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 --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent.rb new file mode 100644 index 0000000000000..87de46f1b8a1b --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent.rb @@ -0,0 +1,134 @@ +require 'concurrent/version' +require 'concurrent/constants' +require 'concurrent/errors' +require 'concurrent/configuration' + +require 'concurrent/atomics' +require 'concurrent/executors' +require 'concurrent/synchronization' + +require 'concurrent/atomic/atomic_markable_reference' +require 'concurrent/atomic/atomic_reference' +require 'concurrent/agent' +require 'concurrent/atom' +require 'concurrent/array' +require 'concurrent/hash' +require 'concurrent/set' +require 'concurrent/map' +require 'concurrent/tuple' +require 'concurrent/async' +require 'concurrent/dataflow' +require 'concurrent/delay' +require 'concurrent/exchanger' +require 'concurrent/future' +require 'concurrent/immutable_struct' +require 'concurrent/ivar' +require 'concurrent/maybe' +require 'concurrent/mutable_struct' +require 'concurrent/mvar' +require 'concurrent/promise' +require 'concurrent/scheduled_task' +require 'concurrent/settable_struct' +require 'concurrent/timer_task' +require 'concurrent/tvar' +require 'concurrent/promises' + +require 'concurrent/thread_safe/synchronized_delegator' +require 'concurrent/thread_safe/util' + +require 'concurrent/options' + +# @!macro internal_implementation_note +# +# @note **Private Implementation:** This abstraction is a private, internal +# implementation detail. It should never be used directly. + +# @!macro monotonic_clock_warning +# +# @note Time calculations on all platforms and languages are sensitive to +# changes to the system clock. To alleviate the potential problems +# associated with changing the system clock while an application is running, +# most modern operating systems provide a monotonic clock that operates +# independently of the system clock. A monotonic clock cannot be used to +# determine human-friendly clock times. A monotonic clock is used exclusively +# for calculating time intervals. Not all Ruby platforms provide access to an +# operating system monotonic clock. On these platforms a pure-Ruby monotonic +# clock will be used as a fallback. An operating system monotonic clock is both +# faster and more reliable than the pure-Ruby implementation. The pure-Ruby +# implementation should be fast and reliable enough for most non-realtime +# operations. At this time the common Ruby platforms that provide access to an +# operating system monotonic clock are MRI 2.1 and above and JRuby (all versions). +# +# @see http://linux.die.net/man/3/clock_gettime Linux clock_gettime(3) + +# @!macro copy_options +# +# ## Copy Options +# +# Object references in Ruby are mutable. This can lead to serious +# problems when the {#value} of an object is a mutable reference. Which +# is always the case unless the value is a `Fixnum`, `Symbol`, or similar +# "primitive" data type. Each instance can be configured with a few +# options that can help protect the program from potentially dangerous +# operations. Each of these options can be optionally set when the object +# instance is created: +# +# * `:dup_on_deref` When true the object will call the `#dup` method on +# the `value` object every time the `#value` method is called +# (default: false) +# * `:freeze_on_deref` When true the object will call the `#freeze` +# method on the `value` object every time the `#value` method is called +# (default: false) +# * `:copy_on_deref` When given a `Proc` object the `Proc` will be run +# every time the `#value` method is called. The `Proc` will be given +# the current `value` as its only argument and the result returned by +# the block will be the return value of the `#value` call. When `nil` +# this option will be ignored (default: nil) +# +# When multiple deref options are set the order of operations is strictly defined. +# The order of deref operations is: +# * `:copy_on_deref` +# * `:dup_on_deref` +# * `:freeze_on_deref` +# +# Because of this ordering there is no need to `#freeze` an object created by a +# provided `:copy_on_deref` block. Simply set `:freeze_on_deref` to `true`. +# Setting both `:dup_on_deref` to `true` and `:freeze_on_deref` to `true` is +# as close to the behavior of a "pure" functional language (like Erlang, Clojure, +# or Haskell) as we are likely to get in Ruby. + +# @!macro deref_options +# +# @option opts [Boolean] :dup_on_deref (false) Call `#dup` before +# returning the data from {#value} +# @option opts [Boolean] :freeze_on_deref (false) Call `#freeze` before +# returning the data from {#value} +# @option opts [Proc] :copy_on_deref (nil) When calling the {#value} +# method, call the given proc passing the internal value as the sole +# argument then return the new value returned from the proc. + +# @!macro executor_and_deref_options +# +# @param [Hash] opts the options used to define the behavior at update and deref +# and to specify the executor on which to perform actions +# @option opts [Executor] :executor when set use the given `Executor` instance. +# Three special values are also supported: `:io` returns the global pool for +# long, blocking (IO) tasks, `:fast` returns the global pool for short, fast +# operations, and `:immediate` returns the global `ImmediateExecutor` object. +# @!macro deref_options + +# @!macro warn.edge +# @api Edge +# @note **Edge Features** are under active development and may change frequently. +# +# - Deprecations are not added before incompatible changes. +# - Edge version: _major_ is always 0, _minor_ bump means incompatible change, +# _patch_ bump means compatible change. +# - Edge features may also lack tests and documentation. +# - Features developed in `concurrent-ruby-edge` are expected to move +# to `concurrent-ruby` when finalised. + + +# {include:file:README.md} +module Concurrent +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/agent.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/agent.rb new file mode 100644 index 0000000000000..2d32926ba14d0 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/agent.rb @@ -0,0 +1,588 @@ +require 'concurrent/configuration' +require 'concurrent/atomic/atomic_reference' +require 'concurrent/atomic/count_down_latch' +require 'concurrent/atomic/thread_local_var' +require 'concurrent/collection/copy_on_write_observer_set' +require 'concurrent/concern/observable' +require 'concurrent/synchronization/lockable_object' + +module Concurrent + + # `Agent` is inspired by Clojure's [agent](http://clojure.org/agents) + # function. An agent is a shared, mutable variable providing independent, + # uncoordinated, *asynchronous* change of individual values. Best used when + # the value will undergo frequent, complex updates. Suitable when the result + # of an update does not need to be known immediately. `Agent` is (mostly) + # functionally equivalent to Clojure's agent, except where the runtime + # prevents parity. + # + # Agents are reactive, not autonomous - there is no imperative message loop + # and no blocking receive. The state of an Agent should be itself immutable + # and the `#value` of an Agent is always immediately available for reading by + # any thread without any messages, i.e. observation does not require + # cooperation or coordination. + # + # Agent action dispatches are made using the various `#send` methods. These + # methods always return immediately. At some point later, in another thread, + # the following will happen: + # + # 1. The given `action` will be applied to the state of the Agent and the + # `args`, if any were supplied. + # 2. The return value of `action` will be passed to the validator lambda, + # if one has been set on the Agent. + # 3. If the validator succeeds or if no validator was given, the return value + # of the given `action` will become the new `#value` of the Agent. See + # `#initialize` for details. + # 4. If any observers were added to the Agent, they will be notified. See + # `#add_observer` for details. + # 5. If during the `action` execution any other dispatches are made (directly + # or indirectly), they will be held until after the `#value` of the Agent + # has been changed. + # + # If any exceptions are thrown by an action function, no nested dispatches + # will occur, and the exception will be cached in the Agent itself. When an + # Agent has errors cached, any subsequent interactions will immediately throw + # an exception, until the agent's errors are cleared. Agent errors can be + # examined with `#error` and the agent restarted with `#restart`. + # + # The actions of all Agents get interleaved amongst threads in a thread pool. + # At any point in time, at most one action for each Agent is being executed. + # Actions dispatched to an agent from another single agent or thread will + # occur in the order they were sent, potentially interleaved with actions + # dispatched to the same agent from other sources. The `#send` method should + # be used for actions that are CPU limited, while the `#send_off` method is + # appropriate for actions that may block on IO. + # + # Unlike in Clojure, `Agent` cannot participate in `Concurrent::TVar` transactions. + # + # ## Example + # + # ``` + # def next_fibonacci(set = nil) + # return [0, 1] if set.nil? + # set + [set[-2..-1].reduce{|sum,x| sum + x }] + # end + # + # # create an agent with an initial value + # agent = Concurrent::Agent.new(next_fibonacci) + # + # # send a few update requests + # 5.times do + # agent.send{|set| next_fibonacci(set) } + # end + # + # # wait for them to complete + # agent.await + # + # # get the current value + # agent.value #=> [0, 1, 1, 2, 3, 5, 8] + # ``` + # + # ## Observation + # + # Agents support observers through the {Concurrent::Observable} mixin module. + # Notification of observers occurs every time an action dispatch returns and + # the new value is successfully validated. Observation will *not* occur if the + # action raises an exception, if validation fails, or when a {#restart} occurs. + # + # When notified the observer will receive three arguments: `time`, `old_value`, + # and `new_value`. The `time` argument is the time at which the value change + # occurred. The `old_value` is the value of the Agent when the action began + # processing. The `new_value` is the value to which the Agent was set when the + # action completed. Note that `old_value` and `new_value` may be the same. + # This is not an error. It simply means that the action returned the same + # value. + # + # ## Nested Actions + # + # It is possible for an Agent action to post further actions back to itself. + # The nested actions will be enqueued normally then processed *after* the + # outer action completes, in the order they were sent, possibly interleaved + # with action dispatches from other threads. Nested actions never deadlock + # with one another and a failure in a nested action will never affect the + # outer action. + # + # Nested actions can be called using the Agent reference from the enclosing + # scope or by passing the reference in as a "send" argument. Nested actions + # cannot be post using `self` from within the action block/proc/lambda; `self` + # in this context will not reference the Agent. The preferred method for + # dispatching nested actions is to pass the Agent as an argument. This allows + # Ruby to more effectively manage the closing scope. + # + # Prefer this: + # + # ``` + # agent = Concurrent::Agent.new(0) + # agent.send(agent) do |value, this| + # this.send {|v| v + 42 } + # 3.14 + # end + # agent.value #=> 45.14 + # ``` + # + # Over this: + # + # ``` + # agent = Concurrent::Agent.new(0) + # agent.send do |value| + # agent.send {|v| v + 42 } + # 3.14 + # end + # ``` + # + # @!macro agent_await_warning + # + # **NOTE** Never, *under any circumstances*, call any of the "await" methods + # ({#await}, {#await_for}, {#await_for!}, and {#wait}) from within an action + # block/proc/lambda. The call will block the Agent and will always fail. + # Calling either {#await} or {#wait} (with a timeout of `nil`) will + # hopelessly deadlock the Agent with no possibility of recovery. + # + # @!macro thread_safe_variable_comparison + # + # @see http://clojure.org/Agents Clojure Agents + # @see http://clojure.org/state Values and Change - Clojure's approach to Identity and State + class Agent < Synchronization::LockableObject + include Concern::Observable + + ERROR_MODES = [:continue, :fail].freeze + private_constant :ERROR_MODES + + AWAIT_FLAG = ::Object.new + private_constant :AWAIT_FLAG + + AWAIT_ACTION = ->(value, latch) { latch.count_down; AWAIT_FLAG } + private_constant :AWAIT_ACTION + + DEFAULT_ERROR_HANDLER = ->(agent, error) { nil } + private_constant :DEFAULT_ERROR_HANDLER + + DEFAULT_VALIDATOR = ->(value) { true } + private_constant :DEFAULT_VALIDATOR + + Job = Struct.new(:action, :args, :executor, :caller) + private_constant :Job + + # Raised during action processing or any other time in an Agent's lifecycle. + class Error < StandardError + def initialize(message = nil) + message ||= 'agent must be restarted before jobs can post' + super(message) + end + end + + # Raised when a new value obtained during action processing or at `#restart` + # fails validation. + class ValidationError < Error + def initialize(message = nil) + message ||= 'invalid value' + super(message) + end + end + + # The error mode this Agent is operating in. See {#initialize} for details. + attr_reader :error_mode + + # Create a new `Agent` with the given initial value and options. + # + # The `:validator` option must be `nil` or a side-effect free proc/lambda + # which takes one argument. On any intended value change the validator, if + # provided, will be called. If the new value is invalid the validator should + # return `false` or raise an error. + # + # The `:error_handler` option must be `nil` or a proc/lambda which takes two + # arguments. When an action raises an error or validation fails, either by + # returning false or raising an error, the error handler will be called. The + # arguments to the error handler will be a reference to the agent itself and + # the error object which was raised. + # + # The `:error_mode` may be either `:continue` (the default if an error + # handler is given) or `:fail` (the default if error handler nil or not + # given). + # + # If an action being run by the agent throws an error or doesn't pass + # validation the error handler, if present, will be called. After the + # handler executes if the error mode is `:continue` the Agent will continue + # as if neither the action that caused the error nor the error itself ever + # happened. + # + # If the mode is `:fail` the Agent will become {#failed?} and will stop + # accepting new action dispatches. Any previously queued actions will be + # held until {#restart} is called. The {#value} method will still work, + # returning the value of the Agent before the error. + # + # @param [Object] initial the initial value + # @param [Hash] opts the configuration options + # + # @option opts [Symbol] :error_mode either `:continue` or `:fail` + # @option opts [nil, Proc] :error_handler the (optional) error handler + # @option opts [nil, Proc] :validator the (optional) validation procedure + def initialize(initial, opts = {}) + super() + synchronize { ns_initialize(initial, opts) } + end + + # The current value (state) of the Agent, irrespective of any pending or + # in-progress actions. The value is always available and is non-blocking. + # + # @return [Object] the current value + def value + @current.value # TODO (pitr 12-Sep-2015): broken unsafe read? + end + + alias_method :deref, :value + + # When {#failed?} and {#error_mode} is `:fail`, returns the error object + # which caused the failure, else `nil`. When {#error_mode} is `:continue` + # will *always* return `nil`. + # + # @return [nil, Error] the error which caused the failure when {#failed?} + def error + @error.value + end + + alias_method :reason, :error + + # @!macro agent_send + # + # Dispatches an action to the Agent and returns immediately. Subsequently, + # in a thread from a thread pool, the {#value} will be set to the return + # value of the action. Action dispatches are only allowed when the Agent + # is not {#failed?}. + # + # The action must be a block/proc/lambda which takes 1 or more arguments. + # The first argument is the current {#value} of the Agent. Any arguments + # passed to the send method via the `args` parameter will be passed to the + # action as the remaining arguments. The action must return the new value + # of the Agent. + # + # * {#send} and {#send!} should be used for actions that are CPU limited + # * {#send_off}, {#send_off!}, and {#<<} are appropriate for actions that + # may block on IO + # * {#send_via} and {#send_via!} are used when a specific executor is to + # be used for the action + # + # @param [Array] args zero or more arguments to be passed to + # the action + # @param [Proc] action the action dispatch to be enqueued + # + # @yield [agent, value, *args] process the old value and return the new + # @yieldparam [Object] value the current {#value} of the Agent + # @yieldparam [Array] args zero or more arguments to pass to the + # action + # @yieldreturn [Object] the new value of the Agent + # + # @!macro send_return + # @return [Boolean] true if the action is successfully enqueued, false if + # the Agent is {#failed?} + def send(*args, &action) + enqueue_action_job(action, args, Concurrent.global_fast_executor) + end + + # @!macro agent_send + # + # @!macro send_bang_return_and_raise + # @return [Boolean] true if the action is successfully enqueued + # @raise [Concurrent::Agent::Error] if the Agent is {#failed?} + def send!(*args, &action) + raise Error.new unless send(*args, &action) + true + end + + # @!macro agent_send + # @!macro send_return + def send_off(*args, &action) + enqueue_action_job(action, args, Concurrent.global_io_executor) + end + + alias_method :post, :send_off + + # @!macro agent_send + # @!macro send_bang_return_and_raise + def send_off!(*args, &action) + raise Error.new unless send_off(*args, &action) + true + end + + # @!macro agent_send + # @!macro send_return + # @param [Concurrent::ExecutorService] executor the executor on which the + # action is to be dispatched + def send_via(executor, *args, &action) + enqueue_action_job(action, args, executor) + end + + # @!macro agent_send + # @!macro send_bang_return_and_raise + # @param [Concurrent::ExecutorService] executor the executor on which the + # action is to be dispatched + def send_via!(executor, *args, &action) + raise Error.new unless send_via(executor, *args, &action) + true + end + + # Dispatches an action to the Agent and returns immediately. Subsequently, + # in a thread from a thread pool, the {#value} will be set to the return + # value of the action. Appropriate for actions that may block on IO. + # + # @param [Proc] action the action dispatch to be enqueued + # @return [Concurrent::Agent] self + # @see #send_off + def <<(action) + send_off(&action) + self + end + + # Blocks the current thread (indefinitely!) until all actions dispatched + # thus far, from this thread or nested by the Agent, have occurred. Will + # block when {#failed?}. Will never return if a failed Agent is {#restart} + # with `:clear_actions` true. + # + # Returns a reference to `self` to support method chaining: + # + # ``` + # current_value = agent.await.value + # ``` + # + # @return [Boolean] self + # + # @!macro agent_await_warning + def await + wait(nil) + self + end + + # Blocks the current thread until all actions dispatched thus far, from this + # thread or nested by the Agent, have occurred, or the timeout (in seconds) + # has elapsed. + # + # @param [Float] timeout the maximum number of seconds to wait + # @return [Boolean] true if all actions complete before timeout else false + # + # @!macro agent_await_warning + def await_for(timeout) + wait(timeout.to_f) + end + + # Blocks the current thread until all actions dispatched thus far, from this + # thread or nested by the Agent, have occurred, or the timeout (in seconds) + # has elapsed. + # + # @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 + # + # @!macro agent_await_warning + def await_for!(timeout) + raise Concurrent::TimeoutError unless wait(timeout.to_f) + true + end + + # Blocks the current thread until all actions dispatched thus far, from this + # thread or nested by the Agent, have occurred, or the timeout (in seconds) + # has elapsed. Will block indefinitely when timeout is nil or not given. + # + # Provided mainly for consistency with other classes in this library. Prefer + # the various `await` methods instead. + # + # @param [Float] timeout the maximum number of seconds to wait + # @return [Boolean] true if all actions complete before timeout else false + # + # @!macro agent_await_warning + def wait(timeout = nil) + latch = Concurrent::CountDownLatch.new(1) + enqueue_await_job(latch) + latch.wait(timeout) + end + + # Is the Agent in a failed state? + # + # @see #restart + def failed? + !@error.value.nil? + end + + alias_method :stopped?, :failed? + + # When an Agent is {#failed?}, changes the Agent {#value} to `new_value` + # then un-fails the Agent so that action dispatches are allowed again. If + # the `:clear_actions` option is give and true, any actions queued on the + # Agent that were being held while it was failed will be discarded, + # otherwise those held actions will proceed. The `new_value` must pass the + # validator if any, or `restart` will raise an exception and the Agent will + # remain failed with its old {#value} and {#error}. Observers, if any, will + # not be notified of the new state. + # + # @param [Object] new_value the new value for the Agent once restarted + # @param [Hash] opts the configuration options + # @option opts [Symbol] :clear_actions true if all enqueued but unprocessed + # actions should be discarded on restart, else false (default: false) + # @return [Boolean] true + # + # @raise [Concurrent:AgentError] when not failed + def restart(new_value, opts = {}) + clear_actions = opts.fetch(:clear_actions, false) + synchronize do + raise Error.new('agent is not failed') unless failed? + raise ValidationError unless ns_validate(new_value) + @current.value = new_value + @error.value = nil + @queue.clear if clear_actions + ns_post_next_job unless @queue.empty? + end + true + end + + class << self + + # Blocks the current thread (indefinitely!) until all actions dispatched + # thus far to all the given Agents, from this thread or nested by the + # given Agents, have occurred. Will block when any of the agents are + # failed. Will never return if a failed Agent is restart with + # `:clear_actions` true. + # + # @param [Array] agents the Agents on which to wait + # @return [Boolean] true + # + # @!macro agent_await_warning + def await(*agents) + agents.each { |agent| agent.await } + true + end + + # Blocks the current thread until all actions dispatched thus far to all + # the given Agents, from this thread or nested by the given Agents, have + # occurred, or the timeout (in seconds) has elapsed. + # + # @param [Float] timeout the maximum number of seconds to wait + # @param [Array] agents the Agents on which to wait + # @return [Boolean] true if all actions complete before timeout else false + # + # @!macro agent_await_warning + def await_for(timeout, *agents) + end_at = Concurrent.monotonic_time + timeout.to_f + ok = agents.length.times do |i| + break false if (delay = end_at - Concurrent.monotonic_time) < 0 + break false unless agents[i].await_for(delay) + end + !!ok + end + + # Blocks the current thread until all actions dispatched thus far to all + # the given Agents, from this thread or nested by the given Agents, have + # occurred, or the timeout (in seconds) has elapsed. + # + # @param [Float] timeout the maximum number of seconds to wait + # @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 + # @!macro agent_await_warning + def await_for!(timeout, *agents) + raise Concurrent::TimeoutError unless await_for(timeout, *agents) + true + end + end + + private + + def ns_initialize(initial, opts) + @error_mode = opts[:error_mode] + @error_handler = opts[:error_handler] + + if @error_mode && !ERROR_MODES.include?(@error_mode) + raise ArgumentError.new('unrecognized error mode') + elsif @error_mode.nil? + @error_mode = @error_handler ? :continue : :fail + end + + @error_handler ||= DEFAULT_ERROR_HANDLER + @validator = opts.fetch(:validator, DEFAULT_VALIDATOR) + @current = Concurrent::AtomicReference.new(initial) + @error = Concurrent::AtomicReference.new(nil) + @caller = Concurrent::ThreadLocalVar.new(nil) + @queue = [] + + self.observers = Collection::CopyOnNotifyObserverSet.new + end + + def enqueue_action_job(action, args, executor) + raise ArgumentError.new('no action given') unless action + job = Job.new(action, args, executor, @caller.value || Thread.current.object_id) + synchronize { ns_enqueue_job(job) } + end + + def enqueue_await_job(latch) + synchronize do + if (index = ns_find_last_job_for_thread) + job = Job.new(AWAIT_ACTION, [latch], Concurrent.global_immediate_executor, + Thread.current.object_id) + ns_enqueue_job(job, index+1) + else + latch.count_down + true + end + end + end + + def ns_enqueue_job(job, index = nil) + # a non-nil index means this is an await job + return false if index.nil? && failed? + index ||= @queue.length + @queue.insert(index, job) + # if this is the only job, post to executor + ns_post_next_job if @queue.length == 1 + true + end + + def ns_post_next_job + @queue.first.executor.post { execute_next_job } + end + + def execute_next_job + job = synchronize { @queue.first } + old_value = @current.value + + @caller.value = job.caller # for nested actions + new_value = job.action.call(old_value, *job.args) + @caller.value = nil + + return if new_value == AWAIT_FLAG + + if ns_validate(new_value) + @current.value = new_value + observers.notify_observers(Time.now, old_value, new_value) + else + handle_error(ValidationError.new) + end + rescue => error + handle_error(error) + ensure + synchronize do + @queue.shift + unless failed? || @queue.empty? + ns_post_next_job + end + end + end + + def ns_validate(value) + @validator.call(value) + rescue + false + end + + def handle_error(error) + # stop new jobs from posting + @error.value = error if @error_mode == :fail + @error_handler.call(self, error) + rescue + # do nothing + end + + def ns_find_last_job_for_thread + @queue.rindex { |job| job.caller == Thread.current.object_id } + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/array.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/array.rb new file mode 100644 index 0000000000000..c8761af8a6e22 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/array.rb @@ -0,0 +1,56 @@ +require 'concurrent/utility/engine' +require 'concurrent/thread_safe/util' + +module Concurrent + + # @!macro concurrent_array + # + # A thread-safe subclass of Array. This version locks against the object + # itself for every method call, ensuring only one thread can be reading + # or writing at a time. This includes iteration methods like `#each`. + # + # @note `a += b` is **not** a **thread-safe** operation on + # `Concurrent::Array`. It reads array `a`, then it creates new `Concurrent::Array` + # which is concatenation of `a` and `b`, then it writes the concatenation to `a`. + # The read and write are independent operations they do not form a single atomic + # operation therefore when two `+=` operations are executed concurrently updates + # may be lost. Use `#concat` instead. + # + # @see http://ruby-doc.org/core/Array.html Ruby standard library `Array` + + # @!macro internal_implementation_note + ArrayImplementation = case + when Concurrent.on_cruby? + # Array is not fully thread-safe on CRuby, see + # https://github.com/ruby-concurrency/concurrent-ruby/issues/929 + # So we will need to add synchronization here + ::Array + + when Concurrent.on_jruby? + require 'jruby/synchronized' + + class JRubyArray < ::Array + include JRuby::Synchronized + end + JRubyArray + + when Concurrent.on_truffleruby? + require 'concurrent/thread_safe/util/data_structures' + + class TruffleRubyArray < ::Array + end + + ThreadSafe::Util.make_synchronized_on_truffleruby TruffleRubyArray + TruffleRubyArray + + else + warn 'Possibly unsupported Ruby implementation' + ::Array + end + private_constant :ArrayImplementation + + # @!macro concurrent_array + class Array < ArrayImplementation + end + +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/async.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/async.rb new file mode 100644 index 0000000000000..f9f8adf00d4e7 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/async.rb @@ -0,0 +1,449 @@ +require 'concurrent/configuration' +require 'concurrent/ivar' +require 'concurrent/synchronization/lockable_object' + +module Concurrent + + # A mixin module that provides simple asynchronous behavior to a class, + # turning it into a simple actor. Loosely based on Erlang's + # [gen_server](http://www.erlang.org/doc/man/gen_server.html), but without + # supervision or linking. + # + # A more feature-rich {Concurrent::Actor} is also available when the + # capabilities of `Async` are too limited. + # + # ```cucumber + # Feature: + # As a stateful, plain old Ruby class + # I want safe, asynchronous behavior + # So my long-running methods don't block the main thread + # ``` + # + # The `Async` module is a way to mix simple yet powerful asynchronous + # capabilities into any plain old Ruby object or class, turning each object + # into a simple Actor. Method calls are processed on a background thread. The + # caller is free to perform other actions while processing occurs in the + # background. + # + # Method calls to the asynchronous object are made via two proxy methods: + # `async` (alias `cast`) and `await` (alias `call`). These proxy methods post + # the method call to the object's background thread and return a "future" + # which will eventually contain the result of the method call. + # + # This behavior is loosely patterned after Erlang's `gen_server` behavior. + # When an Erlang module implements the `gen_server` behavior it becomes + # inherently asynchronous. The `start` or `start_link` function spawns a + # process (similar to a thread but much more lightweight and efficient) and + # returns the ID of the process. Using the process ID, other processes can + # send messages to the `gen_server` via the `cast` and `call` methods. Unlike + # Erlang's `gen_server`, however, `Async` classes do not support linking or + # supervision trees. + # + # ## Basic Usage + # + # When this module is mixed into a class, objects of the class become inherently + # asynchronous. Each object gets its own background thread on which to post + # asynchronous method calls. Asynchronous method calls are executed in the + # background one at a time in the order they are received. + # + # To create an asynchronous class, simply mix in the `Concurrent::Async` module: + # + # ``` + # class Hello + # include Concurrent::Async + # + # def hello(name) + # "Hello, #{name}!" + # end + # end + # ``` + # + # Mixing this module into a class provides each object two proxy methods: + # `async` and `await`. These methods are thread safe with respect to the + # enclosing object. The former proxy allows methods to be called + # asynchronously by posting to the object's internal thread. The latter proxy + # allows a method to be called synchronously but does so safely with respect + # to any pending asynchronous method calls and ensures proper ordering. Both + # methods return a {Concurrent::IVar} which can be inspected for the result + # of the proxied method call. Calling a method with `async` will return a + # `:pending` `IVar` whereas `await` will return a `:complete` `IVar`. + # + # ``` + # class Echo + # include Concurrent::Async + # + # def echo(msg) + # print "#{msg}\n" + # end + # end + # + # horn = Echo.new + # horn.echo('zero') # synchronous, not thread-safe + # # returns the actual return value of the method + # + # horn.async.echo('one') # asynchronous, non-blocking, thread-safe + # # returns an IVar in the :pending state + # + # horn.await.echo('two') # synchronous, blocking, thread-safe + # # returns an IVar in the :complete state + # ``` + # + # ## Let It Fail + # + # The `async` and `await` proxy methods have built-in error protection based + # on Erlang's famous "let it fail" philosophy. Instance methods should not be + # programmed defensively. When an exception is raised by a delegated method + # the proxy will rescue the exception, expose it to the caller as the `reason` + # attribute of the returned future, then process the next method call. + # + # ## Calling Methods Internally + # + # External method calls should *always* use the `async` and `await` proxy + # methods. When one method calls another method, the `async` proxy should + # rarely be used and the `await` proxy should *never* be used. + # + # When an object calls one of its own methods using the `await` proxy the + # second call will be enqueued *behind* the currently running method call. + # Any attempt to wait on the result will fail as the second call will never + # run until after the current call completes. + # + # Calling a method using the `await` proxy from within a method that was + # itself called using `async` or `await` will irreversibly deadlock the + # object. Do *not* do this, ever. + # + # ## Instance Variables and Attribute Accessors + # + # Instance variables do not need to be thread-safe so long as they are private. + # Asynchronous method calls are processed in the order they are received and + # are processed one at a time. Therefore private instance variables can only + # be accessed by one thread at a time. This is inherently thread-safe. + # + # When using private instance variables within asynchronous methods, the best + # practice is to read the instance variable into a local variable at the start + # of the method then update the instance variable at the *end* of the method. + # This way, should an exception be raised during method execution the internal + # state of the object will not have been changed. + # + # ### Reader Attributes + # + # The use of `attr_reader` is discouraged. Internal state exposed externally, + # when necessary, should be done through accessor methods. The instance + # variables exposed by these methods *must* be thread-safe, or they must be + # called using the `async` and `await` proxy methods. These two approaches are + # subtly different. + # + # When internal state is accessed via the `async` and `await` proxy methods, + # the returned value represents the object's state *at the time the call is + # processed*, which may *not* be the state of the object at the time the call + # is made. + # + # To get the state *at the current* time, irrespective of an enqueued method + # calls, a reader method must be called directly. This is inherently unsafe + # unless the instance variable is itself thread-safe, preferably using one + # of the thread-safe classes within this library. Because the thread-safe + # classes within this library are internally-locking or non-locking, they can + # be safely used from within asynchronous methods without causing deadlocks. + # + # Generally speaking, the best practice is to *not* expose internal state via + # reader methods. The best practice is to simply use the method's return value. + # + # ### Writer Attributes + # + # Writer attributes should never be used with asynchronous classes. Changing + # the state externally, even when done in the thread-safe way, is not logically + # consistent. Changes to state need to be timed with respect to all asynchronous + # method calls which my be in-process or enqueued. The only safe practice is to + # pass all necessary data to each method as arguments and let the method update + # the internal state as necessary. + # + # ## Class Constants, Variables, and Methods + # + # ### Class Constants + # + # Class constants do not need to be thread-safe. Since they are read-only and + # immutable they may be safely read both externally and from within + # asynchronous methods. + # + # ### Class Variables + # + # Class variables should be avoided. Class variables represent shared state. + # Shared state is anathema to concurrency. Should there be a need to share + # state using class variables they *must* be thread-safe, preferably + # using the thread-safe classes within this library. When updating class + # variables, never assign a new value/object to the variable itself. Assignment + # is not thread-safe in Ruby. Instead, use the thread-safe update functions + # of the variable itself to change the value. + # + # The best practice is to *never* use class variables with `Async` classes. + # + # ### Class Methods + # + # Class methods which are pure functions are safe. Class methods which modify + # class variables should be avoided, for all the reasons listed above. + # + # ## An Important Note About Thread Safe Guarantees + # + # > Thread safe guarantees can only be made when asynchronous method calls + # > are not mixed with direct method calls. Use only direct method calls + # > when the object is used exclusively on a single thread. Use only + # > `async` and `await` when the object is shared between threads. Once you + # > call a method using `async` or `await`, you should no longer call methods + # > directly on the object. Use `async` and `await` exclusively from then on. + # + # @example + # + # class Echo + # include Concurrent::Async + # + # def echo(msg) + # print "#{msg}\n" + # end + # end + # + # horn = Echo.new + # horn.echo('zero') # synchronous, not thread-safe + # # returns the actual return value of the method + # + # horn.async.echo('one') # asynchronous, non-blocking, thread-safe + # # returns an IVar in the :pending state + # + # horn.await.echo('two') # synchronous, blocking, thread-safe + # # returns an IVar in the :complete state + # + # @see Concurrent::Actor + # @see https://en.wikipedia.org/wiki/Actor_model "Actor Model" at Wikipedia + # @see http://www.erlang.org/doc/man/gen_server.html Erlang gen_server + # @see http://c2.com/cgi/wiki?LetItCrash "Let It Crash" at http://c2.com/ + module Async + + # @!method self.new(*args, &block) + # + # Instanciate a new object and ensure proper initialization of the + # synchronization mechanisms. + # + # @param [Array] args Zero or more arguments to be passed to the + # object's initializer. + # @param [Proc] block Optional block to pass to the object's initializer. + # @return [Object] A properly initialized object of the asynchronous class. + + # Check for the presence of a method on an object and determine if a given + # set of arguments matches the required arity. + # + # @param [Object] obj the object to check against + # @param [Symbol] method the method to check the object for + # @param [Array] args zero or more arguments for the arity check + # + # @raise [NameError] the object does not respond to `method` method + # @raise [ArgumentError] the given `args` do not match the arity of `method` + # + # @note This check is imperfect because of the way Ruby reports the arity of + # methods with a variable number of arguments. It is possible to determine + # if too few arguments are given but impossible to determine if too many + # arguments are given. This check may also fail to recognize dynamic behavior + # of the object, such as methods simulated with `method_missing`. + # + # @see http://www.ruby-doc.org/core-2.1.1/Method.html#method-i-arity Method#arity + # @see http://ruby-doc.org/core-2.1.0/Object.html#method-i-respond_to-3F Object#respond_to? + # @see http://www.ruby-doc.org/core-2.1.0/BasicObject.html#method-i-method_missing BasicObject#method_missing + # + # @!visibility private + def self.validate_argc(obj, method, *args) + argc = args.length + arity = obj.method(method).arity + + if arity >= 0 && argc != arity + raise ArgumentError.new("wrong number of arguments (#{argc} for #{arity})") + elsif arity < 0 && (arity = (arity + 1).abs) > argc + raise ArgumentError.new("wrong number of arguments (#{argc} for #{arity}..*)") + end + end + + # @!visibility private + def self.included(base) + base.singleton_class.send(:alias_method, :original_new, :new) + base.extend(ClassMethods) + super(base) + end + + # @!visibility private + module ClassMethods + def new(*args, &block) + obj = original_new(*args, &block) + obj.send(:init_synchronization) + obj + end + ruby2_keywords :new if respond_to?(:ruby2_keywords, true) + end + private_constant :ClassMethods + + # Delegates asynchronous, thread-safe method calls to the wrapped object. + # + # @!visibility private + class AsyncDelegator < Synchronization::LockableObject + safe_initialization! + + # Create a new delegator object wrapping the given delegate. + # + # @param [Object] delegate the object to wrap and delegate method calls to + def initialize(delegate) + super() + @delegate = delegate + @queue = [] + @executor = Concurrent.global_io_executor + @ruby_pid = $$ + end + + # Delegates method calls to the wrapped object. + # + # @param [Symbol] method the method being called + # @param [Array] args zero or more arguments to the method + # + # @return [IVar] the result of the method call + # + # @raise [NameError] the object does not respond to `method` method + # @raise [ArgumentError] the given `args` do not match the arity of `method` + def method_missing(method, *args, &block) + super unless @delegate.respond_to?(method) + Async::validate_argc(@delegate, method, *args) + + ivar = Concurrent::IVar.new + synchronize do + reset_if_forked + @queue.push [ivar, method, args, block] + @executor.post { perform } if @queue.length == 1 + end + + ivar + end + + # Check whether the method is responsive + # + # @param [Symbol] method the method being called + def respond_to_missing?(method, include_private = false) + @delegate.respond_to?(method) || super + end + + # Perform all enqueued tasks. + # + # This method must be called from within the executor. It must not be + # called while already running. It will loop until the queue is empty. + def perform + loop do + ivar, method, args, block = synchronize { @queue.first } + break unless ivar # queue is empty + + begin + ivar.set(@delegate.send(method, *args, &block)) + rescue => error + ivar.fail(error) + end + + synchronize do + @queue.shift + return if @queue.empty? + end + end + end + + def reset_if_forked + if $$ != @ruby_pid + @queue.clear + @ruby_pid = $$ + end + end + end + private_constant :AsyncDelegator + + # Delegates synchronous, thread-safe method calls to the wrapped object. + # + # @!visibility private + class AwaitDelegator + + # Create a new delegator object wrapping the given delegate. + # + # @param [AsyncDelegator] delegate the object to wrap and delegate method calls to + def initialize(delegate) + @delegate = delegate + end + + # Delegates method calls to the wrapped object. + # + # @param [Symbol] method the method being called + # @param [Array] args zero or more arguments to the method + # + # @return [IVar] the result of the method call + # + # @raise [NameError] the object does not respond to `method` method + # @raise [ArgumentError] the given `args` do not match the arity of `method` + def method_missing(method, *args, &block) + ivar = @delegate.send(method, *args, &block) + ivar.wait + ivar + end + + # Check whether the method is responsive + # + # @param [Symbol] method the method being called + def respond_to_missing?(method, include_private = false) + @delegate.respond_to?(method) || super + end + end + private_constant :AwaitDelegator + + # Causes the chained method call to be performed asynchronously on the + # object's thread. The delegated method will return a future in the + # `:pending` state and the method call will have been scheduled on the + # object's thread. The final disposition of the method call can be obtained + # by inspecting the returned future. + # + # @!macro async_thread_safety_warning + # @note The method call is guaranteed to be thread safe with respect to + # all other method calls against the same object that are called with + # either `async` or `await`. The mutable nature of Ruby references + # (and object orientation in general) prevent any other thread safety + # guarantees. Do NOT mix direct method calls with delegated method calls. + # Use *only* delegated method calls when sharing the object between threads. + # + # @return [Concurrent::IVar] the pending result of the asynchronous operation + # + # @raise [NameError] the object does not respond to the requested method + # @raise [ArgumentError] the given `args` do not match the arity of + # the requested method + def async + @__async_delegator__ + end + alias_method :cast, :async + + # Causes the chained method call to be performed synchronously on the + # current thread. The delegated will return a future in either the + # `:fulfilled` or `:rejected` state and the delegated method will have + # completed. The final disposition of the delegated method can be obtained + # by inspecting the returned future. + # + # @!macro async_thread_safety_warning + # + # @return [Concurrent::IVar] the completed result of the synchronous operation + # + # @raise [NameError] the object does not respond to the requested method + # @raise [ArgumentError] the given `args` do not match the arity of the + # requested method + def await + @__await_delegator__ + end + alias_method :call, :await + + # Initialize the internal serializer and other stnchronization mechanisms. + # + # @note This method *must* be called immediately upon object construction. + # This is the only way thread-safe initialization can be guaranteed. + # + # @!visibility private + def init_synchronization + return self if defined?(@__async_initialized__) && @__async_initialized__ + @__async_initialized__ = true + @__async_delegator__ = AsyncDelegator.new(self) + @__await_delegator__ = AwaitDelegator.new(@__async_delegator__) + self + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atom.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atom.rb new file mode 100644 index 0000000000000..1074006d76a04 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atom.rb @@ -0,0 +1,222 @@ +require 'concurrent/atomic/atomic_reference' +require 'concurrent/collection/copy_on_notify_observer_set' +require 'concurrent/concern/observable' +require 'concurrent/synchronization/object' + +# @!macro thread_safe_variable_comparison +# +# ## Thread-safe Variable Classes +# +# Each of the thread-safe variable classes is designed to solve a different +# problem. In general: +# +# * *{Concurrent::Agent}:* Shared, mutable variable providing independent, +# uncoordinated, *asynchronous* change of individual values. Best used when +# the value will undergo frequent, complex updates. Suitable when the result +# of an update does not need to be known immediately. +# * *{Concurrent::Atom}:* Shared, mutable variable providing independent, +# uncoordinated, *synchronous* change of individual values. Best used when +# the value will undergo frequent reads but only occasional, though complex, +# updates. Suitable when the result of an update must be known immediately. +# * *{Concurrent::AtomicReference}:* A simple object reference that can be updated +# atomically. Updates are synchronous but fast. Best used when updates a +# simple set operations. Not suitable when updates are complex. +# {Concurrent::AtomicBoolean} and {Concurrent::AtomicFixnum} are similar +# but optimized for the given data type. +# * *{Concurrent::Exchanger}:* Shared, stateless synchronization point. Used +# when two or more threads need to exchange data. The threads will pair then +# block on each other until the exchange is complete. +# * *{Concurrent::MVar}:* Shared synchronization point. Used when one thread +# must give a value to another, which must take the value. The threads will +# block on each other until the exchange is complete. +# * *{Concurrent::ThreadLocalVar}:* Shared, mutable, isolated variable which +# holds a different value for each thread which has access. Often used as +# an instance variable in objects which must maintain different state +# for different threads. +# * *{Concurrent::TVar}:* Shared, mutable variables which provide +# *coordinated*, *synchronous*, change of *many* stated. Used when multiple +# value must change together, in an all-or-nothing transaction. + + +module Concurrent + + # Atoms provide a way to manage shared, synchronous, independent state. + # + # An atom is initialized with an initial value and an optional validation + # proc. At any time the value of the atom can be synchronously and safely + # changed. If a validator is given at construction then any new value + # will be checked against the validator and will be rejected if the + # validator returns false or raises an exception. + # + # There are two ways to change the value of an atom: {#compare_and_set} and + # {#swap}. The former will set the new value if and only if it validates and + # the current value matches the new value. The latter will atomically set the + # new value to the result of running the given block if and only if that + # value validates. + # + # ## Example + # + # ``` + # def next_fibonacci(set = nil) + # return [0, 1] if set.nil? + # set + [set[-2..-1].reduce{|sum,x| sum + x }] + # end + # + # # create an atom with an initial value + # atom = Concurrent::Atom.new(next_fibonacci) + # + # # send a few update requests + # 5.times do + # atom.swap{|set| next_fibonacci(set) } + # end + # + # # get the current value + # atom.value #=> [0, 1, 1, 2, 3, 5, 8] + # ``` + # + # ## Observation + # + # Atoms support observers through the {Concurrent::Observable} mixin module. + # Notification of observers occurs every time the value of the Atom changes. + # When notified the observer will receive three arguments: `time`, `old_value`, + # and `new_value`. The `time` argument is the time at which the value change + # occurred. The `old_value` is the value of the Atom when the change began + # The `new_value` is the value to which the Atom was set when the change + # completed. Note that `old_value` and `new_value` may be the same. This is + # not an error. It simply means that the change operation returned the same + # value. + # + # Unlike in Clojure, `Atom` cannot participate in {Concurrent::TVar} transactions. + # + # @!macro thread_safe_variable_comparison + # + # @see http://clojure.org/atoms Clojure Atoms + # @see http://clojure.org/state Values and Change - Clojure's approach to Identity and State + class Atom < Synchronization::Object + include Concern::Observable + + safe_initialization! + attr_atomic(:value) + private :value=, :swap_value, :compare_and_set_value, :update_value + public :value + alias_method :deref, :value + + # @!method value + # The current value of the atom. + # + # @return [Object] The current value. + + # Create a new atom with the given initial value. + # + # @param [Object] value The initial value + # @param [Hash] opts The options used to configure the atom + # @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. + # + # @!macro deref_options + # + # @raise [ArgumentError] if the validator is not a `Proc` (when given) + def initialize(value, opts = {}) + super() + @Validator = opts.fetch(:validator, -> v { true }) + self.observers = Collection::CopyOnNotifyObserverSet.new + self.value = value + end + + # Atomically swaps the value of atom using the given block. The current + # value will be passed to the block, as will any arguments passed as + # arguments to the function. The new value will be validated against the + # (optional) validator proc given at construction. If validation fails the + # value will not be changed. + # + # Internally, {#swap} reads the current value, applies the block to it, and + # attempts to compare-and-set it in. Since another thread may have changed + # the value in the intervening time, it may have to retry, and does so in a + # spin loop. The net effect is that the value will always be the result of + # the application of the supplied block to a current value, atomically. + # However, because the block might be called multiple times, it must be free + # of side effects. + # + # @note The given block may be called multiple times, and thus should be free + # of side effects. + # + # @param [Object] args Zero or more arguments passed to the block. + # + # @yield [value, args] Calculates a new value for the atom based on the + # current value and any supplied arguments. + # @yieldparam value [Object] The current value of the atom. + # @yieldparam args [Object] All arguments passed to the function, in order. + # @yieldreturn [Object] The intended new value of the atom. + # + # @return [Object] The final value of the atom after all operations and + # validations are complete. + # + # @raise [ArgumentError] When no block is given. + def swap(*args) + raise ArgumentError.new('no block given') unless block_given? + + loop do + old_value = value + new_value = yield(old_value, *args) + begin + break old_value unless valid?(new_value) + break new_value if compare_and_set(old_value, new_value) + rescue + break old_value + end + end + end + + # Atomically sets the value of atom to the new value if and only if the + # current value of the atom is identical to the old value and the new + # value successfully validates against the (optional) validator given + # at construction. + # + # @param [Object] old_value The expected current value. + # @param [Object] new_value The intended new value. + # + # @return [Boolean] True if the value is changed else false. + def compare_and_set(old_value, new_value) + if valid?(new_value) && compare_and_set_value(old_value, new_value) + observers.notify_observers(Time.now, old_value, new_value) + true + else + false + end + end + + # Atomically sets the value of atom to the new value without regard for the + # current value so long as the new value successfully validates against the + # (optional) validator given at construction. + # + # @param [Object] new_value The intended new value. + # + # @return [Object] The final value of the atom after all operations and + # validations are complete. + def reset(new_value) + old_value = value + if valid?(new_value) + self.value = new_value + observers.notify_observers(Time.now, old_value, new_value) + new_value + else + old_value + end + end + + private + + # Is the new value valid? + # + # @param [Object] new_value The intended new value. + # @return [Boolean] false if the validator function returns false or raises + # an exception else true + def valid?(new_value) + @Validator.call(new_value) + rescue + false + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/atomic_boolean.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/atomic_boolean.rb new file mode 100644 index 0000000000000..f775691a2a6a5 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/atomic_boolean.rb @@ -0,0 +1,127 @@ +require 'concurrent/utility/native_extension_loader' # load native parts first + +require 'concurrent/atomic/mutex_atomic_boolean' + +module Concurrent + + ################################################################### + + # @!macro atomic_boolean_method_initialize + # + # Creates a new `AtomicBoolean` with the given initial value. + # + # @param [Boolean] initial the initial value + + # @!macro atomic_boolean_method_value_get + # + # Retrieves the current `Boolean` value. + # + # @return [Boolean] the current value + + # @!macro atomic_boolean_method_value_set + # + # Explicitly sets the value. + # + # @param [Boolean] value the new value to be set + # + # @return [Boolean] the current value + + # @!macro atomic_boolean_method_true_question + # + # Is the current value `true` + # + # @return [Boolean] true if the current value is `true`, else false + + # @!macro atomic_boolean_method_false_question + # + # Is the current value `false` + # + # @return [Boolean] true if the current value is `false`, else false + + # @!macro atomic_boolean_method_make_true + # + # Explicitly sets the value to true. + # + # @return [Boolean] true if value has changed, otherwise false + + # @!macro atomic_boolean_method_make_false + # + # Explicitly sets the value to false. + # + # @return [Boolean] true if value has changed, otherwise false + + ################################################################### + + # @!macro atomic_boolean_public_api + # + # @!method initialize(initial = false) + # @!macro atomic_boolean_method_initialize + # + # @!method value + # @!macro atomic_boolean_method_value_get + # + # @!method value=(value) + # @!macro atomic_boolean_method_value_set + # + # @!method true? + # @!macro atomic_boolean_method_true_question + # + # @!method false? + # @!macro atomic_boolean_method_false_question + # + # @!method make_true + # @!macro atomic_boolean_method_make_true + # + # @!method make_false + # @!macro atomic_boolean_method_make_false + + ################################################################### + + # @!visibility private + # @!macro internal_implementation_note + AtomicBooleanImplementation = case + when Concurrent.on_cruby? && Concurrent.c_extensions_loaded? + CAtomicBoolean + when Concurrent.on_jruby? + JavaAtomicBoolean + else + MutexAtomicBoolean + end + private_constant :AtomicBooleanImplementation + + # @!macro atomic_boolean + # + # A boolean value that can be updated atomically. Reads and writes to an atomic + # boolean and thread-safe and guaranteed to succeed. Reads and writes may block + # briefly but no explicit locking is required. + # + # @!macro thread_safe_variable_comparison + # + # Performance: + # + # ``` + # Testing with ruby 2.1.2 + # Testing with Concurrent::MutexAtomicBoolean... + # 2.790000 0.000000 2.790000 ( 2.791454) + # Testing with Concurrent::CAtomicBoolean... + # 0.740000 0.000000 0.740000 ( 0.740206) + # + # Testing with jruby 1.9.3 + # Testing with Concurrent::MutexAtomicBoolean... + # 5.240000 2.520000 7.760000 ( 3.683000) + # Testing with Concurrent::JavaAtomicBoolean... + # 3.340000 0.010000 3.350000 ( 0.855000) + # ``` + # + # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicBoolean.html java.util.concurrent.atomic.AtomicBoolean + # + # @!macro atomic_boolean_public_api + class AtomicBoolean < AtomicBooleanImplementation + # @return [String] Short string representation. + def to_s + format '%s value:%s>', super[0..-2], value + end + + alias_method :inspect, :to_s + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/atomic_fixnum.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/atomic_fixnum.rb new file mode 100644 index 0000000000000..26cd05d869213 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/atomic_fixnum.rb @@ -0,0 +1,144 @@ +require 'concurrent/utility/native_extension_loader' # load native parts first + +require 'concurrent/atomic/mutex_atomic_fixnum' + +module Concurrent + + ################################################################### + + # @!macro atomic_fixnum_method_initialize + # + # Creates a new `AtomicFixnum` with the given initial value. + # + # @param [Fixnum] initial the initial value + # @raise [ArgumentError] if the initial value is not a `Fixnum` + + # @!macro atomic_fixnum_method_value_get + # + # Retrieves the current `Fixnum` value. + # + # @return [Fixnum] the current value + + # @!macro atomic_fixnum_method_value_set + # + # Explicitly sets the value. + # + # @param [Fixnum] value the new value to be set + # + # @return [Fixnum] the current value + # + # @raise [ArgumentError] if the new value is not a `Fixnum` + + # @!macro atomic_fixnum_method_increment + # + # Increases the current value by the given amount (defaults to 1). + # + # @param [Fixnum] delta the amount by which to increase the current value + # + # @return [Fixnum] the current value after incrementation + + # @!macro atomic_fixnum_method_decrement + # + # Decreases the current value by the given amount (defaults to 1). + # + # @param [Fixnum] delta the amount by which to decrease the current value + # + # @return [Fixnum] the current value after decrementation + + # @!macro atomic_fixnum_method_compare_and_set + # + # Atomically sets the value to the given updated value if the current + # value == the expected value. + # + # @param [Fixnum] expect the expected value + # @param [Fixnum] update the new value + # + # @return [Boolean] true if the value was updated else false + + # @!macro atomic_fixnum_method_update + # + # Pass the current value to the given block, replacing it + # with the block's result. May retry if the value changes + # during the block's execution. + # + # @yield [Object] Calculate a new value for the atomic reference using + # given (old) value + # @yieldparam [Object] old_value the starting value of the atomic reference + # + # @return [Object] the new value + + ################################################################### + + # @!macro atomic_fixnum_public_api + # + # @!method initialize(initial = 0) + # @!macro atomic_fixnum_method_initialize + # + # @!method value + # @!macro atomic_fixnum_method_value_get + # + # @!method value=(value) + # @!macro atomic_fixnum_method_value_set + # + # @!method increment(delta = 1) + # @!macro atomic_fixnum_method_increment + # + # @!method decrement(delta = 1) + # @!macro atomic_fixnum_method_decrement + # + # @!method compare_and_set(expect, update) + # @!macro atomic_fixnum_method_compare_and_set + # + # @!method update + # @!macro atomic_fixnum_method_update + + ################################################################### + + # @!visibility private + # @!macro internal_implementation_note + AtomicFixnumImplementation = case + when Concurrent.on_cruby? && Concurrent.c_extensions_loaded? + CAtomicFixnum + when Concurrent.on_jruby? + JavaAtomicFixnum + else + MutexAtomicFixnum + end + private_constant :AtomicFixnumImplementation + + # @!macro atomic_fixnum + # + # A numeric value that can be updated atomically. Reads and writes to an atomic + # fixnum and thread-safe and guaranteed to succeed. Reads and writes may block + # briefly but no explicit locking is required. + # + # @!macro thread_safe_variable_comparison + # + # Performance: + # + # ``` + # Testing with ruby 2.1.2 + # Testing with Concurrent::MutexAtomicFixnum... + # 3.130000 0.000000 3.130000 ( 3.136505) + # Testing with Concurrent::CAtomicFixnum... + # 0.790000 0.000000 0.790000 ( 0.785550) + # + # Testing with jruby 1.9.3 + # Testing with Concurrent::MutexAtomicFixnum... + # 5.460000 2.460000 7.920000 ( 3.715000) + # Testing with Concurrent::JavaAtomicFixnum... + # 4.520000 0.030000 4.550000 ( 1.187000) + # ``` + # + # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicLong.html java.util.concurrent.atomic.AtomicLong + # + # @!macro atomic_fixnum_public_api + class AtomicFixnum < AtomicFixnumImplementation + # @return [String] Short string representation. + def to_s + format '%s value:%s>', super[0..-2], value + end + + alias_method :inspect, :to_s + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb new file mode 100644 index 0000000000000..e16be65772c96 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb @@ -0,0 +1,167 @@ +require 'concurrent/errors' +require 'concurrent/synchronization/object' + +module Concurrent + # An atomic reference which maintains an object reference along with a mark bit + # that can be updated atomically. + # + # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicMarkableReference.html + # java.util.concurrent.atomic.AtomicMarkableReference + class AtomicMarkableReference < ::Concurrent::Synchronization::Object + + attr_atomic(:reference) + private :reference, :reference=, :swap_reference, :compare_and_set_reference, :update_reference + + def initialize(value = nil, mark = false) + super() + self.reference = immutable_array(value, mark) + end + + # Atomically sets the value and mark to the given updated value and + # mark given both: + # - the current value == the expected value && + # - the current mark == the expected mark + # + # @param [Object] expected_val the expected value + # @param [Object] new_val the new value + # @param [Boolean] expected_mark the expected mark + # @param [Boolean] new_mark the new mark + # + # @return [Boolean] `true` if successful. A `false` return indicates + # that the actual value was not equal to the expected value or the + # actual mark was not equal to the expected mark + def compare_and_set(expected_val, new_val, expected_mark, new_mark) + # Memoize a valid reference to the current AtomicReference for + # later comparison. + current = reference + curr_val, curr_mark = current + + # Ensure that that the expected marks match. + return false unless expected_mark == curr_mark + + if expected_val.is_a? Numeric + # If the object is a numeric, we need to ensure we are comparing + # the numerical values + return false unless expected_val == curr_val + else + # Otherwise, we need to ensure we are comparing the object identity. + # Theoretically, this could be incorrect if a user monkey-patched + # `Object#equal?`, but they should know that they are playing with + # fire at that point. + return false unless expected_val.equal? curr_val + end + + prospect = immutable_array(new_val, new_mark) + + compare_and_set_reference current, prospect + end + + alias_method :compare_and_swap, :compare_and_set + + # Gets the current reference and marked values. + # + # @return [Array] the current reference and marked values + def get + reference + end + + # Gets the current value of the reference + # + # @return [Object] the current value of the reference + def value + reference[0] + end + + # Gets the current marked value + # + # @return [Boolean] the current marked value + def mark + reference[1] + end + + alias_method :marked?, :mark + + # _Unconditionally_ sets to the given value of both the reference and + # the mark. + # + # @param [Object] new_val the new value + # @param [Boolean] new_mark the new mark + # + # @return [Array] both the new value and the new mark + def set(new_val, new_mark) + self.reference = immutable_array(new_val, new_mark) + end + + # Pass the current value and marked state to the given block, replacing it + # with the block's results. May retry if the value changes during the + # block's execution. + # + # @yield [Object] Calculate a new value and marked state for the atomic + # reference using given (old) value and (old) marked + # @yieldparam [Object] old_val the starting value of the atomic reference + # @yieldparam [Boolean] old_mark the starting state of marked + # + # @return [Array] the new value and new mark + def update + loop do + old_val, old_mark = reference + new_val, new_mark = yield old_val, old_mark + + if compare_and_set old_val, new_val, old_mark, new_mark + return immutable_array(new_val, new_mark) + end + end + end + + # Pass the current value to the given block, replacing it + # with the block's result. Raise an exception if the update + # fails. + # + # @yield [Object] Calculate a new value and marked state for the atomic + # reference using given (old) value and (old) marked + # @yieldparam [Object] old_val the starting value of the atomic reference + # @yieldparam [Boolean] old_mark the starting state of marked + # + # @return [Array] the new value and marked state + # + # @raise [Concurrent::ConcurrentUpdateError] if the update fails + def try_update! + old_val, old_mark = reference + new_val, new_mark = yield old_val, old_mark + + unless compare_and_set old_val, new_val, old_mark, new_mark + fail ::Concurrent::ConcurrentUpdateError, + 'AtomicMarkableReference: Update failed due to race condition.', + 'Note: If you would like to guarantee an update, please use ' + + 'the `AtomicMarkableReference#update` method.' + end + + immutable_array(new_val, new_mark) + end + + # Pass the current value to the given block, replacing it with the + # block's result. Simply return nil if update fails. + # + # @yield [Object] Calculate a new value and marked state for the atomic + # reference using given (old) value and (old) marked + # @yieldparam [Object] old_val the starting value of the atomic reference + # @yieldparam [Boolean] old_mark the starting state of marked + # + # @return [Array] the new value and marked state, or nil if + # the update failed + def try_update + old_val, old_mark = reference + new_val, new_mark = yield old_val, old_mark + + return unless compare_and_set old_val, new_val, old_mark, new_mark + + immutable_array(new_val, new_mark) + end + + private + + def immutable_array(*args) + args.freeze + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb new file mode 100644 index 0000000000000..bb5fb774598cd --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb @@ -0,0 +1,135 @@ +require 'concurrent/utility/native_extension_loader' # load native parts first + +require 'concurrent/atomic_reference/atomic_direct_update' +require 'concurrent/atomic_reference/numeric_cas_wrapper' +require 'concurrent/atomic_reference/mutex_atomic' + +# Shim for TruffleRuby::AtomicReference +if Concurrent.on_truffleruby? && !defined?(TruffleRuby::AtomicReference) + # @!visibility private + module TruffleRuby + AtomicReference = Truffle::AtomicReference + end +end + +module Concurrent + + # @!macro internal_implementation_note + AtomicReferenceImplementation = case + when Concurrent.on_cruby? && Concurrent.c_extensions_loaded? + # @!visibility private + # @!macro internal_implementation_note + class CAtomicReference + include AtomicDirectUpdate + include AtomicNumericCompareAndSetWrapper + alias_method :compare_and_swap, :compare_and_set + end + CAtomicReference + when Concurrent.on_jruby? + # @!visibility private + # @!macro internal_implementation_note + class JavaAtomicReference + include AtomicDirectUpdate + end + JavaAtomicReference + when Concurrent.on_truffleruby? + class TruffleRubyAtomicReference < TruffleRuby::AtomicReference + include AtomicDirectUpdate + alias_method :value, :get + alias_method :value=, :set + alias_method :compare_and_swap, :compare_and_set + alias_method :swap, :get_and_set + end + TruffleRubyAtomicReference + else + MutexAtomicReference + end + private_constant :AtomicReferenceImplementation + + # An object reference that may be updated atomically. All read and write + # operations have java volatile semantic. + # + # @!macro thread_safe_variable_comparison + # + # @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicReference.html + # @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/package-summary.html + # + # @!method initialize(value = nil) + # @!macro atomic_reference_method_initialize + # @param [Object] value The initial value. + # + # @!method get + # @!macro atomic_reference_method_get + # Gets the current value. + # @return [Object] the current value + # + # @!method set(new_value) + # @!macro atomic_reference_method_set + # Sets to the given value. + # @param [Object] new_value the new value + # @return [Object] the new value + # + # @!method get_and_set(new_value) + # @!macro atomic_reference_method_get_and_set + # Atomically sets to the given value and returns the old value. + # @param [Object] new_value the new value + # @return [Object] the old value + # + # @!method compare_and_set(old_value, new_value) + # @!macro atomic_reference_method_compare_and_set + # + # Atomically sets the value to the given updated value if + # the current value == the expected value. + # + # @param [Object] old_value the expected value + # @param [Object] new_value the new value + # + # @return [Boolean] `true` if successful. A `false` return indicates + # that the actual value was not equal to the expected value. + # + # @!method update + # Pass the current value to the given block, replacing it + # with the block's result. May retry if the value changes + # during the block's execution. + # + # @yield [Object] Calculate a new value for the atomic reference using + # given (old) value + # @yieldparam [Object] old_value the starting value of the atomic reference + # @return [Object] the new value + # + # @!method try_update + # Pass the current value to the given block, replacing it + # with the block's result. Return nil if the update fails. + # + # @yield [Object] Calculate a new value for the atomic reference using + # given (old) value + # @yieldparam [Object] old_value the starting value of the atomic reference + # @note This method was altered to avoid raising an exception by default. + # Instead, this method now returns `nil` in case of failure. For more info, + # please see: https://github.com/ruby-concurrency/concurrent-ruby/pull/336 + # @return [Object] the new value, or nil if update failed + # + # @!method try_update! + # Pass the current value to the given block, replacing it + # with the block's result. Raise an exception if the update + # fails. + # + # @yield [Object] Calculate a new value for the atomic reference using + # given (old) value + # @yieldparam [Object] old_value the starting value of the atomic reference + # @note This behavior mimics the behavior of the original + # `AtomicReference#try_update` API. The reason this was changed was to + # avoid raising exceptions (which are inherently slow) by default. For more + # info: https://github.com/ruby-concurrency/concurrent-ruby/pull/336 + # @return [Object] the new value + # @raise [Concurrent::ConcurrentUpdateError] if the update fails + class AtomicReference < AtomicReferenceImplementation + + # @return [String] Short string representation. + def to_s + format '%s value:%s>', super[0..-2], get + end + + alias_method :inspect, :to_s + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/count_down_latch.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/count_down_latch.rb new file mode 100644 index 0000000000000..d883aed6f251b --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/count_down_latch.rb @@ -0,0 +1,100 @@ +require 'concurrent/utility/engine' +require 'concurrent/atomic/mutex_count_down_latch' +require 'concurrent/atomic/java_count_down_latch' + +module Concurrent + + ################################################################### + + # @!macro count_down_latch_method_initialize + # + # Create a new `CountDownLatch` with the initial `count`. + # + # @param [new] count the initial count + # + # @raise [ArgumentError] if `count` is not an integer or is less than zero + + # @!macro count_down_latch_method_wait + # + # Block on the latch until the counter reaches zero or until `timeout` is reached. + # + # @param [Fixnum] timeout the number of seconds to wait for the counter or `nil` + # to block indefinitely + # @return [Boolean] `true` if the `count` reaches zero else false on `timeout` + + # @!macro count_down_latch_method_count_down + # + # Signal the latch to decrement the counter. Will signal all blocked threads when + # the `count` reaches zero. + + # @!macro count_down_latch_method_count + # + # The current value of the counter. + # + # @return [Fixnum] the current value of the counter + + ################################################################### + + # @!macro count_down_latch_public_api + # + # @!method initialize(count = 1) + # @!macro count_down_latch_method_initialize + # + # @!method wait(timeout = nil) + # @!macro count_down_latch_method_wait + # + # @!method count_down + # @!macro count_down_latch_method_count_down + # + # @!method count + # @!macro count_down_latch_method_count + + ################################################################### + + # @!visibility private + # @!macro internal_implementation_note + CountDownLatchImplementation = case + when Concurrent.on_jruby? + JavaCountDownLatch + else + MutexCountDownLatch + end + private_constant :CountDownLatchImplementation + + # @!macro count_down_latch + # + # A synchronization object that allows one thread to wait on multiple other threads. + # The thread that will wait creates a `CountDownLatch` and sets the initial value + # (normally equal to the number of other threads). The initiating thread passes the + # latch to the other threads then waits for the other threads by calling the `#wait` + # method. Each of the other threads calls `#count_down` when done with its work. + # When the latch counter reaches zero the waiting thread is unblocked and continues + # with its work. A `CountDownLatch` can be used only once. Its value cannot be reset. + # + # @!macro count_down_latch_public_api + # @example Waiter and Decrementer + # latch = Concurrent::CountDownLatch.new(3) + # + # waiter = Thread.new do + # latch.wait() + # puts ("Waiter released") + # end + # + # decrementer = Thread.new do + # sleep(1) + # latch.count_down + # puts latch.count + # + # sleep(1) + # latch.count_down + # puts latch.count + # + # sleep(1) + # latch.count_down + # puts latch.count + # end + # + # [waiter, decrementer].each(&:join) + class CountDownLatch < CountDownLatchImplementation + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb new file mode 100644 index 0000000000000..9ebe29dd09816 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb @@ -0,0 +1,128 @@ +require 'concurrent/synchronization/lockable_object' +require 'concurrent/utility/native_integer' + +module Concurrent + + # A synchronization aid that allows a set of threads to all wait for each + # other to reach a common barrier point. + # @example + # barrier = Concurrent::CyclicBarrier.new(3) + # jobs = Array.new(3) { |i| -> { sleep i; p done: i } } + # process = -> (i) do + # # waiting to start at the same time + # barrier.wait + # # execute job + # jobs[i].call + # # wait for others to finish + # barrier.wait + # end + # threads = 2.times.map do |i| + # Thread.new(i, &process) + # end + # + # # use main as well + # process.call 2 + # + # # here we can be sure that all jobs are processed + class CyclicBarrier < Synchronization::LockableObject + + # @!visibility private + Generation = Struct.new(:status) + private_constant :Generation + + # Create a new `CyclicBarrier` that waits for `parties` threads + # + # @param [Fixnum] parties the number of parties + # @yield an optional block that will be executed that will be executed after + # the last thread arrives and before the others are released + # + # @raise [ArgumentError] if `parties` is not an integer or is less than zero + def initialize(parties, &block) + Utility::NativeInteger.ensure_integer_and_bounds parties + Utility::NativeInteger.ensure_positive_and_no_zero parties + + super(&nil) + synchronize { ns_initialize parties, &block } + end + + # @return [Fixnum] the number of threads needed to pass the barrier + def parties + synchronize { @parties } + end + + # @return [Fixnum] the number of threads currently waiting on the barrier + def number_waiting + synchronize { @number_waiting } + end + + # Blocks on the barrier until the number of waiting threads is equal to + # `parties` or until `timeout` is reached or `reset` is called + # If a block has been passed to the constructor, it will be executed once by + # the last arrived thread before releasing the others + # @param [Fixnum] timeout the number of seconds to wait for the counter or + # `nil` to block indefinitely + # @return [Boolean] `true` if the `count` reaches zero else false on + # `timeout` or on `reset` or if the barrier is broken + def wait(timeout = nil) + synchronize do + + return false unless @generation.status == :waiting + + @number_waiting += 1 + + if @number_waiting == @parties + @action.call if @action + ns_generation_done @generation, :fulfilled + true + else + generation = @generation + if ns_wait_until(timeout) { generation.status != :waiting } + generation.status == :fulfilled + else + ns_generation_done generation, :broken, false + false + end + end + end + end + + # resets the barrier to its initial state + # If there is at least one waiting thread, it will be woken up, the `wait` + # method will return false and the barrier will be broken + # If the barrier is broken, this method restores it to the original state + # + # @return [nil] + def reset + synchronize { ns_generation_done @generation, :reset } + end + + # A barrier can be broken when: + # - a thread called the `reset` method while at least one other thread was waiting + # - at least one thread timed out on `wait` method + # + # A broken barrier can be restored using `reset` it's safer to create a new one + # @return [Boolean] true if the barrier is broken otherwise false + def broken? + synchronize { @generation.status != :waiting } + end + + protected + + def ns_generation_done(generation, status, continue = true) + generation.status = status + ns_next_generation if continue + ns_broadcast + end + + def ns_next_generation + @generation = Generation.new(:waiting) + @number_waiting = 0 + end + + def ns_initialize(parties, &block) + @parties = parties + @action = block + ns_next_generation + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/event.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/event.rb new file mode 100644 index 0000000000000..ccf84c9d1b8a1 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/event.rb @@ -0,0 +1,109 @@ +require 'thread' +require 'concurrent/synchronization/lockable_object' + +module Concurrent + + # Old school kernel-style event reminiscent of Win32 programming in C++. + # + # When an `Event` is created it is in the `unset` state. Threads can choose to + # `#wait` on the event, blocking until released by another thread. When one + # thread wants to alert all blocking threads it calls the `#set` method which + # will then wake up all listeners. Once an `Event` has been set it remains set. + # New threads calling `#wait` will return immediately. An `Event` may be + # `#reset` at any time once it has been set. + # + # @see http://msdn.microsoft.com/en-us/library/windows/desktop/ms682655.aspx + # @example + # event = Concurrent::Event.new + # + # t1 = Thread.new do + # puts "t1 is waiting" + # event.wait(1) + # puts "event occurred" + # end + # + # t2 = Thread.new do + # puts "t2 calling set" + # event.set + # end + # + # [t1, t2].each(&:join) + # + # # prints: + # # t1 is waiting + # # t2 calling set + # # event occurred + class Event < Synchronization::LockableObject + + # Creates a new `Event` in the unset state. Threads calling `#wait` on the + # `Event` will block. + def initialize + super + synchronize { ns_initialize } + end + + # Is the object in the set state? + # + # @return [Boolean] indicating whether or not the `Event` has been set + def set? + synchronize { @set } + end + + # Trigger the event, setting the state to `set` and releasing all threads + # waiting on the event. Has no effect if the `Event` has already been set. + # + # @return [Boolean] should always return `true` + def set + synchronize { ns_set } + end + + def try? + synchronize { @set ? false : ns_set } + end + + # Reset a previously set event back to the `unset` state. + # Has no effect if the `Event` has not yet been set. + # + # @return [Boolean] should always return `true` + def reset + synchronize do + if @set + @set = false + @iteration +=1 + end + true + end + end + + # Wait a given number of seconds for the `Event` to be set by another + # thread. Will wait forever when no `timeout` value is given. Returns + # immediately if the `Event` has already been set. + # + # @return [Boolean] true if the `Event` was set before timeout else false + def wait(timeout = nil) + synchronize do + unless @set + iteration = @iteration + ns_wait_until(timeout) { iteration < @iteration || @set } + else + true + end + end + end + + protected + + def ns_set + unless @set + @set = true + ns_broadcast + end + true + end + + def ns_initialize + @set = false + @iteration = 0 + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/fiber_local_var.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/fiber_local_var.rb new file mode 100644 index 0000000000000..e90fc24f9ecb5 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/fiber_local_var.rb @@ -0,0 +1,109 @@ +require 'concurrent/constants' +require_relative 'locals' + +module Concurrent + + # A `FiberLocalVar` is a variable where the value is different for each fiber. + # Each variable may have a default value, but when you modify the variable only + # the current fiber will ever see that change. + # + # This is similar to Ruby's built-in fiber-local variables (`Thread.current[:name]`), + # but with these major advantages: + # * `FiberLocalVar` has its own identity, it doesn't need a Symbol. + # * Each Ruby's built-in fiber-local variable leaks some memory forever (it's a Symbol held forever on the fiber), + # so it's only OK to create a small amount of them. + # `FiberLocalVar` has no such issue and it is fine to create many of them. + # * Ruby's built-in fiber-local variables leak forever the value set on each fiber (unless set to nil explicitly). + # `FiberLocalVar` automatically removes the mapping for each fiber once the `FiberLocalVar` instance is GC'd. + # + # @example + # v = FiberLocalVar.new(14) + # v.value #=> 14 + # v.value = 2 + # v.value #=> 2 + # + # @example + # v = FiberLocalVar.new(14) + # + # Fiber.new do + # v.value #=> 14 + # v.value = 1 + # v.value #=> 1 + # end.resume + # + # Fiber.new do + # v.value #=> 14 + # v.value = 2 + # v.value #=> 2 + # end.resume + # + # v.value #=> 14 + class FiberLocalVar + LOCALS = FiberLocals.new + + # Creates a fiber local variable. + # + # @param [Object] default the default value when otherwise unset + # @param [Proc] default_block Optional block that gets called to obtain the + # default value for each fiber + def initialize(default = nil, &default_block) + if default && block_given? + raise ArgumentError, "Cannot use both value and block as default value" + end + + if block_given? + @default_block = default_block + @default = nil + else + @default_block = nil + @default = default + end + + @index = LOCALS.next_index(self) + end + + # Returns the value in the current fiber's copy of this fiber-local variable. + # + # @return [Object] the current value + def value + LOCALS.fetch(@index) { default } + end + + # Sets the current fiber's copy of this fiber-local variable to the specified value. + # + # @param [Object] value the value to set + # @return [Object] the new value + def value=(value) + LOCALS.set(@index, value) + end + + # Bind the given value to fiber local storage during + # execution of the given block. + # + # @param [Object] value the value to bind + # @yield the operation to be performed with the bound variable + # @return [Object] the value + def bind(value) + if block_given? + old_value = self.value + self.value = value + begin + yield + ensure + self.value = old_value + end + end + end + + protected + + # @!visibility private + def default + if @default_block + self.value = @default_block.call + else + @default + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/java_count_down_latch.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/java_count_down_latch.rb new file mode 100644 index 0000000000000..3c119bc32c2c4 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/java_count_down_latch.rb @@ -0,0 +1,43 @@ +if Concurrent.on_jruby? + require 'concurrent/utility/native_extension_loader' + + module Concurrent + + # @!macro count_down_latch + # @!visibility private + # @!macro internal_implementation_note + class JavaCountDownLatch + + # @!macro count_down_latch_method_initialize + def initialize(count = 1) + Utility::NativeInteger.ensure_integer_and_bounds(count) + Utility::NativeInteger.ensure_positive(count) + @latch = java.util.concurrent.CountDownLatch.new(count) + end + + # @!macro count_down_latch_method_wait + def wait(timeout = nil) + result = nil + if timeout.nil? + Synchronization::JRuby.sleep_interruptibly { @latch.await } + result = true + else + Synchronization::JRuby.sleep_interruptibly do + result = @latch.await(1000 * timeout, java.util.concurrent.TimeUnit::MILLISECONDS) + end + end + result + end + + # @!macro count_down_latch_method_count_down + def count_down + @latch.countDown + end + + # @!macro count_down_latch_method_count + def count + @latch.getCount + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/locals.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/locals.rb new file mode 100644 index 0000000000000..0a276aedd5251 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/locals.rb @@ -0,0 +1,189 @@ +require 'fiber' +require 'concurrent/utility/engine' +require 'concurrent/constants' + +module Concurrent + # @!visibility private + # @!macro internal_implementation_note + # + # An abstract implementation of local storage, with sub-classes for + # per-thread and per-fiber locals. + # + # Each execution context (EC, thread or fiber) has a lazily initialized array + # of local variable values. Each time a new local variable is created, we + # allocate an "index" for it. + # + # For example, if the allocated index is 1, that means slot #1 in EVERY EC's + # locals array will be used for the value of that variable. + # + # The good thing about using a per-EC structure to hold values, rather than + # a global, is that no synchronization is needed when reading and writing + # those values (since the structure is only ever accessed by a single + # thread). + # + # Of course, when a local variable is GC'd, 1) we need to recover its index + # for use by other new local variables (otherwise the locals arrays could + # get bigger and bigger with time), and 2) we need to null out all the + # references held in the now-unused slots (both to avoid blocking GC of those + # objects, and also to prevent "stale" values from being passed on to a new + # local when the index is reused). + # + # Because we need to null out freed slots, we need to keep references to + # ALL the locals arrays, so we can null out the appropriate slots in all of + # them. This is why we need to use a finalizer to clean up the locals array + # when the EC goes out of scope. + class AbstractLocals + def initialize + @free = [] + @lock = Mutex.new + @all_arrays = {} + @next = 0 + end + + def synchronize + @lock.synchronize { yield } + end + + if Concurrent.on_cruby? + def weak_synchronize + yield + end + else + alias_method :weak_synchronize, :synchronize + end + + def next_index(local) + index = synchronize do + if @free.empty? + @next += 1 + else + @free.pop + end + end + + # When the local goes out of scope, we should free the associated index + # and all values stored into it. + ObjectSpace.define_finalizer(local, local_finalizer(index)) + + index + end + + def free_index(index) + weak_synchronize do + # The cost of GC'ing a TLV is linear in the number of ECs using local + # variables. But that is natural! More ECs means more storage is used + # per local variable. So naturally more CPU time is required to free + # more storage. + # + # DO NOT use each_value which might conflict with new pair assignment + # into the hash in #set method. + @all_arrays.values.each do |locals| + locals[index] = nil + end + + # free index has to be published after the arrays are cleared: + @free << index + end + end + + def fetch(index) + locals = self.locals + value = locals ? locals[index] : nil + + if nil == value + yield + elsif NULL.equal?(value) + nil + else + value + end + end + + def set(index, value) + locals = self.locals! + locals[index] = (nil == value ? NULL : value) + + value + end + + private + + # When the local goes out of scope, clean up that slot across all locals currently assigned. + def local_finalizer(index) + proc do + free_index(index) + end + end + + # When a thread/fiber goes out of scope, remove the array from @all_arrays. + def thread_fiber_finalizer(array_object_id) + proc do + weak_synchronize do + @all_arrays.delete(array_object_id) + end + end + end + + # Returns the locals for the current scope, or nil if none exist. + def locals + raise NotImplementedError + end + + # Returns the locals for the current scope, creating them if necessary. + def locals! + raise NotImplementedError + end + end + + # @!visibility private + # @!macro internal_implementation_note + # An array-backed storage of indexed variables per thread. + class ThreadLocals < AbstractLocals + def locals + Thread.current.thread_variable_get(:concurrent_thread_locals) + end + + def locals! + thread = Thread.current + locals = thread.thread_variable_get(:concurrent_thread_locals) + + unless locals + locals = thread.thread_variable_set(:concurrent_thread_locals, []) + weak_synchronize do + @all_arrays[locals.object_id] = locals + end + # When the thread goes out of scope, we should delete the associated locals: + ObjectSpace.define_finalizer(thread, thread_fiber_finalizer(locals.object_id)) + end + + locals + end + end + + # @!visibility private + # @!macro internal_implementation_note + # An array-backed storage of indexed variables per fiber. + class FiberLocals < AbstractLocals + def locals + Thread.current[:concurrent_fiber_locals] + end + + def locals! + thread = Thread.current + locals = thread[:concurrent_fiber_locals] + + unless locals + locals = thread[:concurrent_fiber_locals] = [] + weak_synchronize do + @all_arrays[locals.object_id] = locals + end + # When the fiber goes out of scope, we should delete the associated locals: + ObjectSpace.define_finalizer(Fiber.current, thread_fiber_finalizer(locals.object_id)) + end + + locals + end + end + + private_constant :AbstractLocals, :ThreadLocals, :FiberLocals +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/lock_local_var.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/lock_local_var.rb new file mode 100644 index 0000000000000..ebf23a2414093 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/lock_local_var.rb @@ -0,0 +1,28 @@ +require 'concurrent/utility/engine' +require_relative 'fiber_local_var' +require_relative 'thread_local_var' + +module Concurrent + # @!visibility private + def self.mutex_owned_per_thread? + return false if Concurrent.on_jruby? || Concurrent.on_truffleruby? + + mutex = Mutex.new + # Lock the mutex: + mutex.synchronize do + # Check if the mutex is still owned in a child fiber: + Fiber.new { mutex.owned? }.resume + end + end + + if mutex_owned_per_thread? + LockLocalVar = ThreadLocalVar + else + LockLocalVar = FiberLocalVar + end + + # Either {FiberLocalVar} or {ThreadLocalVar} depending on whether Mutex (and Monitor) + # are held, respectively, per Fiber or per Thread. + class LockLocalVar + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb new file mode 100644 index 0000000000000..015996b06f04c --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb @@ -0,0 +1,68 @@ +require 'concurrent/synchronization/safe_initialization' + +module Concurrent + + # @!macro atomic_boolean + # @!visibility private + # @!macro internal_implementation_note + class MutexAtomicBoolean + extend Concurrent::Synchronization::SafeInitialization + + # @!macro atomic_boolean_method_initialize + def initialize(initial = false) + super() + @Lock = ::Mutex.new + @value = !!initial + end + + # @!macro atomic_boolean_method_value_get + def value + synchronize { @value } + end + + # @!macro atomic_boolean_method_value_set + def value=(value) + synchronize { @value = !!value } + end + + # @!macro atomic_boolean_method_true_question + def true? + synchronize { @value } + end + + # @!macro atomic_boolean_method_false_question + def false? + synchronize { !@value } + end + + # @!macro atomic_boolean_method_make_true + def make_true + synchronize { ns_make_value(true) } + end + + # @!macro atomic_boolean_method_make_false + def make_false + synchronize { ns_make_value(false) } + end + + protected + + # @!visibility private + def synchronize + if @Lock.owned? + yield + else + @Lock.synchronize { yield } + end + end + + private + + # @!visibility private + def ns_make_value(value) + old = @value + @value = value + old != @value + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb new file mode 100644 index 0000000000000..0ca395579fe09 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb @@ -0,0 +1,81 @@ +require 'concurrent/synchronization/safe_initialization' +require 'concurrent/utility/native_integer' + +module Concurrent + + # @!macro atomic_fixnum + # @!visibility private + # @!macro internal_implementation_note + class MutexAtomicFixnum + extend Concurrent::Synchronization::SafeInitialization + + # @!macro atomic_fixnum_method_initialize + def initialize(initial = 0) + super() + @Lock = ::Mutex.new + ns_set(initial) + end + + # @!macro atomic_fixnum_method_value_get + def value + synchronize { @value } + end + + # @!macro atomic_fixnum_method_value_set + def value=(value) + synchronize { ns_set(value) } + end + + # @!macro atomic_fixnum_method_increment + def increment(delta = 1) + synchronize { ns_set(@value + delta.to_i) } + end + + alias_method :up, :increment + + # @!macro atomic_fixnum_method_decrement + def decrement(delta = 1) + synchronize { ns_set(@value - delta.to_i) } + end + + alias_method :down, :decrement + + # @!macro atomic_fixnum_method_compare_and_set + def compare_and_set(expect, update) + synchronize do + if @value == expect.to_i + @value = update.to_i + true + else + false + end + end + end + + # @!macro atomic_fixnum_method_update + def update + synchronize do + @value = yield @value + end + end + + protected + + # @!visibility private + def synchronize + if @Lock.owned? + yield + else + @Lock.synchronize { yield } + end + end + + private + + # @!visibility private + def ns_set(value) + Utility::NativeInteger.ensure_integer_and_bounds value + @value = value + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/mutex_count_down_latch.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/mutex_count_down_latch.rb new file mode 100644 index 0000000000000..29aa1caa4f296 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/mutex_count_down_latch.rb @@ -0,0 +1,44 @@ +require 'concurrent/synchronization/lockable_object' +require 'concurrent/utility/native_integer' + +module Concurrent + + # @!macro count_down_latch + # @!visibility private + # @!macro internal_implementation_note + class MutexCountDownLatch < Synchronization::LockableObject + + # @!macro count_down_latch_method_initialize + def initialize(count = 1) + Utility::NativeInteger.ensure_integer_and_bounds count + Utility::NativeInteger.ensure_positive count + + super() + synchronize { ns_initialize count } + end + + # @!macro count_down_latch_method_wait + def wait(timeout = nil) + synchronize { ns_wait_until(timeout) { @count == 0 } } + end + + # @!macro count_down_latch_method_count_down + def count_down + synchronize do + @count -= 1 if @count > 0 + ns_broadcast if @count == 0 + end + end + + # @!macro count_down_latch_method_count + def count + synchronize { @count } + end + + protected + + def ns_initialize(count) + @count = count + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb new file mode 100644 index 0000000000000..4347289f1ed10 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb @@ -0,0 +1,131 @@ +require 'concurrent/synchronization/lockable_object' +require 'concurrent/utility/native_integer' + +module Concurrent + + # @!macro semaphore + # @!visibility private + # @!macro internal_implementation_note + class MutexSemaphore < Synchronization::LockableObject + + # @!macro semaphore_method_initialize + def initialize(count) + Utility::NativeInteger.ensure_integer_and_bounds count + + super() + synchronize { ns_initialize count } + end + + # @!macro semaphore_method_acquire + def acquire(permits = 1) + Utility::NativeInteger.ensure_integer_and_bounds permits + Utility::NativeInteger.ensure_positive permits + + synchronize do + try_acquire_timed(permits, nil) + end + + return unless block_given? + + begin + yield + ensure + release(permits) + end + end + + # @!macro semaphore_method_available_permits + def available_permits + synchronize { @free } + end + + # @!macro semaphore_method_drain_permits + # + # Acquires and returns all permits that are immediately available. + # + # @return [Integer] + def drain_permits + synchronize do + @free.tap { |_| @free = 0 } + end + end + + # @!macro semaphore_method_try_acquire + def try_acquire(permits = 1, timeout = nil) + Utility::NativeInteger.ensure_integer_and_bounds permits + Utility::NativeInteger.ensure_positive permits + + 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 + def release(permits = 1) + Utility::NativeInteger.ensure_integer_and_bounds permits + Utility::NativeInteger.ensure_positive permits + + synchronize do + @free += permits + permits.times { ns_signal } + end + nil + end + + # Shrinks the number of available permits by the indicated reduction. + # + # @param [Fixnum] reduction Number of permits to remove. + # + # @raise [ArgumentError] if `reduction` is not an integer or is negative + # + # @raise [ArgumentError] if `@free` - `@reduction` is less than zero + # + # @return [nil] + # + # @!visibility private + def reduce_permits(reduction) + Utility::NativeInteger.ensure_integer_and_bounds reduction + Utility::NativeInteger.ensure_positive reduction + + synchronize { @free -= reduction } + nil + end + + protected + + # @!visibility private + def ns_initialize(count) + @free = count + end + + private + + # @!visibility private + def try_acquire_now(permits) + if @free >= permits + @free -= permits + true + else + false + end + end + + # @!visibility private + def try_acquire_timed(permits, timeout) + ns_wait_until(timeout) { try_acquire_now(permits) } + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb new file mode 100644 index 0000000000000..b26bd17a089ce --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb @@ -0,0 +1,255 @@ +require 'thread' +require 'concurrent/atomic/atomic_fixnum' +require 'concurrent/errors' +require 'concurrent/synchronization/object' +require 'concurrent/synchronization/lock' + +module Concurrent + + # Ruby read-write lock implementation + # + # Allows any number of concurrent readers, but only one concurrent writer + # (And if the "write" lock is taken, any readers who come along will have to wait) + # + # If readers are already active when a writer comes along, the writer will wait for + # all the readers to finish before going ahead. + # Any additional readers that come when the writer is already waiting, will also + # wait (so writers are not starved). + # + # This implementation is based on `java.util.concurrent.ReentrantReadWriteLock`. + # + # @example + # lock = Concurrent::ReadWriteLock.new + # lock.with_read_lock { data.retrieve } + # lock.with_write_lock { data.modify! } + # + # @note Do **not** try to acquire the write lock while already holding a read lock + # **or** try to acquire the write lock while you already have it. + # This will lead to deadlock + # + # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.html java.util.concurrent.ReentrantReadWriteLock + class ReadWriteLock < Synchronization::Object + + # @!visibility private + WAITING_WRITER = 1 << 15 + + # @!visibility private + RUNNING_WRITER = 1 << 29 + + # @!visibility private + MAX_READERS = WAITING_WRITER - 1 + + # @!visibility private + MAX_WRITERS = RUNNING_WRITER - MAX_READERS - 1 + + safe_initialization! + + # Implementation notes: + # A goal is to make the uncontended path for both readers/writers lock-free + # Only if there is reader-writer or writer-writer contention, should locks be used + # Internal state is represented by a single integer ("counter"), and updated + # using atomic compare-and-swap operations + # When the counter is 0, the lock is free + # Each reader increments the counter by 1 when acquiring a read lock + # (and decrements by 1 when releasing the read lock) + # The counter is increased by (1 << 15) for each writer waiting to acquire the + # write lock, and by (1 << 29) if the write lock is taken + + # Create a new `ReadWriteLock` in the unlocked state. + def initialize + super() + @Counter = AtomicFixnum.new(0) # single integer which represents lock state + @ReadLock = Synchronization::Lock.new + @WriteLock = Synchronization::Lock.new + end + + # Execute a block operation within a read lock. + # + # @yield the task to be performed within the lock. + # + # @return [Object] the result of the block operation. + # + # @raise [ArgumentError] when no block is given. + # @raise [Concurrent::ResourceLimitError] if the maximum number of readers + # is exceeded. + def with_read_lock + raise ArgumentError.new('no block given') unless block_given? + acquire_read_lock + begin + yield + ensure + release_read_lock + end + end + + # Execute a block operation within a write lock. + # + # @yield the task to be performed within the lock. + # + # @return [Object] the result of the block operation. + # + # @raise [ArgumentError] when no block is given. + # @raise [Concurrent::ResourceLimitError] if the maximum number of readers + # is exceeded. + def with_write_lock + raise ArgumentError.new('no block given') unless block_given? + acquire_write_lock + begin + yield + ensure + release_write_lock + end + end + + # Acquire a read lock. If a write lock has been acquired will block until + # it is released. Will not block if other read locks have been acquired. + # + # @return [Boolean] true if the lock is successfully acquired + # + # @raise [Concurrent::ResourceLimitError] if the maximum number of readers + # is exceeded. + def acquire_read_lock + while true + c = @Counter.value + raise ResourceLimitError.new('Too many reader threads') if max_readers?(c) + + # If a writer is waiting when we first queue up, we need to wait + if waiting_writer?(c) + @ReadLock.wait_until { !waiting_writer? } + + # after a reader has waited once, they are allowed to "barge" ahead of waiting writers + # but if a writer is *running*, the reader still needs to wait (naturally) + while true + c = @Counter.value + if running_writer?(c) + @ReadLock.wait_until { !running_writer? } + else + return if @Counter.compare_and_set(c, c+1) + end + end + else + break if @Counter.compare_and_set(c, c+1) + end + end + true + end + + # Release a previously acquired read lock. + # + # @return [Boolean] true if the lock is successfully released + def release_read_lock + while true + c = @Counter.value + if @Counter.compare_and_set(c, c-1) + # If one or more writers were waiting, and we were the last reader, wake a writer up + if waiting_writer?(c) && running_readers(c) == 1 + @WriteLock.signal + end + break + end + end + true + end + + # Acquire a write lock. Will block and wait for all active readers and writers. + # + # @return [Boolean] true if the lock is successfully acquired + # + # @raise [Concurrent::ResourceLimitError] if the maximum number of writers + # is exceeded. + def acquire_write_lock + while true + c = @Counter.value + raise ResourceLimitError.new('Too many writer threads') if max_writers?(c) + + if c == 0 # no readers OR writers running + # if we successfully swap the RUNNING_WRITER bit on, then we can go ahead + break if @Counter.compare_and_set(0, RUNNING_WRITER) + 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 + # (they will wait instead) + # However, readers OR writers could decrement right here, OR another writer could increment + @WriteLock.wait_until do + # So we have to do another check inside the synchronized section + # If a writer OR reader is running, then go to sleep + c = @Counter.value + !running_writer?(c) && !running_readers?(c) + end + + # We just came out of a wait + # If we successfully turn the RUNNING_WRITER bit on with an atomic swap, + # Then we are OK to stop waiting and go ahead + # Otherwise go back and wait again + c = @Counter.value + break if !running_writer?(c) && !running_readers?(c) && @Counter.compare_and_set(c, c+RUNNING_WRITER-WAITING_WRITER) + end + break + end + end + true + end + + # Release a previously acquired write lock. + # + # @return [Boolean] true if the lock is successfully released + def release_write_lock + return true unless running_writer? + c = @Counter.update { |counter| counter - RUNNING_WRITER } + @ReadLock.broadcast + @WriteLock.signal if waiting_writers(c) > 0 + true + end + + # Queries if the write lock is held by any thread. + # + # @return [Boolean] true if the write lock is held else false` + def write_locked? + @Counter.value >= RUNNING_WRITER + end + + # Queries whether any threads are waiting to acquire the read or write lock. + # + # @return [Boolean] true if any threads are waiting for a lock else false + def has_waiters? + waiting_writer?(@Counter.value) + end + + private + + # @!visibility private + def running_readers(c = @Counter.value) + c & MAX_READERS + end + + # @!visibility private + def running_readers?(c = @Counter.value) + (c & MAX_READERS) > 0 + end + + # @!visibility private + def running_writer?(c = @Counter.value) + c >= RUNNING_WRITER + end + + # @!visibility private + def waiting_writers(c = @Counter.value) + (c & MAX_WRITERS) / WAITING_WRITER + end + + # @!visibility private + def waiting_writer?(c = @Counter.value) + c >= WAITING_WRITER + end + + # @!visibility private + def max_readers?(c = @Counter.value) + (c & MAX_READERS) == MAX_READERS + end + + # @!visibility private + def max_writers?(c = @Counter.value) + (c & MAX_WRITERS) == MAX_WRITERS + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb new file mode 100644 index 0000000000000..6d72a3a097831 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb @@ -0,0 +1,379 @@ +require 'thread' +require 'concurrent/atomic/atomic_reference' +require 'concurrent/atomic/atomic_fixnum' +require 'concurrent/errors' +require 'concurrent/synchronization/object' +require 'concurrent/synchronization/lock' +require 'concurrent/atomic/lock_local_var' + +module Concurrent + + # Re-entrant read-write lock implementation + # + # Allows any number of concurrent readers, but only one concurrent writer + # (And while the "write" lock is taken, no read locks can be obtained either. + # Hence, the write lock can also be called an "exclusive" lock.) + # + # If another thread has taken a read lock, any thread which wants a write lock + # will block until all the readers release their locks. However, once a thread + # starts waiting to obtain a write lock, any additional readers that come along + # will also wait (so writers are not starved). + # + # A thread can acquire both a read and write lock at the same time. A thread can + # also acquire a read lock OR a write lock more than once. Only when the read (or + # write) lock is released as many times as it was acquired, will the thread + # actually let it go, allowing other threads which might have been waiting + # to proceed. Therefore the lock can be upgraded by first acquiring + # read lock and then write lock and that the lock can be downgraded by first + # having both read and write lock a releasing just the write lock. + # + # If both read and write locks are acquired by the same thread, it is not strictly + # necessary to release them in the same order they were acquired. In other words, + # the following code is legal: + # + # @example + # lock = Concurrent::ReentrantReadWriteLock.new + # lock.acquire_write_lock + # lock.acquire_read_lock + # lock.release_write_lock + # # At this point, the current thread is holding only a read lock, not a write + # # lock. So other threads can take read locks, but not a write lock. + # lock.release_read_lock + # # Now the current thread is not holding either a read or write lock, so + # # another thread could potentially acquire a write lock. + # + # This implementation was inspired by `java.util.concurrent.ReentrantReadWriteLock`. + # + # @example + # lock = Concurrent::ReentrantReadWriteLock.new + # lock.with_read_lock { data.retrieve } + # lock.with_write_lock { data.modify! } + # + # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.html java.util.concurrent.ReentrantReadWriteLock + class ReentrantReadWriteLock < Synchronization::Object + + # Implementation notes: + # + # A goal is to make the uncontended path for both readers/writers mutex-free + # Only if there is reader-writer or writer-writer contention, should mutexes be used + # Otherwise, a single CAS operation is all we need to acquire/release a lock + # + # Internal state is represented by a single integer ("counter"), and updated + # using atomic compare-and-swap operations + # When the counter is 0, the lock is free + # Each thread which has one OR MORE read locks increments the counter by 1 + # (and decrements by 1 when releasing the read lock) + # The counter is increased by (1 << 15) for each writer waiting to acquire the + # write lock, and by (1 << 29) if the write lock is taken + # + # Additionally, each thread uses a thread-local variable to count how many times + # it has acquired a read lock, AND how many times it has acquired a write lock. + # It uses a similar trick; an increment of 1 means a read lock was taken, and + # an increment of (1 << 15) means a write lock was taken + # This is what makes re-entrancy possible + # + # 2 rules are followed to ensure good liveness properties: + # 1) Once a writer has queued up and is waiting for a write lock, no other thread + # can take a lock without waiting + # 2) When a write lock is released, readers are given the "first chance" to wake + # up and acquire a read lock + # Following these rules means readers and writers tend to "take turns", so neither + # can starve the other, even under heavy contention + + # @!visibility private + READER_BITS = 15 + # @!visibility private + WRITER_BITS = 14 + + # Used with @Counter: + # @!visibility private + WAITING_WRITER = 1 << READER_BITS + # @!visibility private + RUNNING_WRITER = 1 << (READER_BITS + WRITER_BITS) + # @!visibility private + MAX_READERS = WAITING_WRITER - 1 + # @!visibility private + MAX_WRITERS = RUNNING_WRITER - MAX_READERS - 1 + + # Used with @HeldCount: + # @!visibility private + WRITE_LOCK_HELD = 1 << READER_BITS + # @!visibility private + READ_LOCK_MASK = WRITE_LOCK_HELD - 1 + # @!visibility private + WRITE_LOCK_MASK = MAX_WRITERS + + safe_initialization! + + # Create a new `ReentrantReadWriteLock` in the unlocked state. + def initialize + super() + @Counter = AtomicFixnum.new(0) # single integer which represents lock state + @ReadQueue = Synchronization::Lock.new # used to queue waiting readers + @WriteQueue = Synchronization::Lock.new # used to queue waiting writers + @HeldCount = LockLocalVar.new(0) # indicates # of R & W locks held by this thread + end + + # Execute a block operation within a read lock. + # + # @yield the task to be performed within the lock. + # + # @return [Object] the result of the block operation. + # + # @raise [ArgumentError] when no block is given. + # @raise [Concurrent::ResourceLimitError] if the maximum number of readers + # is exceeded. + def with_read_lock + raise ArgumentError.new('no block given') unless block_given? + acquire_read_lock + begin + yield + ensure + release_read_lock + end + end + + # Execute a block operation within a write lock. + # + # @yield the task to be performed within the lock. + # + # @return [Object] the result of the block operation. + # + # @raise [ArgumentError] when no block is given. + # @raise [Concurrent::ResourceLimitError] if the maximum number of readers + # is exceeded. + def with_write_lock + raise ArgumentError.new('no block given') unless block_given? + acquire_write_lock + begin + yield + ensure + release_write_lock + end + end + + # Acquire a read lock. If a write lock is held by another thread, will block + # until it is released. + # + # @return [Boolean] true if the lock is successfully acquired + # + # @raise [Concurrent::ResourceLimitError] if the maximum number of readers + # is exceeded. + def acquire_read_lock + if (held = @HeldCount.value) > 0 + # If we already have a lock, there's no need to wait + if held & READ_LOCK_MASK == 0 + # But we do need to update the counter, if we were holding a write + # lock but not a read lock + @Counter.update { |c| c + 1 } + end + @HeldCount.value = held + 1 + return true + end + + while true + c = @Counter.value + raise ResourceLimitError.new('Too many reader threads') if max_readers?(c) + + # If a writer is waiting OR running when we first queue up, we need to wait + if waiting_or_running_writer?(c) + # Before going to sleep, check again with the ReadQueue mutex held + @ReadQueue.synchronize do + @ReadQueue.ns_wait if waiting_or_running_writer? + end + # Note: the above 'synchronize' block could have used #wait_until, + # but that waits repeatedly in a loop, checking the wait condition + # each time it wakes up (to protect against spurious wakeups) + # But we are already in a loop, which is only broken when we successfully + # acquire the lock! So we don't care about spurious wakeups, and would + # rather not pay the extra overhead of using #wait_until + + # After a reader has waited once, they are allowed to "barge" ahead of waiting writers + # But if a writer is *running*, the reader still needs to wait (naturally) + while true + c = @Counter.value + if running_writer?(c) + @ReadQueue.synchronize do + @ReadQueue.ns_wait if running_writer? + end + elsif @Counter.compare_and_set(c, c+1) + @HeldCount.value = held + 1 + return true + end + end + elsif @Counter.compare_and_set(c, c+1) + @HeldCount.value = held + 1 + return true + end + end + end + + # Try to acquire a read lock and return true if we succeed. If it cannot be + # acquired immediately, return false. + # + # @return [Boolean] true if the lock is successfully acquired + def try_read_lock + if (held = @HeldCount.value) > 0 + if held & READ_LOCK_MASK == 0 + # If we hold a write lock, but not a read lock... + @Counter.update { |c| c + 1 } + end + @HeldCount.value = held + 1 + return true + else + c = @Counter.value + if !waiting_or_running_writer?(c) && @Counter.compare_and_set(c, c+1) + @HeldCount.value = held + 1 + return true + end + end + false + end + + # Release a previously acquired read lock. + # + # @return [Boolean] true if the lock is successfully released + def release_read_lock + held = @HeldCount.value = @HeldCount.value - 1 + rlocks_held = held & READ_LOCK_MASK + if rlocks_held == 0 + c = @Counter.update { |counter| counter - 1 } + # If one or more writers were waiting, and we were the last reader, wake a writer up + if waiting_or_running_writer?(c) && running_readers(c) == 0 + @WriteQueue.signal + end + elsif rlocks_held == READ_LOCK_MASK + raise IllegalOperationError, "Cannot release a read lock which is not held" + end + true + end + + # Acquire a write lock. Will block and wait for all active readers and writers. + # + # @return [Boolean] true if the lock is successfully acquired + # + # @raise [Concurrent::ResourceLimitError] if the maximum number of writers + # is exceeded. + def acquire_write_lock + if (held = @HeldCount.value) >= WRITE_LOCK_HELD + # if we already have a write (exclusive) lock, there's no need to wait + @HeldCount.value = held + WRITE_LOCK_HELD + return true + end + + while true + c = @Counter.value + raise ResourceLimitError.new('Too many writer threads') if max_writers?(c) + + # To go ahead and take the lock without waiting, there must be no writer + # 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 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 + # (they will wait instead) + # However, readers OR writers could decrement right here + @WriteQueue.synchronize do + # So we have to do another check inside the synchronized section + # If a writer OR another reader is running, then go to sleep + c = @Counter.value + @WriteQueue.ns_wait if running_writer?(c) || running_readers(c) != held + end + # Note: if you are thinking of replacing the above 'synchronize' block + # with #wait_until, read the comment in #acquire_read_lock first! + + # We just came out of a wait + # If we successfully turn the RUNNING_WRITER bit on with an atomic swap, + # then we are OK to stop waiting and go ahead + # Otherwise go back and wait again + c = @Counter.value + if !running_writer?(c) && + running_readers(c) == held && + @Counter.compare_and_set(c, c+RUNNING_WRITER-WAITING_WRITER) + @HeldCount.value = held + WRITE_LOCK_HELD + return true + end + end + end + end + end + + # Try to acquire a write lock and return true if we succeed. If it cannot be + # acquired immediately, return false. + # + # @return [Boolean] true if the lock is successfully acquired + def try_write_lock + if (held = @HeldCount.value) >= WRITE_LOCK_HELD + @HeldCount.value = held + WRITE_LOCK_HELD + return true + else + c = @Counter.value + if !waiting_or_running_writer?(c) && + running_readers(c) == held && + @Counter.compare_and_set(c, c+RUNNING_WRITER) + @HeldCount.value = held + WRITE_LOCK_HELD + return true + end + end + false + end + + # Release a previously acquired write lock. + # + # @return [Boolean] true if the lock is successfully released + def release_write_lock + held = @HeldCount.value = @HeldCount.value - WRITE_LOCK_HELD + wlocks_held = held & WRITE_LOCK_MASK + if wlocks_held == 0 + c = @Counter.update { |counter| counter - RUNNING_WRITER } + @ReadQueue.broadcast + @WriteQueue.signal if waiting_writers(c) > 0 + elsif wlocks_held == WRITE_LOCK_MASK + raise IllegalOperationError, "Cannot release a write lock which is not held" + end + true + end + + private + + # @!visibility private + def running_readers(c = @Counter.value) + c & MAX_READERS + end + + # @!visibility private + def running_readers?(c = @Counter.value) + (c & MAX_READERS) > 0 + end + + # @!visibility private + def running_writer?(c = @Counter.value) + c >= RUNNING_WRITER + end + + # @!visibility private + def waiting_writers(c = @Counter.value) + (c & MAX_WRITERS) >> READER_BITS + end + + # @!visibility private + def waiting_or_running_writer?(c = @Counter.value) + c >= WAITING_WRITER + end + + # @!visibility private + def max_readers?(c = @Counter.value) + (c & MAX_READERS) == MAX_READERS + end + + # @!visibility private + def max_writers?(c = @Counter.value) + (c & MAX_WRITERS) == MAX_WRITERS + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/semaphore.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/semaphore.rb new file mode 100644 index 0000000000000..f0799f0f41a63 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/semaphore.rb @@ -0,0 +1,163 @@ +require 'concurrent/atomic/mutex_semaphore' + +module Concurrent + + ################################################################### + + # @!macro semaphore_method_initialize + # + # Create a new `Semaphore` with the initial `count`. + # + # @param [Fixnum] count the initial count + # + # @raise [ArgumentError] if `count` is not an integer + + # @!macro semaphore_method_acquire + # + # Acquires the given number of permits from this semaphore, + # 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 zero + # + # @return [nil, BasicObject] Without a block, `nil` is returned. If a block + # is given, its return value is returned. + + # @!macro semaphore_method_available_permits + # + # Returns the current number of permits available in this semaphore. + # + # @return [Integer] + + # @!macro semaphore_method_drain_permits + # + # Acquires and returns all permits that are immediately available. + # + # @return [Integer] + + # @!macro semaphore_method_try_acquire + # + # Acquires the given number of permits from this semaphore, + # only if all are available at the time of invocation or within + # `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 + # + # @param [Fixnum] timeout the number of seconds to wait for the counter + # or `nil` to return immediately + # + # @raise [ArgumentError] if `permits` is not an integer or is less than zero + # + # @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 + # + # Releases the given number of permits, returning them to the semaphore. + # + # @param [Fixnum] permits Number of permits to return to the semaphore. + # + # @raise [ArgumentError] if `permits` is not a number or is less than zero + # + # @return [nil] + + ################################################################### + + # @!macro semaphore_public_api + # + # @!method initialize(count) + # @!macro semaphore_method_initialize + # + # @!method acquire(permits = 1) + # @!macro semaphore_method_acquire + # + # @!method available_permits + # @!macro semaphore_method_available_permits + # + # @!method drain_permits + # @!macro semaphore_method_drain_permits + # + # @!method try_acquire(permits = 1, timeout = nil) + # @!macro semaphore_method_try_acquire + # + # @!method release(permits = 1) + # @!macro semaphore_method_release + + ################################################################### + + # @!visibility private + # @!macro internal_implementation_note + SemaphoreImplementation = if Concurrent.on_jruby? + require 'concurrent/utility/native_extension_loader' + JavaSemaphore + else + MutexSemaphore + end + private_constant :SemaphoreImplementation + + # @!macro semaphore + # + # A counting semaphore. Conceptually, a semaphore maintains a set of + # permits. Each {#acquire} blocks if necessary until a permit is + # available, and then takes it. Each {#release} adds a permit, potentially + # 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 + # semaphore = Concurrent::Semaphore.new(2) + # + # t1 = Thread.new do + # semaphore.acquire + # puts "Thread 1 acquired semaphore" + # end + # + # t2 = Thread.new do + # semaphore.acquire + # puts "Thread 2 acquired semaphore" + # end + # + # t3 = Thread.new do + # semaphore.acquire + # puts "Thread 3 acquired semaphore" + # end + # + # t4 = Thread.new do + # sleep(2) + # puts "Thread 4 releasing semaphore" + # semaphore.release + # end + # + # [t1, t2, t3, t4].each(&:join) + # + # # prints: + # # Thread 3 acquired semaphore + # # Thread 2 acquired semaphore + # # 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 diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb new file mode 100644 index 0000000000000..3b7e12b5bb97c --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb @@ -0,0 +1,111 @@ +require 'concurrent/constants' +require_relative 'locals' + +module Concurrent + + # A `ThreadLocalVar` is a variable where the value is different for each thread. + # Each variable may have a default value, but when you modify the variable only + # the current thread will ever see that change. + # + # This is similar to Ruby's built-in thread-local variables (`Thread#thread_variable_get`), + # but with these major advantages: + # * `ThreadLocalVar` has its own identity, it doesn't need a Symbol. + # * Each Ruby's built-in thread-local variable leaks some memory forever (it's a Symbol held forever on the thread), + # so it's only OK to create a small amount of them. + # `ThreadLocalVar` has no such issue and it is fine to create many of them. + # * Ruby's built-in thread-local variables leak forever the value set on each thread (unless set to nil explicitly). + # `ThreadLocalVar` automatically removes the mapping for each thread once the `ThreadLocalVar` instance is GC'd. + # + # @!macro thread_safe_variable_comparison + # + # @example + # v = ThreadLocalVar.new(14) + # v.value #=> 14 + # v.value = 2 + # v.value #=> 2 + # + # @example + # v = ThreadLocalVar.new(14) + # + # t1 = Thread.new do + # v.value #=> 14 + # v.value = 1 + # v.value #=> 1 + # end + # + # t2 = Thread.new do + # v.value #=> 14 + # v.value = 2 + # v.value #=> 2 + # end + # + # v.value #=> 14 + class ThreadLocalVar + LOCALS = ThreadLocals.new + + # Creates a thread local variable. + # + # @param [Object] default the default value when otherwise unset + # @param [Proc] default_block Optional block that gets called to obtain the + # default value for each thread + def initialize(default = nil, &default_block) + if default && block_given? + raise ArgumentError, "Cannot use both value and block as default value" + end + + if block_given? + @default_block = default_block + @default = nil + else + @default_block = nil + @default = default + end + + @index = LOCALS.next_index(self) + end + + # Returns the value in the current thread's copy of this thread-local variable. + # + # @return [Object] the current value + def value + LOCALS.fetch(@index) { default } + end + + # Sets the current thread's copy of this thread-local variable to the specified value. + # + # @param [Object] value the value to set + # @return [Object] the new value + def value=(value) + LOCALS.set(@index, value) + end + + # Bind the given value to thread local storage during + # execution of the given block. + # + # @param [Object] value the value to bind + # @yield the operation to be performed with the bound variable + # @return [Object] the value + def bind(value) + if block_given? + old_value = self.value + self.value = value + begin + yield + ensure + self.value = old_value + end + end + end + + protected + + # @!visibility private + def default + if @default_block + self.value = @default_block.call + else + @default + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic_reference/atomic_direct_update.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic_reference/atomic_direct_update.rb new file mode 100644 index 0000000000000..5d2d7edd4f540 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic_reference/atomic_direct_update.rb @@ -0,0 +1,37 @@ +require 'concurrent/errors' + +module Concurrent + + # Define update methods that use direct paths + # + # @!visibility private + # @!macro internal_implementation_note + module AtomicDirectUpdate + def update + true until compare_and_set(old_value = get, new_value = yield(old_value)) + new_value + end + + def try_update + old_value = get + new_value = yield old_value + + return unless compare_and_set old_value, new_value + + new_value + end + + def try_update! + old_value = get + new_value = yield old_value + unless compare_and_set(old_value, new_value) + if $VERBOSE + raise ConcurrentUpdateError, "Update failed" + else + raise ConcurrentUpdateError, "Update failed", ConcurrentUpdateError::CONC_UP_ERR_BACKTRACE + end + end + new_value + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb new file mode 100644 index 0000000000000..e5e2a6377d59a --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb @@ -0,0 +1,67 @@ +require 'concurrent/atomic_reference/atomic_direct_update' +require 'concurrent/atomic_reference/numeric_cas_wrapper' +require 'concurrent/synchronization/safe_initialization' + +module Concurrent + + # @!visibility private + # @!macro internal_implementation_note + class MutexAtomicReference + extend Concurrent::Synchronization::SafeInitialization + include AtomicDirectUpdate + include AtomicNumericCompareAndSetWrapper + alias_method :compare_and_swap, :compare_and_set + + # @!macro atomic_reference_method_initialize + def initialize(value = nil) + super() + @Lock = ::Mutex.new + @value = value + end + + # @!macro atomic_reference_method_get + def get + synchronize { @value } + end + alias_method :value, :get + + # @!macro atomic_reference_method_set + def set(new_value) + synchronize { @value = new_value } + end + alias_method :value=, :set + + # @!macro atomic_reference_method_get_and_set + def get_and_set(new_value) + synchronize do + old_value = @value + @value = new_value + old_value + end + end + alias_method :swap, :get_and_set + + # @!macro atomic_reference_method_compare_and_set + def _compare_and_set(old_value, new_value) + synchronize do + if @value.equal? old_value + @value = new_value + true + else + false + end + end + end + + protected + + # @!visibility private + def synchronize + if @Lock.owned? + yield + else + @Lock.synchronize { yield } + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic_reference/numeric_cas_wrapper.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic_reference/numeric_cas_wrapper.rb new file mode 100644 index 0000000000000..709a3822318dc --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic_reference/numeric_cas_wrapper.rb @@ -0,0 +1,28 @@ +module Concurrent + + # Special "compare and set" handling of numeric values. + # + # @!visibility private + # @!macro internal_implementation_note + module AtomicNumericCompareAndSetWrapper + + # @!macro atomic_reference_method_compare_and_set + def compare_and_set(old_value, new_value) + if old_value.kind_of? Numeric + while true + old = get + + return false unless old.kind_of? Numeric + + return false unless old == old_value + + result = _compare_and_set(old, new_value) + return result if result + end + else + _compare_and_set(old_value, new_value) + end + end + + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomics.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomics.rb new file mode 100644 index 0000000000000..16cbe66101b1e --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomics.rb @@ -0,0 +1,10 @@ +require 'concurrent/atomic/atomic_reference' +require 'concurrent/atomic/atomic_boolean' +require 'concurrent/atomic/atomic_fixnum' +require 'concurrent/atomic/cyclic_barrier' +require 'concurrent/atomic/count_down_latch' +require 'concurrent/atomic/event' +require 'concurrent/atomic/read_write_lock' +require 'concurrent/atomic/reentrant_read_write_lock' +require 'concurrent/atomic/semaphore' +require 'concurrent/atomic/thread_local_var' diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb new file mode 100644 index 0000000000000..7c700bd78ac4c --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb @@ -0,0 +1,107 @@ +require 'concurrent/synchronization/lockable_object' + +module Concurrent + module Collection + + # A thread safe observer set implemented using copy-on-read approach: + # observers are added and removed from a thread safe collection; every time + # a notification is required the internal data structure is copied to + # prevent concurrency issues + # + # @api private + class CopyOnNotifyObserverSet < Synchronization::LockableObject + + def initialize + super() + synchronize { ns_initialize } + end + + # @!macro observable_add_observer + def add_observer(observer = nil, func = :update, &block) + if observer.nil? && block.nil? + raise ArgumentError, 'should pass observer as a first argument or block' + elsif observer && block + raise ArgumentError.new('cannot provide both an observer and a block') + end + + if block + observer = block + func = :call + end + + synchronize do + @observers[observer] = func + observer + end + end + + # @!macro observable_delete_observer + def delete_observer(observer) + synchronize do + @observers.delete(observer) + observer + end + end + + # @!macro observable_delete_observers + def delete_observers + synchronize do + @observers.clear + self + end + end + + # @!macro observable_count_observers + def count_observers + synchronize { @observers.count } + end + + # Notifies all registered observers with optional args + # @param [Object] args arguments to be passed to each observer + # @return [CopyOnWriteObserverSet] self + def notify_observers(*args, &block) + observers = duplicate_observers + notify_to(observers, *args, &block) + self + end + + # Notifies all registered observers with optional args and deletes them. + # + # @param [Object] args arguments to be passed to each observer + # @return [CopyOnWriteObserverSet] self + def notify_and_delete_observers(*args, &block) + observers = duplicate_and_clear_observers + notify_to(observers, *args, &block) + self + end + + protected + + def ns_initialize + @observers = {} + end + + private + + def duplicate_and_clear_observers + synchronize do + observers = @observers.dup + @observers.clear + observers + end + end + + def duplicate_observers + synchronize { @observers.dup } + end + + def notify_to(observers, *args) + raise ArgumentError.new('cannot give arguments and a block') if block_given? && !args.empty? + observers.each do |observer, function| + args = yield if block_given? + observer.send(function, *args) + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb new file mode 100644 index 0000000000000..bcb6750d41109 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb @@ -0,0 +1,111 @@ +require 'concurrent/synchronization/lockable_object' + +module Concurrent + module Collection + + # A thread safe observer set implemented using copy-on-write approach: + # every time an observer is added or removed the whole internal data structure is + # duplicated and replaced with a new one. + # + # @api private + class CopyOnWriteObserverSet < Synchronization::LockableObject + + def initialize + super() + synchronize { ns_initialize } + end + + # @!macro observable_add_observer + def add_observer(observer = nil, func = :update, &block) + if observer.nil? && block.nil? + raise ArgumentError, 'should pass observer as a first argument or block' + elsif observer && block + raise ArgumentError.new('cannot provide both an observer and a block') + end + + if block + observer = block + func = :call + end + + synchronize do + new_observers = @observers.dup + new_observers[observer] = func + @observers = new_observers + observer + end + end + + # @!macro observable_delete_observer + def delete_observer(observer) + synchronize do + new_observers = @observers.dup + new_observers.delete(observer) + @observers = new_observers + observer + end + end + + # @!macro observable_delete_observers + def delete_observers + self.observers = {} + self + end + + # @!macro observable_count_observers + def count_observers + observers.count + end + + # Notifies all registered observers with optional args + # @param [Object] args arguments to be passed to each observer + # @return [CopyOnWriteObserverSet] self + def notify_observers(*args, &block) + notify_to(observers, *args, &block) + self + end + + # Notifies all registered observers with optional args and deletes them. + # + # @param [Object] args arguments to be passed to each observer + # @return [CopyOnWriteObserverSet] self + def notify_and_delete_observers(*args, &block) + old = clear_observers_and_return_old + notify_to(old, *args, &block) + self + end + + protected + + def ns_initialize + @observers = {} + end + + private + + def notify_to(observers, *args) + raise ArgumentError.new('cannot give arguments and a block') if block_given? && !args.empty? + observers.each do |observer, function| + args = yield if block_given? + observer.send(function, *args) + end + end + + def observers + synchronize { @observers } + end + + def observers=(new_set) + synchronize { @observers = new_set } + end + + def clear_observers_and_return_old + synchronize do + old_observers = @observers + @observers = {} + old_observers + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/java_non_concurrent_priority_queue.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/java_non_concurrent_priority_queue.rb new file mode 100644 index 0000000000000..2be9e4373a32d --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/java_non_concurrent_priority_queue.rb @@ -0,0 +1,84 @@ +if Concurrent.on_jruby? + + module Concurrent + module Collection + + + # @!macro priority_queue + # + # @!visibility private + # @!macro internal_implementation_note + class JavaNonConcurrentPriorityQueue + + # @!macro priority_queue_method_initialize + def initialize(opts = {}) + order = opts.fetch(:order, :max) + if [:min, :low].include?(order) + @queue = java.util.PriorityQueue.new(11) # 11 is the default initial capacity + else + @queue = java.util.PriorityQueue.new(11, java.util.Collections.reverseOrder()) + end + end + + # @!macro priority_queue_method_clear + def clear + @queue.clear + true + end + + # @!macro priority_queue_method_delete + def delete(item) + found = false + while @queue.remove(item) do + found = true + end + found + end + + # @!macro priority_queue_method_empty + def empty? + @queue.size == 0 + end + + # @!macro priority_queue_method_include + def include?(item) + @queue.contains(item) + end + alias_method :has_priority?, :include? + + # @!macro priority_queue_method_length + def length + @queue.size + end + alias_method :size, :length + + # @!macro priority_queue_method_peek + def peek + @queue.peek + end + + # @!macro priority_queue_method_pop + def pop + @queue.poll + end + alias_method :deq, :pop + alias_method :shift, :pop + + # @!macro priority_queue_method_push + def push(item) + raise ArgumentError.new('cannot enqueue nil') if item.nil? + @queue.add(item) + end + alias_method :<<, :push + alias_method :enq, :push + + # @!macro priority_queue_method_from_list + def self.from_list(list, opts = {}) + queue = new(opts) + list.each{|item| queue << item } + queue + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb new file mode 100644 index 0000000000000..3704410ba0bd4 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb @@ -0,0 +1,160 @@ +require 'concurrent/synchronization/object' + +module Concurrent + + # @!macro warn.edge + class LockFreeStack < Synchronization::Object + + safe_initialization! + + class Node + # TODO (pitr-ch 20-Dec-2016): Could be unified with Stack class? + + # @return [Node] + attr_reader :next_node + + # @return [Object] + attr_reader :value + + # @!visibility private + # allow to nil-ify to free GC when the entry is no longer relevant, not synchronised + attr_writer :value + + def initialize(value, next_node) + @value = value + @next_node = next_node + end + + singleton_class.send :alias_method, :[], :new + end + + # The singleton for empty node + EMPTY = Node[nil, nil] + def EMPTY.next_node + self + end + + attr_atomic(:head) + private :head, :head=, :swap_head, :compare_and_set_head, :update_head + + # @!visibility private + def self.of1(value) + new Node[value, EMPTY] + end + + # @!visibility private + def self.of2(value1, value2) + new Node[value1, Node[value2, EMPTY]] + end + + # @param [Node] head + def initialize(head = EMPTY) + super() + self.head = head + end + + # @param [Node] head + # @return [true, false] + def empty?(head = head()) + head.equal? EMPTY + end + + # @param [Node] head + # @param [Object] value + # @return [true, false] + def compare_and_push(head, value) + compare_and_set_head head, Node[value, head] + end + + # @param [Object] value + # @return [self] + def push(value) + while true + current_head = head + return self if compare_and_set_head current_head, Node[value, current_head] + end + end + + # @return [Node] + def peek + head + end + + # @param [Node] head + # @return [true, false] + def compare_and_pop(head) + compare_and_set_head head, head.next_node + end + + # @return [Object] + def pop + while true + current_head = head + return current_head.value if compare_and_set_head current_head, current_head.next_node + end + end + + # @param [Node] head + # @return [true, false] + def compare_and_clear(head) + compare_and_set_head head, EMPTY + end + + include Enumerable + + # @param [Node] head + # @return [self] + def each(head = nil) + return to_enum(:each, head) unless block_given? + it = head || peek + until it.equal?(EMPTY) + yield it.value + it = it.next_node + end + self + end + + # @return [true, false] + def clear + while true + current_head = head + return false if current_head == EMPTY + return true if compare_and_set_head current_head, EMPTY + end + end + + # @param [Node] head + # @return [true, false] + def clear_if(head) + compare_and_set_head head, EMPTY + end + + # @param [Node] head + # @param [Node] new_head + # @return [true, false] + def replace_if(head, new_head) + compare_and_set_head head, new_head + end + + # @return [self] + # @yield over the cleared stack + # @yieldparam [Object] value + def clear_each(&block) + while true + current_head = head + return self if current_head == EMPTY + if compare_and_set_head current_head, EMPTY + each current_head, &block + return self + end + end + end + + # @return [String] Short string representation. + def to_s + format '%s %s>', super[0..-2], to_a.to_s + end + + alias_method :inspect, :to_s + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb new file mode 100644 index 0000000000000..e0cf9990c52e0 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb @@ -0,0 +1,66 @@ +require 'thread' +require 'concurrent/collection/map/non_concurrent_map_backend' + +module Concurrent + + # @!visibility private + module Collection + + # @!visibility private + class MriMapBackend < NonConcurrentMapBackend + + def initialize(options = nil, &default_proc) + super(options, &default_proc) + @write_lock = Mutex.new + end + + def []=(key, value) + @write_lock.synchronize { super } + end + + def compute_if_absent(key) + if NULL != (stored_value = @backend.fetch(key, NULL)) # fast non-blocking path for the most likely case + stored_value + else + @write_lock.synchronize { super } + end + end + + def compute_if_present(key) + @write_lock.synchronize { super } + end + + def compute(key) + @write_lock.synchronize { super } + end + + def merge_pair(key, value) + @write_lock.synchronize { super } + end + + def replace_pair(key, old_value, new_value) + @write_lock.synchronize { super } + end + + def replace_if_exists(key, new_value) + @write_lock.synchronize { super } + end + + def get_and_set(key, value) + @write_lock.synchronize { super } + end + + def delete(key) + @write_lock.synchronize { super } + end + + def delete_pair(key, value) + @write_lock.synchronize { super } + end + + def clear + @write_lock.synchronize { super } + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb new file mode 100644 index 0000000000000..ca5fd9b48e37b --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb @@ -0,0 +1,148 @@ +require 'concurrent/constants' + +module Concurrent + + # @!visibility private + module Collection + + # @!visibility private + class NonConcurrentMapBackend + + # WARNING: all public methods of the class must operate on the @backend + # directly without calling each other. This is important because of the + # SynchronizedMapBackend which uses a non-reentrant mutex for performance + # reasons. + def initialize(options = nil, &default_proc) + validate_options_hash!(options) if options.kind_of?(::Hash) + set_backend(default_proc) + @default_proc = default_proc + end + + def [](key) + @backend[key] + end + + def []=(key, value) + @backend[key] = value + end + + def compute_if_absent(key) + if NULL != (stored_value = @backend.fetch(key, NULL)) + stored_value + else + @backend[key] = yield + end + end + + def replace_pair(key, old_value, new_value) + if pair?(key, old_value) + @backend[key] = new_value + true + else + false + end + end + + def replace_if_exists(key, new_value) + if NULL != (stored_value = @backend.fetch(key, NULL)) + @backend[key] = new_value + stored_value + end + end + + def compute_if_present(key) + if NULL != (stored_value = @backend.fetch(key, NULL)) + store_computed_value(key, yield(stored_value)) + end + end + + def compute(key) + store_computed_value(key, yield(get_or_default(key, nil))) + end + + def merge_pair(key, value) + if NULL == (stored_value = @backend.fetch(key, NULL)) + @backend[key] = value + else + store_computed_value(key, yield(stored_value)) + end + end + + def get_and_set(key, value) + stored_value = get_or_default(key, nil) + @backend[key] = value + stored_value + end + + def key?(key) + @backend.key?(key) + end + + def delete(key) + @backend.delete(key) + end + + def delete_pair(key, value) + if pair?(key, value) + @backend.delete(key) + true + else + false + end + end + + def clear + @backend.clear + self + end + + def each_pair + dupped_backend.each_pair do |k, v| + yield k, v + end + self + end + + def size + @backend.size + end + + def get_or_default(key, default_value) + @backend.fetch(key, default_value) + end + + private + + def set_backend(default_proc) + if default_proc + @backend = ::Hash.new { |_h, key| default_proc.call(self, key) } + else + @backend = {} + end + end + + def initialize_copy(other) + super + set_backend(@default_proc) + self + end + + def dupped_backend + @backend.dup + end + + def pair?(key, expected_value) + NULL != (stored_value = @backend.fetch(key, NULL)) && expected_value.equal?(stored_value) + end + + def store_computed_value(key, new_value) + if new_value.nil? + @backend.delete(key) + nil + else + @backend[key] = new_value + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/map/synchronized_map_backend.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/map/synchronized_map_backend.rb new file mode 100644 index 0000000000000..efa161ed9eaa6 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/map/synchronized_map_backend.rb @@ -0,0 +1,85 @@ +require 'concurrent/collection/map/non_concurrent_map_backend' + +module Concurrent + + # @!visibility private + module Collection + + # @!visibility private + class SynchronizedMapBackend < NonConcurrentMapBackend + + def initialize(*args, &block) + super + + # WARNING: Mutex is a non-reentrant lock, so the synchronized methods are + # not allowed to call each other. + @mutex = Mutex.new + end + + def [](key) + @mutex.synchronize { super } + end + + def []=(key, value) + @mutex.synchronize { super } + end + + def compute_if_absent(key) + @mutex.synchronize { super } + end + + def compute_if_present(key) + @mutex.synchronize { super } + end + + def compute(key) + @mutex.synchronize { super } + end + + def merge_pair(key, value) + @mutex.synchronize { super } + end + + def replace_pair(key, old_value, new_value) + @mutex.synchronize { super } + end + + def replace_if_exists(key, new_value) + @mutex.synchronize { super } + end + + def get_and_set(key, value) + @mutex.synchronize { super } + end + + def key?(key) + @mutex.synchronize { super } + end + + def delete(key) + @mutex.synchronize { super } + end + + def delete_pair(key, value) + @mutex.synchronize { super } + end + + def clear + @mutex.synchronize { super } + end + + def size + @mutex.synchronize { super } + end + + def get_or_default(key, default_value) + @mutex.synchronize { super } + end + + private + def dupped_backend + @mutex.synchronize { super } + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/map/truffleruby_map_backend.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/map/truffleruby_map_backend.rb new file mode 100644 index 0000000000000..68a1b3884df10 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/map/truffleruby_map_backend.rb @@ -0,0 +1,14 @@ +module Concurrent + + # @!visibility private + module Collection + + # @!visibility private + class TruffleRubyMapBackend < TruffleRuby::ConcurrentMap + def initialize(options = nil) + options ||= {} + super(initial_capacity: options[:initial_capacity], load_factor: options[:load_factor]) + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/non_concurrent_priority_queue.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/non_concurrent_priority_queue.rb new file mode 100644 index 0000000000000..694cd7ac7cdec --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/non_concurrent_priority_queue.rb @@ -0,0 +1,143 @@ +require 'concurrent/utility/engine' +require 'concurrent/collection/java_non_concurrent_priority_queue' +require 'concurrent/collection/ruby_non_concurrent_priority_queue' + +module Concurrent + module Collection + + # @!visibility private + # @!macro internal_implementation_note + NonConcurrentPriorityQueueImplementation = case + when Concurrent.on_jruby? + JavaNonConcurrentPriorityQueue + else + RubyNonConcurrentPriorityQueue + end + private_constant :NonConcurrentPriorityQueueImplementation + + # @!macro priority_queue + # + # A queue collection in which the elements are sorted based on their + # comparison (spaceship) operator `<=>`. Items are added to the queue + # at a position relative to their priority. On removal the element + # with the "highest" priority is removed. By default the sort order is + # from highest to lowest, but a lowest-to-highest sort order can be + # set on construction. + # + # The API is based on the `Queue` class from the Ruby standard library. + # + # The pure Ruby implementation, `RubyNonConcurrentPriorityQueue` uses a heap algorithm + # stored in an array. The algorithm is based on the work of Robert Sedgewick + # and Kevin Wayne. + # + # The JRuby native implementation is a thin wrapper around the standard + # library `java.util.NonConcurrentPriorityQueue`. + # + # When running under JRuby the class `NonConcurrentPriorityQueue` extends `JavaNonConcurrentPriorityQueue`. + # When running under all other interpreters it extends `RubyNonConcurrentPriorityQueue`. + # + # @note This implementation is *not* thread safe. + # + # @see http://en.wikipedia.org/wiki/Priority_queue + # @see http://ruby-doc.org/stdlib-2.0.0/libdoc/thread/rdoc/Queue.html + # + # @see http://algs4.cs.princeton.edu/24pq/index.php#2.6 + # @see http://algs4.cs.princeton.edu/24pq/MaxPQ.java.html + # + # @see http://docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html + # + # @!visibility private + class NonConcurrentPriorityQueue < NonConcurrentPriorityQueueImplementation + + alias_method :has_priority?, :include? + + alias_method :size, :length + + alias_method :deq, :pop + alias_method :shift, :pop + + alias_method :<<, :push + alias_method :enq, :push + + # @!method initialize(opts = {}) + # @!macro priority_queue_method_initialize + # + # Create a new priority queue with no items. + # + # @param [Hash] opts the options for creating the queue + # @option opts [Symbol] :order (:max) dictates the order in which items are + # stored: from highest to lowest when `:max` or `:high`; from lowest to + # highest when `:min` or `:low` + + # @!method clear + # @!macro priority_queue_method_clear + # + # Removes all of the elements from this priority queue. + + # @!method delete(item) + # @!macro priority_queue_method_delete + # + # Deletes all items from `self` that are equal to `item`. + # + # @param [Object] item the item to be removed from the queue + # @return [Object] true if the item is found else false + + # @!method empty? + # @!macro priority_queue_method_empty + # + # Returns `true` if `self` contains no elements. + # + # @return [Boolean] true if there are no items in the queue else false + + # @!method include?(item) + # @!macro priority_queue_method_include + # + # Returns `true` if the given item is present in `self` (that is, if any + # element == `item`), otherwise returns false. + # + # @param [Object] item the item to search for + # + # @return [Boolean] true if the item is found else false + + # @!method length + # @!macro priority_queue_method_length + # + # The current length of the queue. + # + # @return [Fixnum] the number of items in the queue + + # @!method peek + # @!macro priority_queue_method_peek + # + # Retrieves, but does not remove, the head of this queue, or returns `nil` + # if this queue is empty. + # + # @return [Object] the head of the queue or `nil` when empty + + # @!method pop + # @!macro priority_queue_method_pop + # + # Retrieves and removes the head of this queue, or returns `nil` if this + # queue is empty. + # + # @return [Object] the head of the queue or `nil` when empty + + # @!method push(item) + # @!macro priority_queue_method_push + # + # Inserts the specified element into this priority queue. + # + # @param [Object] item the item to insert onto the queue + + # @!method self.from_list(list, opts = {}) + # @!macro priority_queue_method_from_list + # + # Create a new priority queue from the given list. + # + # @param [Enumerable] list the list to build the queue from + # @param [Hash] opts the options for creating the queue + # + # @return [NonConcurrentPriorityQueue] the newly created and populated queue + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb new file mode 100644 index 0000000000000..322b4ac2d95ae --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb @@ -0,0 +1,160 @@ +module Concurrent + module Collection + + # @!macro priority_queue + # + # @!visibility private + # @!macro internal_implementation_note + class RubyNonConcurrentPriorityQueue + + # @!macro priority_queue_method_initialize + def initialize(opts = {}) + order = opts.fetch(:order, :max) + @comparator = [:min, :low].include?(order) ? -1 : 1 + clear + end + + # @!macro priority_queue_method_clear + def clear + @queue = [nil] + @length = 0 + true + end + + # @!macro priority_queue_method_delete + def delete(item) + return false if empty? + original_length = @length + k = 1 + while k <= @length + if @queue[k] == item + swap(k, @length) + @length -= 1 + sink(k) || swim(k) + @queue.pop + else + k += 1 + end + end + @length != original_length + end + + # @!macro priority_queue_method_empty + def empty? + size == 0 + end + + # @!macro priority_queue_method_include + def include?(item) + @queue.include?(item) + end + alias_method :has_priority?, :include? + + # @!macro priority_queue_method_length + def length + @length + end + alias_method :size, :length + + # @!macro priority_queue_method_peek + def peek + empty? ? nil : @queue[1] + end + + # @!macro priority_queue_method_pop + def pop + return nil if empty? + max = @queue[1] + swap(1, @length) + @length -= 1 + sink(1) + @queue.pop + max + end + alias_method :deq, :pop + alias_method :shift, :pop + + # @!macro priority_queue_method_push + def push(item) + raise ArgumentError.new('cannot enqueue nil') if item.nil? + @length += 1 + @queue << item + swim(@length) + true + end + alias_method :<<, :push + alias_method :enq, :push + + # @!macro priority_queue_method_from_list + def self.from_list(list, opts = {}) + queue = new(opts) + list.each{|item| queue << item } + queue + end + + private + + # Exchange the values at the given indexes within the internal array. + # + # @param [Integer] x the first index to swap + # @param [Integer] y the second index to swap + # + # @!visibility private + def swap(x, y) + temp = @queue[x] + @queue[x] = @queue[y] + @queue[y] = temp + end + + # Are the items at the given indexes ordered based on the priority + # order specified at construction? + # + # @param [Integer] x the first index from which to retrieve a comparable value + # @param [Integer] y the second index from which to retrieve a comparable value + # + # @return [Boolean] true if the two elements are in the correct priority order + # else false + # + # @!visibility private + def ordered?(x, y) + (@queue[x] <=> @queue[y]) == @comparator + end + + # Percolate down to maintain heap invariant. + # + # @param [Integer] k the index at which to start the percolation + # + # @!visibility private + def sink(k) + success = false + + while (j = (2 * k)) <= @length do + j += 1 if j < @length && ! ordered?(j, j+1) + break if ordered?(k, j) + swap(k, j) + success = true + k = j + end + + success + end + + # Percolate up to maintain heap invariant. + # + # @param [Integer] k the index at which to start the percolation + # + # @!visibility private + def swim(k) + success = false + + while k > 1 && ! ordered?(k/2, k) do + swap(k, k/2) + k = k/2 + success = true + end + + success + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/deprecation.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/deprecation.rb new file mode 100644 index 0000000000000..35ae4b2c9df68 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/deprecation.rb @@ -0,0 +1,34 @@ +require 'concurrent/concern/logging' + +module Concurrent + module Concern + + # @!visibility private + # @!macro internal_implementation_note + module Deprecation + # TODO require additional parameter: a version. Display when it'll be removed based on that. Error if not removed. + include Concern::Logging + + def deprecated(message, strip = 2) + caller_line = caller(strip).first if strip > 0 + klass = if Module === self + self + else + self.class + end + message = if strip > 0 + format("[DEPRECATED] %s\ncalled on: %s", message, caller_line) + else + format('[DEPRECATED] %s', message) + end + log WARN, klass.to_s, message + end + + def deprecated_method(old_name, new_name) + deprecated "`#{old_name}` is deprecated and it'll removed in next release, use `#{new_name}` instead", 3 + end + + extend self + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/dereferenceable.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/dereferenceable.rb new file mode 100644 index 0000000000000..dc172ba74d93d --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/dereferenceable.rb @@ -0,0 +1,73 @@ +module Concurrent + module Concern + + # Object references in Ruby are mutable. This can lead to serious problems when + # the `#value` of a concurrent object is a mutable reference. Which is always the + # case unless the value is a `Fixnum`, `Symbol`, or similar "primitive" data type. + # Most classes in this library that expose a `#value` getter method do so using the + # `Dereferenceable` mixin module. + # + # @!macro copy_options + module Dereferenceable + # NOTE: This module is going away in 2.0. In the mean time we need it to + # play nicely with the synchronization layer. This means that the + # including class SHOULD be synchronized and it MUST implement a + # `#synchronize` method. Not doing so will lead to runtime errors. + + # Return the value this object represents after applying the options specified + # by the `#set_deref_options` method. + # + # @return [Object] the current value of the object + def value + synchronize { apply_deref_options(@value) } + end + alias_method :deref, :value + + protected + + # Set the internal value of this object + # + # @param [Object] value the new value + def value=(value) + synchronize{ @value = value } + end + + # @!macro dereferenceable_set_deref_options + # Set the options which define the operations #value performs before + # returning data to the caller (dereferencing). + # + # @note Most classes that include this module will call `#set_deref_options` + # from within the constructor, thus allowing these options to be set at + # object creation. + # + # @param [Hash] opts the options defining dereference behavior. + # @option opts [String] :dup_on_deref (false) call `#dup` before returning the data + # @option opts [String] :freeze_on_deref (false) call `#freeze` before returning the data + # @option opts [String] :copy_on_deref (nil) call the given `Proc` passing + # the internal value and returning the value returned from the proc + def set_deref_options(opts = {}) + synchronize{ ns_set_deref_options(opts) } + end + + # @!macro dereferenceable_set_deref_options + # @!visibility private + def ns_set_deref_options(opts) + @dup_on_deref = opts[:dup_on_deref] || opts[:dup] + @freeze_on_deref = opts[:freeze_on_deref] || opts[:freeze] + @copy_on_deref = opts[:copy_on_deref] || opts[:copy] + @do_nothing_on_deref = !(@dup_on_deref || @freeze_on_deref || @copy_on_deref) + nil + end + + # @!visibility private + def apply_deref_options(value) + return nil if value.nil? + return value if @do_nothing_on_deref + value = @copy_on_deref.call(value) if @copy_on_deref + value = value.dup if @dup_on_deref + value = value.freeze if @freeze_on_deref + value + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/logging.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/logging.rb new file mode 100644 index 0000000000000..568a539ebf0b8 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/logging.rb @@ -0,0 +1,116 @@ +require 'logger' +require 'concurrent/atomic/atomic_reference' + +module Concurrent + module Concern + + # Include where logging is needed + # + # @!visibility private + module Logging + include Logger::Severity + + # Logs through {Concurrent.global_logger}, it can be overridden by setting @logger + # @param [Integer] level one of Logger::Severity 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 + def log(level, progname, message = nil, &block) + logger = if defined?(@logger) && @logger + @logger + else + Concurrent.global_logger + end + logger.call level, progname, message, &block + rescue => error + $stderr.puts "`Concurrent.configuration.logger` failed to log #{[level, progname, message, block]}\n" + + "#{error.message} (#{error.class})\n#{error.backtrace.join "\n"}" + end + end + end +end + +module Concurrent + extend Concern::Logging + + # @return [Logger] Logger with provided level and output. + def self.create_simple_logger(level = Logger::FATAL, output = $stderr) + # 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 + + message = block ? block.call : message + formatted_message = case message + when String + message + when Exception + format "%s (%s)\n%s", + message.message, message.class, (message.backtrace || []).join("\n") + else + message.inspect + end + + output.print format "[%s] %5s -- %s: %s\n", + Time.now.strftime('%Y-%m-%d %H:%M:%S.%L'), + Logger::SEV_LABEL[severity], + progname, + formatted_message + true + end + end + + # Use logger created by #create_simple_logger to log concurrent-ruby messages. + def self.use_simple_logger(level = Logger::FATAL, output = $stderr) + Concurrent.global_logger = create_simple_logger level, output + end + + # @return [Logger] Logger with provided level and output. + # @deprecated + def self.create_stdlib_logger(level = Logger::FATAL, output = $stderr) + logger = Logger.new(output) + logger.level = level + logger.formatter = lambda do |severity, datetime, progname, msg| + formatted_message = case msg + when String + msg + when Exception + format "%s (%s)\n%s", + msg.message, msg.class, (msg.backtrace || []).join("\n") + else + msg.inspect + end + format "[%s] %5s -- %s: %s\n", + datetime.strftime('%Y-%m-%d %H:%M:%S.%L'), + severity, + progname, + formatted_message + end + + lambda do |loglevel, progname, message = nil, &block| + logger.add loglevel, message, progname, &block + end + end + + # Use logger created by #create_stdlib_logger to log concurrent-ruby messages. + # @deprecated + def self.use_stdlib_logger(level = Logger::FATAL, output = $stderr) + Concurrent.global_logger = create_stdlib_logger level, output + end + + # TODO (pitr-ch 27-Dec-2016): remove deadlocking stdlib_logger methods + + # Suppresses all output when used for logging. + NULL_LOGGER = lambda { |level, progname, message = nil, &block| } + + # @!visibility private + GLOBAL_LOGGER = AtomicReference.new(create_simple_logger(Logger::WARN)) + private_constant :GLOBAL_LOGGER + + def self.global_logger + GLOBAL_LOGGER.value + end + + def self.global_logger=(value) + GLOBAL_LOGGER.value = value + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/obligation.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/obligation.rb new file mode 100644 index 0000000000000..2c9ac12003502 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/obligation.rb @@ -0,0 +1,220 @@ +require 'thread' +require 'timeout' + +require 'concurrent/atomic/event' +require 'concurrent/concern/dereferenceable' + +module Concurrent + module Concern + + module Obligation + include Concern::Dereferenceable + # NOTE: The Dereferenceable module is going away in 2.0. In the mean time + # we need it to place nicely with the synchronization layer. This means + # that the including class SHOULD be synchronized and it MUST implement a + # `#synchronize` method. Not doing so will lead to runtime errors. + + # Has the obligation been fulfilled? + # + # @return [Boolean] + def fulfilled? + state == :fulfilled + end + alias_method :realized?, :fulfilled? + + # Has the obligation been rejected? + # + # @return [Boolean] + def rejected? + state == :rejected + end + + # Is obligation completion still pending? + # + # @return [Boolean] + def pending? + state == :pending + end + + # Is the obligation still unscheduled? + # + # @return [Boolean] + def unscheduled? + state == :unscheduled + end + + # Has the obligation completed processing? + # + # @return [Boolean] + def complete? + [:fulfilled, :rejected].include? state + end + + # Is the obligation still awaiting completion of processing? + # + # @return [Boolean] + def incomplete? + ! complete? + end + + # The current value of the obligation. Will be `nil` while the state is + # pending or the operation has been rejected. + # + # @param [Numeric] timeout the maximum time in seconds to wait. + # @return [Object] see Dereferenceable#deref + def value(timeout = nil) + wait timeout + deref + end + + # Wait until obligation is complete or the timeout has been reached. + # + # @param [Numeric] timeout the maximum time in seconds to wait. + # @return [Obligation] self + def wait(timeout = nil) + event.wait(timeout) if timeout != 0 && incomplete? + self + end + + # Wait until obligation is complete or the timeout is reached. Will re-raise + # any exceptions raised during processing (but will not raise an exception + # on timeout). + # + # @param [Numeric] timeout the maximum time in seconds to wait. + # @return [Obligation] self + # @raise [Exception] raises the reason when rejected + def wait!(timeout = nil) + wait(timeout).tap { raise self if rejected? } + end + alias_method :no_error!, :wait! + + # The current value of the obligation. Will be `nil` while the state is + # pending or the operation has been rejected. Will re-raise any exceptions + # raised during processing (but will not raise an exception on timeout). + # + # @param [Numeric] timeout the maximum time in seconds to wait. + # @return [Object] see Dereferenceable#deref + # @raise [Exception] raises the reason when rejected + def value!(timeout = nil) + wait(timeout) + if rejected? + raise self + else + deref + end + end + + # The current state of the obligation. + # + # @return [Symbol] the current state + def state + synchronize { @state } + end + + # If an exception was raised during processing this will return the + # exception object. Will return `nil` when the state is pending or if + # the obligation has been successfully fulfilled. + # + # @return [Exception] the exception raised during processing or `nil` + def reason + synchronize { @reason } + end + + # @example allows Obligation to be risen + # rejected_ivar = Ivar.new.fail + # raise rejected_ivar + def exception(*args) + raise 'obligation is not rejected' unless rejected? + reason.exception(*args) + end + + protected + + # @!visibility private + def get_arguments_from(opts = {}) + [*opts.fetch(:args, [])] + end + + # @!visibility private + def init_obligation + @event = Event.new + @value = @reason = nil + end + + # @!visibility private + def event + @event + end + + # @!visibility private + def set_state(success, value, reason) + if success + @value = value + @state = :fulfilled + else + @reason = reason + @state = :rejected + end + end + + # @!visibility private + def state=(value) + synchronize { ns_set_state(value) } + end + + # Atomic compare and set operation + # State is set to `next_state` only if `current state == expected_current`. + # + # @param [Symbol] next_state + # @param [Symbol] expected_current + # + # @return [Boolean] true is state is changed, false otherwise + # + # @!visibility private + def compare_and_set_state(next_state, *expected_current) + synchronize do + if expected_current.include? @state + @state = next_state + true + else + false + end + end + end + + # Executes the block within mutex if current state is included in expected_states + # + # @return block value if executed, false otherwise + # + # @!visibility private + def if_state(*expected_states) + synchronize do + raise ArgumentError.new('no block given') unless block_given? + + if expected_states.include? @state + yield + else + false + end + end + end + + protected + + # Am I in the current state? + # + # @param [Symbol] expected The state to check against + # @return [Boolean] true if in the expected state else false + # + # @!visibility private + def ns_check_state?(expected) + @state == expected + end + + # @!visibility private + def ns_set_state(value) + @state = value + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/observable.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/observable.rb new file mode 100644 index 0000000000000..b5132714bfbbc --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/observable.rb @@ -0,0 +1,110 @@ +require 'concurrent/collection/copy_on_notify_observer_set' +require 'concurrent/collection/copy_on_write_observer_set' + +module Concurrent + module Concern + + # The [observer pattern](http://en.wikipedia.org/wiki/Observer_pattern) is one + # of the most useful design patterns. + # + # The workflow is very simple: + # - an `observer` can register itself to a `subject` via a callback + # - many `observers` can be registered to the same `subject` + # - the `subject` notifies all registered observers when its status changes + # - an `observer` can deregister itself when is no more interested to receive + # event notifications + # + # In a single threaded environment the whole pattern is very easy: the + # `subject` can use a simple data structure to manage all its subscribed + # `observer`s and every `observer` can react directly to every event without + # caring about synchronization. + # + # In a multi threaded environment things are more complex. The `subject` must + # synchronize the access to its data structure and to do so currently we're + # using two specialized ObserverSet: {Concurrent::Concern::CopyOnWriteObserverSet} + # and {Concurrent::Concern::CopyOnNotifyObserverSet}. + # + # When implementing and `observer` there's a very important rule to remember: + # **there are no guarantees about the thread that will execute the callback** + # + # Let's take this example + # ``` + # class Observer + # def initialize + # @count = 0 + # end + # + # def update + # @count += 1 + # end + # end + # + # obs = Observer.new + # [obj1, obj2, obj3, obj4].each { |o| o.add_observer(obs) } + # # execute [obj1, obj2, obj3, obj4] + # ``` + # + # `obs` is wrong because the variable `@count` can be accessed by different + # threads at the same time, so it should be synchronized (using either a Mutex + # or an AtomicFixum) + module Observable + + # @!macro observable_add_observer + # + # Adds an observer to this set. If a block is passed, the observer will be + # created by this method and no other params should be passed. + # + # @param [Object] observer the observer to add + # @param [Symbol] func the function to call on the observer during notification. + # Default is :update + # @return [Object] the added observer + def add_observer(observer = nil, func = :update, &block) + observers.add_observer(observer, func, &block) + end + + # As `#add_observer` but can be used for chaining. + # + # @param [Object] observer the observer to add + # @param [Symbol] func the function to call on the observer during notification. + # @return [Observable] self + def with_observer(observer = nil, func = :update, &block) + add_observer(observer, func, &block) + self + end + + # @!macro observable_delete_observer + # + # Remove `observer` as an observer on this object so that it will no + # longer receive notifications. + # + # @param [Object] observer the observer to remove + # @return [Object] the deleted observer + def delete_observer(observer) + observers.delete_observer(observer) + end + + # @!macro observable_delete_observers + # + # Remove all observers associated with this object. + # + # @return [Observable] self + def delete_observers + observers.delete_observers + self + end + + # @!macro observable_count_observers + # + # Return the number of observers associated with this object. + # + # @return [Integer] the observers count + def count_observers + observers.count_observers + end + + protected + + attr_accessor :observers + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concurrent_ruby.jar b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concurrent_ruby.jar new file mode 100644 index 0000000000000..c0d7b155b675c Binary files /dev/null and b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concurrent_ruby.jar differ diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/configuration.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/configuration.rb new file mode 100644 index 0000000000000..5571d39b0cc47 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/configuration.rb @@ -0,0 +1,105 @@ +require 'thread' +require 'concurrent/delay' +require 'concurrent/errors' +require 'concurrent/concern/deprecation' +require 'concurrent/executor/immediate_executor' +require 'concurrent/executor/fixed_thread_pool' +require 'concurrent/executor/cached_thread_pool' +require 'concurrent/utility/processor_counter' + +module Concurrent + extend Concern::Deprecation + + autoload :Options, 'concurrent/options' + autoload :TimerSet, 'concurrent/executor/timer_set' + autoload :ThreadPoolExecutor, 'concurrent/executor/thread_pool_executor' + + # @!visibility private + GLOBAL_FAST_EXECUTOR = Delay.new { Concurrent.new_fast_executor } + private_constant :GLOBAL_FAST_EXECUTOR + + # @!visibility private + GLOBAL_IO_EXECUTOR = Delay.new { Concurrent.new_io_executor } + private_constant :GLOBAL_IO_EXECUTOR + + # @!visibility private + GLOBAL_TIMER_SET = Delay.new { TimerSet.new } + private_constant :GLOBAL_TIMER_SET + + # @!visibility private + GLOBAL_IMMEDIATE_EXECUTOR = ImmediateExecutor.new + private_constant :GLOBAL_IMMEDIATE_EXECUTOR + + # Disables AtExit handlers including pool auto-termination handlers. + # When disabled it will be the application programmer's responsibility + # to ensure that the handlers are shutdown properly prior to application + # exit by calling `AtExit.run` method. + # + # @note this option should be needed only because of `at_exit` ordering + # issues which may arise when running some of the testing frameworks. + # E.g. Minitest's test-suite runs itself in `at_exit` callback which + # executes after the pools are already terminated. Then auto termination + # needs to be disabled and called manually after test-suite ends. + # @note This method should *never* be called + # from within a gem. It should *only* be used from within the main + # application and even then it should be used only when necessary. + # @deprecated Has no effect since it is no longer needed, see https://github.com/ruby-concurrency/concurrent-ruby/pull/841. + # + def self.disable_at_exit_handlers! + deprecated "Method #disable_at_exit_handlers! has no effect since it is no longer needed, see https://github.com/ruby-concurrency/concurrent-ruby/pull/841." + end + + # Global thread pool optimized for short, fast *operations*. + # + # @return [ThreadPoolExecutor] the thread pool + def self.global_fast_executor + GLOBAL_FAST_EXECUTOR.value! + end + + # Global thread pool optimized for long, blocking (IO) *tasks*. + # + # @return [ThreadPoolExecutor] the thread pool + def self.global_io_executor + GLOBAL_IO_EXECUTOR.value! + end + + def self.global_immediate_executor + GLOBAL_IMMEDIATE_EXECUTOR + end + + # Global thread pool user for global *timers*. + # + # @return [Concurrent::TimerSet] the thread pool + def self.global_timer_set + GLOBAL_TIMER_SET.value! + end + + # General access point to global executors. + # @param [Symbol, Executor] executor_identifier symbols: + # - :fast - {Concurrent.global_fast_executor} + # - :io - {Concurrent.global_io_executor} + # - :immediate - {Concurrent.global_immediate_executor} + # @return [Executor] + def self.executor(executor_identifier) + Options.executor(executor_identifier) + end + + def self.new_fast_executor(opts = {}) + FixedThreadPool.new( + [2, Concurrent.processor_count].max, + auto_terminate: opts.fetch(:auto_terminate, true), + idletime: 60, # 1 minute + max_queue: 0, # unlimited + fallback_policy: :abort, # shouldn't matter -- 0 max queue + name: "fast" + ) + end + + def self.new_io_executor(opts = {}) + CachedThreadPool.new( + auto_terminate: opts.fetch(:auto_terminate, true), + fallback_policy: :abort, # shouldn't matter -- 0 max queue + name: "io" + ) + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/constants.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/constants.rb new file mode 100644 index 0000000000000..676c2afb9a692 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/constants.rb @@ -0,0 +1,8 @@ +module Concurrent + + # Various classes within allows for +nil+ values to be stored, + # so a special +NULL+ token is required to indicate the "nil-ness". + # @!visibility private + NULL = ::Object.new + +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/dataflow.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/dataflow.rb new file mode 100644 index 0000000000000..d55f19d850c34 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/dataflow.rb @@ -0,0 +1,81 @@ +require 'concurrent/future' +require 'concurrent/atomic/atomic_fixnum' + +module Concurrent + + # @!visibility private + class DependencyCounter # :nodoc: + + def initialize(count, &block) + @counter = AtomicFixnum.new(count) + @block = block + end + + def update(time, value, reason) + if @counter.decrement == 0 + @block.call + end + end + end + + # Dataflow allows you to create a task that will be scheduled when all of its data dependencies are available. + # {include:file:docs-source/dataflow.md} + # + # @param [Future] inputs zero or more `Future` operations that this dataflow depends upon + # + # @yield The operation to perform once all the dependencies are met + # @yieldparam [Future] inputs each of the `Future` inputs to the dataflow + # @yieldreturn [Object] the result of the block operation + # + # @return [Object] the result of all the operations + # + # @raise [ArgumentError] if no block is given + # @raise [ArgumentError] if any of the inputs are not `IVar`s + def dataflow(*inputs, &block) + dataflow_with(Concurrent.global_io_executor, *inputs, &block) + end + module_function :dataflow + + def dataflow_with(executor, *inputs, &block) + call_dataflow(:value, executor, *inputs, &block) + end + module_function :dataflow_with + + def dataflow!(*inputs, &block) + dataflow_with!(Concurrent.global_io_executor, *inputs, &block) + end + module_function :dataflow! + + def dataflow_with!(executor, *inputs, &block) + call_dataflow(:value!, executor, *inputs, &block) + end + module_function :dataflow_with! + + private + + def call_dataflow(method, executor, *inputs, &block) + raise ArgumentError.new('an executor must be provided') if executor.nil? + raise ArgumentError.new('no block given') unless block_given? + unless inputs.all? { |input| input.is_a? IVar } + raise ArgumentError.new("Not all dependencies are IVars.\nDependencies: #{ inputs.inspect }") + end + + result = Future.new(executor: executor) do + values = inputs.map { |input| input.send(method) } + block.call(*values) + end + + if inputs.empty? + result.execute + else + counter = DependencyCounter.new(inputs.size) { result.execute } + + inputs.each do |input| + input.add_observer counter + end + end + + result + end + module_function :call_dataflow +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/delay.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/delay.rb new file mode 100644 index 0000000000000..923773cbcaf0f --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/delay.rb @@ -0,0 +1,199 @@ +require 'thread' +require 'concurrent/concern/obligation' +require 'concurrent/executor/immediate_executor' +require 'concurrent/synchronization/lockable_object' + +module Concurrent + + # This file has circular require issues. It must be autoloaded here. + autoload :Options, 'concurrent/options' + + # Lazy evaluation of a block yielding an immutable result. Useful for + # expensive operations that may never be needed. It may be non-blocking, + # supports the `Concern::Obligation` interface, and accepts the injection of + # custom executor upon which to execute the block. Processing of + # block will be deferred until the first time `#value` is called. + # At that time the caller can choose to return immediately and let + # the block execute asynchronously, block indefinitely, or block + # with a timeout. + # + # 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 + # 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 + # blocked on `#value` will return. Subsequent calls to `#value` will immediately + # return the cached value. The operation will only be run once. This means that + # any side effects created by the operation will only happen once as well. + # + # `Delay` includes the `Concurrent::Concern::Dereferenceable` mixin to support thread + # safety of the reference returned by `#value`. + # + # @!macro copy_options + # + # @!macro delay_note_regarding_blocking + # @note The default behavior of `Delay` is to block indefinitely when + # calling either `value` or `wait`, executing the delayed operation on + # the current thread. This makes the `timeout` value completely + # irrelevant. To enable non-blocking behavior, use the `executor` + # constructor option. This will cause the delayed operation to be + # execute on the given executor, allowing the call to timeout. + # + # @see Concurrent::Concern::Dereferenceable + class Delay < Synchronization::LockableObject + include Concern::Obligation + + # NOTE: Because the global thread pools are lazy-loaded with these objects + # there is a performance hit every time we post a new task to one of these + # thread pools. Subsequently it is critical that `Delay` perform as fast + # as possible post-completion. This class has been highly optimized using + # the benchmark script `examples/lazy_and_delay.rb`. Do NOT attempt to + # DRY-up this class or perform other refactoring with running the + # benchmarks and ensuring that performance is not negatively impacted. + + # Create a new `Delay` in the `:pending` state. + # + # @!macro executor_and_deref_options + # + # @yield the delayed operation to perform + # + # @raise [ArgumentError] if no block is given + def initialize(opts = {}, &block) + raise ArgumentError.new('no block given') unless block_given? + super(&nil) + synchronize { ns_initialize(opts, &block) } + end + + # Return the value this object represents after applying the options + # specified by the `#set_deref_options` method. If the delayed operation + # raised an exception this method will return nil. The exception object + # can be accessed via the `#reason` method. + # + # @param [Numeric] timeout the maximum number of seconds to wait + # @return [Object] the current value of the object + # + # @!macro delay_note_regarding_blocking + def value(timeout = nil) + if @executor # TODO (pitr 12-Sep-2015): broken unsafe read? + super + else + # this function has been optimized for performance and + # should not be modified without running new benchmarks + synchronize do + execute = @evaluation_started = true unless @evaluation_started + if execute + begin + set_state(true, @task.call, nil) + rescue => ex + set_state(false, nil, ex) + end + elsif incomplete? + raise IllegalOperationError, 'Recursive call to #value during evaluation of the Delay' + end + end + if @do_nothing_on_deref + @value + else + apply_deref_options(@value) + end + end + end + + # Return the value this object represents after applying the options + # specified by the `#set_deref_options` method. If the delayed operation + # raised an exception, this method will raise that exception (even when) + # the operation has already been executed). + # + # @param [Numeric] timeout the maximum number of seconds to wait + # @return [Object] the current value of the object + # @raise [Exception] when `#rejected?` raises `#reason` + # + # @!macro delay_note_regarding_blocking + def value!(timeout = nil) + if @executor + super + else + result = value + raise @reason if @reason + result + end + end + + # Return the value this object represents after applying the options + # specified by the `#set_deref_options` method. + # + # @param [Integer] timeout (nil) the maximum number of seconds to wait for + # the value to be computed. When `nil` the caller will block indefinitely. + # + # @return [Object] self + # + # @!macro delay_note_regarding_blocking + def wait(timeout = nil) + if @executor + execute_task_once + super(timeout) + else + value + end + self + end + + # Reconfigures the block returning the value if still `#incomplete?` + # + # @yield the delayed operation to perform + # @return [true, false] if success + def reconfigure(&block) + synchronize do + raise ArgumentError.new('no block given') unless block_given? + unless @evaluation_started + @task = block + true + else + false + end + end + end + + protected + + def ns_initialize(opts, &block) + init_obligation + set_deref_options(opts) + @executor = opts[:executor] + + @task = block + @state = :pending + @evaluation_started = false + end + + private + + # @!visibility private + def execute_task_once # :nodoc: + # this function has been optimized for performance and + # should not be modified without running new benchmarks + execute = task = nil + synchronize do + execute = @evaluation_started = true unless @evaluation_started + task = @task + end + + if execute + executor = Options.executor_from_options(executor: @executor) + executor.post do + begin + result = task.call + success = true + rescue => ex + reason = ex + end + synchronize do + set_state(success, result, reason) + event.set + end + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/errors.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/errors.rb new file mode 100644 index 0000000000000..74f1fc3ddab9d --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/errors.rb @@ -0,0 +1,74 @@ +module Concurrent + + Error = Class.new(StandardError) + + # Raised when errors occur during configuration. + ConfigurationError = Class.new(Error) + + # Raised when an asynchronous operation is cancelled before execution. + CancelledOperationError = Class.new(Error) + + # Raised when a lifecycle method (such as `stop`) is called in an improper + # sequence or when the object is in an inappropriate state. + LifecycleError = Class.new(Error) + + # Raised when an attempt is made to violate an immutability guarantee. + ImmutabilityError = Class.new(Error) + + # Raised when an operation is attempted which is not legal given the + # receiver's current state + IllegalOperationError = Class.new(Error) + + # Raised when an object's methods are called when it has not been + # properly initialized. + InitializationError = Class.new(Error) + + # Raised when an object with a start/stop lifecycle has been started an + # excessive number of times. Often used in conjunction with a restart + # policy or strategy. + MaxRestartFrequencyError = Class.new(Error) + + # Raised when an attempt is made to modify an immutable object + # (such as an `IVar`) after its final state has been set. + class MultipleAssignmentError < Error + attr_reader :inspection_data + + def initialize(message = nil, inspection_data = nil) + @inspection_data = inspection_data + super message + end + + def inspect + format '%s %s>', super[0..-2], @inspection_data.inspect + end + end + + # Raised by an `Executor` when it is unable to process a given task, + # possibly because of a reject policy or other internal error. + RejectedExecutionError = Class.new(Error) + + # Raised when any finite resource, such as a lock counter, exceeds its + # maximum limit/threshold. + ResourceLimitError = Class.new(Error) + + # Raised when an operation times out. + TimeoutError = Class.new(Error) + + # Aggregates multiple exceptions. + class MultipleErrors < Error + attr_reader :errors + + def initialize(errors, message = "#{errors.size} errors") + @errors = errors + super [*message, + *errors.map { |e| [format('%s (%s)', e.message, e.class), *e.backtrace] }.flatten(1) + ].join("\n") + end + end + + # @!macro internal_implementation_note + class ConcurrentUpdateError < ThreadError + # frozen pre-allocated backtrace to speed ConcurrentUpdateError + CONC_UP_ERR_BACKTRACE = ['backtrace elided; set verbose to enable'].freeze + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/exchanger.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/exchanger.rb new file mode 100644 index 0000000000000..a5405d252283e --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/exchanger.rb @@ -0,0 +1,353 @@ +require 'concurrent/constants' +require 'concurrent/errors' +require 'concurrent/maybe' +require 'concurrent/atomic/atomic_reference' +require 'concurrent/atomic/count_down_latch' +require 'concurrent/utility/engine' +require 'concurrent/utility/monotonic_time' + +module Concurrent + + # @!macro exchanger + # + # A synchronization point at which threads can pair and swap elements within + # pairs. Each thread presents some object on entry to the exchange method, + # matches with a partner thread, and receives its partner's object on return. + # + # @!macro thread_safe_variable_comparison + # + # This implementation is very simple, using only a single slot for each + # exchanger (unlike more advanced implementations which use an "arena"). + # This approach will work perfectly fine when there are only a few threads + # accessing a single `Exchanger`. Beyond a handful of threads the performance + # will degrade rapidly due to contention on the single slot, but the algorithm + # will remain correct. + # + # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Exchanger.html java.util.concurrent.Exchanger + # @example + # + # exchanger = Concurrent::Exchanger.new + # + # threads = [ + # Thread.new { puts "first: " << exchanger.exchange('foo', 1) }, #=> "first: bar" + # Thread.new { puts "second: " << exchanger.exchange('bar', 1) } #=> "second: foo" + # ] + # threads.each {|t| t.join(2) } + + # @!visibility private + class AbstractExchanger < Synchronization::Object + + # @!visibility private + CANCEL = ::Object.new + private_constant :CANCEL + + def initialize + super + end + + # @!macro exchanger_method_do_exchange + # + # Waits for another thread to arrive at this exchange point (unless the + # current thread is interrupted), and then transfers the given object to + # it, receiving its object in return. The timeout value indicates the + # approximate number of seconds the method should block while waiting + # for the exchange. When the timeout value is `nil` the method will + # block indefinitely. + # + # @param [Object] value the value to exchange with another thread + # @param [Numeric, nil] timeout in seconds, `nil` blocks indefinitely + # + # @!macro exchanger_method_exchange + # + # In some edge cases when a `timeout` is given a return value of `nil` may be + # ambiguous. Specifically, if `nil` is a valid value in the exchange it will + # be impossible to tell whether `nil` is the actual return value or if it + # signifies timeout. When `nil` is a valid value in the exchange consider + # using {#exchange!} or {#try_exchange} instead. + # + # @return [Object] the value exchanged by the other thread or `nil` on timeout + def exchange(value, timeout = nil) + (value = do_exchange(value, timeout)) == CANCEL ? nil : value + end + + # @!macro exchanger_method_do_exchange + # @!macro exchanger_method_exchange_bang + # + # On timeout a {Concurrent::TimeoutError} exception will be raised. + # + # @return [Object] the value exchanged by the other thread + # @raise [Concurrent::TimeoutError] on timeout + def exchange!(value, timeout = nil) + if (value = do_exchange(value, timeout)) == CANCEL + raise Concurrent::TimeoutError + else + value + end + end + + # @!macro exchanger_method_do_exchange + # @!macro exchanger_method_try_exchange + # + # The return value will be a {Concurrent::Maybe} set to `Just` on success or + # `Nothing` on timeout. + # + # @return [Concurrent::Maybe] on success a `Just` maybe will be returned with + # the item exchanged by the other thread as `#value`; on timeout a + # `Nothing` maybe will be returned with {Concurrent::TimeoutError} as `#reason` + # + # @example + # + # exchanger = Concurrent::Exchanger.new + # + # result = exchanger.exchange(:foo, 0.5) + # + # if result.just? + # puts result.value #=> :bar + # else + # puts 'timeout' + # end + def try_exchange(value, timeout = nil) + if (value = do_exchange(value, timeout)) == CANCEL + Concurrent::Maybe.nothing(Concurrent::TimeoutError) + else + Concurrent::Maybe.just(value) + end + end + + private + + # @!macro exchanger_method_do_exchange + # + # @return [Object, CANCEL] the value exchanged by the other thread; {CANCEL} on timeout + def do_exchange(value, timeout) + raise NotImplementedError + end + end + + # @!macro internal_implementation_note + # @!visibility private + class RubyExchanger < AbstractExchanger + # A simplified version of java.util.concurrent.Exchanger written by + # Doug Lea, Bill Scherer, and Michael Scott with assistance from members + # of JCP JSR-166 Expert Group and released to the public domain. It does + # not include the arena or the multi-processor spin loops. + # http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/concurrent/Exchanger.java + + safe_initialization! + + class Node < Concurrent::Synchronization::Object + attr_atomic :value + safe_initialization! + + def initialize(item) + super() + @Item = item + @Latch = Concurrent::CountDownLatch.new + self.value = nil + end + + def latch + @Latch + end + + def item + @Item + end + end + private_constant :Node + + def initialize + super + end + + private + + attr_atomic(:slot) + + # @!macro exchanger_method_do_exchange + # + # @return [Object, CANCEL] the value exchanged by the other thread; {CANCEL} on timeout + def do_exchange(value, timeout) + + # ALGORITHM + # + # From the original Java version: + # + # > The basic idea is to maintain a "slot", which is a reference to + # > a Node containing both an Item to offer and a "hole" waiting to + # > get filled in. If an incoming "occupying" thread sees that the + # > slot is null, it CAS'es (compareAndSets) a Node there and waits + # > for another to invoke exchange. That second "fulfilling" thread + # > sees that the slot is non-null, and so CASes it back to null, + # > also exchanging items by CASing the hole, plus waking up the + # > occupying thread if it is blocked. In each case CAS'es may + # > fail because a slot at first appears non-null but is null upon + # > CAS, or vice-versa. So threads may need to retry these + # > actions. + # + # This version: + # + # An exchange occurs between an "occupier" thread and a "fulfiller" thread. + # The "slot" is used to setup this interaction. The first thread in the + # exchange puts itself into the slot (occupies) and waits for a fulfiller. + # The second thread removes the occupier from the slot and attempts to + # perform the exchange. Removing the occupier also frees the slot for + # another occupier/fulfiller pair. + # + # Because the occupier and the fulfiller are operating independently and + # because there may be contention with other threads, any failed operation + # indicates contention. Both the occupier and the fulfiller operate within + # spin loops. Any failed actions along the happy path will cause the thread + # to repeat the loop and try again. + # + # When a timeout value is given the thread must be cognizant of time spent + # in the spin loop. The remaining time is checked every loop. When the time + # runs out the thread will exit. + # + # A "node" is the data structure used to perform the exchange. Only the + # occupier's node is necessary. It's the node used for the exchange. + # Each node has an "item," a "hole" (self), and a "latch." The item is the + # node's initial value. It never changes. It's what the fulfiller returns on + # success. The occupier's hole is where the fulfiller put its item. It's the + # item that the occupier returns on success. The latch is used for synchronization. + # Because a thread may act as either an occupier or fulfiller (or possibly + # both in periods of high contention) every thread creates a node when + # the exchange method is first called. + # + # The following steps occur within the spin loop. If any actions fail + # the thread will loop and try again, so long as there is time remaining. + # If time runs out the thread will return CANCEL. + # + # Check the slot for an occupier: + # + # * If the slot is empty try to occupy + # * If the slot is full try to fulfill + # + # Attempt to occupy: + # + # * Attempt to CAS myself into the slot + # * Go to sleep and wait to be woken by a fulfiller + # * If the sleep is successful then the fulfiller completed its happy path + # - Return the value from my hole (the value given by the fulfiller) + # * When the sleep fails (time ran out) attempt to cancel the operation + # - Attempt to CAS myself out of the hole + # - If successful there is no contention + # - Return CANCEL + # - On failure, I am competing with a fulfiller + # - Attempt to CAS my hole to CANCEL + # - On success + # - Let the fulfiller deal with my cancel + # - Return CANCEL + # - On failure the fulfiller has completed its happy path + # - Return th value from my hole (the fulfiller's value) + # + # Attempt to fulfill: + # + # * Attempt to CAS the occupier out of the slot + # - On failure loop again + # * Attempt to CAS my item into the occupier's hole + # - On failure the occupier is trying to cancel + # - Loop again + # - On success we are on the happy path + # - Wake the sleeping occupier + # - Return the occupier's item + + value = NULL if value.nil? # The sentinel allows nil to be a valid value + me = Node.new(value) # create my node in case I need to occupy + end_at = Concurrent.monotonic_time + timeout.to_f # The time to give up + + result = loop do + other = slot + if other && compare_and_set_slot(other, nil) + # try to fulfill + if other.compare_and_set_value(nil, value) + # happy path + other.latch.count_down + break other.item + end + elsif other.nil? && compare_and_set_slot(nil, me) + # try to occupy + timeout = end_at - Concurrent.monotonic_time if timeout + if me.latch.wait(timeout) + # happy path + break me.value + else + # attempt to remove myself from the slot + if compare_and_set_slot(me, nil) + break CANCEL + elsif !me.compare_and_set_value(nil, CANCEL) + # I've failed to block the fulfiller + break me.value + end + end + end + break CANCEL if timeout && Concurrent.monotonic_time >= end_at + end + + result == NULL ? nil : result + end + end + + if Concurrent.on_jruby? + require 'concurrent/utility/native_extension_loader' + + # @!macro internal_implementation_note + # @!visibility private + class JavaExchanger < AbstractExchanger + + def initialize + @exchanger = java.util.concurrent.Exchanger.new + end + + private + + # @!macro exchanger_method_do_exchange + # + # @return [Object, CANCEL] the value exchanged by the other thread; {CANCEL} on timeout + def do_exchange(value, timeout) + result = nil + if timeout.nil? + Synchronization::JRuby.sleep_interruptibly do + result = @exchanger.exchange(value) + end + else + Synchronization::JRuby.sleep_interruptibly do + result = @exchanger.exchange(value, 1000 * timeout, java.util.concurrent.TimeUnit::MILLISECONDS) + end + end + result + rescue java.util.concurrent.TimeoutException + CANCEL + end + end + end + + # @!visibility private + # @!macro internal_implementation_note + ExchangerImplementation = case + when Concurrent.on_jruby? + JavaExchanger + else + RubyExchanger + end + private_constant :ExchangerImplementation + + # @!macro exchanger + class Exchanger < ExchangerImplementation + + # @!method initialize + # Creates exchanger instance + + # @!method exchange(value, timeout = nil) + # @!macro exchanger_method_do_exchange + # @!macro exchanger_method_exchange + + # @!method exchange!(value, timeout = nil) + # @!macro exchanger_method_do_exchange + # @!macro exchanger_method_exchange_bang + + # @!method try_exchange(value, timeout = nil) + # @!macro exchanger_method_do_exchange + # @!macro exchanger_method_try_exchange + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb new file mode 100644 index 0000000000000..ac429531bf7bf --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb @@ -0,0 +1,131 @@ +require 'concurrent/errors' +require 'concurrent/concern/deprecation' +require 'concurrent/executor/executor_service' +require 'concurrent/synchronization/lockable_object' + +module Concurrent + + # @!macro abstract_executor_service_public_api + # @!visibility private + class AbstractExecutorService < Synchronization::LockableObject + include ExecutorService + include Concern::Deprecation + + # The set of possible fallback policies that may be set at thread pool creation. + FALLBACK_POLICIES = [:abort, :discard, :caller_runs].freeze + + # @!macro executor_service_attr_reader_fallback_policy + attr_reader :fallback_policy + + attr_reader :name + + # Create a new thread pool. + def initialize(opts = {}, &block) + super(&nil) + synchronize do + @auto_terminate = opts.fetch(:auto_terminate, true) + @name = opts.fetch(:name) if opts.key?(:name) + ns_initialize(opts, &block) + end + end + + def to_s + name ? "#{super[0..-2]} name: #{name}>" : super + end + + # @!macro executor_service_method_shutdown + def shutdown + raise NotImplementedError + end + + # @!macro executor_service_method_kill + def kill + raise NotImplementedError + end + + # @!macro executor_service_method_wait_for_termination + def wait_for_termination(timeout = nil) + raise NotImplementedError + end + + # @!macro executor_service_method_running_question + def running? + synchronize { ns_running? } + end + + # @!macro executor_service_method_shuttingdown_question + def shuttingdown? + synchronize { ns_shuttingdown? } + end + + # @!macro executor_service_method_shutdown_question + def shutdown? + synchronize { ns_shutdown? } + end + + # @!macro executor_service_method_auto_terminate_question + def auto_terminate? + synchronize { @auto_terminate } + end + + # @!macro executor_service_method_auto_terminate_setter + def auto_terminate=(value) + deprecated "Method #auto_terminate= has no effect. Set :auto_terminate option when executor is initialized." + end + + private + + # 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 fallback_action(*args) + case fallback_policy + when :abort + lambda { raise RejectedExecutionError } + when :discard + lambda { false } + when :caller_runs + lambda { + begin + yield(*args) + rescue => ex + # let it fail + log DEBUG, ex + end + true + } + else + lambda { fail "Unknown fallback policy #{fallback_policy}" } + end + end + + def ns_execute(*args, &task) + raise NotImplementedError + end + + # @!macro executor_service_method_ns_shutdown_execution + # + # Callback method called when an orderly shutdown has completed. + # The default behavior is to signal all waiting threads. + def ns_shutdown_execution + # do nothing + end + + # @!macro executor_service_method_ns_kill_execution + # + # Callback method called when the executor has been killed. + # The default behavior is to do nothing. + def ns_kill_execution + # do nothing + end + + def ns_auto_terminate? + @auto_terminate + end + + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/cached_thread_pool.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/cached_thread_pool.rb new file mode 100644 index 0000000000000..de50ed1791c6a --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/cached_thread_pool.rb @@ -0,0 +1,62 @@ +require 'concurrent/utility/engine' +require 'concurrent/executor/thread_pool_executor' + +module Concurrent + + # A thread pool that dynamically grows and shrinks to fit the current workload. + # New threads are created as needed, existing threads are reused, and threads + # that remain idle for too long are killed and removed from the pool. These + # pools are particularly suited to applications that perform a high volume of + # short-lived tasks. + # + # On creation a `CachedThreadPool` has zero running threads. New threads are + # created on the pool as new operations are `#post`. The size of the pool + # will grow until `#max_length` threads are in the pool or until the number + # of threads exceeds the number of running and pending operations. When a new + # operation is post to the pool the first available idle thread will be tasked + # with the new operation. + # + # Should a thread crash for any reason the thread will immediately be removed + # from the pool. Similarly, threads which remain idle for an extended period + # of time will be killed and reclaimed. Thus these thread pools are very + # efficient at reclaiming unused resources. + # + # The API and behavior of this class are based on Java's `CachedThreadPool` + # + # @!macro thread_pool_options + class CachedThreadPool < ThreadPoolExecutor + + # @!macro cached_thread_pool_method_initialize + # + # Create a new thread pool. + # + # @param [Hash] opts the options defining pool behavior. + # @option opts [Symbol] :fallback_policy (`:abort`) the fallback policy + # + # @raise [ArgumentError] if `fallback_policy` is not a known policy + # + # @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executors.html#newCachedThreadPool-- + def initialize(opts = {}) + defaults = { idletime: DEFAULT_THREAD_IDLETIMEOUT } + overrides = { min_threads: 0, + max_threads: DEFAULT_MAX_POOL_SIZE, + max_queue: DEFAULT_MAX_QUEUE_SIZE } + super(defaults.merge(opts).merge(overrides)) + end + + private + + # @!macro cached_thread_pool_method_initialize + # @!visibility private + def ns_initialize(opts) + super(opts) + if Concurrent.on_jruby? + @max_queue = 0 + @executor = java.util.concurrent.Executors.newCachedThreadPool( + DaemonThreadFactory.new(ns_auto_terminate?)) + @executor.setRejectedExecutionHandler(FALLBACK_POLICY_CLASSES[@fallback_policy].new) + @executor.setKeepAliveTime(opts.fetch(:idletime, DEFAULT_THREAD_IDLETIMEOUT), java.util.concurrent.TimeUnit::SECONDS) + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/executor_service.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/executor_service.rb new file mode 100644 index 0000000000000..7e344919e0e6a --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/executor_service.rb @@ -0,0 +1,185 @@ +require 'concurrent/concern/logging' + +module Concurrent + + ################################################################### + + # @!macro executor_service_method_post + # + # Submit a task to the executor for asynchronous processing. + # + # @param [Array] args zero or more arguments to be passed to the task + # + # @yield the asynchronous task to perform + # + # @return [Boolean] `true` if the task is queued, `false` if the executor + # is not running + # + # @raise [ArgumentError] if no task is given + + # @!macro executor_service_method_left_shift + # + # Submit a task to the executor for asynchronous processing. + # + # @param [Proc] task the asynchronous task to perform + # + # @return [self] returns itself + + # @!macro executor_service_method_can_overflow_question + # + # Does the task queue have a maximum size? + # + # @return [Boolean] True if the task queue has a maximum size else false. + + # @!macro executor_service_method_serialized_question + # + # Does this executor guarantee serialization of its operations? + # + # @return [Boolean] True if the executor guarantees that all operations + # will be post in the order they are received and no two operations may + # occur simultaneously. Else false. + + ################################################################### + + # @!macro executor_service_public_api + # + # @!method post(*args, &task) + # @!macro executor_service_method_post + # + # @!method <<(task) + # @!macro executor_service_method_left_shift + # + # @!method can_overflow? + # @!macro executor_service_method_can_overflow_question + # + # @!method serialized? + # @!macro executor_service_method_serialized_question + + ################################################################### + + # @!macro executor_service_attr_reader_fallback_policy + # @return [Symbol] The fallback policy in effect. Either `:abort`, `:discard`, or `:caller_runs`. + + # @!macro executor_service_method_shutdown + # + # Begin an orderly shutdown. Tasks already in the queue will be executed, + # but no new tasks will be accepted. Has no additional effect if the + # thread pool is not running. + + # @!macro executor_service_method_kill + # + # Begin an immediate shutdown. In-progress tasks will be allowed to + # complete but enqueued tasks will be dismissed and no new tasks + # will be accepted. Has no additional effect if the thread pool is + # not running. + + # @!macro executor_service_method_wait_for_termination + # + # Block until executor shutdown is complete or until `timeout` seconds have + # passed. + # + # @note Does not initiate shutdown or termination. Either `shutdown` or `kill` + # must be called before this method (or on another thread). + # + # @param [Integer] timeout the maximum number of seconds to wait for shutdown to complete + # + # @return [Boolean] `true` if shutdown complete or false on `timeout` + + # @!macro executor_service_method_running_question + # + # Is the executor running? + # + # @return [Boolean] `true` when running, `false` when shutting down or shutdown + + # @!macro executor_service_method_shuttingdown_question + # + # Is the executor shuttingdown? + # + # @return [Boolean] `true` when not running and not shutdown, else `false` + + # @!macro executor_service_method_shutdown_question + # + # Is the executor shutdown? + # + # @return [Boolean] `true` when shutdown, `false` when shutting down or running + + # @!macro executor_service_method_auto_terminate_question + # + # Is the executor auto-terminate when the application exits? + # + # @return [Boolean] `true` when auto-termination is enabled else `false`. + + # @!macro executor_service_method_auto_terminate_setter + # + # + # Set the auto-terminate behavior for this executor. + # @deprecated Has no effect + # @param [Boolean] value The new auto-terminate value to set for this executor. + # @return [Boolean] `true` when auto-termination is enabled else `false`. + + ################################################################### + + # @!macro abstract_executor_service_public_api + # + # @!macro executor_service_public_api + # + # @!attribute [r] fallback_policy + # @!macro executor_service_attr_reader_fallback_policy + # + # @!method shutdown + # @!macro executor_service_method_shutdown + # + # @!method kill + # @!macro executor_service_method_kill + # + # @!method wait_for_termination(timeout = nil) + # @!macro executor_service_method_wait_for_termination + # + # @!method running? + # @!macro executor_service_method_running_question + # + # @!method shuttingdown? + # @!macro executor_service_method_shuttingdown_question + # + # @!method shutdown? + # @!macro executor_service_method_shutdown_question + # + # @!method auto_terminate? + # @!macro executor_service_method_auto_terminate_question + # + # @!method auto_terminate=(value) + # @!macro executor_service_method_auto_terminate_setter + + ################################################################### + + # @!macro executor_service_public_api + # @!visibility private + module ExecutorService + include Concern::Logging + + # @!macro executor_service_method_post + def post(*args, &task) + raise NotImplementedError + end + + # @!macro executor_service_method_left_shift + def <<(task) + post(&task) + self + end + + # @!macro executor_service_method_can_overflow_question + # + # @note Always returns `false` + def can_overflow? + false + end + + # @!macro executor_service_method_serialized_question + # + # @note Always returns `false` + def serialized? + false + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb new file mode 100644 index 0000000000000..993c3f1e36670 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb @@ -0,0 +1,224 @@ +require 'concurrent/utility/engine' +require 'concurrent/executor/thread_pool_executor' + +module Concurrent + + # @!macro thread_pool_executor_constant_default_max_pool_size + # Default maximum number of threads that will be created in the pool. + + # @!macro thread_pool_executor_constant_default_min_pool_size + # Default minimum number of threads that will be retained in the pool. + + # @!macro thread_pool_executor_constant_default_max_queue_size + # Default maximum number of tasks that may be added to the task queue. + + # @!macro thread_pool_executor_constant_default_thread_timeout + # Default maximum number of seconds a thread in the pool may remain idle + # before being reclaimed. + + # @!macro thread_pool_executor_constant_default_synchronous + # Default value of the :synchronous option. + + # @!macro thread_pool_executor_attr_reader_max_length + # The maximum number of threads that may be created in the pool. + # @return [Integer] The maximum number of threads that may be created in the pool. + + # @!macro thread_pool_executor_attr_reader_min_length + # The minimum number of threads that may be retained in the pool. + # @return [Integer] The minimum number of threads that may be retained in the pool. + + # @!macro thread_pool_executor_attr_reader_largest_length + # The largest number of threads that have been created in the pool since construction. + # @return [Integer] The largest number of threads that have been created in the pool since construction. + + # @!macro thread_pool_executor_attr_reader_scheduled_task_count + # The number of tasks that have been scheduled for execution on the pool since construction. + # @return [Integer] The number of tasks that have been scheduled for execution on the pool since construction. + + # @!macro thread_pool_executor_attr_reader_completed_task_count + # The number of tasks that have been completed by the pool since construction. + # @return [Integer] The number of tasks that have been completed by the pool since construction. + + # @!macro thread_pool_executor_method_active_count + # The number of threads that are actively executing tasks. + # @return [Integer] The number of threads that are actively executing tasks. + + # @!macro thread_pool_executor_attr_reader_idletime + # The number of seconds that a thread may be idle before being reclaimed. + # @return [Integer] The number of seconds that a thread may be idle before being reclaimed. + + # @!macro thread_pool_executor_attr_reader_synchronous + # Whether or not a value of 0 for :max_queue option means the queue must perform direct hand-off or rather unbounded queue. + # @return [true, false] + + # @!macro thread_pool_executor_attr_reader_max_queue + # The maximum number of tasks that may be waiting in the work queue at any one time. + # When the queue size reaches `max_queue` subsequent tasks will be rejected in + # accordance with the configured `fallback_policy`. + # + # @return [Integer] The maximum number of tasks that may be waiting in the work queue at any one time. + # When the queue size reaches `max_queue` subsequent tasks will be rejected in + # accordance with the configured `fallback_policy`. + + # @!macro thread_pool_executor_attr_reader_length + # The number of threads currently in the pool. + # @return [Integer] The number of threads currently in the pool. + + # @!macro thread_pool_executor_attr_reader_queue_length + # The number of tasks in the queue awaiting execution. + # @return [Integer] The number of tasks in the queue awaiting execution. + + # @!macro thread_pool_executor_attr_reader_remaining_capacity + # 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. + # + # @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 + # + # @!macro abstract_executor_service_public_api + # + # @!attribute [r] max_length + # @!macro thread_pool_executor_attr_reader_max_length + # + # @!attribute [r] min_length + # @!macro thread_pool_executor_attr_reader_min_length + # + # @!attribute [r] largest_length + # @!macro thread_pool_executor_attr_reader_largest_length + # + # @!attribute [r] scheduled_task_count + # @!macro thread_pool_executor_attr_reader_scheduled_task_count + # + # @!attribute [r] completed_task_count + # @!macro thread_pool_executor_attr_reader_completed_task_count + # + # @!attribute [r] idletime + # @!macro thread_pool_executor_attr_reader_idletime + # + # @!attribute [r] max_queue + # @!macro thread_pool_executor_attr_reader_max_queue + # + # @!attribute [r] length + # @!macro thread_pool_executor_attr_reader_length + # + # @!attribute [r] queue_length + # @!macro thread_pool_executor_attr_reader_queue_length + # + # @!attribute [r] remaining_capacity + # @!macro thread_pool_executor_attr_reader_remaining_capacity + # + # @!method can_overflow? + # @!macro executor_service_method_can_overflow_question + # + # @!method prune_pool + # @!macro thread_pool_executor_method_prune_pool + + + + + # @!macro thread_pool_options + # + # **Thread Pool Options** + # + # Thread pools support several configuration options: + # + # * `idletime`: The number of seconds that a thread may be idle before being reclaimed. + # * `name`: The name of the executor (optional). Printed in the executor's `#to_s` output and + # a `-worker-` name is given to its threads if supported by used Ruby + # implementation. `` is uniq for each thread. + # * `max_queue`: The maximum number of tasks that may be waiting in the work queue at + # any one time. When the queue size reaches `max_queue` and no new threads can be created, + # subsequent tasks will be rejected in accordance with the configured `fallback_policy`. + # * `auto_terminate`: When true (default), the threads started will be marked as daemon. + # * `fallback_policy`: The policy defining how rejected tasks are handled. + # + # Three fallback policies are supported: + # + # * `:abort`: Raise a `RejectedExecutionError` exception and discard the task. + # * `:discard`: Discard the task and return false. + # * `:caller_runs`: Execute the task on the calling thread. + # + # **Shutting Down Thread Pools** + # + # Killing a thread pool while tasks are still being processed, either by calling + # the `#kill` method or at application exit, will have unpredictable results. There + # is no way for the thread pool to know what resources are being used by the + # in-progress tasks. When those tasks are killed the impact on those resources + # cannot be predicted. The *best* practice is to explicitly shutdown all thread + # pools using the provided methods: + # + # * Call `#shutdown` to initiate an orderly termination of all in-progress tasks + # * Call `#wait_for_termination` with an appropriate timeout interval an allow + # the orderly shutdown to complete + # * Call `#kill` *only when* the thread pool fails to shutdown in the allotted time + # + # On some runtime platforms (most notably the JVM) the application will not + # exit until all thread pools have been shutdown. To prevent applications from + # "hanging" on exit, all threads can be marked as daemon according to the + # `:auto_terminate` option. + # + # ```ruby + # pool1 = Concurrent::FixedThreadPool.new(5) # threads will be marked as daemon + # pool2 = Concurrent::FixedThreadPool.new(5, auto_terminate: false) # mark threads as non-daemon + # ``` + # + # @note Failure to properly shutdown a thread pool can lead to unpredictable results. + # Please read *Shutting Down Thread Pools* for more information. + # + # @see http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html Java Tutorials: Thread Pools + # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html Java Executors class + # @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html Java ExecutorService interface + # @see https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setDaemon-boolean- + + + + + + # @!macro fixed_thread_pool + # + # A thread pool that reuses a fixed number of threads operating off an unbounded queue. + # At any point, at most `num_threads` will be active processing tasks. When all threads are busy new + # tasks `#post` to the thread pool are enqueued until a thread becomes available. + # Should a thread crash for any reason the thread will immediately be removed + # from the pool and replaced. + # + # The API and behavior of this class are based on Java's `FixedThreadPool` + # + # @!macro thread_pool_options + class FixedThreadPool < ThreadPoolExecutor + + # @!macro fixed_thread_pool_method_initialize + # + # Create a new thread pool. + # + # @param [Integer] num_threads the number of threads to allocate + # @param [Hash] opts the options defining pool behavior. + # @option opts [Symbol] :fallback_policy (`:abort`) the fallback policy + # + # @raise [ArgumentError] if `num_threads` is less than or equal to zero + # @raise [ArgumentError] if `fallback_policy` is not a known policy + # + # @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executors.html#newFixedThreadPool-int- + def initialize(num_threads, opts = {}) + raise ArgumentError.new('number of threads must be greater than zero') if num_threads.to_i < 1 + defaults = { max_queue: DEFAULT_MAX_QUEUE_SIZE, + idletime: DEFAULT_THREAD_IDLETIMEOUT } + overrides = { min_threads: num_threads, + max_threads: num_threads } + super(defaults.merge(opts).merge(overrides)) + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/immediate_executor.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/immediate_executor.rb new file mode 100644 index 0000000000000..282df7a0593ec --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/immediate_executor.rb @@ -0,0 +1,66 @@ +require 'concurrent/atomic/event' +require 'concurrent/executor/abstract_executor_service' +require 'concurrent/executor/serial_executor_service' + +module Concurrent + + # An executor service which runs all operations on the current thread, + # blocking as necessary. Operations are performed in the order they are + # received and no two operations can be performed simultaneously. + # + # This executor service exists mainly for testing an debugging. When used + # it immediately runs every `#post` operation on the current thread, blocking + # that thread until the operation is complete. This can be very beneficial + # during testing because it makes all operations deterministic. + # + # @note Intended for use primarily in testing and debugging. + class ImmediateExecutor < AbstractExecutorService + include SerialExecutorService + + # Creates a new executor + def initialize + @stopped = Concurrent::Event.new + end + + # @!macro executor_service_method_post + def post(*args, &task) + raise ArgumentError.new('no block given') unless block_given? + return false unless running? + task.call(*args) + true + end + + # @!macro executor_service_method_left_shift + def <<(task) + post(&task) + self + end + + # @!macro executor_service_method_running_question + def running? + ! shutdown? + end + + # @!macro executor_service_method_shuttingdown_question + def shuttingdown? + false + end + + # @!macro executor_service_method_shutdown_question + def shutdown? + @stopped.set? + end + + # @!macro executor_service_method_shutdown + def shutdown + @stopped.set + true + end + alias_method :kill, :shutdown + + # @!macro executor_service_method_wait_for_termination + def wait_for_termination(timeout = nil) + @stopped.wait(timeout) + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/indirect_immediate_executor.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/indirect_immediate_executor.rb new file mode 100644 index 0000000000000..4f9769fa3f3b5 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/indirect_immediate_executor.rb @@ -0,0 +1,44 @@ +require 'concurrent/executor/immediate_executor' +require 'concurrent/executor/simple_executor_service' + +module Concurrent + # An executor service which runs all operations on a new thread, blocking + # until it completes. Operations are performed in the order they are received + # and no two operations can be performed simultaneously. + # + # This executor service exists mainly for testing an debugging. When used it + # immediately runs every `#post` operation on a new thread, blocking the + # current thread until the operation is complete. This is similar to how the + # ImmediateExecutor works, but the operation has the full stack of the new + # thread at its disposal. This can be helpful when the operations will spawn + # more operations on the same executor and so on - such a situation might + # overflow the single stack in case of an ImmediateExecutor, which is + # inconsistent with how it would behave for a threaded executor. + # + # @note Intended for use primarily in testing and debugging. + class IndirectImmediateExecutor < ImmediateExecutor + # Creates a new executor + def initialize + super + @internal_executor = SimpleExecutorService.new + end + + # @!macro executor_service_method_post + def post(*args, &task) + raise ArgumentError.new("no block given") unless block_given? + return false unless running? + + event = Concurrent::Event.new + @internal_executor.post do + begin + task.call(*args) + ensure + event.set + end + end + event.wait + + true + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/java_executor_service.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/java_executor_service.rb new file mode 100644 index 0000000000000..b2bc69a6ea58d --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/java_executor_service.rb @@ -0,0 +1,100 @@ +require 'concurrent/utility/engine' + +if Concurrent.on_jruby? + require 'concurrent/errors' + require 'concurrent/executor/abstract_executor_service' + + module Concurrent + + # @!macro abstract_executor_service_public_api + # @!visibility private + class JavaExecutorService < AbstractExecutorService + java_import 'java.lang.Runnable' + + FALLBACK_POLICY_CLASSES = { + abort: java.util.concurrent.ThreadPoolExecutor::AbortPolicy, + discard: java.util.concurrent.ThreadPoolExecutor::DiscardPolicy, + caller_runs: java.util.concurrent.ThreadPoolExecutor::CallerRunsPolicy + }.freeze + private_constant :FALLBACK_POLICY_CLASSES + + def post(*args, &task) + raise ArgumentError.new('no block given') unless block_given? + return fallback_action(*args, &task).call unless running? + @executor.submit Job.new(args, task) + true + rescue Java::JavaUtilConcurrent::RejectedExecutionException + raise RejectedExecutionError + end + + def wait_for_termination(timeout = nil) + if timeout.nil? + ok = @executor.awaitTermination(60, java.util.concurrent.TimeUnit::SECONDS) until ok + true + else + @executor.awaitTermination(1000 * timeout, java.util.concurrent.TimeUnit::MILLISECONDS) + end + end + + def shutdown + synchronize do + @executor.shutdown + nil + end + end + + def kill + synchronize do + @executor.shutdownNow + nil + end + end + + private + + def ns_running? + !(ns_shuttingdown? || ns_shutdown?) + end + + def ns_shuttingdown? + @executor.isShutdown && !@executor.isTerminated + end + + def ns_shutdown? + @executor.isTerminated + end + + class Job + include Runnable + def initialize(args, block) + @args = args + @block = block + end + + def run + @block.call(*@args) + end + end + private_constant :Job + end + + class DaemonThreadFactory + # hide include from YARD + send :include, java.util.concurrent.ThreadFactory + + def initialize(daemonize = true) + @daemonize = daemonize + @java_thread_factory = java.util.concurrent.Executors.defaultThreadFactory + end + + def newThread(runnable) + thread = @java_thread_factory.newThread(runnable) + thread.setDaemon(@daemonize) + return thread + end + end + + private_constant :DaemonThreadFactory + + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/java_single_thread_executor.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/java_single_thread_executor.rb new file mode 100644 index 0000000000000..7aa24f2d723bf --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/java_single_thread_executor.rb @@ -0,0 +1,30 @@ +if Concurrent.on_jruby? + + require 'concurrent/executor/java_executor_service' + require 'concurrent/executor/serial_executor_service' + + module Concurrent + + # @!macro single_thread_executor + # @!macro abstract_executor_service_public_api + # @!visibility private + class JavaSingleThreadExecutor < JavaExecutorService + include SerialExecutorService + + # @!macro single_thread_executor_method_initialize + def initialize(opts = {}) + super(opts) + end + + private + + def ns_initialize(opts) + @executor = java.util.concurrent.Executors.newSingleThreadExecutor( + DaemonThreadFactory.new(ns_auto_terminate?) + ) + @fallback_policy = opts.fetch(:fallback_policy, :discard) + raise ArgumentError.new("#{@fallback_policy} is not a valid fallback policy") unless FALLBACK_POLICY_CLASSES.keys.include?(@fallback_policy) + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/java_thread_pool_executor.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/java_thread_pool_executor.rb new file mode 100644 index 0000000000000..598a5f91f8822 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/java_thread_pool_executor.rb @@ -0,0 +1,145 @@ +if Concurrent.on_jruby? + + require 'concurrent/executor/java_executor_service' + + module Concurrent + + # @!macro thread_pool_executor + # @!macro thread_pool_options + # @!visibility private + class JavaThreadPoolExecutor < JavaExecutorService + + # @!macro thread_pool_executor_constant_default_max_pool_size + DEFAULT_MAX_POOL_SIZE = java.lang.Integer::MAX_VALUE # 2147483647 + + # @!macro thread_pool_executor_constant_default_min_pool_size + DEFAULT_MIN_POOL_SIZE = 0 + + # @!macro thread_pool_executor_constant_default_max_queue_size + DEFAULT_MAX_QUEUE_SIZE = 0 + + # @!macro thread_pool_executor_constant_default_thread_timeout + DEFAULT_THREAD_IDLETIMEOUT = 60 + + # @!macro thread_pool_executor_constant_default_synchronous + DEFAULT_SYNCHRONOUS = false + + # @!macro thread_pool_executor_attr_reader_max_length + attr_reader :max_length + + # @!macro thread_pool_executor_attr_reader_max_queue + attr_reader :max_queue + + # @!macro thread_pool_executor_attr_reader_synchronous + attr_reader :synchronous + + # @!macro thread_pool_executor_method_initialize + def initialize(opts = {}) + super(opts) + end + + # @!macro executor_service_method_can_overflow_question + def can_overflow? + @max_queue != 0 + end + + # @!macro thread_pool_executor_attr_reader_min_length + def min_length + @executor.getCorePoolSize + end + + # @!macro thread_pool_executor_attr_reader_max_length + def max_length + @executor.getMaximumPoolSize + end + + # @!macro thread_pool_executor_attr_reader_length + def length + @executor.getPoolSize + end + + # @!macro thread_pool_executor_attr_reader_largest_length + def largest_length + @executor.getLargestPoolSize + end + + # @!macro thread_pool_executor_attr_reader_scheduled_task_count + def scheduled_task_count + @executor.getTaskCount + end + + # @!macro thread_pool_executor_attr_reader_completed_task_count + def completed_task_count + @executor.getCompletedTaskCount + end + + # @!macro thread_pool_executor_method_active_count + def active_count + @executor.getActiveCount + end + + # @!macro thread_pool_executor_attr_reader_idletime + def idletime + @executor.getKeepAliveTime(java.util.concurrent.TimeUnit::SECONDS) + end + + # @!macro thread_pool_executor_attr_reader_queue_length + def queue_length + @executor.getQueue.size + end + + # @!macro thread_pool_executor_attr_reader_remaining_capacity + def remaining_capacity + @max_queue == 0 ? -1 : @executor.getQueue.remainingCapacity + end + + # @!macro executor_service_method_running_question + def running? + super && !@executor.isTerminating + end + + # @!macro thread_pool_executor_method_prune_pool + def prune_pool + end + + private + + def ns_initialize(opts) + min_length = opts.fetch(:min_threads, DEFAULT_MIN_POOL_SIZE).to_i + max_length = opts.fetch(:max_threads, DEFAULT_MAX_POOL_SIZE).to_i + idletime = opts.fetch(:idletime, DEFAULT_THREAD_IDLETIMEOUT).to_i + @max_queue = opts.fetch(:max_queue, DEFAULT_MAX_QUEUE_SIZE).to_i + @synchronous = opts.fetch(:synchronous, DEFAULT_SYNCHRONOUS) + @fallback_policy = opts.fetch(:fallback_policy, :abort) + + raise ArgumentError.new("`synchronous` cannot be set unless `max_queue` is 0") if @synchronous && @max_queue > 0 + raise ArgumentError.new("`max_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}") if max_length < DEFAULT_MIN_POOL_SIZE + raise ArgumentError.new("`max_threads` cannot be greater than #{DEFAULT_MAX_POOL_SIZE}") if max_length > DEFAULT_MAX_POOL_SIZE + raise ArgumentError.new("`min_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}") if min_length < DEFAULT_MIN_POOL_SIZE + raise ArgumentError.new("`min_threads` cannot be more than `max_threads`") if min_length > max_length + raise ArgumentError.new("#{fallback_policy} is not a valid fallback policy") unless FALLBACK_POLICY_CLASSES.include?(@fallback_policy) + + if @max_queue == 0 + if @synchronous + queue = java.util.concurrent.SynchronousQueue.new + else + queue = java.util.concurrent.LinkedBlockingQueue.new + end + else + queue = java.util.concurrent.LinkedBlockingQueue.new(@max_queue) + end + + @executor = java.util.concurrent.ThreadPoolExecutor.new( + min_length, + max_length, + idletime, + java.util.concurrent.TimeUnit::SECONDS, + queue, + DaemonThreadFactory.new(ns_auto_terminate?), + FALLBACK_POLICY_CLASSES[@fallback_policy].new) + + end + end + + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb new file mode 100644 index 0000000000000..1f7301b947434 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb @@ -0,0 +1,82 @@ +require 'concurrent/executor/abstract_executor_service' +require 'concurrent/atomic/event' + +module Concurrent + + # @!macro abstract_executor_service_public_api + # @!visibility private + class RubyExecutorService < AbstractExecutorService + safe_initialization! + + def initialize(*args, &block) + super + @StopEvent = Event.new + @StoppedEvent = Event.new + end + + def post(*args, &task) + raise ArgumentError.new('no block given') unless block_given? + 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 + + def shutdown + synchronize do + break unless running? + stop_event.set + ns_shutdown_execution + end + true + end + + def kill + synchronize do + break if shutdown? + stop_event.set + ns_kill_execution + stopped_event.set + end + true + end + + def wait_for_termination(timeout = nil) + stopped_event.wait(timeout) + end + + private + + def stop_event + @StopEvent + end + + def stopped_event + @StoppedEvent + end + + def ns_shutdown_execution + stopped_event.set + end + + def ns_running? + !stop_event.set? + end + + def ns_shuttingdown? + !(ns_running? || ns_shutdown?) + end + + def ns_shutdown? + stopped_event.set? + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/ruby_single_thread_executor.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/ruby_single_thread_executor.rb new file mode 100644 index 0000000000000..916337d4baad1 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/ruby_single_thread_executor.rb @@ -0,0 +1,21 @@ +require 'concurrent/executor/ruby_thread_pool_executor' + +module Concurrent + + # @!macro single_thread_executor + # @!macro abstract_executor_service_public_api + # @!visibility private + class RubySingleThreadExecutor < RubyThreadPoolExecutor + + # @!macro single_thread_executor_method_initialize + def initialize(opts = {}) + super( + min_threads: 1, + max_threads: 1, + max_queue: 0, + idletime: DEFAULT_THREAD_IDLETIMEOUT, + fallback_policy: opts.fetch(:fallback_policy, :discard), + ) + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb new file mode 100644 index 0000000000000..9375acf38402b --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb @@ -0,0 +1,373 @@ +require 'thread' +require 'concurrent/atomic/event' +require 'concurrent/concern/logging' +require 'concurrent/executor/ruby_executor_service' +require 'concurrent/utility/monotonic_time' + +module Concurrent + + # @!macro thread_pool_executor + # @!macro thread_pool_options + # @!visibility private + class RubyThreadPoolExecutor < RubyExecutorService + + # @!macro thread_pool_executor_constant_default_max_pool_size + DEFAULT_MAX_POOL_SIZE = 2_147_483_647 # java.lang.Integer::MAX_VALUE + + # @!macro thread_pool_executor_constant_default_min_pool_size + DEFAULT_MIN_POOL_SIZE = 0 + + # @!macro thread_pool_executor_constant_default_max_queue_size + DEFAULT_MAX_QUEUE_SIZE = 0 + + # @!macro thread_pool_executor_constant_default_thread_timeout + DEFAULT_THREAD_IDLETIMEOUT = 60 + + # @!macro thread_pool_executor_constant_default_synchronous + DEFAULT_SYNCHRONOUS = false + + # @!macro thread_pool_executor_attr_reader_max_length + attr_reader :max_length + + # @!macro thread_pool_executor_attr_reader_min_length + attr_reader :min_length + + # @!macro thread_pool_executor_attr_reader_idletime + attr_reader :idletime + + # @!macro thread_pool_executor_attr_reader_max_queue + attr_reader :max_queue + + # @!macro thread_pool_executor_attr_reader_synchronous + attr_reader :synchronous + + # @!macro thread_pool_executor_method_initialize + def initialize(opts = {}) + super(opts) + end + + # @!macro thread_pool_executor_attr_reader_largest_length + def largest_length + synchronize { @largest_length } + end + + # @!macro thread_pool_executor_attr_reader_scheduled_task_count + def scheduled_task_count + synchronize { @scheduled_task_count } + end + + # @!macro thread_pool_executor_attr_reader_completed_task_count + def completed_task_count + synchronize { @completed_task_count } + end + + # @!macro thread_pool_executor_method_active_count + def active_count + synchronize do + @pool.length - @ready.length + end + end + + # @!macro executor_service_method_can_overflow_question + def can_overflow? + synchronize { ns_limited_queue? } + end + + # @!macro thread_pool_executor_attr_reader_length + def length + synchronize { @pool.length } + end + + # @!macro thread_pool_executor_attr_reader_queue_length + def queue_length + synchronize { @queue.length } + end + + # @!macro thread_pool_executor_attr_reader_remaining_capacity + def remaining_capacity + synchronize do + if ns_limited_queue? + @max_queue - @queue.length + else + -1 + end + end + end + + # @!visibility private + def remove_busy_worker(worker) + synchronize { ns_remove_busy_worker worker } + end + + # @!visibility private + def ready_worker(worker, last_message) + synchronize { ns_ready_worker worker, last_message } + end + + # @!visibility private + def worker_died(worker) + synchronize { ns_worker_died worker } + end + + # @!visibility private + def worker_task_completed + synchronize { @completed_task_count += 1 } + end + + # @!macro thread_pool_executor_method_prune_pool + def prune_pool + synchronize { ns_prune_pool } + end + + private + + # @!visibility private + def ns_initialize(opts) + @min_length = opts.fetch(:min_threads, DEFAULT_MIN_POOL_SIZE).to_i + @max_length = opts.fetch(:max_threads, DEFAULT_MAX_POOL_SIZE).to_i + @idletime = opts.fetch(:idletime, DEFAULT_THREAD_IDLETIMEOUT).to_i + @max_queue = opts.fetch(:max_queue, DEFAULT_MAX_QUEUE_SIZE).to_i + @synchronous = opts.fetch(:synchronous, DEFAULT_SYNCHRONOUS) + @fallback_policy = opts.fetch(:fallback_policy, :abort) + + raise ArgumentError.new("`synchronous` cannot be set unless `max_queue` is 0") if @synchronous && @max_queue > 0 + raise ArgumentError.new("#{@fallback_policy} is not a valid fallback policy") unless FALLBACK_POLICIES.include?(@fallback_policy) + raise ArgumentError.new("`max_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}") if @max_length < DEFAULT_MIN_POOL_SIZE + raise ArgumentError.new("`max_threads` cannot be greater than #{DEFAULT_MAX_POOL_SIZE}") if @max_length > DEFAULT_MAX_POOL_SIZE + raise ArgumentError.new("`min_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}") if @min_length < DEFAULT_MIN_POOL_SIZE + raise ArgumentError.new("`min_threads` cannot be more than `max_threads`") if min_length > max_length + + @pool = [] # all workers + @ready = [] # used as a stash (most idle worker is at the start) + @queue = [] # used as queue + # @ready or @queue is empty at all times + @scheduled_task_count = 0 + @completed_task_count = 0 + @largest_length = 0 + @workers_counter = 0 + @ruby_pid = $$ # detects if Ruby has forked + + @gc_interval = opts.fetch(:gc_interval, @idletime / 2.0).to_i # undocumented + @next_gc_time = Concurrent.monotonic_time + @gc_interval + end + + # @!visibility private + def ns_limited_queue? + @max_queue != 0 + end + + # @!visibility private + def ns_execute(*args, &task) + ns_reset_if_forked + + if ns_assign_worker(*args, &task) || ns_enqueue(*args, &task) + @scheduled_task_count += 1 + else + return fallback_action(*args, &task) + end + + ns_prune_pool if @next_gc_time < Concurrent.monotonic_time + nil + end + + # @!visibility private + def ns_shutdown_execution + ns_reset_if_forked + + if @pool.empty? + # nothing to do + stopped_event.set + end + + if @queue.empty? + # no more tasks will be accepted, just stop all workers + @pool.each(&:stop) + end + end + + # @!visibility private + def ns_kill_execution + # TODO log out unprocessed tasks in queue + # TODO try to shutdown first? + @pool.each(&:kill) + @pool.clear + @ready.clear + end + + # tries to assign task to a worker, tries to get one from @ready or to create new one + # @return [true, false] if task is assigned to a worker + # + # @!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 + if worker + worker << [task, args] + true + else + false + end + rescue ThreadError + # Raised when the operating system refuses to create the new thread + return false + end + + # tries to enqueue task + # @return [true, false] if enqueued + # + # @!visibility private + def ns_enqueue(*args, &task) + return false if @synchronous + + if !ns_limited_queue? || @queue.size < @max_queue + @queue << [task, args] + true + else + false + end + end + + # @!visibility private + def ns_worker_died(worker) + ns_remove_busy_worker worker + replacement_worker = ns_add_busy_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 + # @return [nil, Worker] nil of max capacity is reached + # + # @!visibility private + def ns_add_busy_worker + return if @pool.size >= @max_length + + @workers_counter += 1 + @pool << (worker = Worker.new(self, @workers_counter)) + @largest_length = @pool.length if @pool.length > @largest_length + worker + end + + # handle ready worker, giving it new job or assigning back to @ready + # + # @!visibility private + 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? + raise unless last_message + @ready.push([worker, last_message]) + else + worker.stop + end + end + end + + # removes a worker which is not in not tracked in @ready + # + # @!visibility private + def ns_remove_busy_worker(worker) + @pool.delete(worker) + stopped_event.set if @pool.empty? && !running? + true + end + + # try oldest worker if it is idle for enough time, it's returned back at the start + # + # @!visibility private + def ns_prune_pool + now = Concurrent.monotonic_time + stopped_workers = 0 + while !@ready.empty? && (@pool.size - stopped_workers > @min_length) + worker, last_message = @ready.first + if now - last_message > self.idletime + stopped_workers += 1 + @ready.shift + worker << :stop + else break + end + end + + @next_gc_time = Concurrent.monotonic_time + @gc_interval + end + + def ns_reset_if_forked + if $$ != @ruby_pid + @queue.clear + @ready.clear + @pool.clear + @scheduled_task_count = 0 + @completed_task_count = 0 + @largest_length = 0 + @workers_counter = 0 + @ruby_pid = $$ + end + end + + # @!visibility private + class Worker + include Concern::Logging + + def initialize(pool, id) + # instance variables accessed only under pool's lock so no need to sync here again + @queue = Queue.new + @pool = pool + @thread = create_worker @queue, pool, pool.idletime + + if @thread.respond_to?(:name=) + @thread.name = [pool.name, 'worker', id].compact.join('-') + end + end + + def <<(message) + @queue << message + end + + def stop + @queue << :stop + end + + def kill + @thread.kill + end + + private + + def create_worker(queue, pool, idletime) + Thread.new(queue, pool, idletime) do |my_queue, my_pool, my_idletime| + catch(:stop) do + loop do + + case message = my_queue.pop + when :stop + my_pool.remove_busy_worker(self) + throw :stop + + else + task, args = message + run_task my_pool, task, args + my_pool.ready_worker(self, Concurrent.monotonic_time) + end + end + end + end + end + + def run_task(pool, task, args) + task.call(*args) + pool.worker_task_completed + rescue => ex + # let it fail + log DEBUG, ex + rescue Exception => ex + log ERROR, ex + pool.worker_died(self) + throw :stop + end + end + + private_constant :Worker + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb new file mode 100644 index 0000000000000..f796b8571fa44 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb @@ -0,0 +1,35 @@ +require 'concurrent/synchronization/lockable_object' + +module Concurrent + + # A simple utility class that executes a callable and returns and array of three elements: + # success - indicating if the callable has been executed without errors + # value - filled by the callable result if it has been executed without errors, nil otherwise + # reason - the error risen by the callable if it has been executed with errors, nil otherwise + class SafeTaskExecutor < Synchronization::LockableObject + + def initialize(task, opts = {}) + @task = task + @exception_class = opts.fetch(:rescue_exception, false) ? Exception : StandardError + super() # ensures visibility + end + + # @return [Array] + def execute(*args) + success = true + value = reason = nil + + synchronize do + begin + value = @task.call(*args) + success = true + rescue @exception_class => ex + reason = ex + success = false + end + end + + [success, value, reason] + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/serial_executor_service.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/serial_executor_service.rb new file mode 100644 index 0000000000000..f1c38ecfa9c97 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/serial_executor_service.rb @@ -0,0 +1,34 @@ +require 'concurrent/executor/executor_service' + +module Concurrent + + # Indicates that the including `ExecutorService` guarantees + # that all operations will occur in the order they are post and that no + # two operations may occur simultaneously. This module provides no + # functionality and provides no guarantees. That is the responsibility + # of the including class. This module exists solely to allow the including + # object to be interrogated for its serialization status. + # + # @example + # class Foo + # include Concurrent::SerialExecutor + # end + # + # foo = Foo.new + # + # foo.is_a? Concurrent::ExecutorService #=> true + # foo.is_a? Concurrent::SerialExecutor #=> true + # foo.serialized? #=> true + # + # @!visibility private + module SerialExecutorService + include ExecutorService + + # @!macro executor_service_method_serialized_question + # + # @note Always returns `true` + def serialized? + true + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/serialized_execution.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/serialized_execution.rb new file mode 100644 index 0000000000000..4db7c7f0c2135 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/serialized_execution.rb @@ -0,0 +1,107 @@ +require 'concurrent/errors' +require 'concurrent/concern/logging' +require 'concurrent/synchronization/lockable_object' + +module Concurrent + + # Ensures passed jobs in a serialized order never running at the same time. + class SerializedExecution < Synchronization::LockableObject + include Concern::Logging + + def initialize() + super() + synchronize { ns_initialize } + end + + Job = Struct.new(:executor, :args, :block) do + def call + block.call(*args) + end + end + + # Submit a task to the executor for asynchronous processing. + # + # @param [Executor] executor to be used for this job + # + # @param [Array] args zero or more arguments to be passed to the task + # + # @yield the asynchronous task to perform + # + # @return [Boolean] `true` if the task is queued, `false` if the executor + # is not running + # + # @raise [ArgumentError] if no task is given + def post(executor, *args, &task) + posts [[executor, args, task]] + true + end + + # As {#post} but allows to submit multiple tasks at once, it's guaranteed that they will not + # be interleaved by other tasks. + # + # @param [Array, Proc)>] posts array of triplets where + # first is a {ExecutorService}, second is array of args for task, third is a task (Proc) + def posts(posts) + # if can_overflow? + # raise ArgumentError, 'SerializedExecution does not support thread-pools which can overflow' + # end + + return nil if posts.empty? + + jobs = posts.map { |executor, args, task| Job.new executor, args, task } + + job_to_post = synchronize do + if @being_executed + @stash.push(*jobs) + nil + else + @being_executed = true + @stash.push(*jobs[1..-1]) + jobs.first + end + end + + call_job job_to_post if job_to_post + true + end + + private + + def ns_initialize + @being_executed = false + @stash = [] + end + + def call_job(job) + did_it_run = begin + job.executor.post { work(job) } + true + rescue RejectedExecutionError => ex + false + end + + # TODO not the best idea to run it myself + unless did_it_run + begin + work job + rescue => ex + # let it fail + log DEBUG, ex + end + end + end + + # ensures next job is executed if any is stashed + def work(job) + job.call + ensure + synchronize do + job = @stash.shift || (@being_executed = false) + end + + # TODO maybe be able to tell caching pool to just enqueue this job, because the current one end at the end + # of this block + call_job job if job + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/serialized_execution_delegator.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/serialized_execution_delegator.rb new file mode 100644 index 0000000000000..8197781b52f4e --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/serialized_execution_delegator.rb @@ -0,0 +1,28 @@ +require 'delegate' +require 'concurrent/executor/serial_executor_service' +require 'concurrent/executor/serialized_execution' + +module Concurrent + + # A wrapper/delegator for any `ExecutorService` that + # guarantees serialized execution of tasks. + # + # @see [SimpleDelegator](http://www.ruby-doc.org/stdlib-2.1.2/libdoc/delegate/rdoc/SimpleDelegator.html) + # @see Concurrent::SerializedExecution + class SerializedExecutionDelegator < SimpleDelegator + include SerialExecutorService + + def initialize(executor) + @executor = executor + @serializer = SerializedExecution.new + super(executor) + end + + # @!macro executor_service_method_post + def post(*args, &task) + raise ArgumentError.new('no block given') unless block_given? + return false unless running? + @serializer.post(@executor, *args, &task) + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb new file mode 100644 index 0000000000000..0bc62afd38d20 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb @@ -0,0 +1,103 @@ +require 'concurrent/atomic/atomic_boolean' +require 'concurrent/atomic/atomic_fixnum' +require 'concurrent/atomic/event' +require 'concurrent/executor/executor_service' +require 'concurrent/executor/ruby_executor_service' + +module Concurrent + + # An executor service in which every operation spawns a new, + # independently operating thread. + # + # This is perhaps the most inefficient executor service in this + # library. It exists mainly for testing an debugging. Thread creation + # and management is expensive in Ruby and this executor performs no + # resource pooling. This can be very beneficial during testing and + # debugging because it decouples the using code from the underlying + # executor implementation. In production this executor will likely + # lead to suboptimal performance. + # + # @note Intended for use primarily in testing and debugging. + class SimpleExecutorService < RubyExecutorService + + # @!macro executor_service_method_post + def self.post(*args) + raise ArgumentError.new('no block given') unless block_given? + Thread.new(*args) do + Thread.current.abort_on_exception = false + yield(*args) + end + true + end + + # @!macro executor_service_method_left_shift + def self.<<(task) + post(&task) + self + end + + # @!macro executor_service_method_post + def post(*args, &task) + raise ArgumentError.new('no block given') unless block_given? + return false unless running? + @count.increment + Thread.new(*args) do + Thread.current.abort_on_exception = false + begin + yield(*args) + ensure + @count.decrement + @stopped.set if @running.false? && @count.value == 0 + end + end + end + + # @!macro executor_service_method_left_shift + def <<(task) + post(&task) + self + end + + # @!macro executor_service_method_running_question + def running? + @running.true? + end + + # @!macro executor_service_method_shuttingdown_question + def shuttingdown? + @running.false? && ! @stopped.set? + end + + # @!macro executor_service_method_shutdown_question + def shutdown? + @stopped.set? + end + + # @!macro executor_service_method_shutdown + def shutdown + @running.make_false + @stopped.set if @count.value == 0 + true + end + + # @!macro executor_service_method_kill + def kill + @running.make_false + @stopped.set + true + end + + # @!macro executor_service_method_wait_for_termination + def wait_for_termination(timeout = nil) + @stopped.wait(timeout) + end + + private + + def ns_initialize(*args) + @running = Concurrent::AtomicBoolean.new(true) + @stopped = Concurrent::Event.new + @count = Concurrent::AtomicFixnum.new(0) + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/single_thread_executor.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/single_thread_executor.rb new file mode 100644 index 0000000000000..f1474ea9ff46f --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/single_thread_executor.rb @@ -0,0 +1,57 @@ +require 'concurrent/utility/engine' +require 'concurrent/executor/ruby_single_thread_executor' + +module Concurrent + + if Concurrent.on_jruby? + require 'concurrent/executor/java_single_thread_executor' + end + + SingleThreadExecutorImplementation = case + when Concurrent.on_jruby? + JavaSingleThreadExecutor + else + RubySingleThreadExecutor + end + private_constant :SingleThreadExecutorImplementation + + # @!macro single_thread_executor + # + # A thread pool with a single thread an unlimited queue. Should the thread + # die for any reason it will be removed and replaced, thus ensuring that + # the executor will always remain viable and available to process jobs. + # + # A common pattern for background processing is to create a single thread + # on which an infinite loop is run. The thread's loop blocks on an input + # source (perhaps blocking I/O or a queue) and processes each input as it + # 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 + # to errors from within tasks. Also, should the thread die it will + # automatically be restarted. + # + # The API and behavior of this class are based on Java's `SingleThreadExecutor`. + # + # @!macro abstract_executor_service_public_api + class SingleThreadExecutor < SingleThreadExecutorImplementation + + # @!macro single_thread_executor_method_initialize + # + # Create a new thread pool. + # + # @option opts [Symbol] :fallback_policy (:discard) the policy for handling new + # tasks that are received when the queue size has reached + # `max_queue` or the executor has shut down + # + # @raise [ArgumentError] if `:fallback_policy` is not one of the values specified + # in `FALLBACK_POLICIES` + # + # @see http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html + # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html + # @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html + + # @!method initialize(opts = {}) + # @!macro single_thread_executor_method_initialize + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/thread_pool_executor.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/thread_pool_executor.rb new file mode 100644 index 0000000000000..253d46a9d1d0d --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/thread_pool_executor.rb @@ -0,0 +1,88 @@ +require 'concurrent/utility/engine' +require 'concurrent/executor/ruby_thread_pool_executor' + +module Concurrent + + if Concurrent.on_jruby? + require 'concurrent/executor/java_thread_pool_executor' + end + + ThreadPoolExecutorImplementation = case + when Concurrent.on_jruby? + JavaThreadPoolExecutor + else + RubyThreadPoolExecutor + end + private_constant :ThreadPoolExecutorImplementation + + # @!macro thread_pool_executor + # + # An abstraction composed of one or more threads and a task queue. Tasks + # (blocks or `proc` objects) are submitted to the pool and added to the queue. + # The threads in the pool remove the tasks and execute them in the order + # they were received. + # + # A `ThreadPoolExecutor` will automatically adjust the pool size according + # to the bounds set by `min-threads` and `max-threads`. When a new task is + # submitted and fewer than `min-threads` threads are running, a new thread + # is created to handle the request, even if other worker threads are idle. + # If there are more than `min-threads` but less than `max-threads` threads + # running, a new thread will be created only if the queue is full. + # + # Threads that are idle for too long will be garbage collected, down to the + # configured minimum options. Should a thread crash it, too, will be garbage collected. + # + # `ThreadPoolExecutor` is based on the Java class of the same name. From + # the official Java documentation; + # + # > Thread pools address two different problems: they usually provide + # > improved performance when executing large numbers of asynchronous tasks, + # > due to reduced per-task invocation overhead, and they provide a means + # > of bounding and managing the resources, including threads, consumed + # > when executing a collection of tasks. Each ThreadPoolExecutor also + # > maintains some basic statistics, such as the number of completed tasks. + # > + # > To be useful across a wide range of contexts, this class provides many + # > adjustable parameters and extensibility hooks. However, programmers are + # > urged to use the more convenient Executors factory methods + # > [CachedThreadPool] (unbounded thread pool, with automatic thread reclamation), + # > [FixedThreadPool] (fixed size thread pool) and [SingleThreadExecutor] (single + # > background thread), that preconfigure settings for the most common usage + # > scenarios. + # + # @!macro thread_pool_options + # + # @!macro thread_pool_executor_public_api + class ThreadPoolExecutor < ThreadPoolExecutorImplementation + + # @!macro thread_pool_executor_method_initialize + # + # Create a new thread pool. + # + # @param [Hash] opts the options which configure the thread pool. + # + # @option opts [Integer] :max_threads (DEFAULT_MAX_POOL_SIZE) the maximum + # number of threads to be created + # @option opts [Integer] :min_threads (DEFAULT_MIN_POOL_SIZE) When a new task is submitted + # and fewer than `min_threads` are running, a new thread is created + # @option opts [Integer] :idletime (DEFAULT_THREAD_IDLETIMEOUT) the maximum + # number of seconds a thread may be idle before being reclaimed + # @option opts [Integer] :max_queue (DEFAULT_MAX_QUEUE_SIZE) the maximum + # number of tasks allowed in the work queue at any one time; a value of + # zero means the queue may grow without bound + # @option opts [Symbol] :fallback_policy (:abort) the policy for handling new + # tasks that are received when the queue size has reached + # `max_queue` or the executor has shut down + # @option opts [Boolean] :synchronous (DEFAULT_SYNCHRONOUS) whether or not a value of 0 + # for :max_queue means the queue must perform direct hand-off rather than unbounded. + # @raise [ArgumentError] if `:max_threads` is less than one + # @raise [ArgumentError] if `:min_threads` is less than zero + # @raise [ArgumentError] if `:fallback_policy` is not one of the values specified + # in `FALLBACK_POLICIES` + # + # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html + + # @!method initialize(opts = {}) + # @!macro thread_pool_executor_method_initialize + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/timer_set.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/timer_set.rb new file mode 100644 index 0000000000000..759dce093a5b6 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/timer_set.rb @@ -0,0 +1,176 @@ +require 'concurrent/scheduled_task' +require 'concurrent/atomic/event' +require 'concurrent/collection/non_concurrent_priority_queue' +require 'concurrent/executor/executor_service' +require 'concurrent/executor/single_thread_executor' +require 'concurrent/errors' +require 'concurrent/options' + +module Concurrent + + # Executes a collection of tasks, each after a given delay. A master task + # monitors the set and schedules each task for execution at the appropriate + # time. Tasks are run on the global thread pool or on the supplied executor. + # Each task is represented as a `ScheduledTask`. + # + # @see Concurrent::ScheduledTask + # + # @!macro monotonic_clock_warning + class TimerSet < RubyExecutorService + + # Create a new set of timed tasks. + # + # @!macro executor_options + # + # @param [Hash] opts the options used to specify the executor on which to perform actions + # @option opts [Executor] :executor when set use the given `Executor` instance. + # Three special values are also supported: `:task` returns the global task pool, + # `:operation` returns the global operation pool, and `:immediate` returns a new + # `ImmediateExecutor` object. + def initialize(opts = {}) + super(opts) + end + + # Post a task to be execute run after a given delay (in seconds). If the + # delay is less than 1/100th of a second the task will be immediately post + # to the executor. + # + # @param [Float] delay the number of seconds to wait for before executing the task. + # @param [Array] args the arguments passed to the task on execution. + # + # @yield the task to be performed. + # + # @return [Concurrent::ScheduledTask, false] IVar representing the task if the post + # is successful; false after shutdown. + # + # @raise [ArgumentError] if the intended execution time is not in the future. + # @raise [ArgumentError] if no block is given. + def post(delay, *args, &task) + raise ArgumentError.new('no block given') unless block_given? + return false unless running? + opts = { executor: @task_executor, + args: args, + timer_set: self } + task = ScheduledTask.execute(delay, opts, &task) # may raise exception + task.unscheduled? ? false : task + end + + # Begin an immediate shutdown. In-progress tasks will be allowed to + # complete but enqueued tasks will be dismissed and no new tasks + # will be accepted. Has no additional effect if the thread pool is + # not running. + def kill + shutdown + end + + private :<< + + private + + # Initialize the object. + # + # @param [Hash] opts the options to create the object with. + # @!visibility private + def ns_initialize(opts) + @queue = Collection::NonConcurrentPriorityQueue.new(order: :min) + @task_executor = Options.executor_from_options(opts) || Concurrent.global_io_executor + @timer_executor = SingleThreadExecutor.new + @condition = Event.new + @ruby_pid = $$ # detects if Ruby has forked + end + + # Post the task to the internal queue. + # + # @note This is intended as a callback method from ScheduledTask + # only. It is not intended to be used directly. Post a task + # by using the `SchedulesTask#execute` method. + # + # @!visibility private + def post_task(task) + synchronize { ns_post_task(task) } + end + + # @!visibility private + def ns_post_task(task) + return false unless ns_running? + ns_reset_if_forked + if (task.initial_delay) <= 0.01 + task.executor.post { task.process_task } + else + @queue.push(task) + # only post the process method when the queue is empty + @timer_executor.post(&method(:process_tasks)) if @queue.length == 1 + @condition.set + end + true + end + + # Remove the given task from the queue. + # + # @note This is intended as a callback method from `ScheduledTask` + # only. It is not intended to be used directly. Cancel a task + # by using the `ScheduledTask#cancel` method. + # + # @!visibility private + def remove_task(task) + synchronize { @queue.delete(task) } + end + + # `ExecutorService` callback called during shutdown. + # + # @!visibility private + def ns_shutdown_execution + ns_reset_if_forked + @queue.clear + @timer_executor.kill + stopped_event.set + end + + def ns_reset_if_forked + if $$ != @ruby_pid + @queue.clear + @condition.reset + @ruby_pid = $$ + end + end + + # Run a loop and execute tasks in the scheduled order and at the approximate + # scheduled time. If no tasks remain the thread will exit gracefully so that + # garbage collection can occur. If there are no ready tasks it will sleep + # for up to 60 seconds waiting for the next scheduled task. + # + # @!visibility private + def process_tasks + loop do + task = synchronize { @condition.reset; @queue.peek } + break unless task + + now = Concurrent.monotonic_time + diff = task.schedule_time - now + + if diff <= 0 + # We need to remove the task from the queue before passing + # it to the executor, to avoid race conditions where we pass + # the peek'ed task to the executor and then pop a different + # one that's been added in the meantime. + # + # Note that there's no race condition between the peek and + # this pop - this pop could retrieve a different task from + # the peek, but that task would be due to fire now anyway + # (because @queue is a priority queue, and this thread is + # the only reader, so whatever timer is at the head of the + # queue now must have the same pop time, or a closer one, as + # when we peeked). + task = synchronize { @queue.pop } + begin + task.executor.post { task.process_task } + rescue RejectedExecutionError + # ignore and continue + end + else + @condition.wait([diff, 60].min) + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executors.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executors.rb new file mode 100644 index 0000000000000..eb1972ce697a9 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executors.rb @@ -0,0 +1,20 @@ +require 'concurrent/executor/abstract_executor_service' +require 'concurrent/executor/cached_thread_pool' +require 'concurrent/executor/executor_service' +require 'concurrent/executor/fixed_thread_pool' +require 'concurrent/executor/immediate_executor' +require 'concurrent/executor/indirect_immediate_executor' +require 'concurrent/executor/java_executor_service' +require 'concurrent/executor/java_single_thread_executor' +require 'concurrent/executor/java_thread_pool_executor' +require 'concurrent/executor/ruby_executor_service' +require 'concurrent/executor/ruby_single_thread_executor' +require 'concurrent/executor/ruby_thread_pool_executor' +require 'concurrent/executor/cached_thread_pool' +require 'concurrent/executor/safe_task_executor' +require 'concurrent/executor/serial_executor_service' +require 'concurrent/executor/serialized_execution' +require 'concurrent/executor/serialized_execution_delegator' +require 'concurrent/executor/single_thread_executor' +require 'concurrent/executor/thread_pool_executor' +require 'concurrent/executor/timer_set' diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/future.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/future.rb new file mode 100644 index 0000000000000..1af182ecb2805 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/future.rb @@ -0,0 +1,141 @@ +require 'thread' +require 'concurrent/constants' +require 'concurrent/errors' +require 'concurrent/ivar' +require 'concurrent/executor/safe_task_executor' + +require 'concurrent/options' + +# TODO (pitr-ch 14-Mar-2017): deprecate, Future, Promise, etc. + + +module Concurrent + + # {include:file:docs-source/future.md} + # + # @!macro copy_options + # + # @see http://ruby-doc.org/stdlib-2.1.1/libdoc/observer/rdoc/Observable.html Ruby Observable module + # @see http://clojuredocs.org/clojure_core/clojure.core/future Clojure's future function + # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html java.util.concurrent.Future + class Future < IVar + + # Create a new `Future` in the `:unscheduled` state. + # + # @yield the asynchronous operation to perform + # + # @!macro executor_and_deref_options + # + # @option opts [object, Array] :args zero or more arguments to be passed the task + # block on execution + # + # @raise [ArgumentError] if no block is given + def initialize(opts = {}, &block) + raise ArgumentError.new('no block given') unless block_given? + super(NULL, opts.merge(__task_from_block__: block), &nil) + end + + # Execute an `:unscheduled` `Future`. Immediately sets the state to `:pending` and + # passes the block to a new thread/thread pool for eventual execution. + # Does nothing if the `Future` is in any state other than `:unscheduled`. + # + # @return [Future] a reference to `self` + # + # @example Instance and execute in separate steps + # future = Concurrent::Future.new{ sleep(1); 42 } + # future.state #=> :unscheduled + # future.execute + # future.state #=> :pending + # + # @example Instance and execute in one line + # future = Concurrent::Future.new{ sleep(1); 42 }.execute + # future.state #=> :pending + def execute + if compare_and_set_state(:pending, :unscheduled) + @executor.post{ safe_execute(@task, @args) } + self + end + end + + # Create a new `Future` object with the given block, execute it, and return the + # `:pending` object. + # + # @yield the asynchronous operation to perform + # + # @!macro executor_and_deref_options + # + # @option opts [object, Array] :args zero or more arguments to be passed the task + # block on execution + # + # @raise [ArgumentError] if no block is given + # + # @return [Future] the newly created `Future` in the `:pending` state + # + # @example + # future = Concurrent::Future.execute{ sleep(1); 42 } + # future.state #=> :pending + def self.execute(opts = {}, &block) + Future.new(opts, &block).execute + end + + # @!macro ivar_set_method + def set(value = NULL, &block) + check_for_block_or_value!(block_given?, value) + synchronize do + if @state != :unscheduled + raise MultipleAssignmentError + else + @task = block || Proc.new { value } + end + end + execute + end + + # Attempt to cancel the operation if it has not already processed. + # The operation can only be cancelled while still `pending`. It cannot + # be cancelled once it has begun processing or has completed. + # + # @return [Boolean] was the operation successfully cancelled. + def cancel + if compare_and_set_state(:cancelled, :pending) + complete(false, nil, CancelledOperationError.new) + true + else + false + end + end + + # Has the operation been successfully cancelled? + # + # @return [Boolean] + def cancelled? + state == :cancelled + end + + # Wait the given number of seconds for the operation to complete. + # On timeout attempt to cancel the operation. + # + # @param [Numeric] timeout the maximum time in seconds to wait. + # @return [Boolean] true if the operation completed before the timeout + # else false + def wait_or_cancel(timeout) + wait(timeout) + if complete? + true + else + cancel + false + end + end + + protected + + def ns_initialize(value, opts) + super + @state = :unscheduled + @task = opts[:__task_from_block__] + @executor = Options.executor_from_options(opts) || Concurrent.global_io_executor + @args = get_arguments_from(opts) + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/hash.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/hash.rb new file mode 100644 index 0000000000000..db0208e0174fc --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/hash.rb @@ -0,0 +1,52 @@ +require 'concurrent/utility/engine' +require 'concurrent/thread_safe/util' + +module Concurrent + + # @!macro concurrent_hash + # + # A thread-safe subclass of Hash. This version locks against the object + # itself for every method call, ensuring only one thread can be reading + # or writing at a time. This includes iteration methods like `#each`, + # which takes the lock repeatedly when reading an item. + # + # @see http://ruby-doc.org/core/Hash.html Ruby standard library `Hash` + + # @!macro internal_implementation_note + HashImplementation = case + when Concurrent.on_cruby? + # Hash is not fully thread-safe on CRuby, see + # https://bugs.ruby-lang.org/issues/19237 + # https://github.com/ruby/ruby/commit/ffd52412ab + # https://github.com/ruby-concurrency/concurrent-ruby/issues/929 + # So we will need to add synchronization here (similar to Concurrent::Map). + ::Hash + + when Concurrent.on_jruby? + require 'jruby/synchronized' + + class JRubyHash < ::Hash + include JRuby::Synchronized + end + JRubyHash + + when Concurrent.on_truffleruby? + require 'concurrent/thread_safe/util/data_structures' + + class TruffleRubyHash < ::Hash + end + + ThreadSafe::Util.make_synchronized_on_truffleruby TruffleRubyHash + TruffleRubyHash + + else + warn 'Possibly unsupported Ruby implementation' + ::Hash + end + private_constant :HashImplementation + + # @!macro concurrent_hash + class Hash < HashImplementation + end + +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/immutable_struct.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/immutable_struct.rb new file mode 100644 index 0000000000000..48462e8375b87 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/immutable_struct.rb @@ -0,0 +1,101 @@ +require 'concurrent/synchronization/abstract_struct' +require 'concurrent/synchronization/lockable_object' + +module Concurrent + + # A thread-safe, immutable variation of Ruby's standard `Struct`. + # + # @see http://ruby-doc.org/core/Struct.html Ruby standard library `Struct` + module ImmutableStruct + include Synchronization::AbstractStruct + + def self.included(base) + base.safe_initialization! + end + + # @!macro struct_values + def values + ns_values + end + + alias_method :to_a, :values + + # @!macro struct_values_at + def values_at(*indexes) + ns_values_at(indexes) + end + + # @!macro struct_inspect + def inspect + ns_inspect + end + + alias_method :to_s, :inspect + + # @!macro struct_merge + def merge(other, &block) + ns_merge(other, &block) + end + + # @!macro struct_to_h + def to_h + ns_to_h + end + + # @!macro struct_get + def [](member) + ns_get(member) + end + + # @!macro struct_equality + def ==(other) + ns_equality(other) + end + + # @!macro struct_each + def each(&block) + return enum_for(:each) unless block_given? + ns_each(&block) + end + + # @!macro struct_each_pair + def each_pair(&block) + return enum_for(:each_pair) unless block_given? + ns_each_pair(&block) + end + + # @!macro struct_select + def select(&block) + return enum_for(:select) unless block_given? + ns_select(&block) + end + + private + + # @!visibility private + def initialize_copy(original) + super(original) + ns_initialize_copy + end + + # @!macro struct_new + def self.new(*args, &block) + clazz_name = nil + if args.length == 0 + raise ArgumentError.new('wrong number of arguments (0 for 1+)') + elsif args.length > 0 && args.first.is_a?(String) + clazz_name = args.shift + end + FACTORY.define_struct(clazz_name, args, &block) + end + + FACTORY = Class.new(Synchronization::LockableObject) do + def define_struct(name, members, &block) + synchronize do + Synchronization::AbstractStruct.define_struct_class(ImmutableStruct, Synchronization::Object, name, members, &block) + end + end + end.new + private_constant :FACTORY + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/ivar.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/ivar.rb new file mode 100644 index 0000000000000..4165038f8945b --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/ivar.rb @@ -0,0 +1,208 @@ +require 'concurrent/constants' +require 'concurrent/errors' +require 'concurrent/collection/copy_on_write_observer_set' +require 'concurrent/concern/obligation' +require 'concurrent/concern/observable' +require 'concurrent/executor/safe_task_executor' +require 'concurrent/synchronization/lockable_object' + +module Concurrent + + # An `IVar` is like a future that you can assign. As a future is a value that + # is being computed that you can wait on, an `IVar` is a value that is waiting + # to be assigned, that you can wait on. `IVars` are single assignment and + # deterministic. + # + # Then, express futures as an asynchronous computation that assigns an `IVar`. + # The `IVar` becomes the primitive on which [futures](Future) and + # [dataflow](Dataflow) are built. + # + # An `IVar` is a single-element container that is normally created empty, and + # can only be set once. The I in `IVar` stands for immutable. Reading an + # `IVar` normally blocks until it is set. It is safe to set and read an `IVar` + # from different threads. + # + # If you want to have some parallel task set the value in an `IVar`, you want + # a `Future`. If you want to create a graph of parallel tasks all executed + # when the values they depend on are ready you want `dataflow`. `IVar` is + # generally a low-level primitive. + # + # ## Examples + # + # Create, set and get an `IVar` + # + # ```ruby + # ivar = Concurrent::IVar.new + # ivar.set 14 + # ivar.value #=> 14 + # ivar.set 2 # would now be an error + # ``` + # + # ## See Also + # + # 1. For the theory: Arvind, R. Nikhil, and K. Pingali. + # [I-Structures: Data structures for parallel computing](http://dl.acm.org/citation.cfm?id=69562). + # In Proceedings of Workshop on Graph Reduction, 1986. + # 2. For recent application: + # [DataDrivenFuture in Habanero Java from Rice](http://www.cs.rice.edu/~vs3/hjlib/doc/edu/rice/hj/api/HjDataDrivenFuture.html). + class IVar < Synchronization::LockableObject + include Concern::Obligation + include Concern::Observable + + # Create a new `IVar` in the `:pending` state with the (optional) initial value. + # + # @param [Object] value the initial value + # @param [Hash] opts the options to create a message with + # @option opts [String] :dup_on_deref (false) call `#dup` before returning + # the data + # @option opts [String] :freeze_on_deref (false) call `#freeze` before + # returning the data + # @option opts [String] :copy_on_deref (nil) call the given `Proc` passing + # the internal value and returning the value returned from the proc + def initialize(value = NULL, opts = {}, &block) + if value != NULL && block_given? + raise ArgumentError.new('provide only a value or a block') + end + super(&nil) + synchronize { ns_initialize(value, opts, &block) } + end + + # Add an observer on this object that will receive notification on update. + # + # Upon completion the `IVar` will notify all observers in a thread-safe way. + # The `func` method of the observer will be called with three arguments: the + # `Time` at which the `Future` completed the asynchronous operation, the + # final `value` (or `nil` on rejection), and the final `reason` (or `nil` on + # fulfillment). + # + # @param [Object] observer the object that will be notified of changes + # @param [Symbol] func symbol naming the method to call when this + # `Observable` has changes` + def add_observer(observer = nil, func = :update, &block) + raise ArgumentError.new('cannot provide both an observer and a block') if observer && block + direct_notification = false + + if block + observer = block + func = :call + end + + synchronize do + if event.set? + direct_notification = true + else + observers.add_observer(observer, func) + end + end + + observer.send(func, Time.now, self.value, reason) if direct_notification + observer + end + + # @!macro ivar_set_method + # Set the `IVar` to a value and wake or notify all threads waiting on it. + # + # @!macro ivar_set_parameters_and_exceptions + # @param [Object] value the value to store in the `IVar` + # @yield A block operation to use for setting the value + # @raise [ArgumentError] if both a value and a block are given + # @raise [Concurrent::MultipleAssignmentError] if the `IVar` has already + # been set or otherwise completed + # + # @return [IVar] self + def set(value = NULL) + check_for_block_or_value!(block_given?, value) + raise MultipleAssignmentError unless compare_and_set_state(:processing, :pending) + + begin + value = yield if block_given? + complete_without_notification(true, value, nil) + rescue => ex + complete_without_notification(false, nil, ex) + end + + notify_observers(self.value, reason) + self + end + + # @!macro ivar_fail_method + # Set the `IVar` to failed due to some error and wake or notify all threads waiting on it. + # + # @param [Object] reason for the failure + # @raise [Concurrent::MultipleAssignmentError] if the `IVar` has already + # been set or otherwise completed + # @return [IVar] self + def fail(reason = StandardError.new) + complete(false, nil, reason) + end + + # Attempt to set the `IVar` with the given value or block. Return a + # boolean indicating the success or failure of the set operation. + # + # @!macro ivar_set_parameters_and_exceptions + # + # @return [Boolean] true if the value was set else false + def try_set(value = NULL, &block) + set(value, &block) + true + rescue MultipleAssignmentError + false + end + + protected + + # @!visibility private + def ns_initialize(value, opts) + value = yield if block_given? + init_obligation + self.observers = Collection::CopyOnWriteObserverSet.new + set_deref_options(opts) + + @state = :pending + if value != NULL + ns_complete_without_notification(true, value, nil) + end + end + + # @!visibility private + def safe_execute(task, args = []) + if compare_and_set_state(:processing, :pending) + success, val, reason = SafeTaskExecutor.new(task, rescue_exception: true).execute(*@args) + complete(success, val, reason) + yield(success, val, reason) if block_given? + end + end + + # @!visibility private + def complete(success, value, reason) + complete_without_notification(success, value, reason) + notify_observers(self.value, reason) + self + end + + # @!visibility private + def complete_without_notification(success, value, reason) + synchronize { ns_complete_without_notification(success, value, reason) } + self + end + + # @!visibility private + def notify_observers(value, reason) + observers.notify_and_delete_observers{ [Time.now, value, reason] } + end + + # @!visibility private + def ns_complete_without_notification(success, value, reason) + raise MultipleAssignmentError if [:fulfilled, :rejected].include? @state + set_state(success, value, reason) + event.set + end + + # @!visibility private + def check_for_block_or_value!(block_given, value) # :nodoc: + if (block_given && value != NULL) || (! block_given && value == NULL) + raise ArgumentError.new('must set with either a value or a block') + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/map.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/map.rb new file mode 100644 index 0000000000000..601e365042570 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/map.rb @@ -0,0 +1,350 @@ +require 'thread' +require 'concurrent/constants' +require 'concurrent/utility/engine' + +module Concurrent + # @!visibility private + module Collection + + # @!visibility private + MapImplementation = case + when Concurrent.on_jruby? + require 'concurrent/utility/native_extension_loader' + # noinspection RubyResolve + JRubyMapBackend + when Concurrent.on_cruby? + require 'concurrent/collection/map/mri_map_backend' + MriMapBackend + when Concurrent.on_truffleruby? + if defined?(::TruffleRuby::ConcurrentMap) + require 'concurrent/collection/map/truffleruby_map_backend' + TruffleRubyMapBackend + else + require 'concurrent/collection/map/synchronized_map_backend' + SynchronizedMapBackend + end + else + warn 'Concurrent::Map: unsupported Ruby engine, using a fully synchronized Concurrent::Map implementation' + require 'concurrent/collection/map/synchronized_map_backend' + SynchronizedMapBackend + end + end + + # `Concurrent::Map` is a hash-like object and should have much better performance + # characteristics, especially under high concurrency, than `Concurrent::Hash`. + # However, `Concurrent::Map `is not strictly semantically equivalent to a ruby `Hash` + # -- for instance, it does not necessarily retain ordering by insertion time as `Hash` + # does. For most uses it should do fine though, and we recommend you consider + # `Concurrent::Map` instead of `Concurrent::Hash` for your concurrency-safe hash needs. + class Map < Collection::MapImplementation + + # @!macro map.atomic_method + # This method is atomic. + + # @!macro map.atomic_method_with_block + # This method is atomic. + # @note Atomic methods taking a block do not allow the `self` instance + # to be used within the block. Doing so will cause a deadlock. + + # @!method []=(key, value) + # Set a value with key + # @param [Object] key + # @param [Object] value + # @return [Object] the new value + + # @!method compute_if_absent(key) + # Compute and store new value for key if the key is absent. + # @param [Object] key + # @yield new value + # @yieldreturn [Object] new value + # @return [Object] new value or current value + # @!macro map.atomic_method_with_block + + # @!method compute_if_present(key) + # Compute and store new value for key if the key is present. + # @param [Object] key + # @yield new value + # @yieldparam old_value [Object] + # @yieldreturn [Object, nil] new value, when nil the key is removed + # @return [Object, nil] new value or nil + # @!macro map.atomic_method_with_block + + # @!method compute(key) + # Compute and store new value for key. + # @param [Object] key + # @yield compute new value from old one + # @yieldparam old_value [Object, nil] old_value, or nil when key is absent + # @yieldreturn [Object, nil] new value, when nil the key is removed + # @return [Object, nil] new value or nil + # @!macro map.atomic_method_with_block + + # @!method merge_pair(key, value) + # If the key is absent, the value is stored, otherwise new value is + # computed with a block. + # @param [Object] key + # @param [Object] value + # @yield compute new value from old one + # @yieldparam old_value [Object] old value + # @yieldreturn [Object, nil] new value, when nil the key is removed + # @return [Object, nil] new value or nil + # @!macro map.atomic_method_with_block + + # @!method replace_pair(key, old_value, new_value) + # Replaces old_value with new_value if key exists and current value + # matches old_value + # @param [Object] key + # @param [Object] old_value + # @param [Object] new_value + # @return [true, false] true if replaced + # @!macro map.atomic_method + + # @!method replace_if_exists(key, new_value) + # Replaces current value with new_value if key exists + # @param [Object] key + # @param [Object] new_value + # @return [Object, nil] old value or nil + # @!macro map.atomic_method + + # @!method get_and_set(key, value) + # Get the current value under key and set new value. + # @param [Object] key + # @param [Object] value + # @return [Object, nil] old value or nil when the key was absent + # @!macro map.atomic_method + + # @!method delete(key) + # Delete key and its value. + # @param [Object] key + # @return [Object, nil] old value or nil when the key was absent + # @!macro map.atomic_method + + # @!method delete_pair(key, value) + # Delete pair and its value if current value equals the provided value. + # @param [Object] key + # @param [Object] value + # @return [true, false] true if deleted + # @!macro map.atomic_method + + # NonConcurrentMapBackend handles default_proc natively + unless defined?(Collection::NonConcurrentMapBackend) and self < Collection::NonConcurrentMapBackend + + # @param [Hash, nil] options options to set the :initial_capacity or :load_factor. Ignored on some Rubies. + # @param [Proc] default_proc Optional block to compute the default value if the key is not set, like `Hash#default_proc` + def initialize(options = nil, &default_proc) + if options.kind_of?(::Hash) + validate_options_hash!(options) + else + options = nil + end + + super(options) + @default_proc = default_proc + end + + # Get a value with key + # @param [Object] key + # @return [Object] the value + 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 + # would be returned) + # note: nil == value check is not technically necessary + elsif @default_proc && nil == value && NULL == (value = get_or_default(key, NULL)) + @default_proc.call(self, key) + else + value + end + end + end + + alias_method :get, :[] + alias_method :put, :[]= + + # Get a value with key, or default_value when key is absent, + # or fail when no default_value is given. + # @param [Object] key + # @param [Object] default_value + # @yield default value for a key + # @yieldparam key [Object] + # @yieldreturn [Object] default value + # @return [Object] the value or default value + # @raise [KeyError] when key is missing and no default_value is provided + # @!macro map_method_not_atomic + # @note The "fetch-then-act" methods of `Map` are not atomic. `Map` is intended + # to be use as a concurrency primitive with strong happens-before + # guarantees. It is not intended to be used as a high-level abstraction + # supporting complex operations. All read and write operations are + # thread safe, but no guarantees are made regarding race conditions + # between the fetch operation and yielding to the block. Additionally, + # this method does not support recursion. This is due to internal + # constraints that are very unlikely to change in the near future. + def fetch(key, default_value = NULL) + if NULL != (value = get_or_default(key, NULL)) + value + elsif block_given? + yield key + elsif NULL != default_value + default_value + else + raise_fetch_no_key + end + end + + # Fetch value with key, or store default value when key is absent, + # or fail when no default_value is given. This is a two step operation, + # therefore not atomic. The store can overwrite other concurrently + # stored value. + # @param [Object] key + # @param [Object] default_value + # @yield default value for a key + # @yieldparam key [Object] + # @yieldreturn [Object] default value + # @return [Object] the value or default value + def fetch_or_store(key, default_value = NULL) + fetch(key) do + put(key, block_given? ? yield(key) : (NULL == default_value ? raise_fetch_no_key : default_value)) + end + end + + # Insert value into map with key if key is absent in one atomic step. + # @param [Object] key + # @param [Object] value + # @return [Object, nil] the previous value when key was present or nil when there was no key + def put_if_absent(key, value) + computed = false + result = compute_if_absent(key) do + computed = true + value + end + computed ? nil : result + end unless method_defined?(:put_if_absent) + + # Is the value stored in the map. Iterates over all values. + # @param [Object] value + # @return [true, false] + def value?(value) + each_value do |v| + return true if value.equal?(v) + end + false + end + + # All keys + # @return [::Array] keys + def keys + arr = [] + each_pair { |k, v| arr << k } + arr + end unless method_defined?(:keys) + + # All values + # @return [::Array] values + def values + arr = [] + each_pair { |k, v| arr << v } + arr + end unless method_defined?(:values) + + # Iterates over each key. + # @yield for each key in the map + # @yieldparam key [Object] + # @return [self] + # @!macro map.atomic_method_with_block + def each_key + each_pair { |k, v| yield k } + end unless method_defined?(:each_key) + + # Iterates over each value. + # @yield for each value in the map + # @yieldparam value [Object] + # @return [self] + # @!macro map.atomic_method_with_block + def each_value + each_pair { |k, v| yield v } + end unless method_defined?(:each_value) + + # Iterates over each key value pair. + # @yield for each key value pair in the map + # @yieldparam key [Object] + # @yieldparam value [Object] + # @return [self] + # @!macro map.atomic_method_with_block + def each_pair + return enum_for :each_pair unless block_given? + super + end + + alias_method :each, :each_pair unless method_defined?(:each) + + # Find key of a value. + # @param [Object] value + # @return [Object, nil] key or nil when not found + def key(value) + each_pair { |k, v| return k if v == value } + nil + end unless method_defined?(:key) + + # Is map empty? + # @return [true, false] + def empty? + each_pair { |k, v| return false } + true + end unless method_defined?(:empty?) + + # The size of map. + # @return [Integer] size + def size + count = 0 + each_pair { |k, v| count += 1 } + count + end unless method_defined?(:size) + + # @!visibility private + def marshal_dump + raise TypeError, "can't dump hash with default proc" if @default_proc + h = {} + each_pair { |k, v| h[k] = v } + h + end + + # @!visibility private + def marshal_load(hash) + initialize + populate_from(hash) + end + + undef :freeze + + # @!visibility private + def inspect + format '%s entries=%d default_proc=%s>', to_s[0..-2], size.to_s, @default_proc.inspect + end + + private + + def raise_fetch_no_key + raise KeyError, 'key not found' + end + + def initialize_copy(other) + super + populate_from(other) + end + + def populate_from(hash) + hash.each_pair { |k, v| self[k] = v } + self + end + + def validate_options_hash!(options) + if (initial_capacity = options[:initial_capacity]) && (!initial_capacity.kind_of?(Integer) || initial_capacity < 0) + raise ArgumentError, ":initial_capacity must be a positive Integer" + end + if (load_factor = options[:load_factor]) && (!load_factor.kind_of?(Numeric) || load_factor <= 0 || load_factor > 1) + raise ArgumentError, ":load_factor must be a number between 0 and 1" + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/maybe.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/maybe.rb new file mode 100644 index 0000000000000..317c82b86fa2a --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/maybe.rb @@ -0,0 +1,229 @@ +require 'concurrent/synchronization/object' + +module Concurrent + + # A `Maybe` encapsulates an optional value. A `Maybe` either contains a value + # of (represented as `Just`), or it is empty (represented as `Nothing`). Using + # `Maybe` is a good way to deal with errors or exceptional cases without + # resorting to drastic measures such as exceptions. + # + # `Maybe` is a replacement for the use of `nil` with better type checking. + # + # For compatibility with {Concurrent::Concern::Obligation} the predicate and + # accessor methods are aliased as `fulfilled?`, `rejected?`, `value`, and + # `reason`. + # + # ## Motivation + # + # A common pattern in languages with pattern matching, such as Erlang and + # Haskell, is to return *either* a value *or* an error from a function + # Consider this Erlang code: + # + # ```erlang + # case file:consult("data.dat") of + # {ok, Terms} -> do_something_useful(Terms); + # {error, Reason} -> lager:error(Reason) + # end. + # ``` + # + # In this example the standard library function `file:consult` returns a + # [tuple](http://erlang.org/doc/reference_manual/data_types.html#id69044) + # with two elements: an [atom](http://erlang.org/doc/reference_manual/data_types.html#id64134) + # (similar to a ruby symbol) and a variable containing ancillary data. On + # success it returns the atom `ok` and the data from the file. On failure it + # returns `error` and a string with an explanation of the problem. With this + # pattern there is no ambiguity regarding success or failure. If the file is + # empty the return value cannot be misinterpreted as an error. And when an + # error occurs the return value provides useful information. + # + # In Ruby we tend to return `nil` when an error occurs or else we raise an + # exception. Both of these idioms are problematic. Returning `nil` is + # ambiguous because `nil` may also be a valid value. It also lacks + # information pertaining to the nature of the error. Raising an exception + # is both expensive and usurps the normal flow of control. All of these + # problems can be solved with the use of a `Maybe`. + # + # A `Maybe` is unambiguous with regard to whether or not it contains a value. + # When `Just` it contains a value, when `Nothing` it does not. When `Just` + # the value it contains may be `nil`, which is perfectly valid. When + # `Nothing` the reason for the lack of a value is contained as well. The + # previous Erlang example can be duplicated in Ruby in a principled way by + # having functions return `Maybe` objects: + # + # ```ruby + # result = MyFileUtils.consult("data.dat") # returns a Maybe + # if result.just? + # do_something_useful(result.value) # or result.just + # else + # logger.error(result.reason) # or result.nothing + # end + # ``` + # + # @example Returning a Maybe from a Function + # module MyFileUtils + # def self.consult(path) + # file = File.open(path, 'r') + # Concurrent::Maybe.just(file.read) + # rescue => ex + # return Concurrent::Maybe.nothing(ex) + # ensure + # file.close if file + # end + # end + # + # maybe = MyFileUtils.consult('bogus.file') + # maybe.just? #=> false + # maybe.nothing? #=> true + # maybe.reason #=> # + # + # maybe = MyFileUtils.consult('README.md') + # maybe.just? #=> true + # maybe.nothing? #=> false + # maybe.value #=> "# Concurrent Ruby\n[![Gem Version..." + # + # @example Using Maybe with a Block + # result = Concurrent::Maybe.from do + # Client.find(10) # Client is an ActiveRecord model + # end + # + # # -- if the record was found + # result.just? #=> true + # result.value #=> # + # + # # -- if the record was not found + # result.just? #=> false + # result.reason #=> ActiveRecord::RecordNotFound + # + # @example Using Maybe with the Null Object Pattern + # # In a Rails controller... + # result = ClientService.new(10).find # returns a Maybe + # render json: result.or(NullClient.new) + # + # @see https://hackage.haskell.org/package/base-4.2.0.1/docs/Data-Maybe.html Haskell Data.Maybe + # @see https://github.com/purescript/purescript-maybe/blob/master/docs/Data.Maybe.md PureScript Data.Maybe + class Maybe < Synchronization::Object + include Comparable + safe_initialization! + + # Indicates that the given attribute has not been set. + # When `Just` the {#nothing} getter will return `NONE`. + # When `Nothing` the {#just} getter will return `NONE`. + NONE = ::Object.new.freeze + + # The value of a `Maybe` when `Just`. Will be `NONE` when `Nothing`. + attr_reader :just + + # The reason for the `Maybe` when `Nothing`. Will be `NONE` when `Just`. + attr_reader :nothing + + private_class_method :new + + # Create a new `Maybe` using the given block. + # + # Runs the given block passing all function arguments to the block as block + # arguments. If the block runs to completion without raising an exception + # a new `Just` is created with the value set to the return value of the + # block. If the block raises an exception a new `Nothing` is created with + # the reason being set to the raised exception. + # + # @param [Array] args Zero or more arguments to pass to the block. + # @yield The block from which to create a new `Maybe`. + # @yieldparam [Array] args Zero or more block arguments passed as + # arguments to the function. + # + # @return [Maybe] The newly created object. + # + # @raise [ArgumentError] when no block given. + def self.from(*args) + raise ArgumentError.new('no block given') unless block_given? + begin + value = yield(*args) + return new(value, NONE) + rescue => ex + return new(NONE, ex) + end + end + + # Create a new `Just` with the given value. + # + # @param [Object] value The value to set for the new `Maybe` object. + # + # @return [Maybe] The newly created object. + def self.just(value) + return new(value, NONE) + end + + # Create a new `Nothing` with the given (optional) reason. + # + # @param [Exception] error The reason to set for the new `Maybe` object. + # When given a string a new `StandardError` will be created with the + # argument as the message. When no argument is given a new + # `StandardError` with an empty message will be created. + # + # @return [Maybe] The newly created object. + def self.nothing(error = '') + if error.is_a?(Exception) + nothing = error + else + nothing = StandardError.new(error.to_s) + end + return new(NONE, nothing) + end + + # Is this `Maybe` a `Just` (successfully fulfilled with a value)? + # + # @return [Boolean] True if `Just` or false if `Nothing`. + def just? + ! nothing? + end + alias :fulfilled? :just? + + # Is this `Maybe` a `nothing` (rejected with an exception upon fulfillment)? + # + # @return [Boolean] True if `Nothing` or false if `Just`. + def nothing? + @nothing != NONE + end + alias :rejected? :nothing? + + alias :value :just + + alias :reason :nothing + + # Comparison operator. + # + # @return [Integer] 0 if self and other are both `Nothing`; + # -1 if self is `Nothing` and other is `Just`; + # 1 if self is `Just` and other is nothing; + # `self.just <=> other.just` if both self and other are `Just`. + def <=>(other) + if nothing? + other.nothing? ? 0 : -1 + else + other.nothing? ? 1 : just <=> other.just + end + end + + # Return either the value of self or the given default value. + # + # @return [Object] The value of self when `Just`; else the given default. + def or(other) + just? ? just : other + end + + private + + # Create a new `Maybe` with the given attributes. + # + # @param [Object] just The value when `Just` else `NONE`. + # @param [Exception, Object] nothing The exception when `Nothing` else `NONE`. + # + # @return [Maybe] The new `Maybe`. + # + # @!visibility private + def initialize(just, nothing) + @just = just + @nothing = nothing + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/mutable_struct.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/mutable_struct.rb new file mode 100644 index 0000000000000..5d0e9b9af59e0 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/mutable_struct.rb @@ -0,0 +1,239 @@ +require 'concurrent/synchronization/abstract_struct' +require 'concurrent/synchronization/lockable_object' + +module Concurrent + + # An thread-safe variation of Ruby's standard `Struct`. Values can be set at + # construction or safely changed at any time during the object's lifecycle. + # + # @see http://ruby-doc.org/core/Struct.html Ruby standard library `Struct` + module MutableStruct + include Synchronization::AbstractStruct + + # @!macro struct_new + # + # Factory for creating new struct classes. + # + # ``` + # new([class_name] [, member_name]+>) -> StructClass click to toggle source + # new([class_name] [, member_name]+>) {|StructClass| block } -> StructClass + # new(value, ...) -> obj + # StructClass[value, ...] -> obj + # ``` + # + # The first two forms are used to create a new struct subclass `class_name` + # that can contain a value for each member_name . This subclass can be + # used to create instances of the structure like any other Class . + # + # If the `class_name` is omitted an anonymous struct class will be created. + # Otherwise, the name of this struct will appear as a constant in the struct class, + # so it must be unique for all structs under this base class and must start with a + # capital letter. Assigning a struct class to a constant also gives the class + # the name of the constant. + # + # If a block is given it will be evaluated in the context of `StructClass`, passing + # the created class as a parameter. This is the recommended way to customize a struct. + # Subclassing an anonymous struct creates an extra anonymous class that will never be used. + # + # The last two forms create a new instance of a struct subclass. The number of value + # parameters must be less than or equal to the number of attributes defined for the + # struct. Unset parameters default to nil. Passing more parameters than number of attributes + # will raise an `ArgumentError`. + # + # @see http://ruby-doc.org/core/Struct.html#method-c-new Ruby standard library `Struct#new` + + # @!macro struct_values + # + # Returns the values for this struct as an Array. + # + # @return [Array] the values for this struct + # + def values + synchronize { ns_values } + end + alias_method :to_a, :values + + # @!macro struct_values_at + # + # Returns the struct member values for each selector as an Array. + # + # A selector may be either an Integer offset or a Range of offsets (as in `Array#values_at`). + # + # @param [Fixnum, Range] indexes the index(es) from which to obatin the values (in order) + def values_at(*indexes) + synchronize { ns_values_at(indexes) } + end + + # @!macro struct_inspect + # + # Describe the contents of this struct in a string. + # + # @return [String] the contents of this struct in a string + def inspect + synchronize { ns_inspect } + end + alias_method :to_s, :inspect + + # @!macro struct_merge + # + # Returns a new struct containing the contents of `other` and the contents + # of `self`. If no block is specified, the value for entries with duplicate + # keys will be that of `other`. Otherwise the value for each duplicate key + # is determined by calling the block with the key, its value in `self` and + # its value in `other`. + # + # @param [Hash] other the hash from which to set the new values + # @yield an options block for resolving duplicate keys + # @yieldparam [String, Symbol] member the name of the member which is duplicated + # @yieldparam [Object] selfvalue the value of the member in `self` + # @yieldparam [Object] othervalue the value of the member in `other` + # + # @return [Synchronization::AbstractStruct] a new struct with the new values + # + # @raise [ArgumentError] of given a member that is not defined in the struct + def merge(other, &block) + synchronize { ns_merge(other, &block) } + end + + # @!macro struct_to_h + # + # Returns a hash containing the names and values for the struct’s members. + # + # @return [Hash] the names and values for the struct’s members + def to_h + synchronize { ns_to_h } + end + + # @!macro struct_get + # + # Attribute Reference + # + # @param [Symbol, String, Integer] member the string or symbol name of the member + # for which to obtain the value or the member's index + # + # @return [Object] the value of the given struct member or the member at the given index. + # + # @raise [NameError] if the member does not exist + # @raise [IndexError] if the index is out of range. + def [](member) + synchronize { ns_get(member) } + end + + # @!macro struct_equality + # + # Equality + # + # @return [Boolean] true if other has the same struct subclass and has + # equal member values (according to `Object#==`) + def ==(other) + synchronize { ns_equality(other) } + end + + # @!macro struct_each + # + # Yields the value of each struct member in order. If no block is given + # an enumerator is returned. + # + # @yield the operation to be performed on each struct member + # @yieldparam [Object] value each struct value (in order) + def each(&block) + return enum_for(:each) unless block_given? + synchronize { ns_each(&block) } + end + + # @!macro struct_each_pair + # + # Yields the name and value of each struct member in order. If no block is + # given an enumerator is returned. + # + # @yield the operation to be performed on each struct member/value pair + # @yieldparam [Object] member each struct member (in order) + # @yieldparam [Object] value each struct value (in order) + def each_pair(&block) + return enum_for(:each_pair) unless block_given? + synchronize { ns_each_pair(&block) } + end + + # @!macro struct_select + # + # Yields each member value from the struct to the block and returns an Array + # containing the member values from the struct for which the given block + # returns a true value (equivalent to `Enumerable#select`). + # + # @yield the operation to be performed on each struct member + # @yieldparam [Object] value each struct value (in order) + # + # @return [Array] an array containing each value for which the block returns true + def select(&block) + return enum_for(:select) unless block_given? + synchronize { ns_select(&block) } + end + + # @!macro struct_set + # + # Attribute Assignment + # + # Sets the value of the given struct member or the member at the given index. + # + # @param [Symbol, String, Integer] member the string or symbol name of the member + # for which to obtain the value or the member's index + # + # @return [Object] the value of the given struct member or the member at the given index. + # + # @raise [NameError] if the name does not exist + # @raise [IndexError] if the index is out of range. + def []=(member, value) + if member.is_a? Integer + length = synchronize { @values.length } + if member >= length + raise IndexError.new("offset #{member} too large for struct(size:#{length})") + end + synchronize { @values[member] = value } + else + send("#{member}=", value) + end + rescue NoMethodError + raise NameError.new("no member '#{member}' in struct") + end + + private + + # @!visibility private + def initialize_copy(original) + synchronize do + super(original) + ns_initialize_copy + end + end + + # @!macro struct_new + def self.new(*args, &block) + clazz_name = nil + if args.length == 0 + raise ArgumentError.new('wrong number of arguments (0 for 1+)') + elsif args.length > 0 && args.first.is_a?(String) + clazz_name = args.shift + end + FACTORY.define_struct(clazz_name, args, &block) + end + + FACTORY = Class.new(Synchronization::LockableObject) do + def define_struct(name, members, &block) + synchronize do + clazz = Synchronization::AbstractStruct.define_struct_class(MutableStruct, Synchronization::LockableObject, name, members, &block) + members.each_with_index do |member, index| + clazz.send :remove_method, member + clazz.send(:define_method, member) do + synchronize { @values[index] } + end + clazz.send(:define_method, "#{member}=") do |value| + synchronize { @values[index] = value } + end + end + clazz + end + end + end.new + private_constant :FACTORY + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/mvar.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/mvar.rb new file mode 100644 index 0000000000000..dfc41950cf85f --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/mvar.rb @@ -0,0 +1,242 @@ +require 'concurrent/concern/dereferenceable' +require 'concurrent/synchronization/object' + +module Concurrent + + # An `MVar` is a synchronized single element container. They are empty or + # contain one item. Taking a value from an empty `MVar` blocks, as does + # putting a value into a full one. You can either think of them as blocking + # queue of length one, or a special kind of mutable variable. + # + # On top of the fundamental `#put` and `#take` operations, we also provide a + # `#mutate` that is atomic with respect to operations on the same instance. + # These operations all support timeouts. + # + # We also support non-blocking operations `#try_put!` and `#try_take!`, a + # `#set!` that ignores existing values, a `#value` that returns the value + # without removing it or returns `MVar::EMPTY`, and a `#modify!` that yields + # `MVar::EMPTY` if the `MVar` is empty and can be used to set `MVar::EMPTY`. + # You shouldn't use these operations in the first instance. + # + # `MVar` is a [Dereferenceable](Dereferenceable). + # + # `MVar` is related to M-structures in Id, `MVar` in Haskell and `SyncVar` in Scala. + # + # Note that unlike the original Haskell paper, our `#take` is blocking. This is how + # Haskell and Scala do it today. + # + # @!macro copy_options + # + # ## See Also + # + # 1. P. Barth, R. Nikhil, and Arvind. [M-Structures: Extending a parallel, non- strict, functional language with state](http://dl.acm.org/citation.cfm?id=652538). In Proceedings of the 5th + # ACM Conference on Functional Programming Languages and Computer Architecture (FPCA), 1991. + # + # 2. S. Peyton Jones, A. Gordon, and S. Finne. [Concurrent Haskell](http://dl.acm.org/citation.cfm?id=237794). + # In Proceedings of the 23rd Symposium on Principles of Programming Languages + # (PoPL), 1996. + class MVar < Synchronization::Object + include Concern::Dereferenceable + safe_initialization! + + # Unique value that represents that an `MVar` was empty + EMPTY = ::Object.new + + # Unique value that represents that an `MVar` timed out before it was able + # to produce a value. + TIMEOUT = ::Object.new + + # Create a new `MVar`, either empty or with an initial value. + # + # @param [Hash] opts the options controlling how the future will be processed + # + # @!macro deref_options + def initialize(value = EMPTY, opts = {}) + @value = value + @mutex = Mutex.new + @empty_condition = ConditionVariable.new + @full_condition = ConditionVariable.new + set_deref_options(opts) + end + + # Remove the value from an `MVar`, leaving it empty, and blocking if there + # isn't a value. A timeout can be set to limit the time spent blocked, in + # which case it returns `TIMEOUT` if the time is exceeded. + # @return [Object] the value that was taken, or `TIMEOUT` + def take(timeout = nil) + @mutex.synchronize do + wait_for_full(timeout) + + # If we timed out we'll still be empty + if unlocked_full? + value = @value + @value = EMPTY + @empty_condition.signal + apply_deref_options(value) + else + TIMEOUT + end + end + end + + # acquires lock on the from an `MVAR`, yields the value to provided block, + # and release lock. A timeout can be set to limit the time spent blocked, + # in which case it returns `TIMEOUT` if the time is exceeded. + # @return [Object] the value returned by the block, or `TIMEOUT` + def borrow(timeout = nil) + @mutex.synchronize do + wait_for_full(timeout) + + # if we timeoud out we'll still be empty + if unlocked_full? + yield @value + else + TIMEOUT + end + end + end + + # Put a value into an `MVar`, blocking if there is already a value until + # it is empty. A timeout can be set to limit the time spent blocked, in + # which case it returns `TIMEOUT` if the time is exceeded. + # @return [Object] the value that was put, or `TIMEOUT` + def put(value, timeout = nil) + @mutex.synchronize do + wait_for_empty(timeout) + + # If we timed out we won't be empty + if unlocked_empty? + @value = value + @full_condition.signal + apply_deref_options(value) + else + TIMEOUT + end + end + end + + # Atomically `take`, yield the value to a block for transformation, and then + # `put` the transformed value. Returns the transformed value. A timeout can + # be set to limit the time spent blocked, in which case it returns `TIMEOUT` + # if the time is exceeded. + # @return [Object] the transformed value, or `TIMEOUT` + def modify(timeout = nil) + raise ArgumentError.new('no block given') unless block_given? + + @mutex.synchronize do + wait_for_full(timeout) + + # If we timed out we'll still be empty + if unlocked_full? + value = @value + @value = yield value + @full_condition.signal + apply_deref_options(value) + else + TIMEOUT + end + end + end + + # Non-blocking version of `take`, that returns `EMPTY` instead of blocking. + def try_take! + @mutex.synchronize do + if unlocked_full? + value = @value + @value = EMPTY + @empty_condition.signal + apply_deref_options(value) + else + EMPTY + end + end + end + + # Non-blocking version of `put`, that returns whether or not it was successful. + def try_put!(value) + @mutex.synchronize do + if unlocked_empty? + @value = value + @full_condition.signal + true + else + false + end + end + end + + # Non-blocking version of `put` that will overwrite an existing value. + def set!(value) + @mutex.synchronize do + old_value = @value + @value = value + @full_condition.signal + apply_deref_options(old_value) + end + end + + # Non-blocking version of `modify` that will yield with `EMPTY` if there is no value yet. + def modify! + raise ArgumentError.new('no block given') unless block_given? + + @mutex.synchronize do + value = @value + @value = yield value + if unlocked_empty? + @empty_condition.signal + else + @full_condition.signal + end + apply_deref_options(value) + end + end + + # Returns if the `MVar` is currently empty. + def empty? + @mutex.synchronize { @value == EMPTY } + end + + # Returns if the `MVar` currently contains a value. + def full? + !empty? + end + + protected + + def synchronize(&block) + @mutex.synchronize(&block) + end + + private + + def unlocked_empty? + @value == EMPTY + end + + def unlocked_full? + ! unlocked_empty? + end + + def wait_for_full(timeout) + wait_while(@full_condition, timeout) { unlocked_empty? } + end + + def wait_for_empty(timeout) + wait_while(@empty_condition, timeout) { unlocked_full? } + end + + def wait_while(condition, timeout) + if timeout.nil? + while yield + condition.wait(@mutex) + end + else + stop = Concurrent.monotonic_time + timeout + while yield && timeout > 0.0 + condition.wait(@mutex, timeout) + timeout = stop - Concurrent.monotonic_time + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/options.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/options.rb new file mode 100644 index 0000000000000..bdd22a9df15d4 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/options.rb @@ -0,0 +1,42 @@ +require 'concurrent/configuration' + +module Concurrent + + # @!visibility private + module Options + + # Get the requested `Executor` based on the values set in the options hash. + # + # @param [Hash] opts the options defining the requested executor + # @option opts [Executor] :executor when set use the given `Executor` instance. + # Three special values are also supported: `:fast` returns the global fast executor, + # `:io` returns the global io executor, and `:immediate` returns a new + # `ImmediateExecutor` object. + # + # @return [Executor, nil] the requested thread pool, or nil when no option specified + # + # @!visibility private + def self.executor_from_options(opts = {}) # :nodoc: + if identifier = opts.fetch(:executor, nil) + executor(identifier) + else + nil + end + end + + def self.executor(executor_identifier) + case executor_identifier + when :fast + Concurrent.global_fast_executor + when :io + Concurrent.global_io_executor + when :immediate + Concurrent.global_immediate_executor + when Concurrent::ExecutorService + executor_identifier + else + raise ArgumentError, "executor not recognized by '#{executor_identifier}'" + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/promise.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/promise.rb new file mode 100644 index 0000000000000..ccc47dd628c8d --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/promise.rb @@ -0,0 +1,580 @@ +require 'thread' +require 'concurrent/constants' +require 'concurrent/errors' +require 'concurrent/ivar' +require 'concurrent/executor/safe_task_executor' + +require 'concurrent/options' + +module Concurrent + + PromiseExecutionError = Class.new(StandardError) + + # Promises are inspired by the JavaScript [Promises/A](http://wiki.commonjs.org/wiki/Promises/A) + # and [Promises/A+](http://promises-aplus.github.io/promises-spec/) specifications. + # + # > A promise represents the eventual value returned from the single + # > completion of an operation. + # + # Promises are similar to futures and share many of the same behaviours. + # Promises are far more robust, however. Promises can be chained in a tree + # structure where each promise may have zero or more children. Promises are + # chained using the `then` method. The result of a call to `then` is always + # another promise. Promises are resolved asynchronously (with respect to the + # main thread) but in a strict order: parents are guaranteed to be resolved + # before their children, children before their younger siblings. The `then` + # method takes two parameters: an optional block to be executed upon parent + # resolution and an optional callable to be executed upon parent failure. The + # result of each promise is passed to each of its children upon resolution. + # When a promise is rejected all its children will be summarily rejected and + # will receive the reason. + # + # Promises have several possible states: *:unscheduled*, *:pending*, + # *:processing*, *:rejected*, or *:fulfilled*. These are also aggregated as + # `#incomplete?` and `#complete?`. When a Promise is created it is set to + # *:unscheduled*. Once the `#execute` method is called the state becomes + # *:pending*. Once a job is pulled from the thread pool's queue and is given + # to a thread for processing (often immediately upon `#post`) the state + # becomes *:processing*. The future will remain in this state until processing + # is complete. A future that is in the *:unscheduled*, *:pending*, or + # *:processing* is considered `#incomplete?`. A `#complete?` Promise is either + # *:rejected*, indicating that an exception was thrown during processing, or + # *:fulfilled*, indicating success. If a Promise is *:fulfilled* its `#value` + # will be updated to reflect the result of the operation. If *:rejected* the + # `reason` will be updated with a reference to the thrown exception. The + # predicate methods `#unscheduled?`, `#pending?`, `#rejected?`, and + # `#fulfilled?` can be called at any time to obtain the state of the Promise, + # as can the `#state` method, which returns a symbol. + # + # Retrieving the value of a promise is done through the `value` (alias: + # `deref`) method. Obtaining the value of a promise is a potentially blocking + # operation. When a promise is *rejected* a call to `value` will return `nil` + # immediately. When a promise is *fulfilled* a call to `value` will + # immediately return the current value. When a promise is *pending* a call to + # `value` will block until the promise is either *rejected* or *fulfilled*. A + # *timeout* value can be passed to `value` to limit how long the call will + # block. If `nil` the call will block indefinitely. If `0` the call will not + # block. Any other integer or float value will indicate the maximum number of + # seconds to block. + # + # Promises run on the global thread pool. + # + # @!macro copy_options + # + # ### Examples + # + # Start by requiring promises + # + # ```ruby + # require 'concurrent/promise' + # ``` + # + # Then create one + # + # ```ruby + # p = Concurrent::Promise.execute do + # # do something + # 42 + # end + # ``` + # + # Promises can be chained using the `then` method. The `then` method accepts a + # block and an executor, to be executed on fulfillment, and a callable argument to be executed + # on rejection. The result of the each promise is passed as the block argument + # to chained promises. + # + # ```ruby + # p = Concurrent::Promise.new{10}.then{|x| x * 2}.then{|result| result - 10 }.execute + # ``` + # + # And so on, and so on, and so on... + # + # ```ruby + # p = Concurrent::Promise.fulfill(20). + # then{|result| result - 10 }. + # then{|result| result * 3 }. + # then(executor: different_executor){|result| result % 5 }.execute + # ``` + # + # The initial state of a newly created Promise depends on the state of its parent: + # - if parent is *unscheduled* the child will be *unscheduled* + # - if parent is *pending* the child will be *pending* + # - if parent is *fulfilled* the child will be *pending* + # - 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 + # 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. + # + # There are multiple ways to create and execute a new `Promise`. Both ways + # provide identical behavior: + # + # ```ruby + # # create, operate, then execute + # p1 = Concurrent::Promise.new{ "Hello World!" } + # p1.state #=> :unscheduled + # p1.execute + # + # # create and immediately execute + # p2 = Concurrent::Promise.new{ "Hello World!" }.execute + # + # # execute during creation + # p3 = Concurrent::Promise.execute{ "Hello World!" } + # ``` + # + # Once the `execute` method is called a `Promise` becomes `pending`: + # + # ```ruby + # p = Concurrent::Promise.execute{ "Hello, world!" } + # p.state #=> :pending + # p.pending? #=> true + # ``` + # + # Wait a little bit, and the promise will resolve and provide a value: + # + # ```ruby + # p = Concurrent::Promise.execute{ "Hello, world!" } + # sleep(0.1) + # + # p.state #=> :fulfilled + # p.fulfilled? #=> true + # p.value #=> "Hello, world!" + # ``` + # + # If an exception occurs, the promise will be rejected and will provide + # a reason for the rejection: + # + # ```ruby + # p = Concurrent::Promise.execute{ raise StandardError.new("Here comes the Boom!") } + # sleep(0.1) + # + # p.state #=> :rejected + # p.rejected? #=> true + # p.reason #=> "#" + # ``` + # + # #### Rejection + # + # When a promise is rejected all its children will be rejected and will + # receive the rejection `reason` as the rejection callable parameter: + # + # ```ruby + # p = Concurrent::Promise.execute { Thread.pass; raise StandardError } + # + # c1 = p.then(-> reason { 42 }) + # c2 = p.then(-> reason { raise 'Boom!' }) + # + # c1.wait.state #=> :fulfilled + # c1.value #=> 45 + # c2.wait.state #=> :rejected + # c2.reason #=> # + # ``` + # + # Once a promise is rejected it will continue to accept children that will + # receive immediately rejection (they will be executed asynchronously). + # + # #### Aliases + # + # The `then` method is the most generic alias: it accepts a block to be + # executed upon parent fulfillment and a callable to be executed upon parent + # rejection. At least one of them should be passed. The default block is `{ + # |result| result }` that fulfills the child with the parent value. The + # default callable is `{ |reason| raise reason }` that rejects the child with + # the parent reason. + # + # - `on_success { |result| ... }` is the same as `then {|result| ... }` + # - `rescue { |reason| ... }` is the same as `then(Proc.new { |reason| ... } )` + # - `rescue` is aliased by `catch` and `on_error` + class Promise < IVar + + # Initialize a new Promise with the provided options. + # + # @!macro executor_and_deref_options + # + # @!macro promise_init_options + # + # @option opts [Promise] :parent the parent `Promise` when building a chain/tree + # @option opts [Proc] :on_fulfill fulfillment handler + # @option opts [Proc] :on_reject rejection handler + # @option opts [object, Array] :args zero or more arguments to be passed + # the task block on execution + # + # @yield The block operation to be performed asynchronously. + # + # @raise [ArgumentError] if no block is given + # + # @see http://wiki.commonjs.org/wiki/Promises/A + # @see http://promises-aplus.github.io/promises-spec/ + def initialize(opts = {}, &block) + opts.delete_if { |k, v| v.nil? } + super(NULL, opts.merge(__promise_body_from_block__: block), &nil) + end + + # Create a new `Promise` and fulfill it immediately. + # + # @!macro executor_and_deref_options + # + # @!macro promise_init_options + # + # @raise [ArgumentError] if no block is given + # + # @return [Promise] the newly created `Promise` + def self.fulfill(value, opts = {}) + Promise.new(opts).tap { |p| p.send(:synchronized_set_state!, true, value, nil) } + end + + # Create a new `Promise` and reject it immediately. + # + # @!macro executor_and_deref_options + # + # @!macro promise_init_options + # + # @raise [ArgumentError] if no block is given + # + # @return [Promise] the newly created `Promise` + def self.reject(reason, opts = {}) + Promise.new(opts).tap { |p| p.send(:synchronized_set_state!, false, nil, reason) } + end + + # Execute an `:unscheduled` `Promise`. Immediately sets the state to `:pending` and + # passes the block to a new thread/thread pool for eventual execution. + # Does nothing if the `Promise` is in any state other than `:unscheduled`. + # + # @return [Promise] a reference to `self` + def execute + if root? + if compare_and_set_state(:pending, :unscheduled) + set_pending + realize(@promise_body) + end + else + compare_and_set_state(:pending, :unscheduled) + @parent.execute + end + self + end + + # @!macro ivar_set_method + # + # @raise [Concurrent::PromiseExecutionError] if not the root promise + def set(value = NULL, &block) + raise PromiseExecutionError.new('supported only on root promise') unless root? + check_for_block_or_value!(block_given?, value) + synchronize do + if @state != :unscheduled + raise MultipleAssignmentError + else + @promise_body = block || Proc.new { |result| value } + end + end + execute + end + + # @!macro ivar_fail_method + # + # @raise [Concurrent::PromiseExecutionError] if not the root promise + def fail(reason = StandardError.new) + set { raise reason } + end + + # Create a new `Promise` object with the given block, execute it, and return the + # `:pending` object. + # + # @!macro executor_and_deref_options + # + # @!macro promise_init_options + # + # @return [Promise] the newly created `Promise` in the `:pending` state + # + # @raise [ArgumentError] if no block is given + # + # @example + # promise = Concurrent::Promise.execute{ sleep(1); 42 } + # promise.state #=> :pending + def self.execute(opts = {}, &block) + new(opts, &block).execute + end + + # Chain a new promise off the current promise. + # + # @return [Promise] the new promise + # @yield The block operation to be performed asynchronously. + # @overload then(rescuer, executor, &block) + # @param [Proc] rescuer An optional rescue block to be executed if the + # promise is rejected. + # @param [ThreadPool] executor An optional thread pool executor to be used + # in the new Promise + # @overload then(rescuer, executor: executor, &block) + # @param [Proc] rescuer An optional rescue block to be executed if the + # promise is rejected. + # @param [ThreadPool] executor An optional thread pool executor to be used + # in the new Promise + def then(*args, &block) + if args.last.is_a?(::Hash) + executor = args.pop[:executor] + rescuer = args.first + else + rescuer, executor = args + end + + executor ||= @executor + + raise ArgumentError.new('rescuers and block are both missing') if rescuer.nil? && !block_given? + block = Proc.new { |result| result } unless block_given? + child = Promise.new( + parent: self, + executor: executor, + on_fulfill: block, + on_reject: rescuer + ) + + synchronize do + child.state = :pending if @state == :pending + child.on_fulfill(apply_deref_options(@value)) if @state == :fulfilled + child.on_reject(@reason) if @state == :rejected + @children << child + end + + child + end + + # Chain onto this promise an action to be undertaken on success + # (fulfillment). + # + # @yield The block to execute + # + # @return [Promise] self + def on_success(&block) + raise ArgumentError.new('no block given') unless block_given? + self.then(&block) + end + + # Chain onto this promise an action to be undertaken on failure + # (rejection). + # + # @yield The block to execute + # + # @return [Promise] self + def rescue(&block) + self.then(block) + end + + alias_method :catch, :rescue + alias_method :on_error, :rescue + + # Yield the successful result to the block that returns a promise. If that + # promise is also successful the result is the result of the yielded promise. + # If either part fails the whole also fails. + # + # @example + # Promise.execute { 1 }.flat_map { |v| Promise.execute { v + 2 } }.value! #=> 3 + # + # @return [Promise] + def flat_map(&block) + child = Promise.new( + parent: self, + executor: ImmediateExecutor.new, + ) + + on_error { |e| child.on_reject(e) } + on_success do |result1| + begin + inner = block.call(result1) + inner.execute + inner.on_success { |result2| child.on_fulfill(result2) } + inner.on_error { |e| child.on_reject(e) } + rescue => e + child.on_reject(e) + end + end + + child + end + + # Builds a promise that produces the result of promises in an Array + # and fails if any of them fails. + # + # @overload zip(*promises) + # @param [Array] promises + # + # @overload zip(*promises, opts) + # @param [Array] promises + # @param [Hash] opts the configuration options + # @option opts [Executor] :executor (ImmediateExecutor.new) when set use the given `Executor` instance. + # @option opts [Boolean] :execute (true) execute promise before returning + # + # @return [Promise] + def self.zip(*promises) + opts = promises.last.is_a?(::Hash) ? promises.pop.dup : {} + opts[:executor] ||= ImmediateExecutor.new + zero = if !opts.key?(:execute) || opts.delete(:execute) + fulfill([], opts) + else + Promise.new(opts) { [] } + end + + promises.reduce(zero) do |p1, p2| + p1.flat_map do |results| + p2.then do |next_result| + results << next_result + end + end + end + end + + # Builds a promise that produces the result of self and others in an Array + # and fails if any of them fails. + # + # @overload zip(*promises) + # @param [Array] others + # + # @overload zip(*promises, opts) + # @param [Array] others + # @param [Hash] opts the configuration options + # @option opts [Executor] :executor (ImmediateExecutor.new) when set use the given `Executor` instance. + # @option opts [Boolean] :execute (true) execute promise before returning + # + # @return [Promise] + def zip(*others) + self.class.zip(self, *others) + end + + # Aggregates a collection of promises and executes the `then` condition + # if all aggregated promises succeed. Executes the `rescue` handler with + # a `Concurrent::PromiseExecutionError` if any of the aggregated promises + # fail. Upon execution will execute any of the aggregate promises that + # were not already executed. + # + # @!macro promise_self_aggregate + # + # The returned promise will not yet have been executed. Additional `#then` + # and `#rescue` handlers may still be provided. Once the returned promise + # is execute the aggregate promises will be also be executed (if they have + # not been executed already). The results of the aggregate promises will + # be checked upon completion. The necessary `#then` and `#rescue` blocks + # on the aggregating promise will then be executed as appropriate. If the + # `#rescue` handlers are executed the raises exception will be + # `Concurrent::PromiseExecutionError`. + # + # @param [Array] promises Zero or more promises to aggregate + # @return [Promise] an unscheduled (not executed) promise that aggregates + # the promises given as arguments + def self.all?(*promises) + aggregate(:all?, *promises) + end + + # Aggregates a collection of promises and executes the `then` condition + # if any aggregated promises succeed. Executes the `rescue` handler with + # a `Concurrent::PromiseExecutionError` if any of the aggregated promises + # fail. Upon execution will execute any of the aggregate promises that + # were not already executed. + # + # @!macro promise_self_aggregate + def self.any?(*promises) + aggregate(:any?, *promises) + end + + protected + + def ns_initialize(value, opts) + super + + @executor = Options.executor_from_options(opts) || Concurrent.global_io_executor + @args = get_arguments_from(opts) + + @parent = opts.fetch(:parent) { nil } + @on_fulfill = opts.fetch(:on_fulfill) { Proc.new { |result| result } } + @on_reject = opts.fetch(:on_reject) { Proc.new { |reason| raise reason } } + + @promise_body = opts[:__promise_body_from_block__] || Proc.new { |result| result } + @state = :unscheduled + @children = [] + end + + # Aggregate a collection of zero or more promises under a composite promise, + # execute the aggregated promises and collect them into a standard Ruby array, + # call the given Ruby `Ennnumerable` predicate (such as `any?`, `all?`, `none?`, + # or `one?`) on the collection checking for the success or failure of each, + # then executing the composite's `#then` handlers if the predicate returns + # `true` or executing the composite's `#rescue` handlers if the predicate + # returns false. + # + # @!macro promise_self_aggregate + def self.aggregate(method, *promises) + composite = Promise.new do + completed = promises.collect do |promise| + promise.execute if promise.unscheduled? + promise.wait + promise + end + unless completed.empty? || completed.send(method){|promise| promise.fulfilled? } + raise PromiseExecutionError + end + end + composite + end + + # @!visibility private + def set_pending + synchronize do + @state = :pending + @children.each { |c| c.set_pending } + end + end + + # @!visibility private + def root? # :nodoc: + @parent.nil? + end + + # @!visibility private + def on_fulfill(result) + realize Proc.new { @on_fulfill.call(result) } + nil + end + + # @!visibility private + def on_reject(reason) + realize Proc.new { @on_reject.call(reason) } + nil + end + + # @!visibility private + def notify_child(child) + if_state(:fulfilled) { child.on_fulfill(apply_deref_options(@value)) } + if_state(:rejected) { child.on_reject(@reason) } + end + + # @!visibility private + def complete(success, value, reason) + children_to_notify = synchronize do + set_state!(success, value, reason) + @children.dup + end + + children_to_notify.each { |child| notify_child(child) } + observers.notify_and_delete_observers{ [Time.now, self.value, reason] } + end + + # @!visibility private + def realize(task) + @executor.post do + success, value, reason = SafeTaskExecutor.new(task, rescue_exception: true).execute(*@args) + complete(success, value, reason) + end + end + + # @!visibility private + def set_state!(success, value, reason) + set_state(success, value, reason) + event.set + end + + # @!visibility private + def synchronized_set_state!(success, value, reason) + synchronize { set_state!(success, value, reason) } + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/promises.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/promises.rb new file mode 100644 index 0000000000000..c5df8fe9cb9fd --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/promises.rb @@ -0,0 +1,2178 @@ +require 'concurrent/synchronization/object' +require 'concurrent/atomic/atomic_boolean' +require 'concurrent/atomic/atomic_fixnum' +require 'concurrent/collection/lock_free_stack' +require 'concurrent/configuration' +require 'concurrent/errors' +require 'concurrent/re_include' +require 'concurrent/utility/monotonic_time' + +module Concurrent + + # {include:file:docs-source/promises-main.md} + module Promises + + # @!macro promises.param.default_executor + # @param [Executor, :io, :fast] default_executor Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # + # @!macro promises.param.executor + # @param [Executor, :io, :fast] executor Instance of an executor or a name of the + # global executor. The task is executed on it, default executor remains unchanged. + # + # @!macro promises.param.args + # @param [Object] args arguments which are passed to the task when it's executed. + # (It might be prepended with other arguments, see the @yield section). + # + # @!macro promises.shortcut.on + # Shortcut of {#$0_on} with default `:io` executor supplied. + # @see #$0_on + # + # @!macro promises.shortcut.using + # Shortcut of {#$0_using} with default `:io` executor supplied. + # @see #$0_using + # + # @!macro promise.param.task-future + # @yieldreturn will become result of the returned Future. + # Its returned value becomes {Future#value} fulfilling it, + # raised exception becomes {Future#reason} rejecting it. + # + # @!macro promise.param.callback + # @yieldreturn is forgotten. + + # Container of all {Future}, {Event} factory methods. They are never constructed directly with + # new. + module FactoryMethods + extend ReInclude + extend self + + module Configuration + # @return [Executor, :io, :fast] the executor which is used when none is supplied + # to a factory method. The method can be overridden in the receivers of + # `include FactoryMethod` + def default_executor + :io + end + end + + include Configuration + + # @!macro promises.shortcut.on + # @return [ResolvableEvent] + def resolvable_event + resolvable_event_on default_executor + end + + # Creates a resolvable event, user is responsible for resolving the event once + # by calling {Promises::ResolvableEvent#resolve}. + # + # @!macro promises.param.default_executor + # @return [ResolvableEvent] + def resolvable_event_on(default_executor = self.default_executor) + ResolvableEventPromise.new(default_executor).future + end + + # @!macro promises.shortcut.on + # @return [ResolvableFuture] + def resolvable_future + resolvable_future_on default_executor + end + + # Creates resolvable future, user is responsible for resolving the future once by + # {Promises::ResolvableFuture#resolve}, {Promises::ResolvableFuture#fulfill}, + # or {Promises::ResolvableFuture#reject} + # + # @!macro promises.param.default_executor + # @return [ResolvableFuture] + def resolvable_future_on(default_executor = self.default_executor) + ResolvableFuturePromise.new(default_executor).future + end + + # @!macro promises.shortcut.on + # @return [Future] + def future(*args, &task) + future_on(default_executor, *args, &task) + end + + # Constructs a new Future which will be resolved after block is evaluated on default executor. + # Evaluation begins immediately. + # + # @!macro promises.param.default_executor + # @!macro promises.param.args + # @yield [*args] to the task. + # @!macro promise.param.task-future + # @return [Future] + def future_on(default_executor, *args, &task) + ImmediateEventPromise.new(default_executor).future.then(*args, &task) + end + + # Creates a resolved future with will be either fulfilled with the given value or rejected with + # the given reason. + # + # @param [true, false] fulfilled + # @param [Object] value + # @param [Object] reason + # @!macro promises.param.default_executor + # @return [Future] + def resolved_future(fulfilled, value, reason, default_executor = self.default_executor) + ImmediateFuturePromise.new(default_executor, fulfilled, value, reason).future + end + + # Creates a resolved future which will be fulfilled with the given value. + # + # @!macro promises.param.default_executor + # @param [Object] value + # @return [Future] + def fulfilled_future(value, default_executor = self.default_executor) + resolved_future true, value, nil, default_executor + end + + # Creates a resolved future which will be rejected with the given reason. + # + # @!macro promises.param.default_executor + # @param [Object] reason + # @return [Future] + def rejected_future(reason, default_executor = self.default_executor) + resolved_future false, nil, reason, default_executor + end + + # Creates resolved event. + # + # @!macro promises.param.default_executor + # @return [Event] + def resolved_event(default_executor = self.default_executor) + ImmediateEventPromise.new(default_executor).event + end + + # General constructor. Behaves differently based on the argument's type. It's provided for convenience + # but it's better to be explicit. + # + # @see rejected_future, resolved_event, fulfilled_future + # @!macro promises.param.default_executor + # @return [Event, Future] + # + # @overload make_future(nil, default_executor = self.default_executor) + # @param [nil] nil + # @return [Event] resolved event. + # + # @overload make_future(a_future, default_executor = self.default_executor) + # @param [Future] a_future + # @return [Future] a future which will be resolved when a_future is. + # + # @overload make_future(an_event, default_executor = self.default_executor) + # @param [Event] an_event + # @return [Event] an event which will be resolved when an_event is. + # + # @overload make_future(exception, default_executor = self.default_executor) + # @param [Exception] exception + # @return [Future] a rejected future with the exception as its reason. + # + # @overload make_future(value, default_executor = self.default_executor) + # @param [Object] value when none of the above overloads fits + # @return [Future] a fulfilled future with the value. + def make_future(argument = nil, default_executor = self.default_executor) + case argument + when AbstractEventFuture + # returning wrapper would change nothing + argument + when Exception + rejected_future argument, default_executor + when nil + resolved_event default_executor + else + fulfilled_future argument, default_executor + end + end + + # @!macro promises.shortcut.on + # @return [Future, Event] + def delay(*args, &task) + delay_on default_executor, *args, &task + end + + # Creates a new event or future which is resolved only after it is touched, + # see {Concurrent::AbstractEventFuture#touch}. + # + # @!macro promises.param.default_executor + # @overload delay_on(default_executor, *args, &task) + # If task is provided it returns a {Future} representing the result of the task. + # @!macro promises.param.args + # @yield [*args] to the task. + # @!macro promise.param.task-future + # @return [Future] + # @overload delay_on(default_executor) + # If no task is provided, it returns an {Event} + # @return [Event] + def delay_on(default_executor, *args, &task) + event = DelayPromise.new(default_executor).event + task ? event.chain(*args, &task) : event + end + + # @!macro promises.shortcut.on + # @return [Future, Event] + def schedule(intended_time, *args, &task) + schedule_on default_executor, intended_time, *args, &task + end + + # Creates a new event or future which is resolved in intended_time. + # + # @!macro promises.param.default_executor + # @!macro promises.param.intended_time + # @param [Numeric, Time] intended_time `Numeric` means to run in `intended_time` seconds. + # `Time` means to run on `intended_time`. + # @overload schedule_on(default_executor, intended_time, *args, &task) + # If task is provided it returns a {Future} representing the result of the task. + # @!macro promises.param.args + # @yield [*args] to the task. + # @!macro promise.param.task-future + # @return [Future] + # @overload schedule_on(default_executor, intended_time) + # If no task is provided, it returns an {Event} + # @return [Event] + def schedule_on(default_executor, intended_time, *args, &task) + event = ScheduledPromise.new(default_executor, intended_time).event + task ? event.chain(*args, &task) : event + end + + # @!macro promises.shortcut.on + # @return [Future] + def zip_futures(*futures_and_or_events) + zip_futures_on default_executor, *futures_and_or_events + end + + # Creates a new future which is resolved after all futures_and_or_events are resolved. + # Its value is an array of zipped future values. Its reason is an array of reasons for rejection. + # If there is an error it rejects. + # @!macro promises.event-conversion + # If event is supplied, which does not have value and can be only resolved, it's + # represented as `:fulfilled` with value `nil`. + # + # @!macro promises.param.default_executor + # @param [AbstractEventFuture] futures_and_or_events + # @return [Future] + def zip_futures_on(default_executor, *futures_and_or_events) + ZipFuturesPromise.new_blocked_by(futures_and_or_events, default_executor).future + end + + alias_method :zip, :zip_futures + + # @!macro promises.shortcut.on + # @return [Event] + def zip_events(*futures_and_or_events) + zip_events_on default_executor, *futures_and_or_events + end + + # Creates a new event which is resolved after all futures_and_or_events are resolved. + # (Future is resolved when fulfilled or rejected.) + # + # @!macro promises.param.default_executor + # @param [AbstractEventFuture] futures_and_or_events + # @return [Event] + def zip_events_on(default_executor, *futures_and_or_events) + ZipEventsPromise.new_blocked_by(futures_and_or_events, default_executor).event + end + + # @!macro promises.shortcut.on + # @return [Future] + def any_resolved_future(*futures_and_or_events) + any_resolved_future_on default_executor, *futures_and_or_events + end + + alias_method :any, :any_resolved_future + + # Creates a new future which is resolved after the first futures_and_or_events is resolved. + # Its result equals the result of the first resolved future. + # @!macro promises.any-touch + # If resolved it does not propagate {Concurrent::AbstractEventFuture#touch}, leaving delayed + # futures un-executed if they are not required any more. + # @!macro promises.event-conversion + # + # @!macro promises.param.default_executor + # @param [AbstractEventFuture] futures_and_or_events + # @return [Future] + def any_resolved_future_on(default_executor, *futures_and_or_events) + AnyResolvedFuturePromise.new_blocked_by(futures_and_or_events, default_executor).future + end + + # @!macro promises.shortcut.on + # @return [Future] + def any_fulfilled_future(*futures_and_or_events) + any_fulfilled_future_on default_executor, *futures_and_or_events + end + + # Creates a new future which is resolved after the first futures_and_or_events is fulfilled. + # Its result equals the result of the first resolved future or if all futures_and_or_events reject, + # it has reason of the last rejected future. + # @!macro promises.any-touch + # @!macro promises.event-conversion + # + # @!macro promises.param.default_executor + # @param [AbstractEventFuture] futures_and_or_events + # @return [Future] + def any_fulfilled_future_on(default_executor, *futures_and_or_events) + AnyFulfilledFuturePromise.new_blocked_by(futures_and_or_events, default_executor).future + end + + # @!macro promises.shortcut.on + # @return [Event] + def any_event(*futures_and_or_events) + any_event_on default_executor, *futures_and_or_events + end + + # Creates a new event which becomes resolved after the first futures_and_or_events resolves. + # @!macro promises.any-touch + # + # @!macro promises.param.default_executor + # @param [AbstractEventFuture] futures_and_or_events + # @return [Event] + def any_event_on(default_executor, *futures_and_or_events) + AnyResolvedEventPromise.new_blocked_by(futures_and_or_events, default_executor).event + end + + # TODO consider adding first(count, *futures) + # TODO consider adding zip_by(slice, *futures) processing futures in slices + # TODO or rather a generic aggregator taking a function + end + + module InternalStates + # @!visibility private + class State + def resolved? + raise NotImplementedError + end + + def to_sym + raise NotImplementedError + end + end + + # @!visibility private + class Pending < State + def resolved? + false + end + + def to_sym + :pending + end + end + + # @!visibility private + class Reserved < Pending + end + + # @!visibility private + class ResolvedWithResult < State + def resolved? + true + end + + def to_sym + :resolved + end + + def result + [fulfilled?, value, reason] + end + + def fulfilled? + raise NotImplementedError + end + + def value + raise NotImplementedError + end + + def reason + raise NotImplementedError + end + + def apply + raise NotImplementedError + end + end + + # @!visibility private + class Fulfilled < ResolvedWithResult + + def initialize(value) + @Value = value + end + + def fulfilled? + true + end + + def apply(args, block) + block.call value, *args + end + + def value + @Value + end + + def reason + nil + end + + def to_sym + :fulfilled + end + end + + # @!visibility private + class FulfilledArray < Fulfilled + def apply(args, block) + block.call(*value, *args) + end + end + + # @!visibility private + class Rejected < ResolvedWithResult + def initialize(reason) + @Reason = reason + end + + def fulfilled? + false + end + + def value + nil + end + + def reason + @Reason + end + + def to_sym + :rejected + end + + def apply(args, block) + block.call reason, *args + end + end + + # @!visibility private + class PartiallyRejected < ResolvedWithResult + def initialize(value, reason) + super() + @Value = value + @Reason = reason + end + + def fulfilled? + false + end + + def to_sym + :rejected + end + + def value + @Value + end + + def reason + @Reason + end + + def apply(args, block) + block.call(*reason, *args) + end + end + + # @!visibility private + PENDING = Pending.new + # @!visibility private + RESERVED = Reserved.new + # @!visibility private + RESOLVED = Fulfilled.new(nil) + + def RESOLVED.to_sym + :resolved + end + end + + private_constant :InternalStates + + # @!macro promises.shortcut.event-future + # @see Event#$0 + # @see Future#$0 + + # @!macro promises.param.timeout + # @param [Numeric] timeout the maximum time in second to wait. + + # @!macro promises.warn.blocks + # @note This function potentially blocks current thread until the Future is resolved. + # Be careful it can deadlock. Try to chain instead. + + # Common ancestor of {Event} and {Future} classes, many shared methods are defined here. + class AbstractEventFuture < Synchronization::Object + safe_initialization! + attr_atomic(:internal_state) + private :internal_state=, :swap_internal_state, :compare_and_set_internal_state, :update_internal_state + # @!method internal_state + # @!visibility private + + include InternalStates + + def initialize(promise, default_executor) + super() + @Lock = Mutex.new + @Condition = ConditionVariable.new + @Promise = promise + @DefaultExecutor = default_executor + @Callbacks = LockFreeStack.new + @Waiters = AtomicFixnum.new 0 + self.internal_state = PENDING + end + + private :initialize + + # Returns its state. + # @return [Symbol] + # + # @overload an_event.state + # @return [:pending, :resolved] + # @overload a_future.state + # Both :fulfilled, :rejected implies :resolved. + # @return [:pending, :fulfilled, :rejected] + def state + internal_state.to_sym + end + + # Is it in pending state? + # @return [Boolean] + def pending? + !internal_state.resolved? + end + + # Is it in resolved state? + # @return [Boolean] + def resolved? + internal_state.resolved? + end + + # Propagates touch. Requests all the delayed futures, which it depends on, to be + # executed. This method is called by any other method requiring resolved state, like {#wait}. + # @return [self] + def touch + @Promise.touch + self + end + + # @!macro promises.touches + # Calls {Concurrent::AbstractEventFuture#touch}. + + # @!macro promises.method.wait + # Wait (block the Thread) until receiver is {#resolved?}. + # @!macro promises.touches + # + # @!macro promises.warn.blocks + # @!macro promises.param.timeout + # @return [self, true, false] self implies timeout was not used, true implies timeout was used + # and it was resolved, false implies it was not resolved within timeout. + def wait(timeout = nil) + result = wait_until_resolved(timeout) + timeout ? result : self + end + + # Returns default executor. + # @return [Executor] default executor + # @see #with_default_executor + # @see FactoryMethods#future_on + # @see FactoryMethods#resolvable_future + # @see FactoryMethods#any_fulfilled_future_on + # @see similar + def default_executor + @DefaultExecutor + end + + # @!macro promises.shortcut.on + # @return [Future] + def chain(*args, &task) + chain_on @DefaultExecutor, *args, &task + end + + # Chains the task to be executed asynchronously on executor after it is resolved. + # + # @!macro promises.param.executor + # @!macro promises.param.args + # @return [Future] + # @!macro promise.param.task-future + # + # @overload an_event.chain_on(executor, *args, &task) + # @yield [*args] to the task. + # @overload a_future.chain_on(executor, *args, &task) + # @yield [fulfilled, value, reason, *args] to the task. + # @yieldparam [true, false] fulfilled + # @yieldparam [Object] value + # @yieldparam [Object] reason + def chain_on(executor, *args, &task) + ChainPromise.new_blocked_by1(self, executor, executor, args, &task).future + end + + # @return [String] Short string representation. + def to_s + format '%s %s>', super[0..-2], state + end + + alias_method :inspect, :to_s + + # Resolves the resolvable when receiver is resolved. + # + # @param [Resolvable] resolvable + # @return [self] + def chain_resolvable(resolvable) + on_resolution! { resolvable.resolve_with internal_state } + end + + alias_method :tangle, :chain_resolvable + + # @!macro promises.shortcut.using + # @return [self] + def on_resolution(*args, &callback) + on_resolution_using @DefaultExecutor, *args, &callback + end + + # Stores the callback to be executed synchronously on resolving thread after it is + # resolved. + # + # @!macro promises.param.args + # @!macro promise.param.callback + # @return [self] + # + # @overload an_event.on_resolution!(*args, &callback) + # @yield [*args] to the callback. + # @overload a_future.on_resolution!(*args, &callback) + # @yield [fulfilled, value, reason, *args] to the callback. + # @yieldparam [true, false] fulfilled + # @yieldparam [Object] value + # @yieldparam [Object] reason + def on_resolution!(*args, &callback) + add_callback :callback_on_resolution, args, callback + end + + # Stores the callback to be executed asynchronously on executor after it is resolved. + # + # @!macro promises.param.executor + # @!macro promises.param.args + # @!macro promise.param.callback + # @return [self] + # + # @overload an_event.on_resolution_using(executor, *args, &callback) + # @yield [*args] to the callback. + # @overload a_future.on_resolution_using(executor, *args, &callback) + # @yield [fulfilled, value, reason, *args] to the callback. + # @yieldparam [true, false] fulfilled + # @yieldparam [Object] value + # @yieldparam [Object] reason + def on_resolution_using(executor, *args, &callback) + add_callback :async_callback_on_resolution, executor, args, callback + end + + # @!macro promises.method.with_default_executor + # Crates new object with same class with the executor set as its new default executor. + # Any futures depending on it will use the new default executor. + # @!macro promises.shortcut.event-future + # @abstract + # @return [AbstractEventFuture] + def with_default_executor(executor) + raise NotImplementedError + end + + # @!visibility private + def resolve_with(state, raise_on_reassign = true, reserved = false) + if compare_and_set_internal_state(reserved ? RESERVED : PENDING, state) + # go to synchronized block only if there were waiting threads + @Lock.synchronize { @Condition.broadcast } unless @Waiters.value == 0 + call_callbacks state + else + return rejected_resolution(raise_on_reassign, state) + end + self + end + + # For inspection. + # @!visibility private + # @return [Array] + def blocks + @Callbacks.each_with_object([]) do |(method, args), promises| + promises.push(args[0]) if method == :callback_notify_blocked + end + end + + # For inspection. + # @!visibility private + def callbacks + @Callbacks.each.to_a + end + + # For inspection. + # @!visibility private + def promise + @Promise + end + + # For inspection. + # @!visibility private + def touched? + promise.touched? + end + + # For inspection. + # @!visibility private + def waiting_threads + @Waiters.each.to_a + end + + # @!visibility private + def add_callback_notify_blocked(promise, index) + add_callback :callback_notify_blocked, promise, index + end + + # @!visibility private + def add_callback_clear_delayed_node(node) + add_callback(:callback_clear_delayed_node, node) + end + + # @!visibility private + def with_hidden_resolvable + # TODO (pitr-ch 10-Dec-2018): documentation, better name if in edge + self + end + + private + + def add_callback(method, *args) + state = internal_state + if state.resolved? + call_callback method, state, args + else + @Callbacks.push [method, args] + state = internal_state + # take back if it was resolved in the meanwhile + call_callbacks state if state.resolved? + end + self + end + + def callback_clear_delayed_node(state, node) + node.value = nil + end + + # @return [Boolean] + def wait_until_resolved(timeout) + return true if resolved? + + touch + + @Lock.synchronize do + @Waiters.increment + begin + if timeout + start = Concurrent.monotonic_time + until resolved? + break if @Condition.wait(@Lock, timeout) == nil # nil means timeout + timeout -= (Concurrent.monotonic_time - start) + break if timeout <= 0 + end + else + until resolved? + @Condition.wait(@Lock, timeout) + end + end + ensure + # JRuby may raise ConcurrencyError + @Waiters.decrement + end + end + resolved? + end + + def call_callback(method, state, args) + self.send method, state, *args + end + + def call_callbacks(state) + method, args = @Callbacks.pop + while method + call_callback method, state, args + method, args = @Callbacks.pop + end + end + + def with_async(executor, *args, &block) + Concurrent.executor(executor).post(*args, &block) + end + + def async_callback_on_resolution(state, executor, args, callback) + with_async(executor, state, args, callback) do |st, ar, cb| + callback_on_resolution st, ar, cb + end + end + + def callback_notify_blocked(state, promise, index) + promise.on_blocker_resolution self, index + end + end + + # Represents an event which will happen in future (will be resolved). The event is either + # pending or resolved. It should be always resolved. Use {Future} to communicate rejections and + # cancellation. + class Event < AbstractEventFuture + + alias_method :then, :chain + + + # @!macro promises.method.zip + # Creates a new event or a future which will be resolved when receiver and other are. + # Returns an event if receiver and other are events, otherwise returns a future. + # If just one of the parties is Future then the result + # of the returned future is equal to the result of the supplied future. If both are futures + # then the result is as described in {FactoryMethods#zip_futures_on}. + # + # @return [Future, Event] + def zip(other) + if other.is_a?(Future) + ZipFutureEventPromise.new_blocked_by2(other, self, @DefaultExecutor).future + else + ZipEventEventPromise.new_blocked_by2(self, other, @DefaultExecutor).event + end + end + + alias_method :&, :zip + + # Creates a new event which will be resolved when the first of receiver, `event_or_future` + # resolves. + # + # @return [Event] + def any(event_or_future) + AnyResolvedEventPromise.new_blocked_by2(self, event_or_future, @DefaultExecutor).event + end + + alias_method :|, :any + + # Creates new event dependent on receiver which will not evaluate until touched, see {#touch}. + # In other words, it inserts delay into the chain of Futures making rest of it lazy evaluated. + # + # @return [Event] + def delay + event = DelayPromise.new(@DefaultExecutor).event + ZipEventEventPromise.new_blocked_by2(self, event, @DefaultExecutor).event + end + + # @!macro promise.method.schedule + # Creates new event dependent on receiver scheduled to execute on/in intended_time. + # In time is interpreted from the moment the receiver is resolved, therefore it inserts + # delay into the chain. + # + # @!macro promises.param.intended_time + # @return [Event] + def schedule(intended_time) + chain do + event = ScheduledPromise.new(@DefaultExecutor, intended_time).event + ZipEventEventPromise.new_blocked_by2(self, event, @DefaultExecutor).event + end.flat_event + end + + # Converts event to a future. The future is fulfilled when the event is resolved, the future may never fail. + # + # @return [Future] + def to_future + future = Promises.resolvable_future + ensure + chain_resolvable(future) + end + + # Returns self, since this is event + # @return [Event] + def to_event + self + end + + # @!macro promises.method.with_default_executor + # @return [Event] + def with_default_executor(executor) + EventWrapperPromise.new_blocked_by1(self, executor).event + end + + private + + def rejected_resolution(raise_on_reassign, state) + raise Concurrent::MultipleAssignmentError.new('Event can be resolved only once') if raise_on_reassign + return false + end + + def callback_on_resolution(state, args, callback) + callback.call(*args) + end + end + + # Represents a value which will become available in future. May reject with a reason instead, + # e.g. when the tasks raises an exception. + class Future < AbstractEventFuture + + # Is it in fulfilled state? + # @return [Boolean] + def fulfilled? + state = internal_state + state.resolved? && state.fulfilled? + end + + # Is it in rejected state? + # @return [Boolean] + def rejected? + state = internal_state + state.resolved? && !state.fulfilled? + end + + # @!macro promises.warn.nil + # @note Make sure returned `nil` is not confused with timeout, no value when rejected, + # no reason when fulfilled, etc. + # Use more exact methods if needed, like {#wait}, {#value!}, {#result}, etc. + + # @!macro promises.method.value + # Return value of the future. + # @!macro promises.touches + # + # @!macro promises.warn.blocks + # @!macro promises.warn.nil + # @!macro promises.param.timeout + # @!macro promises.param.timeout_value + # @param [Object] timeout_value a value returned by the method when it times out + # @return [Object, nil, timeout_value] the value of the Future when fulfilled, + # timeout_value on timeout, + # nil on rejection. + def value(timeout = nil, timeout_value = nil) + if wait_until_resolved timeout + internal_state.value + else + timeout_value + end + end + + # Returns reason of future's rejection. + # @!macro promises.touches + # + # @!macro promises.warn.blocks + # @!macro promises.warn.nil + # @!macro promises.param.timeout + # @!macro promises.param.timeout_value + # @return [Object, timeout_value] the reason, or timeout_value on timeout, or nil on fulfillment. + def reason(timeout = nil, timeout_value = nil) + if wait_until_resolved timeout + internal_state.reason + else + timeout_value + end + end + + # Returns triplet fulfilled?, value, reason. + # @!macro promises.touches + # + # @!macro promises.warn.blocks + # @!macro promises.param.timeout + # @return [Array(Boolean, Object, Object), nil] triplet of fulfilled?, value, reason, or nil + # on timeout. + def result(timeout = nil) + internal_state.result if wait_until_resolved timeout + end + + # @!macro promises.method.wait + # @raise [Exception] {#reason} on rejection + def wait!(timeout = nil) + result = wait_until_resolved!(timeout) + timeout ? result : self + end + + # @!macro promises.method.value + # @return [Object, nil, timeout_value] the value of the Future when fulfilled, + # or nil on rejection, + # or timeout_value on timeout. + # @raise [Exception] {#reason} on rejection + def value!(timeout = nil, timeout_value = nil) + if wait_until_resolved! timeout + internal_state.value + else + timeout_value + end + end + + # Allows rejected Future to be risen with `raise` method. + # If the reason is not an exception `Runtime.new(reason)` is returned. + # + # @example + # raise Promises.rejected_future(StandardError.new("boom")) + # raise Promises.rejected_future("or just boom") + # @raise [Concurrent::Error] when raising not rejected future + # @return [Exception] + def exception(*args) + raise Concurrent::Error, 'it is not rejected' unless rejected? + raise ArgumentError unless args.size <= 1 + reason = Array(internal_state.reason).flatten.compact + if reason.size > 1 + ex = Concurrent::MultipleErrors.new reason + ex.set_backtrace(caller) + ex + else + ex = if reason[0].respond_to? :exception + reason[0].exception(*args) + else + RuntimeError.new(reason[0]).exception(*args) + end + ex.set_backtrace Array(ex.backtrace) + caller + ex + end + end + + # @!macro promises.shortcut.on + # @return [Future] + def then(*args, &task) + then_on @DefaultExecutor, *args, &task + end + + # Chains the task to be executed asynchronously on executor after it fulfills. Does not run + # the task if it rejects. It will resolve though, triggering any dependent futures. + # + # @!macro promises.param.executor + # @!macro promises.param.args + # @!macro promise.param.task-future + # @return [Future] + # @yield [value, *args] to the task. + def then_on(executor, *args, &task) + ThenPromise.new_blocked_by1(self, executor, executor, args, &task).future + end + + # @!macro promises.shortcut.on + # @return [Future] + def rescue(*args, &task) + rescue_on @DefaultExecutor, *args, &task + end + + # Chains the task to be executed asynchronously on executor after it rejects. Does not run + # the task if it fulfills. It will resolve though, triggering any dependent futures. + # + # @!macro promises.param.executor + # @!macro promises.param.args + # @!macro promise.param.task-future + # @return [Future] + # @yield [reason, *args] to the task. + def rescue_on(executor, *args, &task) + RescuePromise.new_blocked_by1(self, executor, executor, args, &task).future + end + + # @!macro promises.method.zip + # @return [Future] + def zip(other) + if other.is_a?(Future) + ZipFuturesPromise.new_blocked_by2(self, other, @DefaultExecutor).future + else + ZipFutureEventPromise.new_blocked_by2(self, other, @DefaultExecutor).future + end + end + + alias_method :&, :zip + + # Creates a new event which will be resolved when the first of receiver, `event_or_future` + # resolves. Returning future will have value nil if event_or_future is event and resolves + # first. + # + # @return [Future] + def any(event_or_future) + AnyResolvedFuturePromise.new_blocked_by2(self, event_or_future, @DefaultExecutor).future + end + + alias_method :|, :any + + # Creates new future dependent on receiver which will not evaluate until touched, see {#touch}. + # In other words, it inserts delay into the chain of Futures making rest of it lazy evaluated. + # + # @return [Future] + def delay + event = DelayPromise.new(@DefaultExecutor).event + ZipFutureEventPromise.new_blocked_by2(self, event, @DefaultExecutor).future + end + + # @!macro promise.method.schedule + # @return [Future] + def schedule(intended_time) + chain do + event = ScheduledPromise.new(@DefaultExecutor, intended_time).event + ZipFutureEventPromise.new_blocked_by2(self, event, @DefaultExecutor).future + end.flat + end + + # @!macro promises.method.with_default_executor + # @return [Future] + def with_default_executor(executor) + FutureWrapperPromise.new_blocked_by1(self, executor).future + end + + # Creates new future which will have result of the future returned by receiver. If receiver + # rejects it will have its rejection. + # + # @param [Integer] level how many levels of futures should flatten + # @return [Future] + def flat_future(level = 1) + FlatFuturePromise.new_blocked_by1(self, level, @DefaultExecutor).future + end + + alias_method :flat, :flat_future + + # Creates new event which will be resolved when the returned event by receiver is. + # Be careful if the receiver rejects it will just resolve since Event does not hold reason. + # + # @return [Event] + def flat_event + FlatEventPromise.new_blocked_by1(self, @DefaultExecutor).event + end + + # @!macro promises.shortcut.using + # @return [self] + def on_fulfillment(*args, &callback) + on_fulfillment_using @DefaultExecutor, *args, &callback + end + + # Stores the callback to be executed synchronously on resolving thread after it is + # fulfilled. Does nothing on rejection. + # + # @!macro promises.param.args + # @!macro promise.param.callback + # @return [self] + # @yield [value, *args] to the callback. + def on_fulfillment!(*args, &callback) + add_callback :callback_on_fulfillment, args, callback + end + + # Stores the callback to be executed asynchronously on executor after it is + # fulfilled. Does nothing on rejection. + # + # @!macro promises.param.executor + # @!macro promises.param.args + # @!macro promise.param.callback + # @return [self] + # @yield [value, *args] to the callback. + def on_fulfillment_using(executor, *args, &callback) + add_callback :async_callback_on_fulfillment, executor, args, callback + end + + # @!macro promises.shortcut.using + # @return [self] + def on_rejection(*args, &callback) + on_rejection_using @DefaultExecutor, *args, &callback + end + + # Stores the callback to be executed synchronously on resolving thread after it is + # rejected. Does nothing on fulfillment. + # + # @!macro promises.param.args + # @!macro promise.param.callback + # @return [self] + # @yield [reason, *args] to the callback. + def on_rejection!(*args, &callback) + add_callback :callback_on_rejection, args, callback + end + + # Stores the callback to be executed asynchronously on executor after it is + # rejected. Does nothing on fulfillment. + # + # @!macro promises.param.executor + # @!macro promises.param.args + # @!macro promise.param.callback + # @return [self] + # @yield [reason, *args] to the callback. + def on_rejection_using(executor, *args, &callback) + add_callback :async_callback_on_rejection, executor, args, callback + end + + # Allows to use futures as green threads. The receiver has to evaluate to a future which + # represents what should be done next. It basically flattens indefinitely until non Future + # values is returned which becomes result of the returned future. Any encountered exception + # will become reason of the returned future. + # + # @return [Future] + # @param [#call(value)] run_test + # an object which when called returns either Future to keep running with + # or nil, then the run completes with the value. + # The run_test can be used to extract the Future from deeper structure, + # or to distinguish Future which is a resulting value from a future + # which is suppose to continue running. + # @example + # body = lambda do |v| + # v += 1 + # v < 5 ? Promises.future(v, &body) : v + # end + # Promises.future(0, &body).run.value! # => 5 + def run(run_test = method(:run_test)) + RunFuturePromise.new_blocked_by1(self, @DefaultExecutor, run_test).future + end + + # @!visibility private + def apply(args, block) + internal_state.apply args, block + end + + # Converts future to event which is resolved when future is resolved by fulfillment or rejection. + # + # @return [Event] + def to_event + event = Promises.resolvable_event + ensure + chain_resolvable(event) + end + + # Returns self, since this is a future + # @return [Future] + def to_future + self + end + + # @return [String] Short string representation. + def to_s + if resolved? + format '%s with %s>', super[0..-2], (fulfilled? ? value : reason).inspect + else + super + end + end + + alias_method :inspect, :to_s + + private + + def run_test(v) + v if v.is_a?(Future) + end + + def rejected_resolution(raise_on_reassign, state) + if raise_on_reassign + if internal_state == RESERVED + raise Concurrent::MultipleAssignmentError.new( + "Future can be resolved only once. It is already reserved.") + else + raise Concurrent::MultipleAssignmentError.new( + "Future can be resolved only once. It's #{result}, trying to set #{state.result}.", + current_result: result, + new_result: state.result) + end + end + return false + end + + def wait_until_resolved!(timeout = nil) + result = wait_until_resolved(timeout) + raise self if rejected? + result + end + + def async_callback_on_fulfillment(state, executor, args, callback) + with_async(executor, state, args, callback) do |st, ar, cb| + callback_on_fulfillment st, ar, cb + end + end + + def async_callback_on_rejection(state, executor, args, callback) + with_async(executor, state, args, callback) do |st, ar, cb| + callback_on_rejection st, ar, cb + end + end + + def callback_on_fulfillment(state, args, callback) + state.apply args, callback if state.fulfilled? + end + + def callback_on_rejection(state, args, callback) + state.apply args, callback unless state.fulfilled? + end + + def callback_on_resolution(state, args, callback) + callback.call(*state.result, *args) + end + + end + + # Marker module of Future, Event resolved manually. + module Resolvable + include InternalStates + end + + # A Event which can be resolved by user. + class ResolvableEvent < Event + include Resolvable + + # @!macro raise_on_reassign + # @raise [MultipleAssignmentError] when already resolved and raise_on_reassign is true. + + # @!macro promise.param.raise_on_reassign + # @param [Boolean] raise_on_reassign should method raise exception if already resolved + # @return [self, false] false is returned when raise_on_reassign is false and the receiver + # is already resolved. + # + + # Makes the event resolved, which triggers all dependent futures. + # + # @!macro promise.param.raise_on_reassign + # @!macro promise.param.reserved + # @param [true, false] reserved + # Set to true if the resolvable is {#reserve}d by you, + # marks resolution of reserved resolvable events and futures explicitly. + # Advanced feature, ignore unless you use {Resolvable#reserve} from edge. + def resolve(raise_on_reassign = true, reserved = false) + resolve_with RESOLVED, raise_on_reassign, reserved + end + + # Creates new event wrapping receiver, effectively hiding the resolve method. + # + # @return [Event] + def with_hidden_resolvable + @with_hidden_resolvable ||= EventWrapperPromise.new_blocked_by1(self, @DefaultExecutor).event + end + + # Behaves as {AbstractEventFuture#wait} but has one additional optional argument + # resolve_on_timeout. + # + # @param [true, false] resolve_on_timeout + # If it times out and the argument is true it will also resolve the event. + # @return [self, true, false] + # @see AbstractEventFuture#wait + def wait(timeout = nil, resolve_on_timeout = false) + super(timeout) or if resolve_on_timeout + # if it fails to resolve it was resolved in the meantime + # so return true as if there was no timeout + !resolve(false) + else + false + end + end + end + + # A Future which can be resolved by user. + class ResolvableFuture < Future + include Resolvable + + # Makes the future resolved with result of triplet `fulfilled?`, `value`, `reason`, + # which triggers all dependent futures. + # + # @param [true, false] fulfilled + # @param [Object] value + # @param [Object] reason + # @!macro promise.param.raise_on_reassign + # @!macro promise.param.reserved + def resolve(fulfilled = true, value = nil, reason = nil, raise_on_reassign = true, reserved = false) + resolve_with(fulfilled ? Fulfilled.new(value) : Rejected.new(reason), raise_on_reassign, reserved) + end + + # Makes the future fulfilled with `value`, + # which triggers all dependent futures. + # + # @param [Object] value + # @!macro promise.param.raise_on_reassign + # @!macro promise.param.reserved + def fulfill(value, raise_on_reassign = true, reserved = false) + resolve_with Fulfilled.new(value), raise_on_reassign, reserved + end + + # Makes the future rejected with `reason`, + # which triggers all dependent futures. + # + # @param [Object] reason + # @!macro promise.param.raise_on_reassign + # @!macro promise.param.reserved + def reject(reason, raise_on_reassign = true, reserved = false) + resolve_with Rejected.new(reason), raise_on_reassign, reserved + end + + # Evaluates the block and sets its result as future's value fulfilling, if the block raises + # an exception the future rejects with it. + # + # @yield [*args] to the block. + # @yieldreturn [Object] value + # @return [self] + def evaluate_to(*args, &block) + promise.evaluate_to(*args, block) + end + + # Evaluates the block and sets its result as future's value fulfilling, if the block raises + # an exception the future rejects with it. + # + # @yield [*args] to the block. + # @yieldreturn [Object] value + # @return [self] + # @raise [Exception] also raise reason on rejection. + def evaluate_to!(*args, &block) + promise.evaluate_to(*args, block).wait! + end + + # @!macro promises.resolvable.resolve_on_timeout + # @param [::Array(true, Object, nil), ::Array(false, nil, Exception), nil] resolve_on_timeout + # If it times out and the argument is not nil it will also resolve the future + # to the provided resolution. + + # Behaves as {AbstractEventFuture#wait} but has one additional optional argument + # resolve_on_timeout. + # + # @!macro promises.resolvable.resolve_on_timeout + # @return [self, true, false] + # @see AbstractEventFuture#wait + def wait(timeout = nil, resolve_on_timeout = nil) + super(timeout) or if resolve_on_timeout + # if it fails to resolve it was resolved in the meantime + # so return true as if there was no timeout + !resolve(*resolve_on_timeout, false) + else + false + end + end + + # Behaves as {Future#wait!} but has one additional optional argument + # resolve_on_timeout. + # + # @!macro promises.resolvable.resolve_on_timeout + # @return [self, true, false] + # @raise [Exception] {#reason} on rejection + # @see Future#wait! + def wait!(timeout = nil, resolve_on_timeout = nil) + super(timeout) or if resolve_on_timeout + if resolve(*resolve_on_timeout, false) + false + else + # if it fails to resolve it was resolved in the meantime + # so return true as if there was no timeout + raise self if rejected? + true + end + else + false + end + end + + # Behaves as {Future#value} but has one additional optional argument + # resolve_on_timeout. + # + # @!macro promises.resolvable.resolve_on_timeout + # @return [Object, timeout_value, nil] + # @see Future#value + def value(timeout = nil, timeout_value = nil, resolve_on_timeout = nil) + if wait_until_resolved timeout + internal_state.value + else + if resolve_on_timeout + unless resolve(*resolve_on_timeout, false) + # if it fails to resolve it was resolved in the meantime + # so return value as if there was no timeout + return internal_state.value + end + end + timeout_value + end + end + + # Behaves as {Future#value!} but has one additional optional argument + # resolve_on_timeout. + # + # @!macro promises.resolvable.resolve_on_timeout + # @return [Object, timeout_value, nil] + # @raise [Exception] {#reason} on rejection + # @see Future#value! + def value!(timeout = nil, timeout_value = nil, resolve_on_timeout = nil) + if wait_until_resolved! timeout + internal_state.value + else + if resolve_on_timeout + unless resolve(*resolve_on_timeout, false) + # if it fails to resolve it was resolved in the meantime + # so return value as if there was no timeout + raise self if rejected? + return internal_state.value + end + end + timeout_value + end + end + + # Behaves as {Future#reason} but has one additional optional argument + # resolve_on_timeout. + # + # @!macro promises.resolvable.resolve_on_timeout + # @return [Exception, timeout_value, nil] + # @see Future#reason + def reason(timeout = nil, timeout_value = nil, resolve_on_timeout = nil) + if wait_until_resolved timeout + internal_state.reason + else + if resolve_on_timeout + unless resolve(*resolve_on_timeout, false) + # if it fails to resolve it was resolved in the meantime + # so return value as if there was no timeout + return internal_state.reason + end + end + timeout_value + end + end + + # Behaves as {Future#result} but has one additional optional argument + # resolve_on_timeout. + # + # @!macro promises.resolvable.resolve_on_timeout + # @return [::Array(Boolean, Object, Exception), nil] + # @see Future#result + def result(timeout = nil, resolve_on_timeout = nil) + if wait_until_resolved timeout + internal_state.result + else + if resolve_on_timeout + unless resolve(*resolve_on_timeout, false) + # if it fails to resolve it was resolved in the meantime + # so return value as if there was no timeout + internal_state.result + end + end + # otherwise returns nil + end + end + + # Creates new future wrapping receiver, effectively hiding the resolve method and similar. + # + # @return [Future] + def with_hidden_resolvable + @with_hidden_resolvable ||= FutureWrapperPromise.new_blocked_by1(self, @DefaultExecutor).future + end + end + + # @abstract + # @private + class AbstractPromise < Synchronization::Object + safe_initialization! + include InternalStates + + def initialize(future) + super() + @Future = future + end + + def future + @Future + end + + alias_method :event, :future + + def default_executor + future.default_executor + end + + def state + future.state + end + + def touch + end + + def to_s + format '%s %s>', super[0..-2], @Future + end + + alias_method :inspect, :to_s + + def delayed_because + nil + end + + private + + def resolve_with(new_state, raise_on_reassign = true) + @Future.resolve_with(new_state, raise_on_reassign) + end + + # @return [Future] + def evaluate_to(*args, block) + resolve_with Fulfilled.new(block.call(*args)) + rescue Exception => error + resolve_with Rejected.new(error) + raise error unless error.is_a?(StandardError) + end + end + + class ResolvableEventPromise < AbstractPromise + def initialize(default_executor) + super ResolvableEvent.new(self, default_executor) + end + end + + class ResolvableFuturePromise < AbstractPromise + def initialize(default_executor) + super ResolvableFuture.new(self, default_executor) + end + + public :evaluate_to + end + + # @abstract + class InnerPromise < AbstractPromise + end + + # @abstract + class BlockedPromise < InnerPromise + + private_class_method :new + + def self.new_blocked_by1(blocker, *args, &block) + blocker_delayed = blocker.promise.delayed_because + promise = new(blocker_delayed, 1, *args, &block) + blocker.add_callback_notify_blocked promise, 0 + promise + end + + def self.new_blocked_by2(blocker1, blocker2, *args, &block) + blocker_delayed1 = blocker1.promise.delayed_because + blocker_delayed2 = blocker2.promise.delayed_because + delayed = if blocker_delayed1 && blocker_delayed2 + # TODO (pitr-ch 23-Dec-2016): use arrays when we know it will not grow (only flat adds delay) + LockFreeStack.of2(blocker_delayed1, blocker_delayed2) + else + blocker_delayed1 || blocker_delayed2 + end + promise = new(delayed, 2, *args, &block) + blocker1.add_callback_notify_blocked promise, 0 + blocker2.add_callback_notify_blocked promise, 1 + promise + end + + def self.new_blocked_by(blockers, *args, &block) + delayed = blockers.reduce(nil) { |d, f| add_delayed d, f.promise.delayed_because } + promise = new(delayed, blockers.size, *args, &block) + blockers.each_with_index { |f, i| f.add_callback_notify_blocked promise, i } + promise + end + + def self.add_delayed(delayed1, delayed2) + if delayed1 && delayed2 + delayed1.push delayed2 + delayed1 + else + delayed1 || delayed2 + end + end + + def initialize(delayed, blockers_count, future) + super(future) + @Delayed = delayed + @Countdown = AtomicFixnum.new blockers_count + end + + def on_blocker_resolution(future, index) + countdown = process_on_blocker_resolution(future, index) + resolvable = resolvable?(countdown, future, index) + + on_resolvable(future, index) if resolvable + end + + def delayed_because + @Delayed + end + + def touch + clear_and_propagate_touch + end + + # for inspection only + def blocked_by + blocked_by = [] + ObjectSpace.each_object(AbstractEventFuture) { |o| blocked_by.push o if o.blocks.include? self } + blocked_by + end + + private + + def clear_and_propagate_touch(stack_or_element = @Delayed) + return if stack_or_element.nil? + + if stack_or_element.is_a? LockFreeStack + stack_or_element.clear_each { |element| clear_and_propagate_touch element } + else + stack_or_element.touch unless stack_or_element.nil? # if still present + end + end + + # @return [true,false] if resolvable + def resolvable?(countdown, future, index) + countdown.zero? + end + + def process_on_blocker_resolution(future, index) + @Countdown.decrement + end + + def on_resolvable(resolved_future, index) + raise NotImplementedError + end + end + + # @abstract + class BlockedTaskPromise < BlockedPromise + def initialize(delayed, blockers_count, default_executor, executor, args, &task) + raise ArgumentError, 'no block given' unless block_given? + super delayed, 1, Future.new(self, default_executor) + @Executor = executor + @Task = task + @Args = args + end + + def executor + @Executor + end + end + + class ThenPromise < BlockedTaskPromise + private + + def initialize(delayed, blockers_count, default_executor, executor, args, &task) + super delayed, blockers_count, default_executor, executor, args, &task + end + + def on_resolvable(resolved_future, index) + if resolved_future.fulfilled? + Concurrent.executor(@Executor).post(resolved_future, @Args, @Task) do |future, args, task| + evaluate_to lambda { future.apply args, task } + end + else + resolve_with resolved_future.internal_state + end + end + end + + class RescuePromise < BlockedTaskPromise + private + + def initialize(delayed, blockers_count, default_executor, executor, args, &task) + super delayed, blockers_count, default_executor, executor, args, &task + end + + def on_resolvable(resolved_future, index) + if resolved_future.rejected? + Concurrent.executor(@Executor).post(resolved_future, @Args, @Task) do |future, args, task| + evaluate_to lambda { future.apply args, task } + end + else + resolve_with resolved_future.internal_state + end + end + end + + class ChainPromise < BlockedTaskPromise + private + + def on_resolvable(resolved_future, index) + if Future === resolved_future + Concurrent.executor(@Executor).post(resolved_future, @Args, @Task) do |future, args, task| + evaluate_to(*future.result, *args, task) + end + else + Concurrent.executor(@Executor).post(@Args, @Task) do |args, task| + evaluate_to(*args, task) + end + end + end + end + + # will be immediately resolved + class ImmediateEventPromise < InnerPromise + def initialize(default_executor) + super Event.new(self, default_executor).resolve_with(RESOLVED) + end + end + + class ImmediateFuturePromise < InnerPromise + def initialize(default_executor, fulfilled, value, reason) + super Future.new(self, default_executor). + resolve_with(fulfilled ? Fulfilled.new(value) : Rejected.new(reason)) + end + end + + class AbstractFlatPromise < BlockedPromise + + def initialize(delayed_because, blockers_count, event_or_future) + delayed = LockFreeStack.of1(self) + super(delayed, blockers_count, event_or_future) + # noinspection RubyArgCount + @Touched = AtomicBoolean.new false + @DelayedBecause = delayed_because || LockFreeStack.new + + event_or_future.add_callback_clear_delayed_node delayed.peek + end + + def touch + if @Touched.make_true + clear_and_propagate_touch @DelayedBecause + end + end + + private + + def touched? + @Touched.value + end + + def on_resolvable(resolved_future, index) + resolve_with resolved_future.internal_state + end + + def resolvable?(countdown, future, index) + !@Future.internal_state.resolved? && super(countdown, future, index) + end + + def add_delayed_of(future) + delayed = future.promise.delayed_because + if touched? + clear_and_propagate_touch delayed + else + BlockedPromise.add_delayed @DelayedBecause, delayed + clear_and_propagate_touch @DelayedBecause if touched? + end + end + + end + + class FlatEventPromise < AbstractFlatPromise + + private + + def initialize(delayed, blockers_count, default_executor) + super delayed, 2, Event.new(self, default_executor) + end + + def process_on_blocker_resolution(future, index) + countdown = super(future, index) + if countdown.nonzero? + internal_state = future.internal_state + + unless internal_state.fulfilled? + resolve_with RESOLVED + return countdown + end + + value = internal_state.value + case value + when AbstractEventFuture + add_delayed_of value + value.add_callback_notify_blocked self, nil + countdown + else + resolve_with RESOLVED + end + end + countdown + end + + end + + class FlatFuturePromise < AbstractFlatPromise + + private + + def initialize(delayed, blockers_count, levels, default_executor) + raise ArgumentError, 'levels has to be higher than 0' if levels < 1 + # flat promise may result to a future having delayed futures, therefore we have to have empty stack + # to be able to add new delayed futures + super delayed || LockFreeStack.new, 1 + levels, Future.new(self, default_executor) + end + + def process_on_blocker_resolution(future, index) + countdown = super(future, index) + if countdown.nonzero? + internal_state = future.internal_state + + unless internal_state.fulfilled? + resolve_with internal_state + return countdown + end + + value = internal_state.value + case value + when AbstractEventFuture + add_delayed_of value + value.add_callback_notify_blocked self, nil + countdown + else + evaluate_to(lambda { raise TypeError, "returned value #{value.inspect} is not a Future" }) + end + end + countdown + end + + end + + class RunFuturePromise < AbstractFlatPromise + + private + + def initialize(delayed, blockers_count, default_executor, run_test) + super delayed, 1, Future.new(self, default_executor) + @RunTest = run_test + end + + def process_on_blocker_resolution(future, index) + internal_state = future.internal_state + + unless internal_state.fulfilled? + resolve_with internal_state + return 0 + end + + value = internal_state.value + continuation_future = @RunTest.call value + + if continuation_future + add_delayed_of continuation_future + continuation_future.add_callback_notify_blocked self, nil + else + resolve_with internal_state + end + + 1 + end + end + + class ZipEventEventPromise < BlockedPromise + def initialize(delayed, blockers_count, default_executor) + super delayed, 2, Event.new(self, default_executor) + end + + private + + def on_resolvable(resolved_future, index) + resolve_with RESOLVED + end + end + + class ZipFutureEventPromise < BlockedPromise + def initialize(delayed, blockers_count, default_executor) + super delayed, 2, Future.new(self, default_executor) + @result = nil + end + + private + + def process_on_blocker_resolution(future, index) + # first blocking is future, take its result + @result = future.internal_state if index == 0 + # super has to be called after above to piggyback on volatile @Countdown + super future, index + end + + def on_resolvable(resolved_future, index) + resolve_with @result + end + end + + class EventWrapperPromise < BlockedPromise + def initialize(delayed, blockers_count, default_executor) + super delayed, 1, Event.new(self, default_executor) + end + + private + + def on_resolvable(resolved_future, index) + resolve_with RESOLVED + end + end + + class FutureWrapperPromise < BlockedPromise + def initialize(delayed, blockers_count, default_executor) + super delayed, 1, Future.new(self, default_executor) + end + + private + + def on_resolvable(resolved_future, index) + resolve_with resolved_future.internal_state + end + end + + class ZipFuturesPromise < BlockedPromise + + private + + def initialize(delayed, blockers_count, default_executor) + super(delayed, blockers_count, Future.new(self, default_executor)) + @Resolutions = ::Array.new(blockers_count, nil) + + on_resolvable nil, nil if blockers_count == 0 + end + + def process_on_blocker_resolution(future, index) + # TODO (pitr-ch 18-Dec-2016): Can we assume that array will never break under parallel access when never re-sized? + @Resolutions[index] = future.internal_state # has to be set before countdown in super + super future, index + end + + def on_resolvable(resolved_future, index) + all_fulfilled = true + values = ::Array.new(@Resolutions.size) + reasons = ::Array.new(@Resolutions.size) + + @Resolutions.each_with_index do |internal_state, i| + fulfilled, values[i], reasons[i] = internal_state.result + all_fulfilled &&= fulfilled + end + + if all_fulfilled + resolve_with FulfilledArray.new(values) + else + resolve_with PartiallyRejected.new(values, reasons) + end + end + end + + class ZipEventsPromise < BlockedPromise + + private + + def initialize(delayed, blockers_count, default_executor) + super delayed, blockers_count, Event.new(self, default_executor) + + on_resolvable nil, nil if blockers_count == 0 + end + + def on_resolvable(resolved_future, index) + resolve_with RESOLVED + end + end + + # @abstract + class AbstractAnyPromise < BlockedPromise + end + + class AnyResolvedEventPromise < AbstractAnyPromise + + private + + def initialize(delayed, blockers_count, default_executor) + super delayed, blockers_count, Event.new(self, default_executor) + end + + def resolvable?(countdown, future, index) + true + end + + def on_resolvable(resolved_future, index) + resolve_with RESOLVED, false + end + end + + class AnyResolvedFuturePromise < AbstractAnyPromise + + private + + def initialize(delayed, blockers_count, default_executor) + super delayed, blockers_count, Future.new(self, default_executor) + end + + def resolvable?(countdown, future, index) + true + end + + def on_resolvable(resolved_future, index) + resolve_with resolved_future.internal_state, false + end + end + + class AnyFulfilledFuturePromise < AnyResolvedFuturePromise + + private + + def resolvable?(countdown, event_or_future, index) + (event_or_future.is_a?(Event) ? event_or_future.resolved? : event_or_future.fulfilled?) || + # inlined super from BlockedPromise + countdown.zero? + end + end + + class DelayPromise < InnerPromise + + def initialize(default_executor) + event = Event.new(self, default_executor) + @Delayed = LockFreeStack.of1(self) + super event + event.add_callback_clear_delayed_node @Delayed.peek + end + + def touch + @Future.resolve_with RESOLVED + end + + def delayed_because + @Delayed + end + + end + + class ScheduledPromise < InnerPromise + def intended_time + @IntendedTime + end + + def inspect + "#{to_s[0..-2]} intended_time: #{@IntendedTime}>" + end + + private + + def initialize(default_executor, intended_time) + super Event.new(self, default_executor) + + @IntendedTime = intended_time + + in_seconds = begin + now = Time.now + schedule_time = if @IntendedTime.is_a? Time + @IntendedTime + else + now + @IntendedTime + end + [0, schedule_time.to_f - now.to_f].max + end + + Concurrent.global_timer_set.post(in_seconds) do + @Future.resolve_with RESOLVED + end + end + end + + extend FactoryMethods + + private_constant :AbstractPromise, + :ResolvableEventPromise, + :ResolvableFuturePromise, + :InnerPromise, + :BlockedPromise, + :BlockedTaskPromise, + :ThenPromise, + :RescuePromise, + :ChainPromise, + :ImmediateEventPromise, + :ImmediateFuturePromise, + :AbstractFlatPromise, + :FlatFuturePromise, + :FlatEventPromise, + :RunFuturePromise, + :ZipEventEventPromise, + :ZipFutureEventPromise, + :EventWrapperPromise, + :FutureWrapperPromise, + :ZipFuturesPromise, + :ZipEventsPromise, + :AbstractAnyPromise, + :AnyResolvedFuturePromise, + :AnyFulfilledFuturePromise, + :AnyResolvedEventPromise, + :DelayPromise, + :ScheduledPromise + + + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/re_include.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/re_include.rb new file mode 100644 index 0000000000000..600bc6a53568c --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/re_include.rb @@ -0,0 +1,60 @@ +module Concurrent + + # Methods form module A included to a module B, which is already included into class C, + # will not be visible in the C class. If this module is extended to B then A's methods + # are correctly made visible to C. + # + # @example + # module A + # def a + # :a + # end + # end + # + # module B1 + # end + # + # class C1 + # include B1 + # end + # + # module B2 + # extend Concurrent::ReInclude + # end + # + # class C2 + # include B2 + # end + # + # B1.send :include, A + # B2.send :include, A + # + # C1.new.respond_to? :a # => false + # C2.new.respond_to? :a # => true + # + # @!visibility private + module ReInclude + # @!visibility private + def included(base) + (@re_include_to_bases ||= []) << [:include, base] + super(base) + end + + # @!visibility private + def extended(base) + (@re_include_to_bases ||= []) << [:extend, base] + super(base) + end + + # @!visibility private + def include(*modules) + result = super(*modules) + modules.reverse.each do |module_being_included| + (@re_include_to_bases ||= []).each do |method, mod| + mod.send method, module_being_included + end + end + result + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/scheduled_task.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/scheduled_task.rb new file mode 100644 index 0000000000000..429fc0683c6f2 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/scheduled_task.rb @@ -0,0 +1,331 @@ +require 'concurrent/constants' +require 'concurrent/errors' +require 'concurrent/configuration' +require 'concurrent/ivar' +require 'concurrent/collection/copy_on_notify_observer_set' +require 'concurrent/utility/monotonic_time' + +require 'concurrent/options' + +module Concurrent + + # `ScheduledTask` is a close relative of `Concurrent::Future` but with one + # important difference: A `Future` is set to execute as soon as possible + # whereas a `ScheduledTask` is set to execute after a specified delay. This + # implementation is loosely based on Java's + # [ScheduledExecutorService](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html). + # It is a more feature-rich variant of {Concurrent.timer}. + # + # The *intended* schedule time of task execution is set on object construction + # with the `delay` argument. The delay is a numeric (floating point or integer) + # representing a number of seconds in the future. Any other value or a numeric + # equal to or less than zero will result in an exception. The *actual* schedule + # time of task execution is set when the `execute` method is called. + # + # The constructor can also be given zero or more processing options. Currently + # the only supported options are those recognized by the + # [Dereferenceable](Dereferenceable) module. + # + # The final constructor argument is a block representing the task to be performed. + # If no block is given an `ArgumentError` will be raised. + # + # **States** + # + # `ScheduledTask` mixes in the [Obligation](Obligation) module thus giving it + # "future" behavior. This includes the expected lifecycle states. `ScheduledTask` + # has one additional state, however. While the task (block) is being executed the + # state of the object will be `:processing`. This additional state is necessary + # because it has implications for task cancellation. + # + # **Cancellation** + # + # A `:pending` task can be cancelled using the `#cancel` method. A task in any + # other state, including `:processing`, cannot be cancelled. The `#cancel` + # method returns a boolean indicating the success of the cancellation attempt. + # A cancelled `ScheduledTask` cannot be restarted. It is immutable. + # + # **Obligation and Observation** + # + # The result of a `ScheduledTask` can be obtained either synchronously or + # asynchronously. `ScheduledTask` mixes in both the [Obligation](Obligation) + # module and the + # [Observable](http://ruby-doc.org/stdlib-2.0/libdoc/observer/rdoc/Observable.html) + # module from the Ruby standard library. With one exception `ScheduledTask` + # behaves identically to [Future](Observable) with regard to these modules. + # + # @!macro copy_options + # + # @example Basic usage + # + # require 'concurrent/scheduled_task' + # require 'csv' + # require 'open-uri' + # + # class Ticker + # 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, api_key) } + # price.state #=> :pending + # price.pending? #=> true + # price.value(0) #=> nil (does not block) + # + # 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 + # + # task = Concurrent::ScheduledTask.new(2){ 'What does the fox say?' } + # task.state #=> :unscheduled + # task.execute + # task.state #=> pending + # + # # wait for it... + # sleep(3) + # + # task.unscheduled? #=> false + # task.pending? #=> false + # task.fulfilled? #=> true + # task.rejected? #=> false + # task.value #=> 'What does the fox say?' + # + # @example One line creation and execution + # + # task = Concurrent::ScheduledTask.new(2){ 'What does the fox say?' }.execute + # task.state #=> pending + # + # task = Concurrent::ScheduledTask.execute(2){ 'What do you get when you multiply 6 by 9?' } + # task.state #=> pending + # + # @example Failed task execution + # + # task = Concurrent::ScheduledTask.execute(2){ raise StandardError.new('Call me maybe?') } + # task.pending? #=> true + # + # # wait for it... + # sleep(3) + # + # task.unscheduled? #=> false + # task.pending? #=> false + # task.fulfilled? #=> false + # task.rejected? #=> true + # task.value #=> nil + # task.reason #=> # + # + # @example Task execution with observation + # + # observer = Class.new{ + # def update(time, value, reason) + # puts "The task completed at #{time} with value '#{value}'" + # end + # }.new + # + # task = Concurrent::ScheduledTask.new(2){ 'What does the fox say?' } + # task.add_observer(observer) + # task.execute + # task.pending? #=> true + # + # # wait for it... + # sleep(3) + # + # #>> The task completed at 2013-11-07 12:26:09 -0500 with value 'What does the fox say?' + # + # @!macro monotonic_clock_warning + # + # @see Concurrent.timer + class ScheduledTask < IVar + include Comparable + + # The executor on which to execute the task. + # @!visibility private + attr_reader :executor + + # Schedule a task for execution at a specified future time. + # + # @param [Float] delay the number of seconds to wait for before executing the task + # + # @yield the task to be performed + # + # @!macro executor_and_deref_options + # + # @option opts [object, Array] :args zero or more arguments to be passed the task + # block on execution + # + # @raise [ArgumentError] When no block is given + # @raise [ArgumentError] When given a time that is in the past + def initialize(delay, opts = {}, &task) + raise ArgumentError.new('no block given') unless block_given? + raise ArgumentError.new('seconds must be greater than zero') if delay.to_f < 0.0 + + super(NULL, opts, &nil) + + synchronize do + ns_set_state(:unscheduled) + @parent = opts.fetch(:timer_set, Concurrent.global_timer_set) + @args = get_arguments_from(opts) + @delay = delay.to_f + @task = task + @time = nil + @executor = Options.executor_from_options(opts) || Concurrent.global_io_executor + self.observers = Collection::CopyOnNotifyObserverSet.new + end + end + + # The `delay` value given at instanciation. + # + # @return [Float] the initial delay. + def initial_delay + synchronize { @delay } + end + + # The monotonic time at which the the task is scheduled to be executed. + # + # @return [Float] the schedule time or nil if `unscheduled` + def schedule_time + synchronize { @time } + end + + # Comparator which orders by schedule time. + # + # @!visibility private + def <=>(other) + schedule_time <=> other.schedule_time + end + + # Has the task been cancelled? + # + # @return [Boolean] true if the task is in the given state else false + def cancelled? + synchronize { ns_check_state?(:cancelled) } + end + + # In the task execution in progress? + # + # @return [Boolean] true if the task is in the given state else false + def processing? + synchronize { ns_check_state?(:processing) } + end + + # Cancel this task and prevent it from executing. A task can only be + # cancelled if it is pending or unscheduled. + # + # @return [Boolean] true if successfully cancelled else false + def cancel + if compare_and_set_state(:cancelled, :pending, :unscheduled) + complete(false, nil, CancelledOperationError.new) + # To avoid deadlocks this call must occur outside of #synchronize + # Changing the state above should prevent redundant calls + @parent.send(:remove_task, self) + else + false + end + end + + # Reschedule the task using the original delay and the current time. + # A task can only be reset while it is `:pending`. + # + # @return [Boolean] true if successfully rescheduled else false + def reset + synchronize{ ns_reschedule(@delay) } + end + + # Reschedule the task using the given delay and the current time. + # A task can only be reset while it is `:pending`. + # + # @param [Float] delay the number of seconds to wait for before executing the task + # + # @return [Boolean] true if successfully rescheduled else false + # + # @raise [ArgumentError] When given a time that is in the past + def reschedule(delay) + delay = delay.to_f + raise ArgumentError.new('seconds must be greater than zero') if delay < 0.0 + synchronize{ ns_reschedule(delay) } + end + + # Execute an `:unscheduled` `ScheduledTask`. Immediately sets the state to `:pending` + # and starts counting down toward execution. Does nothing if the `ScheduledTask` is + # in any state other than `:unscheduled`. + # + # @return [ScheduledTask] a reference to `self` + def execute + if compare_and_set_state(:pending, :unscheduled) + synchronize{ ns_schedule(@delay) } + end + self + end + + # Create a new `ScheduledTask` object with the given block, execute it, and return the + # `:pending` object. + # + # @param [Float] delay the number of seconds to wait for before executing the task + # + # @!macro executor_and_deref_options + # + # @return [ScheduledTask] the newly created `ScheduledTask` in the `:pending` state + # + # @raise [ArgumentError] if no block is given + def self.execute(delay, opts = {}, &task) + new(delay, opts, &task).execute + end + + # Execute the task. + # + # @!visibility private + def process_task + safe_execute(@task, @args) + end + + protected :set, :try_set, :fail, :complete + + protected + + # Schedule the task using the given delay and the current time. + # + # @param [Float] delay the number of seconds to wait for before executing the task + # + # @return [Boolean] true if successfully rescheduled else false + # + # @!visibility private + def ns_schedule(delay) + @delay = delay + @time = Concurrent.monotonic_time + @delay + @parent.send(:post_task, self) + end + + # Reschedule the task using the given delay and the current time. + # A task can only be reset while it is `:pending`. + # + # @param [Float] delay the number of seconds to wait for before executing the task + # + # @return [Boolean] true if successfully rescheduled else false + # + # @!visibility private + def ns_reschedule(delay) + return false unless ns_check_state?(:pending) + @parent.send(:remove_task, self) && ns_schedule(delay) + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/set.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/set.rb new file mode 100644 index 0000000000000..eee4effdfd2d6 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/set.rb @@ -0,0 +1,64 @@ +require 'concurrent/utility/engine' +require 'concurrent/thread_safe/util' +require 'set' + +module Concurrent + + # @!macro concurrent_set + # + # A thread-safe subclass of Set. This version locks against the object + # itself for every method call, ensuring only one thread can be reading + # or writing at a time. This includes iteration methods like `#each`. + # + # @note `a += b` is **not** a **thread-safe** operation on + # `Concurrent::Set`. It reads Set `a`, then it creates new `Concurrent::Set` + # which is union of `a` and `b`, then it writes the union to `a`. + # The read and write are independent operations they do not form a single atomic + # operation therefore when two `+=` operations are executed concurrently updates + # may be lost. Use `#merge` instead. + # + # @see http://ruby-doc.org/stdlib-2.4.0/libdoc/set/rdoc/Set.html Ruby standard library `Set` + + # @!macro internal_implementation_note + SetImplementation = case + when Concurrent.on_cruby? + # The CRuby implementation of Set is written in Ruby itself and is + # not thread safe for certain methods. + require 'monitor' + require 'concurrent/thread_safe/util/data_structures' + + class CRubySet < ::Set + end + + ThreadSafe::Util.make_synchronized_on_cruby CRubySet + CRubySet + + when Concurrent.on_jruby? + require 'jruby/synchronized' + + class JRubySet < ::Set + include JRuby::Synchronized + end + + JRubySet + + when Concurrent.on_truffleruby? + require 'concurrent/thread_safe/util/data_structures' + + class TruffleRubySet < ::Set + end + + ThreadSafe::Util.make_synchronized_on_truffleruby TruffleRubySet + TruffleRubySet + + else + warn 'Possibly unsupported Ruby implementation' + ::Set + end + private_constant :SetImplementation + + # @!macro concurrent_set + class Set < SetImplementation + end +end + diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/settable_struct.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/settable_struct.rb new file mode 100644 index 0000000000000..99b85619fd370 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/settable_struct.rb @@ -0,0 +1,139 @@ +require 'concurrent/errors' +require 'concurrent/synchronization/abstract_struct' +require 'concurrent/synchronization/lockable_object' + +module Concurrent + + # An thread-safe, write-once variation of Ruby's standard `Struct`. + # Each member can have its value set at most once, either at construction + # or any time thereafter. Attempting to assign a value to a member + # that has already been set will result in a `Concurrent::ImmutabilityError`. + # + # @see http://ruby-doc.org/core/Struct.html Ruby standard library `Struct` + # @see http://en.wikipedia.org/wiki/Final_(Java) Java `final` keyword + module SettableStruct + include Synchronization::AbstractStruct + + # @!macro struct_values + def values + synchronize { ns_values } + end + alias_method :to_a, :values + + # @!macro struct_values_at + def values_at(*indexes) + synchronize { ns_values_at(indexes) } + end + + # @!macro struct_inspect + def inspect + synchronize { ns_inspect } + end + alias_method :to_s, :inspect + + # @!macro struct_merge + def merge(other, &block) + synchronize { ns_merge(other, &block) } + end + + # @!macro struct_to_h + def to_h + synchronize { ns_to_h } + end + + # @!macro struct_get + def [](member) + synchronize { ns_get(member) } + end + + # @!macro struct_equality + def ==(other) + synchronize { ns_equality(other) } + end + + # @!macro struct_each + def each(&block) + return enum_for(:each) unless block_given? + synchronize { ns_each(&block) } + end + + # @!macro struct_each_pair + def each_pair(&block) + return enum_for(:each_pair) unless block_given? + synchronize { ns_each_pair(&block) } + end + + # @!macro struct_select + def select(&block) + return enum_for(:select) unless block_given? + synchronize { ns_select(&block) } + end + + # @!macro struct_set + # + # @raise [Concurrent::ImmutabilityError] if the given member has already been set + def []=(member, value) + if member.is_a? Integer + length = synchronize { @values.length } + if member >= length + raise IndexError.new("offset #{member} too large for struct(size:#{length})") + end + synchronize do + unless @values[member].nil? + raise Concurrent::ImmutabilityError.new('struct member has already been set') + end + @values[member] = value + end + else + send("#{member}=", value) + end + rescue NoMethodError + raise NameError.new("no member '#{member}' in struct") + end + + private + + # @!visibility private + def initialize_copy(original) + synchronize do + super(original) + ns_initialize_copy + end + end + + # @!macro struct_new + def self.new(*args, &block) + clazz_name = nil + if args.length == 0 + raise ArgumentError.new('wrong number of arguments (0 for 1+)') + elsif args.length > 0 && args.first.is_a?(String) + clazz_name = args.shift + end + FACTORY.define_struct(clazz_name, args, &block) + end + + FACTORY = Class.new(Synchronization::LockableObject) do + def define_struct(name, members, &block) + synchronize do + clazz = Synchronization::AbstractStruct.define_struct_class(SettableStruct, Synchronization::LockableObject, name, members, &block) + members.each_with_index do |member, index| + clazz.send :remove_method, member if clazz.instance_methods.include? member + clazz.send(:define_method, member) do + synchronize { @values[index] } + end + clazz.send(:define_method, "#{member}=") do |value| + synchronize do + unless @values[index].nil? + raise Concurrent::ImmutabilityError.new('struct member has already been set') + end + @values[index] = value + end + end + end + clazz + end + end + end.new + private_constant :FACTORY + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization.rb new file mode 100644 index 0000000000000..6d8cf4bd584d4 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization.rb @@ -0,0 +1,13 @@ +require 'concurrent/utility/native_extension_loader' # load native parts first + +require 'concurrent/synchronization/object' +require 'concurrent/synchronization/lockable_object' +require 'concurrent/synchronization/condition' +require 'concurrent/synchronization/lock' + +module Concurrent + # @!visibility private + module Synchronization + end +end + diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb new file mode 100644 index 0000000000000..d9050b312fd45 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb @@ -0,0 +1,102 @@ +require 'concurrent/utility/native_extension_loader' # load native parts first +require 'concurrent/utility/monotonic_time' +require 'concurrent/synchronization/object' + +module Concurrent + module Synchronization + + # @!visibility private + class AbstractLockableObject < Synchronization::Object + + protected + + # @!macro synchronization_object_method_synchronize + # + # @yield runs the block synchronized against this object, + # equivalent of java's `synchronize(this) {}` + # @note can by made public in descendants if required by `public :synchronize` + def synchronize + raise NotImplementedError + end + + # @!macro synchronization_object_method_ns_wait_until + # + # Wait until condition is met or timeout passes, + # protects against spurious wake-ups. + # @param [Numeric, nil] timeout in seconds, `nil` means no timeout + # @yield condition to be met + # @yieldreturn [true, false] + # @return [true, false] if condition met + # @note only to be used inside synchronized block + # @note to provide direct access to this method in a descendant add method + # ``` + # def wait_until(timeout = nil, &condition) + # synchronize { ns_wait_until(timeout, &condition) } + # end + # ``` + def ns_wait_until(timeout = nil, &condition) + if timeout + wait_until = Concurrent.monotonic_time + timeout + loop do + now = Concurrent.monotonic_time + condition_result = condition.call + return condition_result if now >= wait_until || condition_result + ns_wait wait_until - now + end + else + ns_wait timeout until condition.call + true + end + end + + # @!macro synchronization_object_method_ns_wait + # + # Wait until another thread calls #signal or #broadcast, + # spurious wake-ups can happen. + # + # @param [Numeric, nil] timeout in seconds, `nil` means no timeout + # @return [self] + # @note only to be used inside synchronized block + # @note to provide direct access to this method in a descendant add method + # ``` + # def wait(timeout = nil) + # synchronize { ns_wait(timeout) } + # end + # ``` + def ns_wait(timeout = nil) + raise NotImplementedError + end + + # @!macro synchronization_object_method_ns_signal + # + # Signal one waiting thread. + # @return [self] + # @note only to be used inside synchronized block + # @note to provide direct access to this method in a descendant add method + # ``` + # def signal + # synchronize { ns_signal } + # end + # ``` + def ns_signal + raise NotImplementedError + end + + # @!macro synchronization_object_method_ns_broadcast + # + # Broadcast to all waiting threads. + # @return [self] + # @note only to be used inside synchronized block + # @note to provide direct access to this method in a descendant add method + # ``` + # def broadcast + # synchronize { ns_broadcast } + # end + # ``` + def ns_broadcast + raise NotImplementedError + end + + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/abstract_object.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/abstract_object.rb new file mode 100644 index 0000000000000..7cd2decf99ca5 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/abstract_object.rb @@ -0,0 +1,22 @@ +module Concurrent + module Synchronization + + # @!visibility private + # @!macro internal_implementation_note + class AbstractObject + def initialize + # nothing to do + end + + # @!visibility private + # @abstract + def full_memory_barrier + raise NotImplementedError + end + + def self.attr_volatile(*names) + raise NotImplementedError + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb new file mode 100644 index 0000000000000..1fe90c1649bf8 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb @@ -0,0 +1,171 @@ +module Concurrent + module Synchronization + + # @!visibility private + # @!macro internal_implementation_note + module AbstractStruct + + # @!visibility private + def initialize(*values) + super() + ns_initialize(*values) + end + + # @!macro struct_length + # + # Returns the number of struct members. + # + # @return [Fixnum] the number of struct members + def length + self.class::MEMBERS.length + end + alias_method :size, :length + + # @!macro struct_members + # + # Returns the struct members as an array of symbols. + # + # @return [Array] the struct members as an array of symbols + def members + self.class::MEMBERS.dup + end + + protected + + # @!macro struct_values + # + # @!visibility private + def ns_values + @values.dup + end + + # @!macro struct_values_at + # + # @!visibility private + def ns_values_at(indexes) + @values.values_at(*indexes) + end + + # @!macro struct_to_h + # + # @!visibility private + def ns_to_h + length.times.reduce({}){|memo, i| memo[self.class::MEMBERS[i]] = @values[i]; memo} + end + + # @!macro struct_get + # + # @!visibility private + def ns_get(member) + if member.is_a? Integer + if member >= @values.length + raise IndexError.new("offset #{member} too large for struct(size:#{@values.length})") + end + @values[member] + else + send(member) + end + rescue NoMethodError + raise NameError.new("no member '#{member}' in struct") + end + + # @!macro struct_equality + # + # @!visibility private + def ns_equality(other) + self.class == other.class && self.values == other.values + end + + # @!macro struct_each + # + # @!visibility private + def ns_each + values.each{|value| yield value } + end + + # @!macro struct_each_pair + # + # @!visibility private + def ns_each_pair + @values.length.times do |index| + yield self.class::MEMBERS[index], @values[index] + end + end + + # @!macro struct_select + # + # @!visibility private + def ns_select + values.select{|value| yield value } + end + + # @!macro struct_inspect + # + # @!visibility private + def ns_inspect + struct = pr_underscore(self.class.ancestors[1]) + clazz = ((self.class.to_s =~ /^#" + end + + # @!macro struct_merge + # + # @!visibility private + def ns_merge(other, &block) + self.class.new(*self.to_h.merge(other, &block).values) + end + + # @!visibility private + def ns_initialize_copy + @values = @values.map do |val| + begin + val.clone + rescue TypeError + val + end + end + end + + # @!visibility private + def pr_underscore(clazz) + word = clazz.to_s.dup # dup string to workaround JRuby 9.2.0.0 bug https://github.com/jruby/jruby/issues/5229 + word.gsub!(/::/, '/') + word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2') + word.gsub!(/([a-z\d])([A-Z])/,'\1_\2') + word.tr!("-", "_") + word.downcase! + word + end + + # @!visibility private + def self.define_struct_class(parent, base, name, members, &block) + clazz = Class.new(base || Object) do + include parent + self.const_set(:MEMBERS, members.collect{|member| member.to_s.to_sym}.freeze) + def ns_initialize(*values) + raise ArgumentError.new('struct size differs') if values.length > length + @values = values.fill(nil, values.length..length-1) + end + end + unless name.nil? + begin + parent.send :remove_const, name if parent.const_defined?(name, false) + parent.const_set(name, clazz) + clazz + rescue NameError + raise NameError.new("identifier #{name} needs to be constant") + end + end + members.each_with_index do |member, index| + clazz.send :remove_method, member if clazz.instance_methods.include? member + clazz.send(:define_method, member) do + @values[index] + end + end + clazz.class_exec(&block) unless block.nil? + clazz.singleton_class.send :alias_method, :[], :new + clazz + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/condition.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/condition.rb new file mode 100644 index 0000000000000..5daa68be8ab54 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/condition.rb @@ -0,0 +1,62 @@ +require 'concurrent/synchronization/lockable_object' + +module Concurrent + module Synchronization + + # @!visibility private + # TODO (pitr-ch 04-Dec-2016): should be in edge + class Condition < LockableObject + safe_initialization! + + # TODO (pitr 12-Sep-2015): locks two objects, improve + # TODO (pitr 26-Sep-2015): study + # http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/java/util/concurrent/locks/AbstractQueuedSynchronizer.java#AbstractQueuedSynchronizer.Node + + singleton_class.send :alias_method, :private_new, :new + private_class_method :new + + def initialize(lock) + super() + @Lock = lock + end + + def wait(timeout = nil) + @Lock.synchronize { ns_wait(timeout) } + end + + def ns_wait(timeout = nil) + synchronize { super(timeout) } + end + + def wait_until(timeout = nil, &condition) + @Lock.synchronize { ns_wait_until(timeout, &condition) } + end + + def ns_wait_until(timeout = nil, &condition) + synchronize { super(timeout, &condition) } + end + + def signal + @Lock.synchronize { ns_signal } + end + + def ns_signal + synchronize { super } + end + + def broadcast + @Lock.synchronize { ns_broadcast } + end + + def ns_broadcast + synchronize { super } + end + end + + class LockableObject < LockableObjectImplementation + def new_condition + Condition.private_new(self) + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/full_memory_barrier.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/full_memory_barrier.rb new file mode 100644 index 0000000000000..139e08d854e01 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/full_memory_barrier.rb @@ -0,0 +1,29 @@ +require 'concurrent/utility/native_extension_loader' # load native parts first + +module Concurrent + module Synchronization + case + when Concurrent.on_cruby? + def self.full_memory_barrier + # relying on undocumented behavior of CRuby, GVL acquire has lock which ensures visibility of ivars + # https://github.com/ruby/ruby/blob/ruby_2_2/thread_pthread.c#L204-L211 + end + + when Concurrent.on_jruby? + require 'concurrent/utility/native_extension_loader' + def self.full_memory_barrier + JRubyAttrVolatile.full_memory_barrier + end + + when Concurrent.on_truffleruby? + def self.full_memory_barrier + TruffleRuby.full_memory_barrier + end + + else + warn 'Possibly unsupported Ruby implementation' + def self.full_memory_barrier + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/jruby_lockable_object.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/jruby_lockable_object.rb new file mode 100644 index 0000000000000..76930461bdb8c --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/jruby_lockable_object.rb @@ -0,0 +1,15 @@ +require 'concurrent/utility/native_extension_loader' # load native parts first + +module Concurrent + module Synchronization + + if Concurrent.on_jruby? + + # @!visibility private + # @!macro internal_implementation_note + class JRubyLockableObject < AbstractLockableObject + + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/lock.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/lock.rb new file mode 100644 index 0000000000000..f90e0b5f76872 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/lock.rb @@ -0,0 +1,38 @@ +require 'concurrent/synchronization/lockable_object' + +module Concurrent + module Synchronization + + # @!visibility private + # TODO (pitr-ch 04-Dec-2016): should be in edge + class Lock < LockableObject + # TODO use JavaReentrantLock on JRuby + + public :synchronize + + def wait(timeout = nil) + synchronize { ns_wait(timeout) } + end + + public :ns_wait + + def wait_until(timeout = nil, &condition) + synchronize { ns_wait_until(timeout, &condition) } + end + + public :ns_wait_until + + def signal + synchronize { ns_signal } + end + + public :ns_signal + + def broadcast + synchronize { ns_broadcast } + end + + public :ns_broadcast + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/lockable_object.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/lockable_object.rb new file mode 100644 index 0000000000000..08d2ff66cd824 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/lockable_object.rb @@ -0,0 +1,75 @@ +require 'concurrent/utility/engine' +require 'concurrent/synchronization/abstract_lockable_object' +require 'concurrent/synchronization/mutex_lockable_object' +require 'concurrent/synchronization/jruby_lockable_object' + +module Concurrent + module Synchronization + + # @!visibility private + # @!macro internal_implementation_note + LockableObjectImplementation = case + when Concurrent.on_cruby? + MutexLockableObject + when Concurrent.on_jruby? + JRubyLockableObject + when Concurrent.on_truffleruby? + MutexLockableObject + else + warn 'Possibly unsupported Ruby implementation' + MonitorLockableObject + end + private_constant :LockableObjectImplementation + + # Safe synchronization under any Ruby implementation. + # It provides methods like {#synchronize}, {#wait}, {#signal} and {#broadcast}. + # Provides a single layer which can improve its implementation over time without changes needed to + # the classes using it. Use {Synchronization::Object} not this abstract class. + # + # @note this object does not support usage together with + # [`Thread#wakeup`](http://ruby-doc.org/core/Thread.html#method-i-wakeup) + # and [`Thread#raise`](http://ruby-doc.org/core/Thread.html#method-i-raise). + # `Thread#sleep` and `Thread#wakeup` will work as expected but mixing `Synchronization::Object#wait` and + # `Thread#wakeup` will not work on all platforms. + # + # @see Event implementation as an example of this class use + # + # @example simple + # class AnClass < Synchronization::Object + # def initialize + # super + # synchronize { @value = 'asd' } + # end + # + # def value + # synchronize { @value } + # end + # end + # + # @!visibility private + class LockableObject < LockableObjectImplementation + + # TODO (pitr 12-Sep-2015): make private for c-r, prohibit subclassing + # TODO (pitr 12-Sep-2015): we inherit too much ourselves :/ + + # @!method initialize(*args, &block) + # @!macro synchronization_object_method_initialize + + # @!method synchronize + # @!macro synchronization_object_method_synchronize + + # @!method wait_until(timeout = nil, &condition) + # @!macro synchronization_object_method_ns_wait_until + + # @!method wait(timeout = nil) + # @!macro synchronization_object_method_ns_wait + + # @!method signal + # @!macro synchronization_object_method_ns_signal + + # @!method broadcast + # @!macro synchronization_object_method_ns_broadcast + + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb new file mode 100644 index 0000000000000..acc9745a2e292 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb @@ -0,0 +1,89 @@ +require 'concurrent/synchronization/abstract_lockable_object' + +module Concurrent + module Synchronization + + # @!visibility private + # @!macro internal_implementation_note + module ConditionSignalling + protected + + def ns_signal + @__Condition__.signal + self + end + + def ns_broadcast + @__Condition__.broadcast + self + end + end + + + # @!visibility private + # @!macro internal_implementation_note + class MutexLockableObject < AbstractLockableObject + include ConditionSignalling + + safe_initialization! + + def initialize + super() + @__Lock__ = ::Mutex.new + @__Condition__ = ::ConditionVariable.new + end + + def initialize_copy(other) + super + @__Lock__ = ::Mutex.new + @__Condition__ = ::ConditionVariable.new + end + + protected + + def synchronize + if @__Lock__.owned? + yield + else + @__Lock__.synchronize { yield } + end + end + + def ns_wait(timeout = nil) + @__Condition__.wait @__Lock__, timeout + self + end + end + + # @!visibility private + # @!macro internal_implementation_note + class MonitorLockableObject < AbstractLockableObject + include ConditionSignalling + + safe_initialization! + + def initialize + super() + @__Lock__ = ::Monitor.new + @__Condition__ = @__Lock__.new_cond + end + + def initialize_copy(other) + super + @__Lock__ = ::Monitor.new + @__Condition__ = @__Lock__.new_cond + end + + protected + + def synchronize # TODO may be a problem with lock.synchronize { lock.wait } + @__Lock__.synchronize { yield } + end + + def ns_wait(timeout = nil) + @__Condition__.wait timeout + self + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/object.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/object.rb new file mode 100644 index 0000000000000..e839c9f18890f --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/object.rb @@ -0,0 +1,151 @@ +require 'concurrent/utility/native_extension_loader' # load native parts first + +require 'concurrent/synchronization/safe_initialization' +require 'concurrent/synchronization/volatile' +require 'concurrent/atomic/atomic_reference' + +module Concurrent + module Synchronization + + # Abstract object providing final, volatile, ans CAS extensions to build other concurrent abstractions. + # - final instance variables see {Object.safe_initialization!} + # - volatile instance variables see {Object.attr_volatile} + # - volatile instance variables see {Object.attr_atomic} + # @!visibility private + class Object < AbstractObject + include Volatile + + # TODO make it a module if possible + + # @!method self.attr_volatile(*names) + # Creates methods for reading and writing (as `attr_accessor` does) to a instance variable with + # volatile (Java) semantic. The instance variable should be accessed only through generated methods. + # + # @param [::Array] names of the instance variables to be volatile + # @return [::Array] names of defined method names + + # Has to be called by children. + def initialize + super + __initialize_atomic_fields__ + end + + def self.safe_initialization! + extend SafeInitialization unless safe_initialization? + end + + def self.safe_initialization? + self.singleton_class < SafeInitialization + end + + # For testing purposes, quite slow. Injects assert code to new method which will raise if class instance contains + # any instance variables with CamelCase names and isn't {.safe_initialization?}. + # @raise when offend found + # @return [true] + def self.ensure_safe_initialization_when_final_fields_are_present + Object.class_eval do + def self.new(*args, &block) + object = super(*args, &block) + ensure + has_final_field = object.instance_variables.any? { |v| v.to_s =~ /^@[A-Z]/ } + if has_final_field && !safe_initialization? + raise "there was an instance of #{object.class} with final field but not marked with safe_initialization!" + end + end + end + true + end + + # 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. + # 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)`. + # @param [::Array] names of the instance variables to be volatile with CAS. + # @return [::Array] names of defined method names. + # @!macro attr_atomic + # @!method $1 + # @return [Object] The $1. + # @!method $1=(new_$1) + # Set the $1. + # @return [Object] new_$1. + # @!method swap_$1(new_$1) + # Set the $1 to new_$1 and return the old $1. + # @return [Object] old $1 + # @!method compare_and_set_$1(expected_$1, new_$1) + # Sets the $1 to new_$1 if the current $1 is expected_$1 + # @return [true, false] + # @!method update_$1(&block) + # Updates the $1 using the block. + # @yield [Object] Calculate a new $1 using given (old) $1 + # @yieldparam [Object] old $1 + # @return [Object] new $1 + def self.attr_atomic(*names) + @__atomic_fields__ ||= [] + @__atomic_fields__ += names + safe_initialization! + define_initialize_atomic_fields + + names.each do |name| + ivar = :"@Atomic#{name.to_s.gsub(/(?:^|_)(.)/) { $1.upcase }}" + class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def #{name} + #{ivar}.get + end + + def #{name}=(value) + #{ivar}.set value + end + + def swap_#{name}(value) + #{ivar}.swap value + end + + def compare_and_set_#{name}(expected, value) + #{ivar}.compare_and_set expected, value + end + + def update_#{name}(&block) + #{ivar}.update(&block) + end + RUBY + end + names.flat_map { |n| [n, :"#{n}=", :"swap_#{n}", :"compare_and_set_#{n}", :"update_#{n}"] } + end + + # @param [true, false] inherited should inherited volatile with CAS fields be returned? + # @return [::Array] Returns defined volatile with CAS fields on this class. + def self.atomic_attributes(inherited = true) + @__atomic_fields__ ||= [] + ((superclass.atomic_attributes if superclass.respond_to?(:atomic_attributes) && inherited) || []) + @__atomic_fields__ + end + + # @return [true, false] is the attribute with name atomic? + def self.atomic_attribute?(name) + atomic_attributes.include? name + end + + private + + def self.define_initialize_atomic_fields + assignments = @__atomic_fields__.map do |name| + "@Atomic#{name.to_s.gsub(/(?:^|_)(.)/) { $1.upcase }} = Concurrent::AtomicReference.new(nil)" + end.join("\n") + + class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def __initialize_atomic_fields__ + super + #{assignments} + end + RUBY + end + + private_class_method :define_initialize_atomic_fields + + def __initialize_atomic_fields__ + end + + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/safe_initialization.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/safe_initialization.rb new file mode 100644 index 0000000000000..f785e35229fa3 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/safe_initialization.rb @@ -0,0 +1,36 @@ +require 'concurrent/synchronization/full_memory_barrier' + +module Concurrent + module Synchronization + + # @!visibility private + # @!macro internal_implementation_note + # + # By extending this module, a class and all its children are marked to be constructed safely. Meaning that + # all writes (ivar initializations) are made visible to all readers of newly constructed object. It ensures + # same behaviour as Java's final fields. + # + # Due to using Kernel#extend, the module is not included again if already present in the ancestors, + # which avoids extra overhead. + # + # @example + # class AClass < Concurrent::Synchronization::Object + # extend Concurrent::Synchronization::SafeInitialization + # + # def initialize + # @AFinalValue = 'value' # published safely, #foo will never return nil + # end + # + # def foo + # @AFinalValue + # end + # end + module SafeInitialization + def new(*args, &block) + super(*args, &block) + ensure + Concurrent::Synchronization.full_memory_barrier + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/volatile.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/volatile.rb new file mode 100644 index 0000000000000..46e8ba6a48ca1 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/volatile.rb @@ -0,0 +1,101 @@ +require 'concurrent/utility/native_extension_loader' # load native parts first +require 'concurrent/utility/engine' +require 'concurrent/synchronization/full_memory_barrier' + +module Concurrent + module Synchronization + + # Volatile adds the attr_volatile class method when included. + # + # @example + # class Foo + # include Concurrent::Synchronization::Volatile + # + # attr_volatile :bar + # + # def initialize + # self.bar = 1 + # end + # end + # + # foo = Foo.new + # foo.bar + # => 1 + # foo.bar = 2 + # => 2 + # + # @!visibility private + module Volatile + def self.included(base) + base.extend(ClassMethods) + end + + def full_memory_barrier + Synchronization.full_memory_barrier + end + + module ClassMethods + if Concurrent.on_cruby? + def attr_volatile(*names) + names.each do |name| + ivar = :"@volatile_#{name}" + class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def #{name} + #{ivar} + end + + def #{name}=(value) + #{ivar} = value + end + RUBY + end + names.map { |n| [n, :"#{n}="] }.flatten + end + + elsif Concurrent.on_jruby? + def attr_volatile(*names) + names.each do |name| + ivar = :"@volatile_#{name}" + + class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def #{name} + ::Concurrent::Synchronization::JRubyAttrVolatile.instance_variable_get_volatile(self, :#{ivar}) + end + + def #{name}=(value) + ::Concurrent::Synchronization::JRubyAttrVolatile.instance_variable_set_volatile(self, :#{ivar}, value) + end + RUBY + + end + names.map { |n| [n, :"#{n}="] }.flatten + end + + else + warn 'Possibly unsupported Ruby implementation' unless Concurrent.on_truffleruby? + + def attr_volatile(*names) + names.each do |name| + ivar = :"@volatile_#{name}" + + class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def #{name} + ::Concurrent::Synchronization.full_memory_barrier + #{ivar} + end + + def #{name}=(value) + #{ivar} = value + ::Concurrent::Synchronization.full_memory_barrier + end + RUBY + end + + names.map { |n| [n, :"#{n}="] }.flatten + end + end + end + + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb new file mode 100644 index 0000000000000..019d84382d609 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb @@ -0,0 +1,47 @@ +require 'delegate' +require 'monitor' + +module Concurrent + # This class provides a trivial way to synchronize all calls to a given object + # by wrapping it with a `Delegator` that performs `Monitor#enter/exit` calls + # around the delegated `#send`. Example: + # + # array = [] # not thread-safe on many impls + # array = SynchronizedDelegator.new([]) # thread-safe + # + # A simple `Monitor` provides a very coarse-grained way to synchronize a given + # object, in that it will cause synchronization for methods that have no need + # for it, but this is a trivial way to get thread-safety where none may exist + # currently on some implementations. + # + # This class is currently being considered for inclusion into stdlib, via + # https://bugs.ruby-lang.org/issues/8556 + # + # @!visibility private + class SynchronizedDelegator < SimpleDelegator + def setup + @old_abort = Thread.abort_on_exception + Thread.abort_on_exception = true + end + + def teardown + Thread.abort_on_exception = @old_abort + end + + def initialize(obj) + __setobj__(obj) + @monitor = Monitor.new + end + + def method_missing(method, *args, &block) + monitor = @monitor + begin + monitor.enter + super + ensure + monitor.exit + end + end + + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util.rb new file mode 100644 index 0000000000000..c67084a26fa3a --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util.rb @@ -0,0 +1,16 @@ +module Concurrent + + # @!visibility private + module ThreadSafe + + # @!visibility private + module Util + + # TODO (pitr-ch 15-Oct-2016): migrate to Utility::NativeInteger + FIXNUM_BIT_SIZE = (0.size * 8) - 2 + MAX_INT = (2 ** FIXNUM_BIT_SIZE) - 1 + # TODO (pitr-ch 15-Oct-2016): migrate to Utility::ProcessorCounter + CPU_COUNT = 16 # is there a way to determine this? + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/adder.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/adder.rb new file mode 100644 index 0000000000000..7a6e8d5c0e132 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/adder.rb @@ -0,0 +1,74 @@ +require 'concurrent/thread_safe/util' +require 'concurrent/thread_safe/util/striped64' + +module Concurrent + + # @!visibility private + module ThreadSafe + + # @!visibility private + module Util + + # A Ruby port of the Doug Lea's jsr166e.LondAdder class version 1.8 + # available in public domain. + # + # Original source code available here: + # http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/LongAdder.java?revision=1.8 + # + # One or more variables that together maintain an initially zero + # sum. When updates (method +add+) are contended across threads, + # the set of variables may grow dynamically to reduce contention. + # Method +sum+ returns the current total combined across the + # variables maintaining the sum. + # + # This class is usually preferable to single +Atomic+ reference when + # multiple threads update a common sum that is used for purposes such + # as collecting statistics, not for fine-grained synchronization + # control. Under low update contention, the two classes have similar + # characteristics. But under high contention, expected throughput of + # this class is significantly higher, at the expense of higher space + # consumption. + # + # @!visibility private + class Adder < Striped64 + # Adds the given value. + def add(x) + if (current_cells = cells) || !cas_base_computed {|current_base| current_base + x} + was_uncontended = true + hash = hash_code + unless current_cells && (cell = current_cells.volatile_get_by_hash(hash)) && (was_uncontended = cell.cas_computed {|current_value| current_value + x}) + retry_update(x, hash, was_uncontended) {|current_value| current_value + x} + end + end + end + + def increment + add(1) + end + + def decrement + add(-1) + end + + # Returns the current sum. The returned value is _NOT_ an + # atomic snapshot: Invocation in the absence of concurrent + # updates returns an accurate result, but concurrent updates that + # occur while the sum is being calculated might not be + # incorporated. + def sum + x = base + if current_cells = cells + current_cells.each do |cell| + x += cell.value if cell + end + end + x + end + + def reset + internal_reset(0) + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb new file mode 100644 index 0000000000000..01eb98f4aa603 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb @@ -0,0 +1,52 @@ +require 'concurrent/thread_safe/util' +require 'concurrent/utility/engine' + +# Shim for TruffleRuby.synchronized +if Concurrent.on_truffleruby? && !TruffleRuby.respond_to?(:synchronized) + module TruffleRuby + def self.synchronized(object, &block) + Truffle::System.synchronized(object, &block) + end + end +end + +module Concurrent + module ThreadSafe + module Util + def self.make_synchronized_on_cruby(klass) + klass.class_eval do + def initialize(*args, &block) + @_monitor = Monitor.new + super + end + + def initialize_copy(other) + # make sure a copy is not sharing a monitor with the original object! + @_monitor = Monitor.new + super + end + end + + klass.superclass.instance_methods(false).each do |method| + klass.class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def #{method}(*args) + monitor = @_monitor + monitor or raise("BUG: Internal monitor was not properly initialized. Please report this to the concurrent-ruby developers.") + monitor.synchronize { super } + end + RUBY + end + end + + def self.make_synchronized_on_truffleruby(klass) + klass.superclass.instance_methods(false).each do |method| + klass.class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def #{method}(*args, &block) + TruffleRuby.synchronized(self) { super(*args, &block) } + end + RUBY + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/power_of_two_tuple.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/power_of_two_tuple.rb new file mode 100644 index 0000000000000..b54be39c4cc84 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/power_of_two_tuple.rb @@ -0,0 +1,38 @@ +require 'concurrent/thread_safe/util' +require 'concurrent/tuple' + +module Concurrent + + # @!visibility private + module ThreadSafe + + # @!visibility private + module Util + + # @!visibility private + class PowerOfTwoTuple < Concurrent::Tuple + + def initialize(size) + raise ArgumentError, "size must be a power of 2 (#{size.inspect} provided)" unless size > 0 && size & (size - 1) == 0 + super(size) + end + + def hash_to_index(hash) + (size - 1) & hash + end + + def volatile_get_by_hash(hash) + volatile_get(hash_to_index(hash)) + end + + def volatile_set_by_hash(hash, value) + volatile_set(hash_to_index(hash), value) + end + + def next_in_size_table + self.class.new(size << 1) + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/striped64.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/striped64.rb new file mode 100644 index 0000000000000..4169c3d36607b --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/striped64.rb @@ -0,0 +1,246 @@ +require 'concurrent/thread_safe/util' +require 'concurrent/thread_safe/util/power_of_two_tuple' +require 'concurrent/thread_safe/util/volatile' +require 'concurrent/thread_safe/util/xor_shift_random' + +module Concurrent + + # @!visibility private + module ThreadSafe + + # @!visibility private + module Util + + # A Ruby port of the Doug Lea's jsr166e.Striped64 class version 1.6 + # available in public domain. + # + # Original source code available here: + # http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/Striped64.java?revision=1.6 + # + # Class holding common representation and mechanics for classes supporting + # dynamic striping on 64bit values. + # + # This class maintains a lazily-initialized table of atomically updated + # variables, plus an extra +base+ field. The table size is a power of two. + # Indexing uses masked per-thread hash codes. Nearly all methods on this + # class are private, accessed directly by subclasses. + # + # Table entries are of class +Cell+; a variant of AtomicLong padded to + # reduce cache contention on most processors. Padding is overkill for most + # Atomics because they are usually irregularly scattered in memory and thus + # don't interfere much with each other. But Atomic objects residing in + # arrays will tend to be placed adjacent to each other, and so will most + # often share cache lines (with a huge negative performance impact) without + # this precaution. + # + # In part because +Cell+s are relatively large, we avoid creating them until + # they are needed. When there is no contention, all updates are made to the + # +base+ field. Upon first contention (a failed CAS on +base+ update), the + # table is initialized to size 2. The table size is doubled upon further + # contention until reaching the nearest power of two greater than or equal + # to the number of CPUS. Table slots remain empty (+nil+) until they are + # needed. + # + # A single spinlock (+busy+) is used for initializing and resizing the + # table, as well as populating slots with new +Cell+s. There is no need for + # a blocking lock: When the lock is not available, threads try other slots + # (or the base). During these retries, there is increased contention and + # reduced locality, which is still better than alternatives. + # + # Per-thread hash codes are initialized to random values. Contention and/or + # table collisions are indicated by failed CASes when performing an update + # operation (see method +retry_update+). Upon a collision, if the table size + # is less than the capacity, it is doubled in size unless some other thread + # holds the lock. If a hashed slot is empty, and lock is available, a new + # +Cell+ is created. Otherwise, if the slot exists, a CAS is tried. Retries + # proceed by "double hashing", using a secondary hash (XorShift) to try to + # find a free slot. + # + # The table size is capped because, when there are more threads than CPUs, + # supposing that each thread were bound to a CPU, there would exist a + # perfect hash function mapping threads to slots that eliminates collisions. + # When we reach capacity, we search for this mapping by randomly varying the + # hash codes of colliding threads. Because search is random, and collisions + # only become known via CAS failures, convergence can be slow, and because + # threads are typically not bound to CPUS forever, may not occur at all. + # However, despite these limitations, observed contention rates are + # typically low in these cases. + # + # It is possible for a +Cell+ to become unused when threads that once hashed + # to it terminate, as well as in the case where doubling the table causes no + # thread to hash to it under expanded mask. We do not try to detect or + # remove such cells, under the assumption that for long-running instances, + # observed contention levels will recur, so the cells will eventually be + # needed again; and for short-lived ones, it does not matter. + # + # @!visibility private + class Striped64 + + # Padded variant of AtomicLong supporting only raw accesses plus CAS. + # The +value+ field is placed between pads, hoping that the JVM doesn't + # reorder them. + # + # Optimisation note: It would be possible to use a release-only + # form of CAS here, if it were provided. + # + # @!visibility private + class Cell < Concurrent::AtomicReference + + alias_method :cas, :compare_and_set + + def cas_computed + cas(current_value = value, yield(current_value)) + end + + # @!visibility private + def self.padding + # TODO: this only adds padding after the :value slot, need to find a way to add padding before the slot + # TODO (pitr-ch 28-Jul-2018): the padding instance vars may not be created + # hide from yardoc in a method + attr_reader :padding_0, :padding_1, :padding_2, :padding_3, :padding_4, :padding_5, :padding_6, :padding_7, :padding_8, :padding_9, :padding_10, :padding_11 + end + padding + end + + extend Volatile + attr_volatile :cells, # Table of cells. When non-null, size is a power of 2. + :base, # Base value, used mainly when there is no contention, but also as a fallback during table initialization races. Updated via CAS. + :busy # Spinlock (locked via CAS) used when resizing and/or creating Cells. + + alias_method :busy?, :busy + + def initialize + super() + self.busy = false + self.base = 0 + end + + # Handles cases of updates involving initialization, resizing, + # creating new Cells, and/or contention. See above for + # explanation. This method suffers the usual non-modularity + # problems of optimistic retry code, relying on rechecked sets of + # reads. + # + # Arguments: + # [+x+] + # the value + # [+hash_code+] + # hash code used + # [+x+] + # false if CAS failed before call + def retry_update(x, hash_code, was_uncontended) # :yields: current_value + hash = hash_code + collided = false # True if last slot nonempty + while true + if current_cells = cells + if !(cell = current_cells.volatile_get_by_hash(hash)) + if busy? + collided = false + else # Try to attach new Cell + if try_to_install_new_cell(Cell.new(x), hash) # Optimistically create and try to insert new cell + break + else + redo # Slot is now non-empty + end + end + elsif !was_uncontended # CAS already known to fail + was_uncontended = true # Continue after rehash + elsif cell.cas_computed {|current_value| yield current_value} + break + elsif current_cells.size >= CPU_COUNT || cells != current_cells # At max size or stale + collided = false + elsif collided && expand_table_unless_stale(current_cells) + collided = false + redo # Retry with expanded table + else + collided = true + end + hash = XorShiftRandom.xorshift(hash) + + elsif try_initialize_cells(x, hash) || cas_base_computed {|current_base| yield current_base} + break + end + end + self.hash_code = hash + end + + private + # Static per-thread hash code key. Shared across all instances to + # reduce Thread locals pollution and because adjustments due to + # collisions in one table are likely to be appropriate for + # others. + THREAD_LOCAL_KEY = "#{name}.hash_code".to_sym + + # A thread-local hash code accessor. The code is initially + # random, but may be set to a different value upon collisions. + def hash_code + Thread.current[THREAD_LOCAL_KEY] ||= XorShiftRandom.get + end + + def hash_code=(hash) + Thread.current[THREAD_LOCAL_KEY] = hash + end + + # Sets base and all +cells+ to the given value. + def internal_reset(initial_value) + current_cells = cells + self.base = initial_value + if current_cells + current_cells.each do |cell| + cell.value = initial_value if cell + end + end + end + + def cas_base_computed + cas_base(current_base = base, yield(current_base)) + end + + def free? + !busy? + end + + def try_initialize_cells(x, hash) + if free? && !cells + try_in_busy do + unless cells # Recheck under lock + new_cells = PowerOfTwoTuple.new(2) + new_cells.volatile_set_by_hash(hash, Cell.new(x)) + self.cells = new_cells + end + end + end + end + + def expand_table_unless_stale(current_cells) + try_in_busy do + if current_cells == cells # Recheck under lock + new_cells = current_cells.next_in_size_table + current_cells.each_with_index {|x, i| new_cells.volatile_set(i, x)} + self.cells = new_cells + end + end + end + + def try_to_install_new_cell(new_cell, hash) + try_in_busy do + # Recheck under lock + if (current_cells = cells) && !current_cells.volatile_get(i = current_cells.hash_to_index(hash)) + current_cells.volatile_set(i, new_cell) + end + end + end + + def try_in_busy + if cas_busy(false, true) + begin + yield + ensure + self.busy = false + end + end + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/volatile.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/volatile.rb new file mode 100644 index 0000000000000..cdac2a396a791 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/volatile.rb @@ -0,0 +1,75 @@ +require 'concurrent/thread_safe/util' + +module Concurrent + + # @!visibility private + module ThreadSafe + + # @!visibility private + module Util + + # @!visibility private + module Volatile + + # Provides +volatile+ (in the JVM's sense) attribute accessors implemented + # atop of +Concurrent::AtomicReference+. + # + # Usage: + # class Foo + # extend Concurrent::ThreadSafe::Util::Volatile + # attr_volatile :foo, :bar + # + # def initialize(bar) + # super() # must super() into parent initializers before using the volatile attribute accessors + # self.bar = bar + # end + # + # def hello + # my_foo = foo # volatile read + # self.foo = 1 # volatile write + # cas_foo(1, 2) # => true | a strong CAS + # end + # end + def attr_volatile(*attr_names) + return if attr_names.empty? + include(Module.new do + atomic_ref_setup = attr_names.map {|attr_name| "@__#{attr_name} = Concurrent::AtomicReference.new"} + initialize_copy_setup = attr_names.zip(atomic_ref_setup).map do |attr_name, ref_setup| + "#{ref_setup}(other.instance_variable_get(:@__#{attr_name}).get)" + end + class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 + def initialize(*) + super + #{atomic_ref_setup.join('; ')} + end + + def initialize_copy(other) + super + #{initialize_copy_setup.join('; ')} + end + RUBY_EVAL + + attr_names.each do |attr_name| + class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 + def #{attr_name} + @__#{attr_name}.get + end + + def #{attr_name}=(value) + @__#{attr_name}.set(value) + end + + def compare_and_set_#{attr_name}(old_value, new_value) + @__#{attr_name}.compare_and_set(old_value, new_value) + end + RUBY_EVAL + + alias_method :"cas_#{attr_name}", :"compare_and_set_#{attr_name}" + alias_method :"lazy_set_#{attr_name}", :"#{attr_name}=" + end + end) + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/xor_shift_random.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/xor_shift_random.rb new file mode 100644 index 0000000000000..bdde2dd8b363f --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/xor_shift_random.rb @@ -0,0 +1,50 @@ +require 'concurrent/thread_safe/util' + +module Concurrent + + # @!visibility private + module ThreadSafe + + # @!visibility private + module Util + + # A xorshift random number (positive +Fixnum+s) generator, provides + # reasonably cheap way to generate thread local random numbers without + # contending for the global +Kernel.rand+. + # + # 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 + # do_something_at_random + # end + # end + module XorShiftRandom + extend self + MAX_XOR_SHIFTABLE_INT = MAX_INT - 1 + + # Generates an initial non-zero positive +Fixnum+ via +Kernel.rand+. + def get + Kernel.rand(MAX_XOR_SHIFTABLE_INT) + 1 # 0 can't be xorshifted + end + + # xorshift based on: http://www.jstatsoft.org/v08/i14/paper + if 0.size == 4 + # using the "yˆ=y>>a; yˆ=y<>c;" transform with the (a,b,c) tuple with values (3,1,14) to minimise Bignum overflows + def xorshift(x) + x ^= x >> 3 + x ^= (x << 1) & MAX_INT # cut-off Bignum overflow + x ^= x >> 14 + end + else + # using the "yˆ=y>>a; yˆ=y<>c;" transform with the (a,b,c) tuple with values (1,1,54) to minimise Bignum overflows + def xorshift(x) + x ^= x >> 1 + x ^= (x << 1) & MAX_INT # cut-off Bignum overflow + x ^= x >> 54 + end + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/timer_task.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/timer_task.rb new file mode 100644 index 0000000000000..dd2037f62a107 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/timer_task.rb @@ -0,0 +1,361 @@ +require 'concurrent/collection/copy_on_notify_observer_set' +require 'concurrent/concern/dereferenceable' +require 'concurrent/concern/observable' +require 'concurrent/atomic/atomic_boolean' +require 'concurrent/executor/executor_service' +require 'concurrent/executor/ruby_executor_service' +require 'concurrent/executor/safe_task_executor' +require 'concurrent/scheduled_task' + +module Concurrent + + # A very common concurrency pattern is to run a thread that performs a task at + # regular intervals. The thread that performs the task sleeps for the given + # interval then wakes up and performs the task. Lather, rinse, repeat... This + # pattern causes two problems. First, it is difficult to test the business + # logic of the task because the task itself is tightly coupled with the + # concurrency logic. Second, an exception raised while performing the task can + # cause the entire thread to abend. In a long-running application where the + # task thread is intended to run for days/weeks/years a crashed task thread + # can pose a significant problem. `TimerTask` alleviates both problems. + # + # When a `TimerTask` is launched it starts a thread for monitoring the + # execution interval. The `TimerTask` thread does not perform the task, + # however. Instead, the TimerTask launches the task on a separate thread. + # 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. + # + # One other advantage of `TimerTask` is that it forces the business logic to + # be completely decoupled from the concurrency logic. The business logic can + # be tested separately then passed to the `TimerTask` for scheduling and + # running. + # + # A `TimerTask` supports two different types of interval calculations. + # A fixed delay will always wait the same amount of time between the + # completion of one task and the start of the next. A fixed rate will + # attempt to maintain a constant rate of execution regardless of the + # duration of the task. For example, if a fixed rate task is scheduled + # to run every 60 seconds but the task itself takes 10 seconds to + # complete, the next task will be scheduled to run 50 seconds after + # the start of the previous task. If the task takes 70 seconds to + # complete, the next task will be start immediately after the previous + # task completes. Tasks will not be executed concurrently. + # + # In some cases it may be necessary for a `TimerTask` to affect its own + # execution cycle. To facilitate this, a reference to the TimerTask instance + # is passed as an argument to the provided block every time the task is + # executed. + # + # The `TimerTask` class includes the `Dereferenceable` mixin module so the + # result of the last execution is always available via the `#value` method. + # Dereferencing options can be passed to the `TimerTask` during construction or + # at any later time using the `#set_deref_options` method. + # + # `TimerTask` supports notification through the Ruby standard library + # {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). + # + # @!macro copy_options + # + # @example Basic usage + # task = Concurrent::TimerTask.new{ puts 'Boom!' } + # task.execute + # + # task.execution_interval #=> 60 (default) + # + # # wait 60 seconds... + # #=> 'Boom!' + # + # task.shutdown #=> true + # + # @example Configuring `:execution_interval` + # task = Concurrent::TimerTask.new(execution_interval: 5) do + # puts 'Boom!' + # end + # + # task.execution_interval #=> 5 + # + # @example Immediate execution with `:run_now` + # task = Concurrent::TimerTask.new(run_now: true){ puts 'Boom!' } + # task.execute + # + # #=> 'Boom!' + # + # @example Configuring `:interval_type` with either :fixed_delay or :fixed_rate, default is :fixed_delay + # task = Concurrent::TimerTask.new(execution_interval: 5, interval_type: :fixed_rate) do + # puts 'Boom!' + # end + # task.interval_type #=> :fixed_rate + # + # @example Last `#value` and `Dereferenceable` mixin + # task = Concurrent::TimerTask.new( + # dup_on_deref: true, + # execution_interval: 5 + # ){ Time.now } + # + # task.execute + # Time.now #=> 2013-11-07 18:06:50 -0500 + # sleep(10) + # task.value #=> 2013-11-07 18:06:55 -0500 + # + # @example Controlling execution from within the block + # timer_task = Concurrent::TimerTask.new(execution_interval: 1) do |task| + # task.execution_interval.to_i.times{ print 'Boom! ' } + # print "\n" + # task.execution_interval += 1 + # if task.execution_interval > 5 + # puts 'Stopping...' + # task.shutdown + # end + # end + # + # timer_task.execute + # #=> Boom! + # #=> Boom! Boom! + # #=> Boom! Boom! Boom! + # #=> Boom! Boom! Boom! Boom! + # #=> Boom! Boom! Boom! Boom! Boom! + # #=> Stopping... + # + # @example Observation + # class TaskObserver + # def update(time, result, ex) + # if result + # print "(#{time}) Execution successfully returned #{result}\n" + # else + # print "(#{time}) Execution failed with error #{ex}\n" + # end + # end + # end + # + # task = Concurrent::TimerTask.new(execution_interval: 1){ 42 } + # task.add_observer(TaskObserver.new) + # task.execute + # sleep 4 + # + # #=> (2013-10-13 19:08:58 -0400) Execution successfully returned 42 + # #=> (2013-10-13 19:08:59 -0400) Execution successfully returned 42 + # #=> (2013-10-13 19:09:00 -0400) Execution successfully returned 42 + # task.shutdown + # + # task = Concurrent::TimerTask.new(execution_interval: 1){ sleep } + # task.add_observer(TaskObserver.new) + # task.execute + # + # #=> (2013-10-13 19:07:25 -0400) Execution timed out + # #=> (2013-10-13 19:07:27 -0400) Execution timed out + # #=> (2013-10-13 19:07:29 -0400) Execution timed out + # task.shutdown + # + # task = Concurrent::TimerTask.new(execution_interval: 1){ raise StandardError } + # task.add_observer(TaskObserver.new) + # task.execute + # + # #=> (2013-10-13 19:09:37 -0400) Execution failed with error StandardError + # #=> (2013-10-13 19:09:38 -0400) Execution failed with error StandardError + # #=> (2013-10-13 19:09:39 -0400) Execution failed with error StandardError + # task.shutdown + # + # @see http://ruby-doc.org/stdlib-2.0/libdoc/observer/rdoc/Observable.html + # @see http://docs.oracle.com/javase/7/docs/api/java/util/TimerTask.html + class TimerTask < RubyExecutorService + include Concern::Dereferenceable + include Concern::Observable + + # Default `:execution_interval` in seconds. + EXECUTION_INTERVAL = 60 + + # Maintain the interval between the end of one execution and the start of the next execution. + FIXED_DELAY = :fixed_delay + + # Maintain the interval between the start of one execution and the start of the next. + # If execution time exceeds the interval, the next execution will start immediately + # after the previous execution finishes. Executions will not run concurrently. + FIXED_RATE = :fixed_rate + + # Default `:interval_type` + DEFAULT_INTERVAL_TYPE = FIXED_DELAY + + # Create a new TimerTask with the given task and configuration. + # + # @!macro timer_task_initialize + # @param [Hash] opts the options defining task execution. + # @option opts [Float] :execution_interval number of seconds between + # task executions (default: EXECUTION_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) + # @options opts [Symbol] :interval_type method to calculate the interval + # between executions, can be either :fixed_rate or :fixed_delay. + # (default: :fixed_delay) + # @option opts [Executor] executor, default is `global_io_executor` + # + # @!macro deref_options + # + # @raise ArgumentError when no block is given. + # + # @yield to the block after :execution_interval seconds have passed since + # the last yield + # @yieldparam task a reference to the `TimerTask` instance so that the + # block can control its own lifecycle. Necessary since `self` will + # refer to the execution context of the block rather than the running + # `TimerTask`. + # + # @return [TimerTask] the new `TimerTask` + def initialize(opts = {}, &task) + raise ArgumentError.new('no block given') unless block_given? + super + set_deref_options opts + end + + # Is the executor running? + # + # @return [Boolean] `true` when running, `false` when shutting down or shutdown + def running? + @running.true? + end + + # Execute a previously created `TimerTask`. + # + # @return [TimerTask] a reference to `self` + # + # @example Instance and execute in separate steps + # task = Concurrent::TimerTask.new(execution_interval: 10){ print "Hello World\n" } + # task.running? #=> false + # task.execute + # task.running? #=> true + # + # @example Instance and execute in one line + # task = Concurrent::TimerTask.new(execution_interval: 10){ print "Hello World\n" }.execute + # task.running? #=> true + def execute + synchronize do + if @running.false? + @running.make_true + schedule_next_task(@run_now ? 0 : @execution_interval) + end + end + self + end + + # Create and execute a new `TimerTask`. + # + # @!macro timer_task_initialize + # + # @example + # task = Concurrent::TimerTask.execute(execution_interval: 10){ print "Hello World\n" } + # task.running? #=> true + def self.execute(opts = {}, &task) + TimerTask.new(opts, &task).execute + end + + # @!attribute [rw] execution_interval + # @return [Fixnum] Number of seconds after the task completes before the + # task is performed again. + def execution_interval + synchronize { @execution_interval } + end + + # @!attribute [rw] execution_interval + # @return [Fixnum] Number of seconds after the task completes before the + # task is performed again. + def execution_interval=(value) + if (value = value.to_f) <= 0.0 + raise ArgumentError.new('must be greater than zero') + else + synchronize { @execution_interval = value } + end + end + + # @!attribute [r] interval_type + # @return [Symbol] method to calculate the interval between executions + attr_reader :interval_type + + # @!attribute [rw] timeout_interval + # @return [Fixnum] Number of seconds the task can run before it is + # considered to have failed. + def 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) + warn 'TimerTask timeouts are now ignored as these were not able to be implemented correctly' + end + + private :post, :<< + + private + + def ns_initialize(opts, &task) + set_deref_options(opts) + + self.execution_interval = opts[:execution] || opts[:execution_interval] || EXECUTION_INTERVAL + if opts[:interval_type] && ![FIXED_DELAY, FIXED_RATE].include?(opts[:interval_type]) + raise ArgumentError.new('interval_type must be either :fixed_delay or :fixed_rate') + end + 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] + @interval_type = opts[:interval_type] || DEFAULT_INTERVAL_TYPE + @task = Concurrent::SafeTaskExecutor.new(task) + @executor = opts[:executor] || Concurrent.global_io_executor + @running = Concurrent::AtomicBoolean.new(false) + @value = nil + + self.observers = Collection::CopyOnNotifyObserverSet.new + end + + # @!visibility private + def ns_shutdown_execution + @running.make_false + super + end + + # @!visibility private + def ns_kill_execution + @running.make_false + super + end + + # @!visibility private + def schedule_next_task(interval = execution_interval) + ScheduledTask.execute(interval, executor: @executor, args: [Concurrent::Event.new], &method(:execute_task)) + nil + end + + # @!visibility private + def execute_task(completion) + return nil unless @running.true? + start_time = Concurrent.monotonic_time + _success, value, reason = @task.execute(self) + if completion.try? + self.value = value + schedule_next_task(calculate_next_interval(start_time)) + time = Time.now + observers.notify_observers do + [time, self.value, reason] + end + end + nil + end + + # @!visibility private + def calculate_next_interval(start_time) + if @interval_type == FIXED_RATE + run_time = Concurrent.monotonic_time - start_time + [execution_interval - run_time, 0].max + else # FIXED_DELAY + execution_interval + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/tuple.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/tuple.rb new file mode 100644 index 0000000000000..56212cfd15cc6 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/tuple.rb @@ -0,0 +1,82 @@ +require 'concurrent/atomic/atomic_reference' + +module Concurrent + + # A fixed size array with volatile (synchronized, thread safe) getters/setters. + # Mixes in Ruby's `Enumerable` module for enhanced search, sort, and traversal. + # + # @example + # tuple = Concurrent::Tuple.new(16) + # + # tuple.set(0, :foo) #=> :foo | volatile write + # tuple.get(0) #=> :foo | volatile read + # tuple.compare_and_set(0, :foo, :bar) #=> true | strong CAS + # tuple.cas(0, :foo, :baz) #=> false | strong CAS + # tuple.get(0) #=> :bar | volatile read + # + # @see https://en.wikipedia.org/wiki/Tuple Tuple entry at Wikipedia + # @see http://www.erlang.org/doc/reference_manual/data_types.html#id70396 Erlang Tuple + # @see http://ruby-doc.org/core-2.2.2/Enumerable.html Enumerable + class Tuple + include Enumerable + + # The (fixed) size of the tuple. + attr_reader :size + + # Create a new tuple of the given size. + # + # @param [Integer] size the number of elements in the tuple + def initialize(size) + @size = size + @tuple = tuple = ::Array.new(size) + i = 0 + while i < size + tuple[i] = Concurrent::AtomicReference.new + i += 1 + end + end + + # Get the value of the element at the given index. + # + # @param [Integer] i the index from which to retrieve the value + # @return [Object] the value at the given index or nil if the index is out of bounds + def get(i) + return nil if i >= @size || i < 0 + @tuple[i].get + end + alias_method :volatile_get, :get + + # Set the element at the given index to the given value + # + # @param [Integer] i the index for the element to set + # @param [Object] value the value to set at the given index + # + # @return [Object] the new value of the element at the given index or nil if the index is out of bounds + def set(i, value) + return nil if i >= @size || i < 0 + @tuple[i].set(value) + end + alias_method :volatile_set, :set + + # Set the value at the given index to the new value if and only if the current + # value matches the given old value. + # + # @param [Integer] i the index for the element to set + # @param [Object] old_value the value to compare against the current value + # @param [Object] new_value the value to set at the given index + # + # @return [Boolean] true if the value at the given element was set else false + def compare_and_set(i, old_value, new_value) + return false if i >= @size || i < 0 + @tuple[i].compare_and_set(old_value, new_value) + end + alias_method :cas, :compare_and_set + + # Calls the given block once for each element in self, passing that element as a parameter. + # + # @yieldparam [Object] ref the `Concurrent::AtomicReference` object at the current index + def each + @tuple.each {|ref| yield ref.get} + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/tvar.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/tvar.rb new file mode 100644 index 0000000000000..5d02ef090fd0c --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/tvar.rb @@ -0,0 +1,222 @@ +require 'set' +require 'concurrent/synchronization/object' + +module Concurrent + + # A `TVar` is a transactional variable - a single-element container that + # is used as part of a transaction - see `Concurrent::atomically`. + # + # @!macro thread_safe_variable_comparison + # + # {include:file:docs-source/tvar.md} + class TVar < Synchronization::Object + safe_initialization! + + # Create a new `TVar` with an initial value. + def initialize(value) + @value = value + @lock = Mutex.new + end + + # Get the value of a `TVar`. + def value + Concurrent::atomically do + Transaction::current.read(self) + end + end + + # Set the value of a `TVar`. + def value=(value) + Concurrent::atomically do + Transaction::current.write(self, value) + end + end + + # @!visibility private + def unsafe_value # :nodoc: + @value + end + + # @!visibility private + def unsafe_value=(value) # :nodoc: + @value = value + end + + # @!visibility private + def unsafe_lock # :nodoc: + @lock + end + + end + + # Run a block that reads and writes `TVar`s as a single atomic transaction. + # With respect to the value of `TVar` objects, the transaction is atomic, in + # that it either happens or it does not, consistent, in that the `TVar` + # objects involved will never enter an illegal state, and isolated, in that + # transactions never interfere with each other. You may recognise these + # properties from database transactions. + # + # There are some very important and unusual semantics that you must be aware of: + # + # * Most importantly, the block that you pass to atomically may be executed + # more than once. In most cases your code should be free of + # side-effects, except for via TVar. + # + # * If an exception escapes an atomically block it will abort the transaction. + # + # * It is undefined behaviour to use callcc or Fiber with atomically. + # + # * If you create a new thread within an atomically, it will not be part of + # the transaction. Creating a thread counts as a side-effect. + # + # Transactions within transactions are flattened to a single transaction. + # + # @example + # a = new TVar(100_000) + # b = new TVar(100) + # + # Concurrent::atomically do + # a.value -= 10 + # b.value += 10 + # end + def atomically + raise ArgumentError.new('no block given') unless block_given? + + # Get the current transaction + + transaction = Transaction::current + + # Are we not already in a transaction (not nested)? + + if transaction.nil? + # New transaction + + begin + # Retry loop + + loop do + + # Create a new transaction + + transaction = Transaction.new + Transaction::current = transaction + + # Run the block, aborting on exceptions + + begin + result = yield + rescue Transaction::AbortError => e + transaction.abort + result = Transaction::ABORTED + rescue Transaction::LeaveError => e + transaction.abort + break result + rescue => e + transaction.abort + raise e + end + # If we can commit, break out of the loop + + if result != Transaction::ABORTED + if transaction.commit + break result + end + end + end + ensure + # Clear the current transaction + + Transaction::current = nil + end + else + # Nested transaction - flatten it and just run the block + + yield + end + end + + # Abort a currently running transaction - see `Concurrent::atomically`. + def abort_transaction + raise Transaction::AbortError.new + end + + # Leave a transaction without committing or aborting - see `Concurrent::atomically`. + def leave_transaction + raise Transaction::LeaveError.new + end + + module_function :atomically, :abort_transaction, :leave_transaction + + private + + # @!visibility private + class Transaction + + ABORTED = ::Object.new + + OpenEntry = Struct.new(:value, :modified) + + AbortError = Class.new(StandardError) + LeaveError = Class.new(StandardError) + + def initialize + @open_tvars = {} + end + + def read(tvar) + entry = open(tvar) + entry.value + end + + def write(tvar, value) + entry = open(tvar) + entry.modified = true + entry.value = value + end + + def open(tvar) + entry = @open_tvars[tvar] + + unless entry + unless tvar.unsafe_lock.try_lock + Concurrent::abort_transaction + end + + entry = OpenEntry.new(tvar.unsafe_value, false) + @open_tvars[tvar] = entry + end + + entry + end + + def abort + unlock + end + + def commit + @open_tvars.each do |tvar, entry| + if entry.modified + tvar.unsafe_value = entry.value + end + end + + unlock + end + + def unlock + @open_tvars.each_key do |tvar| + tvar.unsafe_lock.unlock + end + end + + def self.current + Thread.current[:current_tvar_transaction] + end + + def self.current=(transaction) + Thread.current[:current_tvar_transaction] = transaction + end + + end + +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/engine.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/engine.rb new file mode 100644 index 0000000000000..0c574b2abb893 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/engine.rb @@ -0,0 +1,45 @@ +module Concurrent + # @!visibility private + module Utility + + # @!visibility private + module EngineDetector + def on_cruby? + RUBY_ENGINE == 'ruby' + end + + def on_jruby? + RUBY_ENGINE == 'jruby' + end + + def on_truffleruby? + RUBY_ENGINE == 'truffleruby' + end + + def on_windows? + !(RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/).nil? + end + + def on_osx? + !(RbConfig::CONFIG['host_os'] =~ /darwin|mac os/).nil? + end + + def on_linux? + !(RbConfig::CONFIG['host_os'] =~ /linux/).nil? + end + + def ruby_version(version = RUBY_VERSION, comparison, major, minor, patch) + result = (version.split('.').map(&:to_i) <=> [major, minor, patch]) + comparisons = { :== => [0], + :>= => [1, 0], + :<= => [-1, 0], + :> => [1], + :< => [-1] } + comparisons.fetch(comparison).include? result + end + end + end + + # @!visibility private + extend Utility::EngineDetector +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/monotonic_time.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/monotonic_time.rb new file mode 100644 index 0000000000000..1c987d8a411fc --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/monotonic_time.rb @@ -0,0 +1,19 @@ +module Concurrent + + # @!macro monotonic_get_time + # + # Returns the current time as 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 + def monotonic_time(unit = :float_second) + Process.clock_gettime(Process::CLOCK_MONOTONIC, unit) + end + module_function :monotonic_time +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb new file mode 100644 index 0000000000000..bf7bab354e832 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb @@ -0,0 +1,77 @@ +require 'concurrent/utility/engine' +# Synchronization::AbstractObject must be defined before loading the extension +require 'concurrent/synchronization/abstract_object' + +module Concurrent + # @!visibility private + module Utility + # @!visibility private + module NativeExtensionLoader + + def allow_c_extensions? + Concurrent.on_cruby? + end + + def c_extensions_loaded? + defined?(@c_extensions_loaded) && @c_extensions_loaded + end + + def load_native_extensions + if Concurrent.on_cruby? && !c_extensions_loaded? + ['concurrent/concurrent_ruby_ext', + "concurrent/#{RUBY_VERSION[0..2]}/concurrent_ruby_ext" + ].each { |p| try_load_c_extension p } + end + + if Concurrent.on_jruby? && !java_extensions_loaded? + begin + require 'concurrent/concurrent_ruby.jar' + set_java_extensions_loaded + rescue LoadError => e + raise e, "Java extensions are required for JRuby.\n" + e.message, e.backtrace + end + end + end + + private + + def load_error_path(error) + if error.respond_to? :path + error.path + else + error.message.split(' -- ').last + end + end + + def set_c_extensions_loaded + @c_extensions_loaded = true + end + + def java_extensions_loaded? + defined?(@java_extensions_loaded) && @java_extensions_loaded + end + + def set_java_extensions_loaded + @java_extensions_loaded = true + end + + def try_load_c_extension(path) + require path + set_c_extensions_loaded + rescue LoadError => e + if load_error_path(e) == path + # move on with pure-Ruby implementations + # TODO (pitr-ch 12-Jul-2018): warning on verbose? + else + raise e + end + end + + end + end + + # @!visibility private + extend Utility::NativeExtensionLoader +end + +Concurrent.load_native_extensions diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/native_integer.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/native_integer.rb new file mode 100644 index 0000000000000..de1cdc306a1bd --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/native_integer.rb @@ -0,0 +1,54 @@ +module Concurrent + # @!visibility private + module Utility + # @private + module NativeInteger + # http://stackoverflow.com/questions/535721/ruby-max-integer + MIN_VALUE = -(2**(0.size * 8 - 2)) + MAX_VALUE = (2**(0.size * 8 - 2) - 1) + + def ensure_upper_bound(value) + if value > MAX_VALUE + raise RangeError.new("#{value} is greater than the maximum value of #{MAX_VALUE}") + end + value + end + + def ensure_lower_bound(value) + if value < MIN_VALUE + raise RangeError.new("#{value} is less than the maximum value of #{MIN_VALUE}") + end + value + end + + def ensure_integer(value) + unless value.is_a?(Integer) + raise ArgumentError.new("#{value} is not an Integer") + end + value + end + + def ensure_integer_and_bounds(value) + ensure_integer value + ensure_upper_bound value + ensure_lower_bound value + end + + def ensure_positive(value) + if value < 0 + raise ArgumentError.new("#{value} cannot be negative") + end + value + end + + def ensure_positive_and_no_zero(value) + if value < 1 + raise ArgumentError.new("#{value} cannot be negative or zero") + end + value + end + + extend self + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/processor_counter.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/processor_counter.rb new file mode 100644 index 0000000000000..2489cbd76b1de --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/processor_counter.rb @@ -0,0 +1,220 @@ +require 'etc' +require 'rbconfig' +require 'concurrent/delay' + +module Concurrent + # @!visibility private + module Utility + + # @!visibility private + class ProcessorCounter + 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 + @processor_count.value + end + + def physical_processor_count + @physical_processor_count.value + end + + def available_processor_count + cpu_count = processor_count.to_f + quota = cpu_quota + + return cpu_count if quota.nil? + + # cgroup cpus quotas have no limits, so they can be set to higher than the + # real count of cores. + if quota > cpu_count + cpu_count + else + quota + end + end + + def cpu_quota + @cpu_quota.value + end + + def cpu_shares + @cpu_shares.value + end + + private + + def compute_processor_count + if Concurrent.on_jruby? + java.lang.Runtime.getRuntime.availableProcessors + else + Etc.nprocessors + end + end + + def compute_physical_processor_count + ppc = case RbConfig::CONFIG["target_os"] + when /darwin\d\d/ + IO.popen("/usr/sbin/sysctl -n hw.physicalcpu", &:read).to_i + when /linux/ + cores = {} # unique physical ID / core ID combinations + phy = 0 + IO.read("/proc/cpuinfo").scan(/^physical id.*|^core id.*/) do |ln| + if ln.start_with?("physical") + phy = ln[/\d+/] + elsif ln.start_with?("core") + cid = phy + ":" + ln[/\d+/] + cores[cid] = true if not cores[cid] + end + end + 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 -Property NumberOfCores | 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 + # fall back to logical count if physical info is invalid + ppc > 0 ? ppc : processor_count + rescue + 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") + # cgroups v2: https://docs.kernel.org/admin-guide/cgroup-v2.html#cpu-interface-files + cpu_max = File.read("/sys/fs/cgroup/cpu.max") + return nil if cpu_max.start_with?("max ") # no limit + max, period = cpu_max.split.map(&:to_f) + max / period + 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 + # 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 + 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 + + # create the default ProcessorCounter on load + @processor_counter = Utility::ProcessorCounter.new + singleton_class.send :attr_reader, :processor_counter + + # Number of processors seen by the OS and used for process scheduling. For + # performance reasons the calculated value will be memoized on the first + # call. + # + # When running under JRuby the Java runtime call + # `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." We still memoize this value once under + # JRuby. + # + # Otherwise Ruby's Etc.nprocessors will be used. + # + # @return [Integer] number of processors seen by the OS or Java runtime + # + # @see http://docs.oracle.com/javase/6/docs/api/java/lang/Runtime.html#availableProcessors() + def self.processor_count + processor_counter.processor_count + end + + # Number of physical processor cores on the current system. For performance + # reasons the calculated value will be memoized on the first call. + # + # On Windows the Win32 API will be queried for the `NumberOfCores from + # Win32_Processor`. This will return the total number "of cores for the + # current instance of the processor." On Unix-like operating systems either + # the `hwprefs` or `sysctl` utility will be called in a subshell and the + # returned value will be used. In the rare case where none of these methods + # work or an exception is raised the function will simply return 1. + # + # @return [Integer] number physical processor cores on the current system + # + # @see https://github.com/grosser/parallel/blob/4fc8b89d08c7091fe0419ca8fba1ec3ce5a8d185/lib/parallel.rb + # + # @see http://msdn.microsoft.com/en-us/library/aa394373(v=vs.85).aspx + # @see http://www.unix.com/man-page/osx/1/HWPREFS/ + # @see http://linux.die.net/man/8/sysctl + def self.physical_processor_count + processor_counter.physical_processor_count + end + + # Number of processors cores available for process scheduling. + # 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 [Float] number of available processors + def self.available_processor_count + processor_counter.available_processor_count + end + + # The maximum number of processors cores available for process scheduling. + # Returns `nil` if there is no enforced limit, or a `Float` if the + # process is inside a cgroup with a dedicated CPU quota (typically Docker). + # + # Note that nothing prevents setting a CPU quota higher than the actual number of + # cores on the system. + # + # For performance reasons the calculated value will be memoized on the first + # call. + # + # @return [nil, Float] Maximum number of available processors as set by a cgroup CPU quota, or nil if none set + 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/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/version.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/version.rb new file mode 100644 index 0000000000000..1b0c4c22f4acb --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/version.rb @@ -0,0 +1,3 @@ +module Concurrent + VERSION = '1.3.4' +end