# 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

- .atomic_resolution(resolvable_map) ⇒ true, false

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

- .locking_order_by(resolvable) ⇒ Comparable

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

## Instance Method Summary collapse

- #release ⇒ true, false

  On successful release of the reservation.

- #reserve ⇒ true, false

  Reserves the event or future, if reserved others are prevented from resolving it.

## 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:

- atomic_resolution

    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

### #release ⇒ `true`, `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

### #reserve ⇒ `true`, `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