模块 Gem::Timeout

Timeout 用于处理长时间运行的代码块

概要

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

描述

Gem::Timeout 提供了一种方法,用于在固定时间内未完成的情况下自动终止可能长时间运行的操作。

版权

© 2000 Network Applied Communication Laboratory, Inc.

版权

© 2000 Information-technology Promotion Agency, Japan

常量

VERSION

版本

公共类方法

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

在一个代码块中执行操作,如果该操作耗时超过 sec 秒,则抛出一个错误。

sec

等待代码块终止的秒数。可以使用任何非负数或 nil,包括指定小数秒的浮点数。值为 0 或 nil 将执行代码块而不设置任何超时。任何负数都将引发 ArgumentError。

klass

如果代码块未能在 sec 秒内终止,则抛出 Exception 类。省略时将使用默认值,Gem::Timeout::Error

message

Exception 类一起抛出的 Error 消息。省略时将使用默认值,“执行已过期”。

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

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

如果定义了调度器,则将通过调用 Scheduler#timeout_after 来处理超时。

请注意,这既是模块 Gem::Timeout 的方法,因此您可以将 include Gem::Timeout 包含到您的类中,使其具有一个 timeout 方法,并且它也是一个模块方法,因此您可以直接将其作为 Gem::Timeout.timeout() 调用。

# File rubygems/vendor/timeout/lib/timeout.rb, line 167
def timeout(sec, klass = nil, message = nil, &block)   #:yield: +sec+
  return yield(sec) if sec == nil or sec.zero?
  raise ArgumentError, "Timeout sec must be a non-negative number" if 0 > sec

  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

  Gem::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

等待代码块终止的秒数。可以使用任何非负数或 nil,包括指定小数秒的浮点数。值为 0 或 nil 将执行代码块而不设置任何超时。任何负数都将引发 ArgumentError。

klass

如果代码块未能在 sec 秒内终止,则抛出 Exception 类。省略时将使用默认值,Gem::Timeout::Error

message

Exception 类一起抛出的 Error 消息。省略时将使用默认值,“执行已过期”。

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

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

如果定义了调度器,则将通过调用 Scheduler#timeout_after 来处理超时。

请注意,这既是模块 Gem::Timeout 的方法,因此您可以将 include Gem::Timeout 包含到您的类中,使其具有一个 timeout 方法,并且它也是一个模块方法,因此您可以直接将其作为 Gem::Timeout.timeout() 调用。

# File rubygems/vendor/timeout/lib/timeout.rb, line 167
def timeout(sec, klass = nil, message = nil, &block)   #:yield: +sec+
  return yield(sec) if sec == nil or sec.zero?
  raise ArgumentError, "Timeout sec must be a non-negative number" if 0 > sec

  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

  Gem::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