Represents a value which will become available in future. May reject with a reason instead, e.g. when the tasks raises an exception.
Creates a new event which will be resolved when the first of receiver, `event_or_future` resolves. Returning future will have value nil if event_or_future is event and resolves first.
@return [Future]
# File lib/concurrent/promises.rb, line 1023 def any(event_or_future) AnyResolvedFuturePromise.new_blocked_by2(self, event_or_future, @DefaultExecutor).future end
@!visibility private
# File lib/concurrent/promises.rb, line 1147 def apply(args, block) internal_state.apply args, block end
Creates new future dependent on receiver which will not evaluate until touched, see {#touch}. In other words, it inserts delay into the chain of Futures making rest of it lazy evaluated.
@return [Future]
# File lib/concurrent/promises.rb, line 1033 def delay event = DelayPromise.new(@DefaultExecutor).event ZipFutureEventPromise.new_blocked_by2(self, event, @DefaultExecutor).future end
Allows rejected Future to be risen with `raise` method. @example
raise Promises.rejected_future(StandardError.new("boom"))
@raise [StandardError] when raising not rejected future @return [Exception]
# File lib/concurrent/promises.rb, line 956 def exception(*args) raise Concurrent::Error, 'it is not rejected' unless rejected? 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.set_backtrace Array(ex.backtrace) + caller ex end end
Creates new event which will be resolved when the returned event by receiver is. Be careful if the receiver rejects it will just resolve since Event does not hold reason.
@return [Event]
# File lib/concurrent/promises.rb, line 1068 def flat_event FlatEventPromise.new_blocked_by1(self, @DefaultExecutor).event end
Creates new future which will have result of the future returned by receiver. If receiver rejects it will have its rejection.
@param [Integer] level how many levels of futures should flatten @return [Future]
# File lib/concurrent/promises.rb, line 1058 def flat_future(level = 1) FlatFuturePromise.new_blocked_by1(self, level, @DefaultExecutor).future end
Is it in fulfilled state? @return [Boolean]
# File lib/concurrent/promises.rb, line 886 def fulfilled? state = internal_state state.resolved? && state.fulfilled? end
@!macro promises.shortcut.using @return [self]
# File lib/concurrent/promises.rb, line 1074 def on_fulfillment(*args, &callback) on_fulfillment_using @DefaultExecutor, *args, &callback end
Stores the callback to be executed synchronously on resolving thread after it is fulfilled. Does nothing on rejection.
@!macro promises.param.args @!macro promise.param.callback @return [self] @yield [value, *args] to the callback.
# File lib/concurrent/promises.rb, line 1085 def on_fulfillment!(*args, &callback) add_callback :callback_on_fulfillment, args, callback end
Stores the callback to be executed asynchronously on executor after it is fulfilled. Does nothing on rejection.
@!macro promises.param.executor @!macro promises.param.args @!macro promise.param.callback @return [self] @yield [value, *args] to the callback.
# File lib/concurrent/promises.rb, line 1097 def on_fulfillment_using(executor, *args, &callback) add_callback :async_callback_on_fulfillment, executor, args, callback end
@!macro promises.shortcut.using @return [self]
# File lib/concurrent/promises.rb, line 1103 def on_rejection(*args, &callback) on_rejection_using @DefaultExecutor, *args, &callback end
Stores the callback to be executed synchronously on resolving thread after it is rejected. Does nothing on fulfillment.
@!macro promises.param.args @!macro promise.param.callback @return [self] @yield [reason, *args] to the callback.
# File lib/concurrent/promises.rb, line 1114 def on_rejection!(*args, &callback) add_callback :callback_on_rejection, args, callback end
Stores the callback to be executed asynchronously on executor after it is rejected. Does nothing on fulfillment.
@!macro promises.param.executor @!macro promises.param.args @!macro promise.param.callback @return [self] @yield [reason, *args] to the callback.
# File lib/concurrent/promises.rb, line 1126 def on_rejection_using(executor, *args, &callback) add_callback :async_callback_on_rejection, executor, args, callback end
Returns reason of future's rejection. @!macro promises.touches
@!macro promises.warn.blocks @!macro promises.warn.nil @!macro promises.param.timeout @return [Exception, nil] nil on timeout or fulfillment.
# File lib/concurrent/promises.rb, line 922 def reason(timeout = nil) internal_state.reason if wait_until_resolved timeout end
Is it in rejected state? @return [Boolean]
# File lib/concurrent/promises.rb, line 893 def rejected? state = internal_state state.resolved? && !state.fulfilled? end
@!macro promises.shortcut.on @return [Future]
# File lib/concurrent/promises.rb, line 990 def rescue(*args, &task) rescue_on @DefaultExecutor, *args, &task end
Chains the task to be executed asynchronously on executor after it rejects. Does not run the task if it fulfills. It will resolve though, triggering any dependent futures.
@!macro promises.param.executor @!macro promises.param.args @!macro promise.param.task-future @return [Future] @yield [reason, *args] to the task.
# File lib/concurrent/promises.rb, line 1002 def rescue_on(executor, *args, &task) RescuePromise.new_blocked_by1(self, @DefaultExecutor, executor, args, &task).future end
Returns triplet fulfilled?, value, reason. @!macro promises.touches
@!macro promises.warn.blocks @!macro promises.param.timeout @return [Array(Boolean, Object, Exception), nil] triplet of fulfilled?, value, reason, or nil
on timeout.
# File lib/concurrent/promises.rb, line 933 def result(timeout = nil) internal_state.result if wait_until_resolved timeout end
Allows to use futures as green threads. The receiver has to evaluate to a future which represents what should be done next. It basically flattens indefinitely until non Future values is returned which becomes result of the returned future. Any encountered exception will become reason of the returned future.
@return [Future] @example
body = lambda do |v| v += 1 v < 5 ? Promises.future(v, &body) : v end Promises.future(0, &body).run.value! # => 5
# File lib/concurrent/promises.rb, line 1142 def run RunFuturePromise.new_blocked_by1(self, @DefaultExecutor).future end
@!macro promise.method.schedule @return [Future]
# File lib/concurrent/promises.rb, line 1040 def schedule(intended_time) chain do event = ScheduledPromise.new(@DefaultExecutor, intended_time).event ZipFutureEventPromise.new_blocked_by2(self, event, @DefaultExecutor).future end.flat end
@!macro promises.shortcut.on @return [Future]
# File lib/concurrent/promises.rb, line 972 def then(*args, &task) then_on @DefaultExecutor, *args, &task end
Chains the task to be executed asynchronously on executor after it fulfills. Does not run the task if it rejects. It will resolve though, triggering any dependent futures.
@!macro promises.param.executor @!macro promises.param.args @!macro promise.param.task-future @return [Future] @yield [value, *args] to the task.
# File lib/concurrent/promises.rb, line 984 def then_on(executor, *args, &task) ThenPromise.new_blocked_by1(self, @DefaultExecutor, executor, args, &task).future end
Converts future to event which is resolved when future is resolved by fulfillment or rejection.
@return [Event]
# File lib/concurrent/promises.rb, line 1154 def to_event event = Promises.resolvable_event ensure chain_resolvable(event) end
Returns self, since this is a future @return [Future]
# File lib/concurrent/promises.rb, line 1162 def to_future self end
@!macro promises.method.value
Return value of the future. @!macro promises.touches @!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.
# File lib/concurrent/promises.rb, line 911 def value(timeout = nil) internal_state.value if wait_until_resolved timeout end
@!macro promises.method.value @return [Object, nil] the value of the Future when fulfilled, nil on timeout. @raise [Exception] {#reason} on rejection
# File lib/concurrent/promises.rb, line 947 def value!(timeout = nil) internal_state.value if wait_until_resolved! timeout end
@!macro promises.method.wait @raise [Exception] {#reason} on rejection
# File lib/concurrent/promises.rb, line 939 def wait!(timeout = nil) result = wait_until_resolved!(timeout) timeout ? result : self end
@!macro promises.method.with_default_executor @return [Future]
# File lib/concurrent/promises.rb, line 1049 def with_default_executor(executor) FutureWrapperPromise.new_blocked_by1(self, executor).future end
@!macro promises.method.zip @return [Future]
# File lib/concurrent/promises.rb, line 1008 def zip(other) if other.is_a?(Future) ZipFuturesPromise.new_blocked_by2(self, other, @DefaultExecutor).future else ZipFutureEventPromise.new_blocked_by2(self, other, @DefaultExecutor).future end end
# File lib/concurrent/promises.rb, line 1183 def async_callback_on_fulfillment(state, executor, args, callback) with_async(executor, state, args, callback) do |st, ar, cb| callback_on_fulfillment st, ar, cb end end
# File lib/concurrent/promises.rb, line 1189 def async_callback_on_rejection(state, executor, args, callback) with_async(executor, state, args, callback) do |st, ar, cb| callback_on_rejection st, ar, cb end end
# File lib/concurrent/promises.rb, line 1195 def callback_on_fulfillment(state, args, callback) state.apply args, callback if state.fulfilled? end
# File lib/concurrent/promises.rb, line 1199 def callback_on_rejection(state, args, callback) state.apply args, callback unless state.fulfilled? end
# File lib/concurrent/promises.rb, line 1203 def callback_on_resolution(state, args, callback) callback.call(*state.result, *args) end
# File lib/concurrent/promises.rb, line 1168 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) end return false end
# File lib/concurrent/promises.rb, line 1177 def wait_until_resolved!(timeout = nil) result = wait_until_resolved(timeout) raise self if rejected? result end