Module: Concurrent::Promises::Resolvable

Included in:
ResolvableEvent, ResolvableFuture
Defined in:
lib/concurrent-ruby/concurrent/promises.rb,
lib/concurrent-ruby-edge/concurrent/edge/promises.rb

Overview

Marker module of Future, Event resolved manually.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.atomic_resolution(resolvable_map) ⇒ true, false

Resolves all passed events and futures to the given resolutions if possible (all are unresolved) or none.

Parameters:

  • resolvable_map (Hash{Resolvable=>resolve_arguments}, Array<Array(Resolvable, resolve_arguments)>)

    collection of resolvable events and futures which should be resolved all at once and what should they be resolved to, examples:

    { a_resolvable_future1 => [true, :val, nil],
      a_resolvable_future2 => [false, nil, :err],
      a_resolvable_event => [] }
    

    or

    [[a_resolvable_future1, [true, :val, nil]],
     [a_resolvable_future2, [false, nil, :err]],
     [a_resolvable_event, []]]
    

Returns:

  • (true, false)

    if success



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/concurrent-ruby-edge/concurrent/edge/promises.rb', line 150

def self.atomic_resolution(resolvable_map)
  # atomic_resolution event => [], future => [true, :v, nil]
  sorted = resolvable_map.to_a.sort_by { |resolvable, _| locking_order_by resolvable }

  reserved = 0
  while reserved < sorted.size && sorted[reserved].first.reserve
    reserved += 1
  end

  if reserved == sorted.size
    sorted.each { |resolvable, args| resolvable.resolve(*args, true, true) }
    true
  else
    while reserved > 0
      reserved -= 1
      raise 'has to be reserved' unless sorted[reserved].first.release
    end
    false
  end
end

.locking_order_by(resolvable) ⇒ Comparable

Returns an item to sort the resolvable events or futures by to get the right global locking order of resolvable events or futures.

Returns:

  • (Comparable)

    an item to sort the resolvable events or futures by to get the right global locking order of resolvable events or futures

See Also:



128
129
130
# File 'lib/concurrent-ruby-edge/concurrent/edge/promises.rb', line 128

def self.locking_order_by(resolvable)
  resolvable.object_id
end

Instance Method Details

#releasetrue, false

Returns on successful release of the reservation.

Returns:

  • (true, false)

    on successful release of the reservation



121
122
123
# File 'lib/concurrent-ruby-edge/concurrent/edge/promises.rb', line 121

def release
  compare_and_set_internal_state(RESERVED, PENDING)
end

#reservetrue, false

Reserves the event or future, if reserved others are prevented from resolving it. Advanced feature. Be careful about the order of reservation to avoid deadlocks, the method blocks if the future or event is already reserved until it is released or resolved.

Examples:

f = Concurrent::Promises.resolvable_future
reserved = f.reserve
Thread.new { f.resolve true, :val, nil } # fails
f.resolve true, :val, nil, true if reserved # must be called only if reserved

Returns:

  • (true, false)

    on successful reservation



111
112
113
114
115
116
117
118
# File 'lib/concurrent-ruby-edge/concurrent/edge/promises.rb', line 111

def reserve
  while true
    return true if compare_and_set_internal_state(PENDING, RESERVED)
    return false if resolved?
    # FIXME (pitr-ch 17-Jan-2019): sleep until given up or resolved instead of busy wait
    Thread.pass
  end
end