Merge pull request #5861 from Homebrew/dependabot/bundler/Library/Homebrew/concurrent-ruby-1.1.5
Bump concurrent-ruby from 1.1.4 to 1.1.5 in /Library/Homebrew
This commit is contained in:
commit
0f07fe5c5c
1
.gitignore
vendored
1
.gitignore
vendored
@ -88,6 +88,7 @@
|
|||||||
**/vendor/bundle/ruby/*/gems/concurrent-ruby-*/lib/synchronization/
|
**/vendor/bundle/ruby/*/gems/concurrent-ruby-*/lib/synchronization/
|
||||||
**/vendor/bundle/ruby/*/gems/concurrent-ruby-*/lib/thread_safe/
|
**/vendor/bundle/ruby/*/gems/concurrent-ruby-*/lib/thread_safe/
|
||||||
**/vendor/bundle/ruby/*/gems/concurrent-ruby-*/lib/utility/
|
**/vendor/bundle/ruby/*/gems/concurrent-ruby-*/lib/utility/
|
||||||
|
**/vendor/bundle/ruby/*/gems/concurrent-ruby-*/lib/*/*.jar
|
||||||
**/vendor/bundle/ruby/*/gems/i18n-*/lib/i18n/tests*
|
**/vendor/bundle/ruby/*/gems/i18n-*/lib/i18n/tests*
|
||||||
**/vendor/bundle/ruby/*/gems/thread_safe-*/lib/thread_safe/util
|
**/vendor/bundle/ruby/*/gems/thread_safe-*/lib/thread_safe/util
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,7 @@ GEM
|
|||||||
tzinfo (~> 1.1)
|
tzinfo (~> 1.1)
|
||||||
ast (2.4.0)
|
ast (2.4.0)
|
||||||
backports (3.12.0)
|
backports (3.12.0)
|
||||||
concurrent-ruby (1.1.4)
|
concurrent-ruby (1.1.5)
|
||||||
connection_pool (2.2.2)
|
connection_pool (2.2.2)
|
||||||
coveralls (0.8.22)
|
coveralls (0.8.22)
|
||||||
json (>= 1.8, < 3)
|
json (>= 1.8, < 3)
|
||||||
|
|||||||
@ -22,12 +22,12 @@ module Homebrew
|
|||||||
|
|
||||||
ohai "cd #{HOMEBREW_LIBRARY_PATH}"
|
ohai "cd #{HOMEBREW_LIBRARY_PATH}"
|
||||||
HOMEBREW_LIBRARY_PATH.cd do
|
HOMEBREW_LIBRARY_PATH.cd do
|
||||||
ohai "bundle pristine"
|
|
||||||
safe_system "bundle", "pristine"
|
|
||||||
|
|
||||||
ohai "bundle install --standalone"
|
ohai "bundle install --standalone"
|
||||||
safe_system "bundle", "install", "--standalone"
|
safe_system "bundle", "install", "--standalone"
|
||||||
|
|
||||||
|
ohai "bundle pristine"
|
||||||
|
safe_system "bundle", "pristine"
|
||||||
|
|
||||||
ohai "git add vendor/bundle"
|
ohai "git add vendor/bundle"
|
||||||
system "git", "add", "vendor/bundle"
|
system "git", "add", "vendor/bundle"
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@ require 'rbconfig'
|
|||||||
ruby_engine = defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'
|
ruby_engine = defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'
|
||||||
ruby_version = RbConfig::CONFIG["ruby_version"]
|
ruby_version = RbConfig::CONFIG["ruby_version"]
|
||||||
path = File.expand_path('..', __FILE__)
|
path = File.expand_path('..', __FILE__)
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/concurrent-ruby-1.1.4/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/concurrent-ruby-1.1.5/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/i18n-1.6.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/i18n-1.6.0/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/minitest-5.11.3/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/minitest-5.11.3/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/thread_safe-0.3.6/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/thread_safe-0.3.6/lib"
|
||||||
|
|||||||
Binary file not shown.
@ -1,4 +0,0 @@
|
|||||||
module Concurrent
|
|
||||||
VERSION = '1.1.4'
|
|
||||||
EDGE_VERSION = '0.4.1'
|
|
||||||
end
|
|
||||||
@ -21,8 +21,9 @@ module Concurrent
|
|||||||
# @!macro internal_implementation_note
|
# @!macro internal_implementation_note
|
||||||
ArrayImplementation = case
|
ArrayImplementation = case
|
||||||
when Concurrent.on_cruby?
|
when Concurrent.on_cruby?
|
||||||
# Because MRI never runs code in parallel, the existing
|
# Array is thread-safe in practice because CRuby runs
|
||||||
# non-thread-safe structures should usually work fine.
|
# threads one at a time and does not do context
|
||||||
|
# switching during the execution of C functions.
|
||||||
::Array
|
::Array
|
||||||
|
|
||||||
when Concurrent.on_jruby?
|
when Concurrent.on_jruby?
|
||||||
@ -63,4 +64,3 @@ module Concurrent
|
|||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -333,6 +333,13 @@ module Concurrent
|
|||||||
ivar
|
ivar
|
||||||
end
|
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.
|
# Perform all enqueued tasks.
|
||||||
#
|
#
|
||||||
# This method must be called from within the executor. It must not be
|
# This method must be called from within the executor. It must not be
|
||||||
@ -383,6 +390,13 @@ module Concurrent
|
|||||||
ivar.wait
|
ivar.wait
|
||||||
ivar
|
ivar
|
||||||
end
|
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
|
end
|
||||||
private_constant :AwaitDelegator
|
private_constant :AwaitDelegator
|
||||||
|
|
||||||
@ -79,10 +79,10 @@ module Concurrent
|
|||||||
# @!method value=(value)
|
# @!method value=(value)
|
||||||
# @!macro atomic_fixnum_method_value_set
|
# @!macro atomic_fixnum_method_value_set
|
||||||
#
|
#
|
||||||
# @!method increment(delta)
|
# @!method increment(delta = 1)
|
||||||
# @!macro atomic_fixnum_method_increment
|
# @!macro atomic_fixnum_method_increment
|
||||||
#
|
#
|
||||||
# @!method decrement(delta)
|
# @!method decrement(delta = 1)
|
||||||
# @!macro atomic_fixnum_method_decrement
|
# @!macro atomic_fixnum_method_decrement
|
||||||
#
|
#
|
||||||
# @!method compare_and_set(expect, update)
|
# @!method compare_and_set(expect, update)
|
||||||
@ -53,7 +53,7 @@ module Concurrent
|
|||||||
|
|
||||||
# @param [Node] head
|
# @param [Node] head
|
||||||
# @return [true, false]
|
# @return [true, false]
|
||||||
def empty?(head = self.head)
|
def empty?(head = head())
|
||||||
head.equal? EMPTY
|
head.equal? EMPTY
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -48,11 +48,9 @@ module Concurrent
|
|||||||
def post(delay, *args, &task)
|
def post(delay, *args, &task)
|
||||||
raise ArgumentError.new('no block given') unless block_given?
|
raise ArgumentError.new('no block given') unless block_given?
|
||||||
return false unless running?
|
return false unless running?
|
||||||
opts = {
|
opts = { executor: @task_executor,
|
||||||
executor: @task_executor,
|
args: args,
|
||||||
args: args,
|
timer_set: self }
|
||||||
timer_set: self
|
|
||||||
}
|
|
||||||
task = ScheduledTask.execute(delay, opts, &task) # may raise exception
|
task = ScheduledTask.execute(delay, opts, &task) # may raise exception
|
||||||
task.unscheduled? ? false : task
|
task.unscheduled? ? false : task
|
||||||
end
|
end
|
||||||
@ -74,11 +72,11 @@ module Concurrent
|
|||||||
# @param [Hash] opts the options to create the object with.
|
# @param [Hash] opts the options to create the object with.
|
||||||
# @!visibility private
|
# @!visibility private
|
||||||
def ns_initialize(opts)
|
def ns_initialize(opts)
|
||||||
@queue = Collection::NonConcurrentPriorityQueue.new(order: :min)
|
@queue = Collection::NonConcurrentPriorityQueue.new(order: :min)
|
||||||
@task_executor = Options.executor_from_options(opts) || Concurrent.global_io_executor
|
@task_executor = Options.executor_from_options(opts) || Concurrent.global_io_executor
|
||||||
@timer_executor = SingleThreadExecutor.new
|
@timer_executor = SingleThreadExecutor.new
|
||||||
@condition = Event.new
|
@condition = Event.new
|
||||||
@ruby_pid = $$ # detects if Ruby has forked
|
@ruby_pid = $$ # detects if Ruby has forked
|
||||||
self.auto_terminate = opts.fetch(:auto_terminate, true)
|
self.auto_terminate = opts.fetch(:auto_terminate, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -90,7 +88,7 @@ module Concurrent
|
|||||||
#
|
#
|
||||||
# @!visibility private
|
# @!visibility private
|
||||||
def post_task(task)
|
def post_task(task)
|
||||||
synchronize{ ns_post_task(task) }
|
synchronize { ns_post_task(task) }
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
# @!visibility private
|
||||||
@ -98,7 +96,7 @@ module Concurrent
|
|||||||
return false unless ns_running?
|
return false unless ns_running?
|
||||||
ns_reset_if_forked
|
ns_reset_if_forked
|
||||||
if (task.initial_delay) <= 0.01
|
if (task.initial_delay) <= 0.01
|
||||||
task.executor.post{ task.process_task }
|
task.executor.post { task.process_task }
|
||||||
else
|
else
|
||||||
@queue.push(task)
|
@queue.push(task)
|
||||||
# only post the process method when the queue is empty
|
# only post the process method when the queue is empty
|
||||||
@ -116,7 +114,7 @@ module Concurrent
|
|||||||
#
|
#
|
||||||
# @!visibility private
|
# @!visibility private
|
||||||
def remove_task(task)
|
def remove_task(task)
|
||||||
synchronize{ @queue.delete(task) }
|
synchronize { @queue.delete(task) }
|
||||||
end
|
end
|
||||||
|
|
||||||
# `ExecutorService` callback called during shutdown.
|
# `ExecutorService` callback called during shutdown.
|
||||||
@ -148,7 +146,7 @@ module Concurrent
|
|||||||
task = synchronize { @condition.reset; @queue.peek }
|
task = synchronize { @condition.reset; @queue.peek }
|
||||||
break unless task
|
break unless task
|
||||||
|
|
||||||
now = Concurrent.monotonic_time
|
now = Concurrent.monotonic_time
|
||||||
diff = task.schedule_time - now
|
diff = task.schedule_time - now
|
||||||
|
|
||||||
if diff <= 0
|
if diff <= 0
|
||||||
@ -165,7 +163,7 @@ module Concurrent
|
|||||||
# queue now must have the same pop time, or a closer one, as
|
# queue now must have the same pop time, or a closer one, as
|
||||||
# when we peeked).
|
# when we peeked).
|
||||||
task = synchronize { @queue.pop }
|
task = synchronize { @queue.pop }
|
||||||
task.executor.post{ task.process_task }
|
task.executor.post { task.process_task }
|
||||||
else
|
else
|
||||||
@condition.wait([diff, 60].min)
|
@condition.wait([diff, 60].min)
|
||||||
end
|
end
|
||||||
@ -15,8 +15,9 @@ module Concurrent
|
|||||||
# @!macro internal_implementation_note
|
# @!macro internal_implementation_note
|
||||||
HashImplementation = case
|
HashImplementation = case
|
||||||
when Concurrent.on_cruby?
|
when Concurrent.on_cruby?
|
||||||
# Because MRI never runs code in parallel, the existing
|
# Hash is thread-safe in practice because CRuby runs
|
||||||
# non-thread-safe structures should usually work fine.
|
# threads one at a time and does not do context
|
||||||
|
# switching during the execution of C functions.
|
||||||
::Hash
|
::Hash
|
||||||
|
|
||||||
when Concurrent.on_jruby?
|
when Concurrent.on_jruby?
|
||||||
@ -56,4 +57,3 @@ module Concurrent
|
|||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -43,6 +43,7 @@ module Concurrent
|
|||||||
# new.
|
# new.
|
||||||
module FactoryMethods
|
module FactoryMethods
|
||||||
extend ReInclude
|
extend ReInclude
|
||||||
|
extend self
|
||||||
|
|
||||||
module Configuration
|
module Configuration
|
||||||
# @return [Executor, :io, :fast] the executor which is used when none is supplied
|
# @return [Executor, :io, :fast] the executor which is used when none is supplied
|
||||||
@ -92,16 +93,14 @@ module Concurrent
|
|||||||
future_on(default_executor, *args, &task)
|
future_on(default_executor, *args, &task)
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!macro promises.future-on1
|
# Constructs new Future which will be resolved after block is evaluated on default executor.
|
||||||
# Constructs new Future which will be resolved after block is evaluated on default executor.
|
|
||||||
# Evaluation begins immediately.
|
# Evaluation begins immediately.
|
||||||
#
|
#
|
||||||
# @!macro promises.future-on2
|
# @!macro promises.param.default_executor
|
||||||
# @!macro promises.param.default_executor
|
# @!macro promises.param.args
|
||||||
# @!macro promises.param.args
|
# @yield [*args] to the task.
|
||||||
# @yield [*args] to the task.
|
# @!macro promise.param.task-future
|
||||||
# @!macro promise.param.task-future
|
# @return [Future]
|
||||||
# @return [Future]
|
|
||||||
def future_on(default_executor, *args, &task)
|
def future_on(default_executor, *args, &task)
|
||||||
ImmediateEventPromise.new(default_executor).future.then(*args, &task)
|
ImmediateEventPromise.new(default_executor).future.then(*args, &task)
|
||||||
end
|
end
|
||||||
@ -109,6 +108,9 @@ module Concurrent
|
|||||||
# Creates resolved future with will be either fulfilled with the given value or rejection with
|
# Creates resolved future with will be either fulfilled with the given value or rejection with
|
||||||
# the given reason.
|
# the given reason.
|
||||||
#
|
#
|
||||||
|
# @param [true, false] fulfilled
|
||||||
|
# @param [Object] value
|
||||||
|
# @param [Object] reason
|
||||||
# @!macro promises.param.default_executor
|
# @!macro promises.param.default_executor
|
||||||
# @return [Future]
|
# @return [Future]
|
||||||
def resolved_future(fulfilled, value, reason, default_executor = self.default_executor)
|
def resolved_future(fulfilled, value, reason, default_executor = self.default_executor)
|
||||||
@ -118,6 +120,7 @@ module Concurrent
|
|||||||
# Creates resolved future with will be fulfilled with the given value.
|
# Creates resolved future with will be fulfilled with the given value.
|
||||||
#
|
#
|
||||||
# @!macro promises.param.default_executor
|
# @!macro promises.param.default_executor
|
||||||
|
# @param [Object] value
|
||||||
# @return [Future]
|
# @return [Future]
|
||||||
def fulfilled_future(value, default_executor = self.default_executor)
|
def fulfilled_future(value, default_executor = self.default_executor)
|
||||||
resolved_future true, value, nil, default_executor
|
resolved_future true, value, nil, default_executor
|
||||||
@ -126,6 +129,7 @@ module Concurrent
|
|||||||
# Creates resolved future with will be rejected with the given reason.
|
# Creates resolved future with will be rejected with the given reason.
|
||||||
#
|
#
|
||||||
# @!macro promises.param.default_executor
|
# @!macro promises.param.default_executor
|
||||||
|
# @param [Object] reason
|
||||||
# @return [Future]
|
# @return [Future]
|
||||||
def rejected_future(reason, default_executor = self.default_executor)
|
def rejected_future(reason, default_executor = self.default_executor)
|
||||||
resolved_future false, nil, reason, default_executor
|
resolved_future false, nil, reason, default_executor
|
||||||
@ -146,23 +150,23 @@ module Concurrent
|
|||||||
# @!macro promises.param.default_executor
|
# @!macro promises.param.default_executor
|
||||||
# @return [Event, Future]
|
# @return [Event, Future]
|
||||||
#
|
#
|
||||||
# @overload create(nil, default_executor = self.default_executor)
|
# @overload make_future(nil, default_executor = self.default_executor)
|
||||||
# @param [nil] nil
|
# @param [nil] nil
|
||||||
# @return [Event] resolved event.
|
# @return [Event] resolved event.
|
||||||
#
|
#
|
||||||
# @overload create(a_future, default_executor = self.default_executor)
|
# @overload make_future(a_future, default_executor = self.default_executor)
|
||||||
# @param [Future] a_future
|
# @param [Future] a_future
|
||||||
# @return [Future] a future which will be resolved when a_future is.
|
# @return [Future] a future which will be resolved when a_future is.
|
||||||
#
|
#
|
||||||
# @overload create(an_event, default_executor = self.default_executor)
|
# @overload make_future(an_event, default_executor = self.default_executor)
|
||||||
# @param [Event] an_event
|
# @param [Event] an_event
|
||||||
# @return [Event] an event which will be resolved when an_event is.
|
# @return [Event] an event which will be resolved when an_event is.
|
||||||
#
|
#
|
||||||
# @overload create(exception, default_executor = self.default_executor)
|
# @overload make_future(exception, default_executor = self.default_executor)
|
||||||
# @param [Exception] exception
|
# @param [Exception] exception
|
||||||
# @return [Future] a rejected future with the exception as its reason.
|
# @return [Future] a rejected future with the exception as its reason.
|
||||||
#
|
#
|
||||||
# @overload create(value, default_executor = self.default_executor)
|
# @overload make_future(value, default_executor = self.default_executor)
|
||||||
# @param [Object] value when none of the above overloads fits
|
# @param [Object] value when none of the above overloads fits
|
||||||
# @return [Future] a fulfilled future with the value.
|
# @return [Future] a fulfilled future with the value.
|
||||||
def make_future(argument = nil, default_executor = self.default_executor)
|
def make_future(argument = nil, default_executor = self.default_executor)
|
||||||
@ -180,34 +184,53 @@ module Concurrent
|
|||||||
end
|
end
|
||||||
|
|
||||||
# @!macro promises.shortcut.on
|
# @!macro promises.shortcut.on
|
||||||
# @return [Future]
|
# @return [Future, Event]
|
||||||
def delay(*args, &task)
|
def delay(*args, &task)
|
||||||
delay_on default_executor, *args, &task
|
delay_on default_executor, *args, &task
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!macro promises.future-on1
|
# Creates new event or future which is resolved only after it is touched,
|
||||||
# The task will be evaluated only after the future is touched, see {AbstractEventFuture#touch}
|
# see {Concurrent::AbstractEventFuture#touch}.
|
||||||
#
|
#
|
||||||
# @!macro promises.future-on2
|
# @!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)
|
def delay_on(default_executor, *args, &task)
|
||||||
DelayPromise.new(default_executor).event.chain(*args, &task)
|
event = DelayPromise.new(default_executor).event
|
||||||
|
task ? event.chain(*args, &task) : event
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!macro promises.shortcut.on
|
# @!macro promises.shortcut.on
|
||||||
# @return [Future]
|
# @return [Future, Event]
|
||||||
def schedule(intended_time, *args, &task)
|
def schedule(intended_time, *args, &task)
|
||||||
schedule_on default_executor, intended_time, *args, &task
|
schedule_on default_executor, intended_time, *args, &task
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!macro promises.future-on1
|
# Creates new event or future which is resolved in intended_time.
|
||||||
# The task is planned for execution in intended_time.
|
|
||||||
#
|
#
|
||||||
# @!macro promises.future-on2
|
# @!macro promises.param.default_executor
|
||||||
# @!macro promises.param.intended_time
|
# @!macro promises.param.intended_time
|
||||||
# @param [Numeric, Time] intended_time `Numeric` means to run in `intended_time` seconds.
|
# @param [Numeric, Time] intended_time `Numeric` means to run in `intended_time` seconds.
|
||||||
# `Time` means to run on `intended_time`.
|
# `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)
|
def schedule_on(default_executor, intended_time, *args, &task)
|
||||||
ScheduledPromise.new(default_executor, intended_time).event.chain(*args, &task)
|
event = ScheduledPromise.new(default_executor, intended_time).event
|
||||||
|
task ? event.chain(*args, &task) : event
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!macro promises.shortcut.on
|
# @!macro promises.shortcut.on
|
||||||
@ -259,7 +282,7 @@ module Concurrent
|
|||||||
# Creates new future which is resolved after first futures_and_or_events is resolved.
|
# Creates new future which is resolved after first futures_and_or_events is resolved.
|
||||||
# Its result equals result of the first resolved future.
|
# Its result equals result of the first resolved future.
|
||||||
# @!macro promises.any-touch
|
# @!macro promises.any-touch
|
||||||
# If resolved it does not propagate {AbstractEventFuture#touch}, leaving delayed
|
# If resolved it does not propagate {Concurrent::AbstractEventFuture#touch}, leaving delayed
|
||||||
# futures un-executed if they are not required any more.
|
# futures un-executed if they are not required any more.
|
||||||
# @!macro promises.event-conversion
|
# @!macro promises.event-conversion
|
||||||
#
|
#
|
||||||
@ -311,7 +334,7 @@ module Concurrent
|
|||||||
end
|
end
|
||||||
|
|
||||||
module InternalStates
|
module InternalStates
|
||||||
# @private
|
# @!visibility private
|
||||||
class State
|
class State
|
||||||
def resolved?
|
def resolved?
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
@ -322,9 +345,7 @@ module Concurrent
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private_constant :State
|
# @!visibility private
|
||||||
|
|
||||||
# @private
|
|
||||||
class Pending < State
|
class Pending < State
|
||||||
def resolved?
|
def resolved?
|
||||||
false
|
false
|
||||||
@ -335,9 +356,11 @@ module Concurrent
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private_constant :Pending
|
# @!visibility private
|
||||||
|
class Reserved < Pending
|
||||||
|
end
|
||||||
|
|
||||||
# @private
|
# @!visibility private
|
||||||
class ResolvedWithResult < State
|
class ResolvedWithResult < State
|
||||||
def resolved?
|
def resolved?
|
||||||
true
|
true
|
||||||
@ -368,9 +391,7 @@ module Concurrent
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private_constant :ResolvedWithResult
|
# @!visibility private
|
||||||
|
|
||||||
# @private
|
|
||||||
class Fulfilled < ResolvedWithResult
|
class Fulfilled < ResolvedWithResult
|
||||||
|
|
||||||
def initialize(value)
|
def initialize(value)
|
||||||
@ -398,18 +419,14 @@ module Concurrent
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private_constant :Fulfilled
|
# @!visibility private
|
||||||
|
|
||||||
# @private
|
|
||||||
class FulfilledArray < Fulfilled
|
class FulfilledArray < Fulfilled
|
||||||
def apply(args, block)
|
def apply(args, block)
|
||||||
block.call(*value, *args)
|
block.call(*value, *args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private_constant :FulfilledArray
|
# @!visibility private
|
||||||
|
|
||||||
# @private
|
|
||||||
class Rejected < ResolvedWithResult
|
class Rejected < ResolvedWithResult
|
||||||
def initialize(reason)
|
def initialize(reason)
|
||||||
@Reason = reason
|
@Reason = reason
|
||||||
@ -436,9 +453,7 @@ module Concurrent
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private_constant :Rejected
|
# @!visibility private
|
||||||
|
|
||||||
# @private
|
|
||||||
class PartiallyRejected < ResolvedWithResult
|
class PartiallyRejected < ResolvedWithResult
|
||||||
def initialize(value, reason)
|
def initialize(value, reason)
|
||||||
super()
|
super()
|
||||||
@ -467,24 +482,38 @@ module Concurrent
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private_constant :PartiallyRejected
|
# @!visibility private
|
||||||
|
PENDING = Pending.new
|
||||||
PENDING = Pending.new
|
# @!visibility private
|
||||||
|
RESERVED = Reserved.new
|
||||||
|
# @!visibility private
|
||||||
RESOLVED = Fulfilled.new(nil)
|
RESOLVED = Fulfilled.new(nil)
|
||||||
|
|
||||||
def RESOLVED.to_sym
|
def RESOLVED.to_sym
|
||||||
:resolved
|
:resolved
|
||||||
end
|
end
|
||||||
|
|
||||||
private_constant :PENDING, :RESOLVED
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private_constant :InternalStates
|
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.
|
# Common ancestor of {Event} and {Future} classes, many shared methods are defined here.
|
||||||
class AbstractEventFuture < Synchronization::Object
|
class AbstractEventFuture < Synchronization::Object
|
||||||
safe_initialization!
|
safe_initialization!
|
||||||
private(*attr_atomic(:internal_state) - [:internal_state])
|
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
|
include InternalStates
|
||||||
|
|
||||||
@ -501,17 +530,6 @@ module Concurrent
|
|||||||
|
|
||||||
private :initialize
|
private :initialize
|
||||||
|
|
||||||
# @!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.
|
|
||||||
|
|
||||||
# Returns its state.
|
# Returns its state.
|
||||||
# @return [Symbol]
|
# @return [Symbol]
|
||||||
#
|
#
|
||||||
@ -545,7 +563,7 @@ module Concurrent
|
|||||||
end
|
end
|
||||||
|
|
||||||
# @!macro promises.touches
|
# @!macro promises.touches
|
||||||
# Calls {AbstractEventFuture#touch}.
|
# Calls {Concurrent::AbstractEventFuture#touch}.
|
||||||
|
|
||||||
# @!macro promises.method.wait
|
# @!macro promises.method.wait
|
||||||
# Wait (block the Thread) until receiver is {#resolved?}.
|
# Wait (block the Thread) until receiver is {#resolved?}.
|
||||||
@ -553,7 +571,7 @@ module Concurrent
|
|||||||
#
|
#
|
||||||
# @!macro promises.warn.blocks
|
# @!macro promises.warn.blocks
|
||||||
# @!macro promises.param.timeout
|
# @!macro promises.param.timeout
|
||||||
# @return [Future, true, false] self implies timeout was not used, true implies timeout was used
|
# @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.
|
# and it was resolved, false implies it was not resolved within timeout.
|
||||||
def wait(timeout = nil)
|
def wait(timeout = nil)
|
||||||
result = wait_until_resolved(timeout)
|
result = wait_until_resolved(timeout)
|
||||||
@ -590,7 +608,7 @@ module Concurrent
|
|||||||
# @yield [fulfilled, value, reason, *args] to the task.
|
# @yield [fulfilled, value, reason, *args] to the task.
|
||||||
# @yieldparam [true, false] fulfilled
|
# @yieldparam [true, false] fulfilled
|
||||||
# @yieldparam [Object] value
|
# @yieldparam [Object] value
|
||||||
# @yieldparam [Exception] reason
|
# @yieldparam [Object] reason
|
||||||
def chain_on(executor, *args, &task)
|
def chain_on(executor, *args, &task)
|
||||||
ChainPromise.new_blocked_by1(self, @DefaultExecutor, executor, args, &task).future
|
ChainPromise.new_blocked_by1(self, @DefaultExecutor, executor, args, &task).future
|
||||||
end
|
end
|
||||||
@ -631,7 +649,7 @@ module Concurrent
|
|||||||
# @yield [fulfilled, value, reason, *args] to the callback.
|
# @yield [fulfilled, value, reason, *args] to the callback.
|
||||||
# @yieldparam [true, false] fulfilled
|
# @yieldparam [true, false] fulfilled
|
||||||
# @yieldparam [Object] value
|
# @yieldparam [Object] value
|
||||||
# @yieldparam [Exception] reason
|
# @yieldparam [Object] reason
|
||||||
def on_resolution!(*args, &callback)
|
def on_resolution!(*args, &callback)
|
||||||
add_callback :callback_on_resolution, args, callback
|
add_callback :callback_on_resolution, args, callback
|
||||||
end
|
end
|
||||||
@ -649,7 +667,7 @@ module Concurrent
|
|||||||
# @yield [fulfilled, value, reason, *args] to the callback.
|
# @yield [fulfilled, value, reason, *args] to the callback.
|
||||||
# @yieldparam [true, false] fulfilled
|
# @yieldparam [true, false] fulfilled
|
||||||
# @yieldparam [Object] value
|
# @yieldparam [Object] value
|
||||||
# @yieldparam [Exception] reason
|
# @yieldparam [Object] reason
|
||||||
def on_resolution_using(executor, *args, &callback)
|
def on_resolution_using(executor, *args, &callback)
|
||||||
add_callback :async_callback_on_resolution, executor, args, callback
|
add_callback :async_callback_on_resolution, executor, args, callback
|
||||||
end
|
end
|
||||||
@ -665,8 +683,8 @@ module Concurrent
|
|||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
# @!visibility private
|
||||||
def resolve_with(state, raise_on_reassign = true)
|
def resolve_with(state, raise_on_reassign = true, reserved = false)
|
||||||
if compare_and_set_internal_state(PENDING, state)
|
if compare_and_set_internal_state(reserved ? RESERVED : PENDING, state)
|
||||||
# go to synchronized block only if there were waiting threads
|
# go to synchronized block only if there were waiting threads
|
||||||
@Lock.synchronize { @Condition.broadcast } unless @Waiters.value == 0
|
@Lock.synchronize { @Condition.broadcast } unless @Waiters.value == 0
|
||||||
call_callbacks state
|
call_callbacks state
|
||||||
@ -719,6 +737,12 @@ module Concurrent
|
|||||||
add_callback(:callback_clear_delayed_node, node)
|
add_callback(:callback_clear_delayed_node, node)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# @!visibility private
|
||||||
|
def with_hidden_resolvable
|
||||||
|
# TODO (pitr-ch 10-Dec-2018): documentation, better name if in edge
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def add_callback(method, *args)
|
def add_callback(method, *args)
|
||||||
@ -907,9 +931,17 @@ module Concurrent
|
|||||||
# @!macro promises.warn.blocks
|
# @!macro promises.warn.blocks
|
||||||
# @!macro promises.warn.nil
|
# @!macro promises.warn.nil
|
||||||
# @!macro promises.param.timeout
|
# @!macro promises.param.timeout
|
||||||
# @return [Object, nil] the value of the Future when fulfilled, nil on timeout or rejection.
|
# @!macro promises.param.timeout_value
|
||||||
def value(timeout = nil)
|
# @param [Object] timeout_value a value returned by the method when it times out
|
||||||
internal_state.value if wait_until_resolved timeout
|
# @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
|
end
|
||||||
|
|
||||||
# Returns reason of future's rejection.
|
# Returns reason of future's rejection.
|
||||||
@ -918,9 +950,14 @@ module Concurrent
|
|||||||
# @!macro promises.warn.blocks
|
# @!macro promises.warn.blocks
|
||||||
# @!macro promises.warn.nil
|
# @!macro promises.warn.nil
|
||||||
# @!macro promises.param.timeout
|
# @!macro promises.param.timeout
|
||||||
# @return [Exception, nil] nil on timeout or fulfillment.
|
# @!macro promises.param.timeout_value
|
||||||
def reason(timeout = nil)
|
# @return [Object, timeout_value] the reason, or timeout_value on timeout, or nil on fulfillment.
|
||||||
internal_state.reason if wait_until_resolved timeout
|
def reason(timeout = nil, timeout_value = nil)
|
||||||
|
if wait_until_resolved timeout
|
||||||
|
internal_state.reason
|
||||||
|
else
|
||||||
|
timeout_value
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns triplet fulfilled?, value, reason.
|
# Returns triplet fulfilled?, value, reason.
|
||||||
@ -928,7 +965,7 @@ module Concurrent
|
|||||||
#
|
#
|
||||||
# @!macro promises.warn.blocks
|
# @!macro promises.warn.blocks
|
||||||
# @!macro promises.param.timeout
|
# @!macro promises.param.timeout
|
||||||
# @return [Array(Boolean, Object, Exception), nil] triplet of fulfilled?, value, reason, or nil
|
# @return [Array(Boolean, Object, Object), nil] triplet of fulfilled?, value, reason, or nil
|
||||||
# on timeout.
|
# on timeout.
|
||||||
def result(timeout = nil)
|
def result(timeout = nil)
|
||||||
internal_state.result if wait_until_resolved timeout
|
internal_state.result if wait_until_resolved timeout
|
||||||
@ -942,26 +979,40 @@ module Concurrent
|
|||||||
end
|
end
|
||||||
|
|
||||||
# @!macro promises.method.value
|
# @!macro promises.method.value
|
||||||
# @return [Object, nil] the value of the Future when fulfilled, nil on timeout.
|
# @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
|
# @raise [Exception] {#reason} on rejection
|
||||||
def value!(timeout = nil)
|
def value!(timeout = nil, timeout_value = nil)
|
||||||
internal_state.value if wait_until_resolved! timeout
|
if wait_until_resolved! timeout
|
||||||
|
internal_state.value
|
||||||
|
else
|
||||||
|
timeout_value
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Allows rejected Future to be risen with `raise` method.
|
# Allows rejected Future to be risen with `raise` method.
|
||||||
|
# If the reason is not an exception `Runtime.new(reason)` is returned.
|
||||||
|
#
|
||||||
# @example
|
# @example
|
||||||
# raise Promises.rejected_future(StandardError.new("boom"))
|
# raise Promises.rejected_future(StandardError.new("boom"))
|
||||||
# @raise [StandardError] when raising not rejected future
|
# raise Promises.rejected_future("or just boom")
|
||||||
|
# @raise [Concurrent::Error] when raising not rejected future
|
||||||
# @return [Exception]
|
# @return [Exception]
|
||||||
def exception(*args)
|
def exception(*args)
|
||||||
raise Concurrent::Error, 'it is not rejected' unless rejected?
|
raise Concurrent::Error, 'it is not rejected' unless rejected?
|
||||||
|
raise ArgumentError unless args.size <= 1
|
||||||
reason = Array(internal_state.reason).flatten.compact
|
reason = Array(internal_state.reason).flatten.compact
|
||||||
if reason.size > 1
|
if reason.size > 1
|
||||||
ex = Concurrent::MultipleErrors.new reason
|
ex = Concurrent::MultipleErrors.new reason
|
||||||
ex.set_backtrace(caller)
|
ex.set_backtrace(caller)
|
||||||
ex
|
ex
|
||||||
else
|
else
|
||||||
ex = reason[0].clone.exception(*args)
|
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.set_backtrace Array(ex.backtrace) + caller
|
||||||
ex
|
ex
|
||||||
end
|
end
|
||||||
@ -1133,14 +1184,20 @@ module Concurrent
|
|||||||
# will become reason of the returned future.
|
# will become reason of the returned future.
|
||||||
#
|
#
|
||||||
# @return [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
|
# @example
|
||||||
# body = lambda do |v|
|
# body = lambda do |v|
|
||||||
# v += 1
|
# v += 1
|
||||||
# v < 5 ? Promises.future(v, &body) : v
|
# v < 5 ? Promises.future(v, &body) : v
|
||||||
# end
|
# end
|
||||||
# Promises.future(0, &body).run.value! # => 5
|
# Promises.future(0, &body).run.value! # => 5
|
||||||
def run
|
def run(run_test = method(:run_test))
|
||||||
RunFuturePromise.new_blocked_by1(self, @DefaultExecutor).future
|
RunFuturePromise.new_blocked_by1(self, @DefaultExecutor, run_test).future
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!visibility private
|
# @!visibility private
|
||||||
@ -1163,13 +1220,34 @@ module Concurrent
|
|||||||
self
|
self
|
||||||
end
|
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
|
private
|
||||||
|
|
||||||
|
def run_test(v)
|
||||||
|
v if v.is_a?(Future)
|
||||||
|
end
|
||||||
|
|
||||||
def rejected_resolution(raise_on_reassign, state)
|
def rejected_resolution(raise_on_reassign, state)
|
||||||
if raise_on_reassign
|
if raise_on_reassign
|
||||||
raise Concurrent::MultipleAssignmentError.new(
|
if internal_state == RESERVED
|
||||||
"Future can be resolved only once. It's #{result}, trying to set #{state.result}.",
|
raise Concurrent::MultipleAssignmentError.new(
|
||||||
current_result: result, new_result: state.result)
|
"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
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
@ -1206,15 +1284,15 @@ module Concurrent
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Marker module of Future, Event resolved manually by user.
|
# Marker module of Future, Event resolved manually.
|
||||||
module Resolvable
|
module Resolvable
|
||||||
|
include InternalStates
|
||||||
end
|
end
|
||||||
|
|
||||||
# A Event which can be resolved by user.
|
# A Event which can be resolved by user.
|
||||||
class ResolvableEvent < Event
|
class ResolvableEvent < Event
|
||||||
include Resolvable
|
include Resolvable
|
||||||
|
|
||||||
|
|
||||||
# @!macro raise_on_reassign
|
# @!macro raise_on_reassign
|
||||||
# @raise [MultipleAssignmentError] when already resolved and raise_on_reassign is true.
|
# @raise [MultipleAssignmentError] when already resolved and raise_on_reassign is true.
|
||||||
|
|
||||||
@ -1227,8 +1305,13 @@ module Concurrent
|
|||||||
# Makes the event resolved, which triggers all dependent futures.
|
# Makes the event resolved, which triggers all dependent futures.
|
||||||
#
|
#
|
||||||
# @!macro promise.param.raise_on_reassign
|
# @!macro promise.param.raise_on_reassign
|
||||||
def resolve(raise_on_reassign = true)
|
# @!macro promise.param.reserved
|
||||||
resolve_with RESOLVED, raise_on_reassign
|
# @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
|
end
|
||||||
|
|
||||||
# Creates new event wrapping receiver, effectively hiding the resolve method.
|
# Creates new event wrapping receiver, effectively hiding the resolve method.
|
||||||
@ -1237,6 +1320,23 @@ module Concurrent
|
|||||||
def with_hidden_resolvable
|
def with_hidden_resolvable
|
||||||
@with_hidden_resolvable ||= EventWrapperPromise.new_blocked_by1(self, @DefaultExecutor).event
|
@with_hidden_resolvable ||= EventWrapperPromise.new_blocked_by1(self, @DefaultExecutor).event
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
# A Future which can be resolved by user.
|
# A Future which can be resolved by user.
|
||||||
@ -1246,29 +1346,38 @@ module Concurrent
|
|||||||
# Makes the future resolved with result of triplet `fulfilled?`, `value`, `reason`,
|
# Makes the future resolved with result of triplet `fulfilled?`, `value`, `reason`,
|
||||||
# which triggers all dependent futures.
|
# which triggers all dependent futures.
|
||||||
#
|
#
|
||||||
|
# @param [true, false] fulfilled
|
||||||
|
# @param [Object] value
|
||||||
|
# @param [Object] reason
|
||||||
# @!macro promise.param.raise_on_reassign
|
# @!macro promise.param.raise_on_reassign
|
||||||
def resolve(fulfilled = true, value = nil, reason = nil, raise_on_reassign = true)
|
# @!macro promise.param.reserved
|
||||||
resolve_with(fulfilled ? Fulfilled.new(value) : Rejected.new(reason), raise_on_reassign)
|
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
|
end
|
||||||
|
|
||||||
# Makes the future fulfilled with `value`,
|
# Makes the future fulfilled with `value`,
|
||||||
# which triggers all dependent futures.
|
# which triggers all dependent futures.
|
||||||
#
|
#
|
||||||
|
# @param [Object] value
|
||||||
# @!macro promise.param.raise_on_reassign
|
# @!macro promise.param.raise_on_reassign
|
||||||
def fulfill(value, raise_on_reassign = true)
|
# @!macro promise.param.reserved
|
||||||
promise.fulfill(value, raise_on_reassign)
|
def fulfill(value, raise_on_reassign = true, reserved = false)
|
||||||
|
resolve_with Fulfilled.new(value), raise_on_reassign, reserved
|
||||||
end
|
end
|
||||||
|
|
||||||
# Makes the future rejected with `reason`,
|
# Makes the future rejected with `reason`,
|
||||||
# which triggers all dependent futures.
|
# which triggers all dependent futures.
|
||||||
#
|
#
|
||||||
|
# @param [Object] reason
|
||||||
# @!macro promise.param.raise_on_reassign
|
# @!macro promise.param.raise_on_reassign
|
||||||
def reject(reason, raise_on_reassign = true)
|
# @!macro promise.param.reserved
|
||||||
promise.reject(reason, raise_on_reassign)
|
def reject(reason, raise_on_reassign = true, reserved = false)
|
||||||
|
resolve_with Rejected.new(reason), raise_on_reassign, reserved
|
||||||
end
|
end
|
||||||
|
|
||||||
# Evaluates the block and sets its result as future's value fulfilling, if the block raises
|
# Evaluates the block and sets its result as future's value fulfilling, if the block raises
|
||||||
# an exception the future rejects with it.
|
# an exception the future rejects with it.
|
||||||
|
#
|
||||||
# @yield [*args] to the block.
|
# @yield [*args] to the block.
|
||||||
# @yieldreturn [Object] value
|
# @yieldreturn [Object] value
|
||||||
# @return [self]
|
# @return [self]
|
||||||
@ -1278,6 +1387,7 @@ module Concurrent
|
|||||||
|
|
||||||
# Evaluates the block and sets its result as future's value fulfilling, if the block raises
|
# Evaluates the block and sets its result as future's value fulfilling, if the block raises
|
||||||
# an exception the future rejects with it.
|
# an exception the future rejects with it.
|
||||||
|
#
|
||||||
# @yield [*args] to the block.
|
# @yield [*args] to the block.
|
||||||
# @yieldreturn [Object] value
|
# @yieldreturn [Object] value
|
||||||
# @return [self]
|
# @return [self]
|
||||||
@ -1286,6 +1396,135 @@ module Concurrent
|
|||||||
promise.evaluate_to(*args, block).wait!
|
promise.evaluate_to(*args, block).wait!
|
||||||
end
|
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.
|
# Creates new future wrapping receiver, effectively hiding the resolve method and similar.
|
||||||
#
|
#
|
||||||
# @return [Future]
|
# @return [Future]
|
||||||
@ -1358,14 +1597,6 @@ module Concurrent
|
|||||||
super ResolvableFuture.new(self, default_executor)
|
super ResolvableFuture.new(self, default_executor)
|
||||||
end
|
end
|
||||||
|
|
||||||
def fulfill(value, raise_on_reassign)
|
|
||||||
resolve_with Fulfilled.new(value), raise_on_reassign
|
|
||||||
end
|
|
||||||
|
|
||||||
def reject(reason, raise_on_reassign)
|
|
||||||
resolve_with Rejected.new(reason), raise_on_reassign
|
|
||||||
end
|
|
||||||
|
|
||||||
public :evaluate_to
|
public :evaluate_to
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1615,7 +1846,7 @@ module Concurrent
|
|||||||
|
|
||||||
value = internal_state.value
|
value = internal_state.value
|
||||||
case value
|
case value
|
||||||
when Future, Event
|
when AbstractEventFuture
|
||||||
add_delayed_of value
|
add_delayed_of value
|
||||||
value.add_callback_notify_blocked self, nil
|
value.add_callback_notify_blocked self, nil
|
||||||
countdown
|
countdown
|
||||||
@ -1651,12 +1882,10 @@ module Concurrent
|
|||||||
|
|
||||||
value = internal_state.value
|
value = internal_state.value
|
||||||
case value
|
case value
|
||||||
when Future
|
when AbstractEventFuture
|
||||||
add_delayed_of value
|
add_delayed_of value
|
||||||
value.add_callback_notify_blocked self, nil
|
value.add_callback_notify_blocked self, nil
|
||||||
countdown
|
countdown
|
||||||
when Event
|
|
||||||
evaluate_to(lambda { raise TypeError, 'cannot flatten to Event' })
|
|
||||||
else
|
else
|
||||||
evaluate_to(lambda { raise TypeError, "returned value #{value.inspect} is not a Future" })
|
evaluate_to(lambda { raise TypeError, "returned value #{value.inspect} is not a Future" })
|
||||||
end
|
end
|
||||||
@ -1670,8 +1899,9 @@ module Concurrent
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def initialize(delayed, blockers_count, default_executor)
|
def initialize(delayed, blockers_count, default_executor, run_test)
|
||||||
super delayed, 1, Future.new(self, default_executor)
|
super delayed, 1, Future.new(self, default_executor)
|
||||||
|
@RunTest = run_test
|
||||||
end
|
end
|
||||||
|
|
||||||
def process_on_blocker_resolution(future, index)
|
def process_on_blocker_resolution(future, index)
|
||||||
@ -1682,11 +1912,12 @@ module Concurrent
|
|||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
|
|
||||||
value = internal_state.value
|
value = internal_state.value
|
||||||
case value
|
continuation_future = @RunTest.call value
|
||||||
when Future
|
|
||||||
add_delayed_of value
|
if continuation_future
|
||||||
value.add_callback_notify_blocked self, nil
|
add_delayed_of continuation_future
|
||||||
|
continuation_future.add_callback_notify_blocked self, nil
|
||||||
else
|
else
|
||||||
resolve_with internal_state
|
resolve_with internal_state
|
||||||
end
|
end
|
||||||
@ -1805,23 +2036,6 @@ module Concurrent
|
|||||||
class AbstractAnyPromise < BlockedPromise
|
class AbstractAnyPromise < BlockedPromise
|
||||||
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 AnyResolvedEventPromise < AbstractAnyPromise
|
class AnyResolvedEventPromise < AbstractAnyPromise
|
||||||
|
|
||||||
private
|
private
|
||||||
@ -1839,6 +2053,23 @@ module Concurrent
|
|||||||
end
|
end
|
||||||
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
|
class AnyFulfilledFuturePromise < AnyResolvedFuturePromise
|
||||||
|
|
||||||
private
|
private
|
||||||
@ -152,6 +152,7 @@ module Concurrent
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
clazz.class_exec(&block) unless block.nil?
|
clazz.class_exec(&block) unless block.nil?
|
||||||
|
clazz.singleton_class.send :alias_method, :[], :new
|
||||||
clazz
|
clazz
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -1,5 +1,7 @@
|
|||||||
module Concurrent
|
module Concurrent
|
||||||
module Synchronization
|
module Synchronization
|
||||||
|
|
||||||
|
# @!visibility private
|
||||||
# TODO (pitr-ch 04-Dec-2016): should be in edge
|
# TODO (pitr-ch 04-Dec-2016): should be in edge
|
||||||
class Condition < LockableObject
|
class Condition < LockableObject
|
||||||
safe_initialization!
|
safe_initialization!
|
||||||
@ -3,6 +3,7 @@ module Concurrent
|
|||||||
|
|
||||||
if Concurrent.on_jruby? && Concurrent.java_extensions_loaded?
|
if Concurrent.on_jruby? && Concurrent.java_extensions_loaded?
|
||||||
|
|
||||||
|
# @!visibility private
|
||||||
module JRubyAttrVolatile
|
module JRubyAttrVolatile
|
||||||
def self.included(base)
|
def self.included(base)
|
||||||
base.extend(ClassMethods)
|
base.extend(ClassMethods)
|
||||||
@ -1,5 +1,7 @@
|
|||||||
module Concurrent
|
module Concurrent
|
||||||
module Synchronization
|
module Synchronization
|
||||||
|
|
||||||
|
# @!visibility private
|
||||||
# TODO (pitr-ch 04-Dec-2016): should be in edge
|
# TODO (pitr-ch 04-Dec-2016): should be in edge
|
||||||
class Lock < LockableObject
|
class Lock < LockableObject
|
||||||
# TODO use JavaReentrantLock on JRuby
|
# TODO use JavaReentrantLock on JRuby
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user