模块 Timeout

Timeout 长时间运行的代码块

概述

require 'timeout'
status = Timeout::timeout(5) {
  # Something that should be interrupted if it takes more than 5 seconds...
}

描述

Timeout 提供了一种方法,可以在潜在长时间运行的操作未在固定时间内完成时自动终止该操作。

以前的版本没有使用模块进行命名空间,但是为了向后兼容,提供了 timeout。您应该优先使用 Timeout.timeout

版权

© 2000 Network Applied Communication Laboratory, Inc.

版权

© 2000 Information-technology Promotion Agency, Japan

常量

VERSION

公共类方法

timeout(sec, klass = nil, message = nil) { |sec| ... } 点击切换源代码

在代码块中执行操作,如果该操作花费的时间超过 sec 秒,则引发错误。

sec

等待代码块终止的秒数。可以使用任何数字,包括浮点数来指定小数秒。值为 0 或 nil 将在没有任何超时的情况下执行代码块。

klass

Exception Class,如果代码块在 sec 秒内未能终止,则会引发该异常。省略将使用默认值 Timeout::Error

message

Error 消息,用于与 Exception Class 一起引发。省略将使用默认值“执行超时”。

如果代码块在 sec 秒之前完成,则返回代码块的结果,否则根据 klass 的值抛出异常。

用于终止给定代码块的抛出异常不能在代码块内部被捕获,除非显式给出 klass。但是,代码块可以使用 ensure 来防止处理异常。因此,此方法不能依赖于对不受信任的代码块强制执行超时。

如果定义了调度程序,它将用于通过调用 Scheduler#timeout_after 来处理超时。

请注意,这既是模块 Timeout 的方法,因此您可以将 include Timeout 添加到您的类中,使它们拥有 timeout 方法,同时也是一个模块方法,因此您可以直接调用它,例如 Timeout.timeout()

# File lib/timeout.rb, line 169
def timeout(sec, klass = nil, message = nil, &block)   #:yield: +sec+
  return yield(sec) if sec == nil or sec.zero?

  message ||= "execution expired"

  if Fiber.respond_to?(:current_scheduler) && (scheduler = Fiber.current_scheduler)&.respond_to?(:timeout_after)
    return scheduler.timeout_after(sec, klass || Error, message, &block)
  end

  Timeout.ensure_timeout_thread_created
  perform = Proc.new do |exc|
    request = Request.new(Thread.current, sec, exc, message)
    QUEUE_MUTEX.synchronize do
      QUEUE << request
      CONDVAR.signal
    end
    begin
      return yield(sec)
    ensure
      request.finished
    end
  end

  if klass
    perform.call(klass)
  else
    Error.handle_timeout(message, &perform)
  end
end

私有实例方法

timeout(sec, klass = nil, message = nil) { |sec| ... } 点击切换源代码

在代码块中执行操作,如果该操作花费的时间超过 sec 秒,则引发错误。

sec

等待代码块终止的秒数。可以使用任何数字,包括浮点数来指定小数秒。值为 0 或 nil 将在没有任何超时的情况下执行代码块。

klass

Exception Class,如果代码块在 sec 秒内未能终止,则会引发该异常。省略将使用默认值 Timeout::Error

message

Error 消息,用于与 Exception Class 一起引发。省略将使用默认值“执行超时”。

如果代码块在 sec 秒之前完成,则返回代码块的结果,否则根据 klass 的值抛出异常。

用于终止给定代码块的抛出异常不能在代码块内部被捕获,除非显式给出 klass。但是,代码块可以使用 ensure 来防止处理异常。因此,此方法不能依赖于对不受信任的代码块强制执行超时。

如果定义了调度程序,它将用于通过调用 Scheduler#timeout_after 来处理超时。

请注意,这既是模块 Timeout 的方法,因此您可以将 include Timeout 添加到您的类中,使它们拥有 timeout 方法,同时也是一个模块方法,因此您可以直接调用它,例如 Timeout.timeout()

# File lib/timeout.rb, line 169
def timeout(sec, klass = nil, message = nil, &block)   #:yield: +sec+
  return yield(sec) if sec == nil or sec.zero?

  message ||= "execution expired"

  if Fiber.respond_to?(:current_scheduler) && (scheduler = Fiber.current_scheduler)&.respond_to?(:timeout_after)
    return scheduler.timeout_after(sec, klass || Error, message, &block)
  end

  Timeout.ensure_timeout_thread_created
  perform = Proc.new do |exc|
    request = Request.new(Thread.current, sec, exc, message)
    QUEUE_MUTEX.synchronize do
      QUEUE << request
      CONDVAR.signal
    end
    begin
      return yield(sec)
    ensure
      request.finished
    end
  end

  if klass
    perform.call(klass)
  else
    Error.handle_timeout(message, &perform)
  end
end