Class: Concurrent::Promise

Inherits:
Object
  • Object
show all
Includes:
Obligation
Defined in:
lib/concurrent/promise.rb

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Obligation

#completed?, #exception, #fulfilled?, #incomplete?, #no_error!, #pending?, #reason, #rejected?, #state, #unscheduled?, #value, #value!, #wait

Methods included from Dereferenceable

#value

Constructor Details

#initialize(opts = {}, &block) ⇒ Promise

Initialize a new Promise with the provided options.

Parameters:

  • opts (Hash) (defaults to: {})

    the options used to define the behavior at update and deref

Options Hash (opts):

  • :parent (Promise)

    the parent ‘Promise` when building a chain/tree

  • :on_fulfill (Proc)

    fulfillment handler

  • :on_reject (Proc)

    rejection handler

  • :operation (Boolean) — default: false

    when ‘true` will execute the future on the global operation pool (for long-running operations), when `false` will execute the future on the global task pool (for short-running tasks)

  • :executor (object)

    when provided will run all operations on this executor rather than the global thread pool (overrides :operation)

  • :dup_on_deref (String) — default: false

    call ‘#dup` before returning the data

  • :freeze_on_deref (String) — default: false

    call ‘#freeze` before returning the data

  • :copy_on_deref (String) — default: nil

    call the given ‘Proc` passing the internal value and returning the value returned from the proc

See Also:



32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/concurrent/promise.rb', line 32

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

Class Method Details

.execute(opts = {}, &block) ⇒ Object

Since:

  • 0.5.0



73
74
75
# File 'lib/concurrent/promise.rb', line 73

def self.execute(opts = {}, &block)
  new(opts, &block).execute
end

.fulfill(value, opts = {}) ⇒ Promise

Returns:



48
49
50
# File 'lib/concurrent/promise.rb', line 48

def self.fulfill(value, opts = {})
  Promise.new(opts).tap { |p| p.send(:synchronized_set_state!, true, value, nil) }
end

.reject(reason, opts = {}) ⇒ Promise

Returns:



54
55
56
# File 'lib/concurrent/promise.rb', line 54

def self.reject(reason, opts = {})
  Promise.new(opts).tap { |p| p.send(:synchronized_set_state!, false, nil, reason) }
end

Instance Method Details

#executePromise

Returns:

Since:

  • 0.5.0



60
61
62
63
64
65
66
67
68
69
70
# File 'lib/concurrent/promise.rb', line 60

def execute
  if root?
    if compare_and_set_state(:pending, :unscheduled)
      set_pending
      realize(@promise_body)
    end
  else
    @parent.execute
  end
  self
end

#on_success(&block) ⇒ Promise

Returns:

Raises:

  • (ArgumentError)


99
100
101
102
# File 'lib/concurrent/promise.rb', line 99

def on_success(&block)
  raise ArgumentError.new('no block given') unless block_given?
  self.then &block
end

#rescue(&block) ⇒ Promise Also known as: catch, on_error

Returns:



105
106
107
# File 'lib/concurrent/promise.rb', line 105

def rescue(&block)
  self.then(block)
end

#then(rescuer = nil, &block) ⇒ Promise

Returns the new promise.

Returns:

Raises:

  • (ArgumentError)


78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/concurrent/promise.rb', line 78

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