class Concurrent::Promise
def self.execute(opts = {}, &block)
- Since: - 0.5.0
def self.execute(opts = {}, &block) new(opts, &block).execute end
def self.fulfill(value, opts = {})
-
(Promise)
-
def self.fulfill(value, opts = {}) Promise.new(opts).tap { |p| p.send(:synchronized_set_state!, true, value, nil) } end
def self.reject(reason, opts = {})
-
(Promise)
-
def self.reject(reason, opts = {}) Promise.new(opts).tap { |p| p.send(:synchronized_set_state!, false, nil, reason) } end
def execute
- Since: - 0.5.0
Returns:
-
(Promise)
-
def execute if root? if compare_and_set_state(:pending, :unscheduled) set_pending realize(@promise_body) end else @parent.execute end self end
def initialize(opts = {}, &block)
- See: http://promises-aplus.github.io/promises-spec/ -
See: http://wiki.commonjs.org/wiki/Promises/A -
Options Hash:
(**opts)
-
:copy_on_deref
(String
) -- call the given `Proc` passing the internal value and -
:freeze_on_deref
(String
) -- call `#freeze` before returning the data -
:dup_on_deref
(String
) -- call `#dup` before returning the data -
:executor
(object
) -- when provided will run all operations on -
:operation
(Boolean
) -- when `true` will execute the future on the global -
:on_reject
(Proc
) -- rejection handler -
:on_fulfill
(Proc
) -- fulfillment handler -
:parent
(Promise
) -- the parent `Promise` when building a chain/tree
Parameters:
-
opts
(Hash
) -- the options used to define the behavior at update and deref
def initialize(opts = {}, &block) opts.delete_if { |k, v| v.nil? } @executor = OptionsParser::get_executor_from(opts) @parent = opts.fetch(:parent) { nil } @on_fulfill = opts.fetch(:on_fulfill) { Proc.new { |result| result } } @on_reject = opts.fetch(:on_reject) { Proc.new { |reason| raise reason } } @promise_body = block || Proc.new { |result| result } @state = :unscheduled @children = [] init_obligation end
def notify_child(child)
def notify_child(child) if_state(:fulfilled) { child.on_fulfill(apply_deref_options(@value)) } if_state(:rejected) { child.on_reject(@reason) } end
def on_fulfill(result)
def on_fulfill(result) realize Proc.new { @on_fulfill.call(result) } nil end
def on_reject(reason)
def on_reject(reason) realize Proc.new { @on_reject.call(reason) } nil end
def on_success(&block)
-
(Promise)
-
def on_success(&block) raise ArgumentError.new('no block given') unless block_given? self.then &block end
def realize(task)
def realize(task) @executor.post do success, value, reason = SafeTaskExecutor.new(task).execute children_to_notify = mutex.synchronize do set_state!(success, value, reason) @children.dup end children_to_notify.each { |child| notify_child(child) } end end
def rescue(&block)
-
(Promise)
-
def rescue(&block) self.then(block) end
def root? # :nodoc:
@!visibility private
def root? # :nodoc: @parent.nil? end
def set_pending
def set_pending mutex.synchronize do @state = :pending @children.each { |c| c.set_pending } end end
def set_state!(success, value, reason)
def set_state!(success, value, reason) set_state(success, value, reason) event.set end
def synchronized_set_state!(success, value, reason)
def synchronized_set_state!(success, value, reason) mutex.lock set_state!(success, value, reason) mutex.unlock end
def then(rescuer = nil, &block)
-
(Promise)
- the new promise
def then(rescuer = nil, &block) raise ArgumentError.new('rescuers and block are both missing') if rescuer.nil? && !block_given? block = Proc.new { |result| result } if block.nil? child = Promise.new( parent: self, executor: @executor, on_fulfill: block, on_reject: rescuer ) mutex.synchronize do child.state = :pending if @state == :pending child.on_fulfill(apply_deref_options(@value)) if @state == :fulfilled child.on_reject(@reason) if @state == :rejected @children << child end child end