Skip to content

Commit

Permalink
Add signature of Timeout
Browse files Browse the repository at this point in the history
  • Loading branch information
m11o committed Feb 2, 2021
1 parent 590bac7 commit dfc3dcd
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 0 deletions.
94 changes: 94 additions & 0 deletions stdlib/timeout/0/timeout.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Timeout long-running blocks
#
# ## Synopsis
#
# require 'timeout'
# status = Timeout::timeout(5) {
# # Something that should be interrupted if it takes more than 5 seconds...
# }
#
# ## Description
#
# Timeout provides a way to auto-terminate a potentially long-running operation
# if it hasn't finished in a fixed amount of time.
#
# Previous versions didn't use a module for namespacing, however #timeout is
# provided for backwards compatibility. You should prefer Timeout.timeout
# instead.
#
# ## Copyright
#
# Copyright
# : (C) 2000 Network Applied Communication Laboratory, Inc.
# Copyright
# : (C) 2000 Information-technology Promotion Agency, Japan
#
module Timeout
# Perform an operation in a block, raising an error if it takes longer than
# `sec` seconds to complete.
#
# `sec`
# : Number of seconds to wait for the block to terminate. Any number may be
# used, including Floats to specify fractional seconds. A value of 0 or
# `nil` will execute the block without any timeout.
# `klass`
# : Exception Class to raise if the block fails to terminate in `sec` seconds.
# Omitting will use the default, Timeout::Error
# `message`
# : Error message to raise with Exception Class. Omitting will use the
# default, "execution expired"
#
#
# Returns the result of the block **if** the block completed before `sec`
# seconds, otherwise throws an exception, based on the value of `klass`.
#
# The exception thrown to terminate the given block cannot be rescued inside the
# block unless `klass` is given explicitly. However, the block can use ensure to
# prevent the handling of the exception. For that reason, this method cannot be
# relied on to enforce timeouts for untrusted blocks.
#
# Note that this is both a method of module Timeout, so you can `include
# Timeout` into your classes so they have a #timeout method, as well as a module
# method, so you can call it directly as Timeout.timeout().
#
# # arglists 💪👽🚨 << Delete this section
# timeout(sec, klass = nil, message = nil) { |sec| ... }
#
def self.timeout: (Numeric? sec, ?singleton(Exception) klass, ?String message) { (Numeric sec) -> untyped } -> untyped

private

# Perform an operation in a block, raising an error if it takes longer than
# `sec` seconds to complete.
#
# `sec`
# : Number of seconds to wait for the block to terminate. Any number may be
# used, including Floats to specify fractional seconds. A value of 0 or
# `nil` will execute the block without any timeout.
# `klass`
# : Exception Class to raise if the block fails to terminate in `sec` seconds.
# Omitting will use the default, Timeout::Error
# `message`
# : Error message to raise with Exception Class. Omitting will use the
# default, "execution expired"
#
#
# Returns the result of the block **if** the block completed before `sec`
# seconds, otherwise throws an exception, based on the value of `klass`.
#
# The exception thrown to terminate the given block cannot be rescued inside the
# block unless `klass` is given explicitly. However, the block can use ensure to
# prevent the handling of the exception. For that reason, this method cannot be
# relied on to enforce timeouts for untrusted blocks.
#
# Note that this is both a method of module Timeout, so you can `include
# Timeout` into your classes so they have a #timeout method, as well as a module
# method, so you can call it directly as Timeout.timeout().
#
# # arglists 💪👽🚨 << Delete this section
# timeout(sec, klass = nil, message = nil) { |sec| ... }
#
def timeout: (Numeric? sec, ?singleton(Exception) klass, ?String message) { (Numeric sec) -> untyped } -> untyped
end

Timeout::VERSION: String
41 changes: 41 additions & 0 deletions test/stdlib/Timeout_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
require_relative "test_helper"
require "timeout"
require "bigdecimal"

class TimeoutSingletonTest < Test::Unit::TestCase
include TypeAssertions

library "timeout"
testing "singleton(::Timeout)"

class TimeoutTestException < Exception; end # exception class for test

def test_timeout
proc = Proc.new { |sec| sec * sec }
assert_send_type "(::Integer sec) { (::Integer sec) -> untyped } -> untyped",
Timeout, :timeout, 5, &proc
assert_send_type "(::Float sec) { (::Float sec) -> untyped } -> untyped",
Timeout, :timeout, 1.2, &proc
assert_send_type "(::Rational sec) { (::Rational sec) -> untyped } -> untyped",
Timeout, :timeout, Rational(5, 3), &proc
assert_send_type "(::BigDecimal sec) { (::BigDecimal sec) -> untyped } -> untyped",
Timeout, :timeout, BigDecimal("1.123456789123456789"), &proc

hard_process = Proc.new { _calc_pi }
refute_send_type "(::Numeric sec) { (::Numeric sec) -> untyped } -> untyped",
Timeout, :timeout, 0.001, &hard_process
refute_send_type "(::Numeric sec, singleton(Exception) klass) { (::Numeric sec) -> untyped } -> untyped",
Timeout, :timeout, 0.001, TimeoutTestException, &hard_process
refute_send_type "(::Numeric sec, singleton(Exception) klass, String message) { (::Numeric sec) -> untyped } -> untyped",
Timeout, :timeout, 0.001, TimeoutTestException, "timeout test error", &hard_process
end

def _calc_pi
min = [0, 0]
loop do
x = rand
y = rand
x**2 + y**2 < 1.0 ? min[0] += 1 : min[1] += 1
end
end
end

0 comments on commit dfc3dcd

Please sign in to comment.