Created
December 11, 2011 11:08
-
-
Save ileitch/1459987 to your computer and use it in GitHub Desktop.
Interruptible sleep in Ruby
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module InterruptibleSleep | |
def interruptible_sleep(seconds) | |
@_sleep_check, @_sleep_interrupt = IO.pipe | |
IO.select([@_sleep_check], nil, nil, seconds) | |
end | |
def interrupt_sleep | |
@_sleep_interrupt.close if @_sleep_interrupt | |
end | |
end | |
class Test | |
include InterruptibleSleep | |
def start | |
puts "start" | |
interruptible_sleep 10 | |
puts "sleep interrupted!" | |
end | |
def stop | |
puts "stop" | |
interrupt_sleep | |
end | |
end | |
test = Test.new | |
Signal.trap('SIGINT') { test.stop } | |
test.start |
Fwiw, the pattern here with the IO pipes appears to break on macs when they wake up from sleep. I don't know what causes it, but the app will get stuck reading from the pipe indefinitely and need to be killed. This is a different way of accomplishing the same thing that does not use pipes:
class InterruptibleSleeper
def sleep(seconds)
@sleeper = Thread.current
Kernel.sleep seconds
end
def interrupt_sleep
Thread.new { @sleeper&.run }
end
end
This assumes that the thread that started the sleeping is still alive always, but additional safeguards could be put in place if that's an iffy thing.
This relies on the fact that Thread#run
wakes threads up from sleep if another thread tells them to run.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
In case if somebody wants to stop threads: