Sha256: fd0e675b4f68215a63e14b6b461154a5d2c5d0c9858125087f3b6083f9b3e4a8

Contents?: true

Size: 1.14 KB

Versions: 6

Compression:

Stored size: 1.14 KB

Contents

# frozen_string_literal: true

export_default :CancelScope

require 'fiber'

Exceptions = import('./exceptions')

# A cancellation scope that can be used to cancel an asynchronous task
class CancelScope
  def initialize(opts = {})
    @opts = opts
    @error_class = @opts[:mode] == :cancel ? Exceptions::Cancel : Exceptions::MoveOn
  end

  def cancel!
    @cancelled = true
    @fiber.cancelled = true
    @fiber.transfer @error_class.new(self, @opts[:value])
  end

  def start_timeout
    @timeout = EV::Timer.new(@opts[:timeout], 0)
    @timeout.start { cancel! }
  end

  def reset_timeout
    @timeout.reset
  end

  def disable
    @timeout&.stop
  end

  def call
    start_timeout if @opts[:timeout]
    @fiber = Fiber.current
    @fiber.cancelled = nil
    yield self
  rescue Exceptions::MoveOn => e
    e.scope == self ? e.value : raise(e)
  ensure
    @timeout&.stop
    protect(&@when_cancelled) if @cancelled && @when_cancelled
  end

  def when_cancelled(&block)
    @when_cancelled = block
  end

  def cancelled?
    @cancelled
  end

  def protect(&block)
    @fiber.cancelled = false
    block.()
  ensure
    @fiber.cancelled = @cancelled
  end
end

Version data entries

6 entries across 6 versions & 1 rubygems

Version Path
polyphony-0.19 lib/polyphony/core/cancel_scope.rb
polyphony-0.17 lib/polyphony/core/cancel_scope.rb
polyphony-0.16 lib/polyphony/core/cancel_scope.rb
polyphony-0.15 lib/polyphony/core/cancel_scope.rb
polyphony-0.14 lib/polyphony/core/cancel_scope.rb
polyphony-0.13 lib/polyphony/core/cancel_scope.rb