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/thread_safe/
|
||||
**/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/thread_safe-*/lib/thread_safe/util
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ GEM
|
||||
tzinfo (~> 1.1)
|
||||
ast (2.4.0)
|
||||
backports (3.12.0)
|
||||
concurrent-ruby (1.1.4)
|
||||
concurrent-ruby (1.1.5)
|
||||
connection_pool (2.2.2)
|
||||
coveralls (0.8.22)
|
||||
json (>= 1.8, < 3)
|
||||
|
||||
@ -22,12 +22,12 @@ module Homebrew
|
||||
|
||||
ohai "cd #{HOMEBREW_LIBRARY_PATH}"
|
||||
HOMEBREW_LIBRARY_PATH.cd do
|
||||
ohai "bundle pristine"
|
||||
safe_system "bundle", "pristine"
|
||||
|
||||
ohai "bundle install --standalone"
|
||||
safe_system "bundle", "install", "--standalone"
|
||||
|
||||
ohai "bundle pristine"
|
||||
safe_system "bundle", "pristine"
|
||||
|
||||
ohai "git add vendor/bundle"
|
||||
system "git", "add", "vendor/bundle"
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@ require 'rbconfig'
|
||||
ruby_engine = defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'
|
||||
ruby_version = RbConfig::CONFIG["ruby_version"]
|
||||
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/minitest-5.11.3/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
|
||||
ArrayImplementation = case
|
||||
when Concurrent.on_cruby?
|
||||
# Because MRI never runs code in parallel, the existing
|
||||
# non-thread-safe structures should usually work fine.
|
||||
# Array is thread-safe in practice because CRuby runs
|
||||
# threads one at a time and does not do context
|
||||
# switching during the execution of C functions.
|
||||
::Array
|
||||
|
||||
when Concurrent.on_jruby?
|
||||
@ -63,4 +64,3 @@ module Concurrent
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -333,6 +333,13 @@ module Concurrent
|
||||
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
|
||||
@ -383,6 +390,13 @@ module Concurrent
|
||||
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
|
||||
|
||||
@ -79,10 +79,10 @@ module Concurrent
|
||||
# @!method value=(value)
|
||||
# @!macro atomic_fixnum_method_value_set
|
||||
#
|
||||
# @!method increment(delta)
|
||||
# @!method increment(delta = 1)
|
||||
# @!macro atomic_fixnum_method_increment
|
||||
#
|
||||
# @!method decrement(delta)
|
||||
# @!method decrement(delta = 1)
|
||||
# @!macro atomic_fixnum_method_decrement
|
||||
#
|
||||
# @!method compare_and_set(expect, update)
|
||||
@ -53,7 +53,7 @@ module Concurrent
|
||||
|
||||
# @param [Node] head
|
||||
# @return [true, false]
|
||||
def empty?(head = self.head)
|
||||
def empty?(head = head())
|
||||
head.equal? EMPTY
|
||||
end
|
||||
|
||||
@ -48,11 +48,9 @@ module Concurrent
|
||||
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
|
||||
}
|
||||
opts = { executor: @task_executor,
|
||||
args: args,
|
||||
timer_set: self }
|
||||
task = ScheduledTask.execute(delay, opts, &task) # may raise exception
|
||||
task.unscheduled? ? false : task
|
||||
end
|
||||
@ -74,11 +72,11 @@ module Concurrent
|
||||
# @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
|
||||
@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
|
||||
self.auto_terminate = opts.fetch(:auto_terminate, true)
|
||||
end
|
||||
|
||||
@ -90,7 +88,7 @@ module Concurrent
|
||||
#
|
||||
# @!visibility private
|
||||
def post_task(task)
|
||||
synchronize{ ns_post_task(task) }
|
||||
synchronize { ns_post_task(task) }
|
||||
end
|
||||
|
||||
# @!visibility private
|
||||
@ -98,7 +96,7 @@ module Concurrent
|
||||
return false unless ns_running?
|
||||
ns_reset_if_forked
|
||||
if (task.initial_delay) <= 0.01
|
||||
task.executor.post{ task.process_task }
|
||||
task.executor.post { task.process_task }
|
||||
else
|
||||
@queue.push(task)
|
||||
# only post the process method when the queue is empty
|
||||
@ -116,7 +114,7 @@ module Concurrent
|
||||
#
|
||||
# @!visibility private
|
||||
def remove_task(task)
|
||||
synchronize{ @queue.delete(task) }
|
||||
synchronize { @queue.delete(task) }
|
||||
end
|
||||
|
||||
# `ExecutorService` callback called during shutdown.
|
||||
@ -148,7 +146,7 @@ module Concurrent
|
||||
task = synchronize { @condition.reset; @queue.peek }
|
||||
break unless task
|
||||
|
||||
now = Concurrent.monotonic_time
|
||||
now = Concurrent.monotonic_time
|
||||
diff = task.schedule_time - now
|
||||
|
||||
if diff <= 0
|
||||
@ -165,7 +163,7 @@ module Concurrent
|
||||
# queue now must have the same pop time, or a closer one, as
|
||||
# when we peeked).
|
||||
task = synchronize { @queue.pop }
|
||||
task.executor.post{ task.process_task }
|
||||
task.executor.post { task.process_task }
|
||||
else
|
||||
@condition.wait([diff, 60].min)
|
||||
end
|
||||
@ -15,8 +15,9 @@ module Concurrent
|
||||
# @!macro internal_implementation_note
|
||||
HashImplementation = case
|
||||
when Concurrent.on_cruby?
|
||||
# Because MRI never runs code in parallel, the existing
|
||||
# non-thread-safe structures should usually work fine.
|
||||
# Hash is thread-safe in practice because CRuby runs
|
||||
# threads one at a time and does not do context
|
||||
# switching during the execution of C functions.
|
||||
::Hash
|
||||
|
||||
when Concurrent.on_jruby?
|
||||
@ -56,4 +57,3 @@ module Concurrent
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -43,6 +43,7 @@ module Concurrent
|
||||
# new.
|
||||
module FactoryMethods
|
||||
extend ReInclude
|
||||
extend self
|
||||
|
||||
module Configuration
|
||||
# @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)
|
||||
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.
|
||||
#
|
||||
# @!macro promises.future-on2
|
||||
# @!macro promises.param.default_executor
|
||||
# @!macro promises.param.args
|
||||
# @yield [*args] to the task.
|
||||
# @!macro promise.param.task-future
|
||||
# @return [Future]
|
||||
# @!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
|
||||
@ -109,6 +108,9 @@ module Concurrent
|
||||
# Creates resolved future with will be either fulfilled with the given value or rejection 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)
|
||||
@ -118,6 +120,7 @@ module Concurrent
|
||||
# Creates resolved future with 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
|
||||
@ -126,6 +129,7 @@ module Concurrent
|
||||
# Creates resolved future with 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
|
||||
@ -146,23 +150,23 @@ module Concurrent
|
||||
# @!macro promises.param.default_executor
|
||||
# @return [Event, Future]
|
||||
#
|
||||
# @overload create(nil, default_executor = self.default_executor)
|
||||
# @overload make_future(nil, default_executor = self.default_executor)
|
||||
# @param [nil] nil
|
||||
# @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
|
||||
# @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
|
||||
# @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
|
||||
# @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
|
||||
# @return [Future] a fulfilled future with the value.
|
||||
def make_future(argument = nil, default_executor = self.default_executor)
|
||||
@ -180,34 +184,53 @@ module Concurrent
|
||||
end
|
||||
|
||||
# @!macro promises.shortcut.on
|
||||
# @return [Future]
|
||||
# @return [Future, Event]
|
||||
def delay(*args, &task)
|
||||
delay_on default_executor, *args, &task
|
||||
end
|
||||
|
||||
# @!macro promises.future-on1
|
||||
# The task will be evaluated only after the future is touched, see {AbstractEventFuture#touch}
|
||||
# Creates new event or future which is resolved only after it is touched,
|
||||
# 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)
|
||||
DelayPromise.new(default_executor).event.chain(*args, &task)
|
||||
event = DelayPromise.new(default_executor).event
|
||||
task ? event.chain(*args, &task) : event
|
||||
end
|
||||
|
||||
# @!macro promises.shortcut.on
|
||||
# @return [Future]
|
||||
# @return [Future, Event]
|
||||
def schedule(intended_time, *args, &task)
|
||||
schedule_on default_executor, intended_time, *args, &task
|
||||
end
|
||||
|
||||
# @!macro promises.future-on1
|
||||
# The task is planned for execution in intended_time.
|
||||
# Creates new event or future which is resolved in intended_time.
|
||||
#
|
||||
# @!macro promises.future-on2
|
||||
# @!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)
|
||||
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
|
||||
|
||||
# @!macro promises.shortcut.on
|
||||
@ -259,7 +282,7 @@ module Concurrent
|
||||
# Creates new future which is resolved after first futures_and_or_events is resolved.
|
||||
# Its result equals result of the first resolved future.
|
||||
# @!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.
|
||||
# @!macro promises.event-conversion
|
||||
#
|
||||
@ -311,7 +334,7 @@ module Concurrent
|
||||
end
|
||||
|
||||
module InternalStates
|
||||
# @private
|
||||
# @!visibility private
|
||||
class State
|
||||
def resolved?
|
||||
raise NotImplementedError
|
||||
@ -322,9 +345,7 @@ module Concurrent
|
||||
end
|
||||
end
|
||||
|
||||
private_constant :State
|
||||
|
||||
# @private
|
||||
# @!visibility private
|
||||
class Pending < State
|
||||
def resolved?
|
||||
false
|
||||
@ -335,9 +356,11 @@ module Concurrent
|
||||
end
|
||||
end
|
||||
|
||||
private_constant :Pending
|
||||
# @!visibility private
|
||||
class Reserved < Pending
|
||||
end
|
||||
|
||||
# @private
|
||||
# @!visibility private
|
||||
class ResolvedWithResult < State
|
||||
def resolved?
|
||||
true
|
||||
@ -368,9 +391,7 @@ module Concurrent
|
||||
end
|
||||
end
|
||||
|
||||
private_constant :ResolvedWithResult
|
||||
|
||||
# @private
|
||||
# @!visibility private
|
||||
class Fulfilled < ResolvedWithResult
|
||||
|
||||
def initialize(value)
|
||||
@ -398,18 +419,14 @@ module Concurrent
|
||||
end
|
||||
end
|
||||
|
||||
private_constant :Fulfilled
|
||||
|
||||
# @private
|
||||
# @!visibility private
|
||||
class FulfilledArray < Fulfilled
|
||||
def apply(args, block)
|
||||
block.call(*value, *args)
|
||||
end
|
||||
end
|
||||
|
||||
private_constant :FulfilledArray
|
||||
|
||||
# @private
|
||||
# @!visibility private
|
||||
class Rejected < ResolvedWithResult
|
||||
def initialize(reason)
|
||||
@Reason = reason
|
||||
@ -436,9 +453,7 @@ module Concurrent
|
||||
end
|
||||
end
|
||||
|
||||
private_constant :Rejected
|
||||
|
||||
# @private
|
||||
# @!visibility private
|
||||
class PartiallyRejected < ResolvedWithResult
|
||||
def initialize(value, reason)
|
||||
super()
|
||||
@ -467,24 +482,38 @@ module Concurrent
|
||||
end
|
||||
end
|
||||
|
||||
private_constant :PartiallyRejected
|
||||
|
||||
PENDING = Pending.new
|
||||
# @!visibility private
|
||||
PENDING = Pending.new
|
||||
# @!visibility private
|
||||
RESERVED = Reserved.new
|
||||
# @!visibility private
|
||||
RESOLVED = Fulfilled.new(nil)
|
||||
|
||||
def RESOLVED.to_sym
|
||||
:resolved
|
||||
end
|
||||
|
||||
private_constant :PENDING, :RESOLVED
|
||||
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!
|
||||
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
|
||||
|
||||
@ -501,17 +530,6 @@ module Concurrent
|
||||
|
||||
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.
|
||||
# @return [Symbol]
|
||||
#
|
||||
@ -545,7 +563,7 @@ module Concurrent
|
||||
end
|
||||
|
||||
# @!macro promises.touches
|
||||
# Calls {AbstractEventFuture#touch}.
|
||||
# Calls {Concurrent::AbstractEventFuture#touch}.
|
||||
|
||||
# @!macro promises.method.wait
|
||||
# Wait (block the Thread) until receiver is {#resolved?}.
|
||||
@ -553,7 +571,7 @@ module Concurrent
|
||||
#
|
||||
# @!macro promises.warn.blocks
|
||||
# @!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.
|
||||
def wait(timeout = nil)
|
||||
result = wait_until_resolved(timeout)
|
||||
@ -590,7 +608,7 @@ module Concurrent
|
||||
# @yield [fulfilled, value, reason, *args] to the task.
|
||||
# @yieldparam [true, false] fulfilled
|
||||
# @yieldparam [Object] value
|
||||
# @yieldparam [Exception] reason
|
||||
# @yieldparam [Object] reason
|
||||
def chain_on(executor, *args, &task)
|
||||
ChainPromise.new_blocked_by1(self, @DefaultExecutor, executor, args, &task).future
|
||||
end
|
||||
@ -631,7 +649,7 @@ module Concurrent
|
||||
# @yield [fulfilled, value, reason, *args] to the callback.
|
||||
# @yieldparam [true, false] fulfilled
|
||||
# @yieldparam [Object] value
|
||||
# @yieldparam [Exception] reason
|
||||
# @yieldparam [Object] reason
|
||||
def on_resolution!(*args, &callback)
|
||||
add_callback :callback_on_resolution, args, callback
|
||||
end
|
||||
@ -649,7 +667,7 @@ module Concurrent
|
||||
# @yield [fulfilled, value, reason, *args] to the callback.
|
||||
# @yieldparam [true, false] fulfilled
|
||||
# @yieldparam [Object] value
|
||||
# @yieldparam [Exception] reason
|
||||
# @yieldparam [Object] reason
|
||||
def on_resolution_using(executor, *args, &callback)
|
||||
add_callback :async_callback_on_resolution, executor, args, callback
|
||||
end
|
||||
@ -665,8 +683,8 @@ module Concurrent
|
||||
end
|
||||
|
||||
# @!visibility private
|
||||
def resolve_with(state, raise_on_reassign = true)
|
||||
if compare_and_set_internal_state(PENDING, state)
|
||||
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
|
||||
@ -719,6 +737,12 @@ module Concurrent
|
||||
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)
|
||||
@ -907,9 +931,17 @@ module Concurrent
|
||||
# @!macro promises.warn.blocks
|
||||
# @!macro promises.warn.nil
|
||||
# @!macro promises.param.timeout
|
||||
# @return [Object, nil] the value of the Future when fulfilled, nil on timeout or rejection.
|
||||
def value(timeout = nil)
|
||||
internal_state.value if wait_until_resolved 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.
|
||||
@ -918,9 +950,14 @@ module Concurrent
|
||||
# @!macro promises.warn.blocks
|
||||
# @!macro promises.warn.nil
|
||||
# @!macro promises.param.timeout
|
||||
# @return [Exception, nil] nil on timeout or fulfillment.
|
||||
def reason(timeout = nil)
|
||||
internal_state.reason if wait_until_resolved 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.
|
||||
@ -928,7 +965,7 @@ module Concurrent
|
||||
#
|
||||
# @!macro promises.warn.blocks
|
||||
# @!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.
|
||||
def result(timeout = nil)
|
||||
internal_state.result if wait_until_resolved timeout
|
||||
@ -942,26 +979,40 @@ module Concurrent
|
||||
end
|
||||
|
||||
# @!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
|
||||
def value!(timeout = nil)
|
||||
internal_state.value if wait_until_resolved! timeout
|
||||
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 [StandardError] when raising not rejected future
|
||||
# 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 = 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
|
||||
end
|
||||
@ -1133,14 +1184,20 @@ module Concurrent
|
||||
# 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
|
||||
RunFuturePromise.new_blocked_by1(self, @DefaultExecutor).future
|
||||
def run(run_test = method(:run_test))
|
||||
RunFuturePromise.new_blocked_by1(self, @DefaultExecutor, run_test).future
|
||||
end
|
||||
|
||||
# @!visibility private
|
||||
@ -1163,13 +1220,34 @@ module Concurrent
|
||||
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
|
||||
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)
|
||||
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
|
||||
@ -1206,15 +1284,15 @@ module Concurrent
|
||||
|
||||
end
|
||||
|
||||
# Marker module of Future, Event resolved manually by user.
|
||||
# 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.
|
||||
|
||||
@ -1227,8 +1305,13 @@ module Concurrent
|
||||
# Makes the event resolved, which triggers all dependent futures.
|
||||
#
|
||||
# @!macro promise.param.raise_on_reassign
|
||||
def resolve(raise_on_reassign = true)
|
||||
resolve_with RESOLVED, 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.
|
||||
@ -1237,6 +1320,23 @@ module Concurrent
|
||||
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.
|
||||
@ -1246,29 +1346,38 @@ module Concurrent
|
||||
# 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
|
||||
def resolve(fulfilled = true, value = nil, reason = nil, raise_on_reassign = true)
|
||||
resolve_with(fulfilled ? Fulfilled.new(value) : Rejected.new(reason), 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
|
||||
def fulfill(value, raise_on_reassign = true)
|
||||
promise.fulfill(value, 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
|
||||
def reject(reason, raise_on_reassign = true)
|
||||
promise.reject(reason, 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]
|
||||
@ -1278,6 +1387,7 @@ module Concurrent
|
||||
|
||||
# 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]
|
||||
@ -1286,6 +1396,135 @@ module Concurrent
|
||||
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]
|
||||
@ -1358,14 +1597,6 @@ module Concurrent
|
||||
super ResolvableFuture.new(self, default_executor)
|
||||
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
|
||||
end
|
||||
|
||||
@ -1615,7 +1846,7 @@ module Concurrent
|
||||
|
||||
value = internal_state.value
|
||||
case value
|
||||
when Future, Event
|
||||
when AbstractEventFuture
|
||||
add_delayed_of value
|
||||
value.add_callback_notify_blocked self, nil
|
||||
countdown
|
||||
@ -1651,12 +1882,10 @@ module Concurrent
|
||||
|
||||
value = internal_state.value
|
||||
case value
|
||||
when Future
|
||||
when AbstractEventFuture
|
||||
add_delayed_of value
|
||||
value.add_callback_notify_blocked self, nil
|
||||
countdown
|
||||
when Event
|
||||
evaluate_to(lambda { raise TypeError, 'cannot flatten to Event' })
|
||||
else
|
||||
evaluate_to(lambda { raise TypeError, "returned value #{value.inspect} is not a Future" })
|
||||
end
|
||||
@ -1670,8 +1899,9 @@ module Concurrent
|
||||
|
||||
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)
|
||||
@RunTest = run_test
|
||||
end
|
||||
|
||||
def process_on_blocker_resolution(future, index)
|
||||
@ -1682,11 +1912,12 @@ module Concurrent
|
||||
return 0
|
||||
end
|
||||
|
||||
value = internal_state.value
|
||||
case value
|
||||
when Future
|
||||
add_delayed_of value
|
||||
value.add_callback_notify_blocked self, nil
|
||||
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
|
||||
@ -1805,23 +2036,6 @@ module Concurrent
|
||||
class AbstractAnyPromise < BlockedPromise
|
||||
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
|
||||
|
||||
private
|
||||
@ -1839,6 +2053,23 @@ module Concurrent
|
||||
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
|
||||
@ -152,6 +152,7 @@ module Concurrent
|
||||
end
|
||||
end
|
||||
clazz.class_exec(&block) unless block.nil?
|
||||
clazz.singleton_class.send :alias_method, :[], :new
|
||||
clazz
|
||||
end
|
||||
end
|
||||
@ -1,5 +1,7 @@
|
||||
module Concurrent
|
||||
module Synchronization
|
||||
|
||||
# @!visibility private
|
||||
# TODO (pitr-ch 04-Dec-2016): should be in edge
|
||||
class Condition < LockableObject
|
||||
safe_initialization!
|
||||
@ -3,6 +3,7 @@ module Concurrent
|
||||
|
||||
if Concurrent.on_jruby? && Concurrent.java_extensions_loaded?
|
||||
|
||||
# @!visibility private
|
||||
module JRubyAttrVolatile
|
||||
def self.included(base)
|
||||
base.extend(ClassMethods)
|
||||
@ -1,5 +1,7 @@
|
||||
module Concurrent
|
||||
module Synchronization
|
||||
|
||||
# @!visibility private
|
||||
# TODO (pitr-ch 04-Dec-2016): should be in edge
|
||||
class Lock < LockableObject
|
||||
# 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