]>
git.saurik.com Git - redis.git/blob - client-libraries/ruby/lib/better_timeout.rb
8 # Copyright - (C) 2008 Evan Phoenix
9 # Copyright:: (C) 2000 Network Applied Communication Laboratory, Inc.
10 # Copyright:: (C) 2000 Information-technology Promotion Agency, Japan
16 # A way of performing a potentially long-running operation in a thread, and
17 # terminating it's execution if it hasn't finished within fixed amount of
20 # Previous versions of timeout didn't use a module for namespace. This version
21 # provides both Timeout.timeout, and a backwards-compatible #timeout.
26 # status = Timeout::timeout(5) {
27 # # Something that should be interrupted if it takes too much time...
36 # Raised by Timeout#timeout when the block times out.
41 # A mutex to protect @requests
44 # All the outstanding TimeoutRequests
47 # Represents +thr+ asking for it to be timeout at in +secs+
48 # seconds. At timeout, raise +exc+.
50 def initialize(secs
, thr
, exc
)
56 attr_reader
:thread, :left
58 # Called because +time+ seconds have gone by. Returns
59 # true if the request has no more time left to run.
65 # Raise @exception if @thread.
67 if @thread and @thread.alive
?
68 @thread.raise @exception, "execution expired"
74 # Abort this request, ie, we don't care about tracking
82 def self.add_timeout(time
, exc
)
84 @controller ||= Thread
.new
do
94 min
= @requests.min
{ |a
,b
| a
.left
<=> b
.left
}
97 slept_for
= sleep(min
.left
)
100 @requests.delete_if
do |r
|
101 if r
.elapsed(slept_for
)
113 req
= TimeoutRequest
.new(time
, Thread
.current
, exc
)
115 @mutex.synchronize
do
125 # Executes the method's block. If the block execution terminates before +sec+
126 # seconds has passed, it returns true. If not, it terminates the execution
127 # and raises +exception+ (which defaults to Timeout::Error).
129 # Note that this is both a method of module Timeout, so you can 'include
130 # Timeout' into your classes so they have a #timeout method, as well as a
131 # module method, so you can call it directly as Timeout.timeout().
133 def timeout(sec
, exception
=Error
)
134 return yield if sec
== nil or sec
.zero
?
135 raise ThreadError
, "timeout within critical session" if Thread
.critical
137 req
= Timeout
.add_timeout sec
, exception
146 module_function
:timeout
153 # Timeout::timeout(n, e, &block).
155 # Defined for backwards compatibility with earlier versions of timeout.rb, see
158 def timeout(n
, e
=Timeout
::Error, &block
) # :nodoc:
159 Timeout
::timeout(n
, e
, &block
)
163 # Another name for Timeout::Error, defined for backwards compatibility with
164 # earlier versions of timeout.rb.
166 TimeoutError
= Timeout
::Error # :nodoc:
172 p
timeout(5, TimeoutError
) {