Skip to content

Instantly share code, notes, and snippets.

@jballanc
Created July 13, 2010 03:14
Show Gist options
  • Save jballanc/473410 to your computer and use it in GitHub Desktop.
Save jballanc/473410 to your computer and use it in GitHub Desktop.
diff --git a/lib/timeout.rb b/lib/timeout.rb
index 297b769..8399639 100644
--- a/lib/timeout.rb
+++ b/lib/timeout.rb
@@ -40,21 +40,22 @@ module Timeout
# 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().
- def timeout(sec, klass = nil) #:yield: +sec+
+ def timeout(sec, klass = nil, &block) #:yield: +sec+
return yield(sec) if sec == nil or sec.zero?
exception = klass || Class.new(ExitException)
begin
- x = Thread.current
- y = Thread.start {
- begin
- sleep sec
- rescue => e
- x.raise e
- else
- x.raise exception, "execution expired" if x.alive?
+ @t = @ret = nil
+ @s = Dispatch::Semaphore.new(0)
+
+ Dispatch::Queue.concurrent.async do
+ @t = Thread.new do
+ @ret = block.call(sec)
+ @s.signal
end
- }
- return yield(sec)
+ end
+ raise exception, "execution expired" if not @s.wait(sec)
+ return @ret
+
rescue exception => e
rej = /\A#{Regexp.quote(__FILE__)}:#{__LINE__-4}\z/o
(bt = e.backtrace).reject! {|m| rej =~ m}
@@ -67,9 +68,8 @@ module Timeout
# would be expected outside.
raise Error, e.message, e.backtrace
ensure
- if y and y.alive?
- y.kill
- y.join # make sure y is dead.
+ if @t and @t.alive?
+ @t.kill
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment