Class: WEBrick::Utils::TimeoutHandler

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
lib/webrick/utils.rb

Overview

Class used to manage timeout handlers across multiple threads.

Timeout handlers should be managed by using the class methods which are synchronized.

id = TimeoutHandler.register(10, Timeout::Error)
begin
  sleep 20
  puts 'foo'
ensure
  TimeoutHandler.cancel(id)
end

will raise Timeout::Error

id = TimeoutHandler.register(10, Timeout::Error)
begin
  sleep 5
  puts 'foo'
ensure
  TimeoutHandler.cancel(id)
end

will print 'foo'

Constant Summary collapse

TimeoutMutex =

Mutex used to synchronize access across threads

Mutex.new

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeTimeoutHandler

Creates a new TimeoutHandler. You should use ::register and ::cancel instead of creating the timeout handler directly.


161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/webrick/utils.rb', line 161

def initialize
  @timeout_info = Hash.new
  Thread.start{
    while true
      now = Time.now
      @timeout_info.keys.each{|thread|
        ary = @timeout_info[thread]
        next unless ary
        ary.dup.each{|info|
          time, exception = *info
          interrupt(thread, info.object_id, exception) if time < now
        }
      }
      sleep 0.5
    end
  }
end

Class Method Details

.cancel(id) ⇒ Object

Cancels the timeout handler id


152
153
154
155
156
# File 'lib/webrick/utils.rb', line 152

def TimeoutHandler.cancel(id)
  TimeoutMutex.synchronize{
    instance.cancel(Thread.current, id)
  }
end

.register(seconds, exception) ⇒ Object

Registers a new timeout handler

time

Timeout in seconds

exception

Exception to raise when timeout elapsed


144
145
146
147
148
# File 'lib/webrick/utils.rb', line 144

def TimeoutHandler.register(seconds, exception)
  TimeoutMutex.synchronize{
    instance.register(Thread.current, Time.now + seconds, exception)
  }
end

Instance Method Details

#cancel(thread, id) ⇒ Object

Cancels the timeout handler id


202
203
204
205
206
207
208
209
210
211
# File 'lib/webrick/utils.rb', line 202

def cancel(thread, id)
  if ary = @timeout_info[thread]
    ary.delete_if{|info| info.object_id == id }
    if ary.empty?
      @timeout_info.delete(thread)
    end
    return true
  end
  return false
end

#interrupt(thread, id, exception) ⇒ Object

Interrupts the timeout handler id and raises exception


181
182
183
184
185
186
187
# File 'lib/webrick/utils.rb', line 181

def interrupt(thread, id, exception)
  TimeoutMutex.synchronize{
    if cancel(thread, id) && thread.alive?
      thread.raise(exception, "execution timeout")
    end
  }
end

#register(thread, time, exception) ⇒ Object

Registers a new timeout handler

time

Timeout in seconds

exception

Exception to raise when timeout elapsed


194
195
196
197
198
# File 'lib/webrick/utils.rb', line 194

def register(thread, time, exception)
  @timeout_info[thread] ||= Array.new
  @timeout_info[thread] << [time, exception]
  return @timeout_info[thread].last.object_id
end