module Is::Async

public

Makes objects async-aware.

Public Instance Methods

async() { || ... } click to toggle source
public

Call behavior asychronously, returning a future.

# File lib/is/async.rb, line 14
def async
  if block_given?
    task = ::Async::Reactor.run { |current|
      begin
        yield
      ensure
        current.yield
      end
    }

    Core::Async::Future.new(task)
  else
    Core::Async::Wrapper.new(self)
  end
end

Private Instance Methods

await() { || ... } click to toggle source
public

Call behavior synchronously but within an async context, waiting on the result.

# File lib/is/async.rb, line 32
        def await
  if (task = ::Async::Task.current?)
    reference = task.async { |current|
      begin
        yield
      ensure
        current.yield
      end
    }

    wait_all(reference)
  else
    ::Async::Reactor.run { |task|
      async {
        yield
      }.result
    }.wait
  end
rescue UncaughtThrowError => error
  throw error.tag, error.value
end
aware() { || ... } click to toggle source
public

Call behavior within an async context without additional nesting.

# File lib/is/async.rb, line 56
        def aware
  if ::Async::Task.current?
    yield
  else
    await do
      yield
    end
  end
end
cancel() click to toggle source
public

Cancels the current async behavior if in progress.

# File lib/is/async.rb, line 108
        def cancel
  if (task = ::Async::Task.current?)
    task.stop
  end
end
defer() click to toggle source
public

Yields control to allow other fibers to execute.

# File lib/is/async.rb, line 100
        def defer
  if (task = ::Async::Task.current?)
    task.yield
  end
end
internal_async() { |task| ... } click to toggle source
# File lib/is/async.rb, line 125
        def internal_async
  ::Async::Reactor.run do |task|
    yield task
  end
end
internal_await() { |task| ... } click to toggle source
# File lib/is/async.rb, line 131
        def internal_await
  if (task = ::Async::Task.current?)
    reference = task.async {
      yield task
    }

    wait_all(reference)
  else
    ::Async::Reactor.run { |task|
      yield task
    }.wait
  end
end
resolve(value) click to toggle source
public

Resolves a potential future to a final result.

# File lib/is/async.rb, line 116
        def resolve(value)
  case value
  when Core::Async::Future
    value.result
  else
    value
  end
end
sleep(seconds) click to toggle source
public

Sleeps for `seconds` in a proper async context.

# File lib/is/async.rb, line 68
        def sleep(seconds)
  internal_await do |task|
    task.sleep(seconds)
  end
end
timeout(seconds) { || ... } click to toggle source
public

Call asynchonous behavior in a proper async context, wrapped in a timeout.

Raises `Core::Async::Timeout` if execution exceeds `seconds`.

# File lib/is/async.rb, line 78
        def timeout(seconds)
  internal_await do |task|
    timed_task = internal_async {
      yield
    }

    if seconds && seconds > 0
      task.with_timeout(seconds, Core::Async::Timeout) do
        timed_task.wait
      end
    else
      timed_task.wait
    end
  ensure
    timed_task&.stop
  end
rescue UncaughtThrowError => error
  throw error.tag, error.value
end
wait_all(task) click to toggle source
# File lib/is/async.rb, line 145
        def wait_all(task)
  task.children&.each do |child|
    wait_all(child)
  end

  task.wait
end