Class: Gienah::Future

Inherits:
Object
  • Object
show all
Defined in:
lib/gienah/future.rb,
sig/gienah.rbs

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(id, on_cancel: nil) ⇒ Future

Returns a new instance of Future.

Parameters:

  • id (Integer)
  • on_cancel: (^(Integer) -> untyped) (defaults to: nil)


5
6
7
8
9
10
11
# File 'lib/gienah/future.rb', line 5

def initialize(id, on_cancel: nil)
  @id = id
  @on_cancel = on_cancel
  @lock = Mutex.new
  @ready = ConditionVariable.new
  @callbacks = []
end

Instance Attribute Details

#id ⇒ Integer (readonly)

Returns the value of attribute id.

Returns:

  • (Integer)


13
14
15
# File 'lib/gienah/future.rb', line 13

def id
  @id
end

Instance Method Details

#await(timeout: nil) ⇒ Object

Parameters:

  • timeout: (Numeric, nil) (defaults to: nil)

Returns:

  • (Object)


29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/gienah/future.rb', line 29

def await(timeout: nil)
  validate_timeout(timeout)
  deadline = timeout && Process.clock_gettime(Process::CLOCK_MONOTONIC) + timeout
  timed_out = false
  result = @lock.synchronize do
    until @done
      remaining = deadline && deadline - Process.clock_gettime(Process::CLOCK_MONOTONIC)
      if remaining && remaining <= 0
        timed_out = true
        break
      end
      @ready.wait(@lock, remaining)
    end
    break if timed_out
    raise @error if @error
    @value
  end
  if timed_out
    cancel
    raise Gienah::Timeout, "request #{@id} timed out"
  end
  result
end

#cancel ⇒ Boolean

Returns:

  • (Boolean)


63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/gienah/future.rb', line 63

def cancel
  callback = @lock.synchronize do
    return false if @done || @cancelling
    @cancelling = true
    @on_cancel
  end
  begin
    callback&.call(@id)
  rescue StandardError
    nil
  end
  fulfill(error: Error.new("request #{@id} cancelled"))
  true
end

#done? ⇒ Boolean

Returns:

  • (Boolean)


78
79
80
# File 'lib/gienah/future.rb', line 78

def done?
  @lock.synchronize { !!@done }
end

#fulfill(value = nil, error: nil) ⇒ Future

Parameters:

  • value (Object) (defaults to: nil)
  • error: (Exception, nil) (defaults to: nil)

Returns:



15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/gienah/future.rb', line 15

def fulfill(value = nil, error: nil)
  callbacks = @lock.synchronize do
    return self if @done
    @value = value
    @error = error
    @done = true
    @ready.broadcast
    callbacks, @callbacks = @callbacks, []
    callbacks
  end
  callbacks.each { |callback| callback.call(@value, @error) }
  self
end

#then {|arg0, arg1| ... } ⇒ Future

Yields:

Yield Parameters:

  • arg0 (Object)
  • arg1 (Exception, nil)

Yield Returns:

  • (Object)

Returns:

Raises:

  • (ArgumentError)


53
54
55
56
57
58
59
60
61
# File 'lib/gienah/future.rb', line 53

def then(&callback)
  raise ArgumentError, "callback required" unless callback
  ready = @lock.synchronize do
    @callbacks << callback unless @done
    @done
  end
  callback.call(@value, @error) if ready
  self
end