Class: LittleGhost::Support::CancellationToken

Inherits:
Object
  • Object
show all
Defined in:
lib/little_ghost/support/cancellation_token.rb

Overview

CancellationToken lets related work stop cooperatively without killing its calling thread. Child tokens make cancellation flow through a run's tree of work.

Cancellation is idempotent and flows only downward. Long-running extensions should call #raise_if_cancelled! at bounded intervals.

Instance Method Summary collapse

Constructor Details

#initialize(parent: nil) ⇒ CancellationToken

Optionally attaches this token to parent.



13
14
15
16
17
18
19
20
# File 'lib/little_ghost/support/cancellation_token.rb', line 13

def initialize(parent: nil)
  @cancelled = false
  @mutex = Mutex.new
  @condition = ConditionVariable.new
  @children = {}
  @parent = parent
  parent&.send(:attach, self)
end

Instance Method Details

#cancelObject

Cancels this token and all currently attached children.



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/little_ghost/support/cancellation_token.rb', line 26

def cancel
  parent, children = @mutex.synchronize do
    return self if @cancelled

    @cancelled = true
    @condition.broadcast
    parent = @parent
    @parent = nil
    children = @children.keys
    @children.clear
    [parent, children]
  end
  parent&.send(:detach, self)
  children.each(&:cancel)
  self
end

#cancelled?Boolean

Indicates whether cancellation has been requested.

Returns:

  • (Boolean)


44
45
46
# File 'lib/little_ghost/support/cancellation_token.rb', line 44

def cancelled?
  @mutex.synchronize { @cancelled }
end

#childObject

Creates a child cancelled automatically with this token.



23
# File 'lib/little_ghost/support/cancellation_token.rb', line 23

def child = self.class.new(parent: self)

#raise_if_cancelled!Object

Raises CancelledError when cancellation has been requested.

Raises:



49
50
51
# File 'lib/little_ghost/support/cancellation_token.rb', line 49

def raise_if_cancelled!
  raise CancelledError, "The run was cancelled" if cancelled?
end

#wait(timeout) ⇒ Object

Waits up to timeout seconds for cancellation.



54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/little_ghost/support/cancellation_token.rb', line 54

def wait(timeout)
  deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + Float(timeout)
  @mutex.synchronize do
    until @cancelled
      remaining = deadline - Process.clock_gettime(Process::CLOCK_MONOTONIC)
      break unless remaining.positive?

      @condition.wait(@mutex, remaining)
    end
    @cancelled
  end
end