Skip to content

Commit

Permalink
take the advantage of Thread.handle_interrupt
Browse files Browse the repository at this point in the history
  • Loading branch information
godfat committed Jan 8, 2015
1 parent f6da085 commit 6e67ab3
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 12 deletions.
31 changes: 21 additions & 10 deletions lib/rest-core/promise.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,6 @@ def future_response
def defer
if pool_size < 0 # negative number for blocking call
self.thread = Thread.current # set working thread
# set timeout after thread set, before yield (because yield is blocking)
env[TIMER].on_timeout{ cancel_task } if env[TIMER] # set timeout
protected_yield{ yield } # avoid any exception and do the job
else
backtrace = caller + self.class.backtrace
Expand All @@ -83,8 +81,6 @@ def defer
protected_yield{ yield }
end
end
# set timeout after thread/task set
env[TIMER].on_timeout{ cancel_task(backtrace) } if env[TIMER]
end
end

Expand Down Expand Up @@ -154,14 +150,29 @@ def rejecting error
# called in a new thread if pool_size == 0, otherwise from the pool
# i.e. requesting thread
def protected_yield
yield
rescue Exception => e # could be Timeout::Error
mutex.synchronize do
never_raise_yield do
env[TIMER].cancel if env[TIMER]
self.class.set_backtrace(e)
if env[TIMER]
Thread.handle_interrupt(env[TIMER].error => :never) do
timeout_protected_yield{ yield }
end
else
yield
end
rescue Exception => e
handle_exception(e)
end

def timeout_protected_yield
env[TIMER].on_timeout{ cancel_task } # set timeout
Thread.handle_interrupt(env[TIMER].error => :on_blocking) do
yield
end
ensure
env[TIMER].cancel
end

def handle_exception e
mutex.synchronize do
self.class.set_backtrace(e)
if done? # log user callback error
callback_error(e)
else # IOError, SystemCallError, etc
Expand Down
5 changes: 3 additions & 2 deletions lib/rest-core/timer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,17 @@ def initialize timeout, error, &block
self.timeout = timeout
self.error = error
self.block = block
start
start if block_given?
end

def on_timeout &block
self.block = block
start if block_given?
end

# should never raise!
def cancel
timer.cancel
timer.cancel if timer
self.block = nil
end

Expand Down

0 comments on commit 6e67ab3

Please sign in to comment.