PageRenderTime 26ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/maglevdns/stoppablethread.rb

https://github.com/dlitz/maglevdns
Ruby | 66 lines | 37 code | 8 blank | 21 comment | 2 complexity | 6d22b1c99e2c495a901ff4dd07d2b7c1 MD5 | raw file
  1. #--
  2. # MaglevDNS
  3. # Copyright (c) 2009 Dwayne C. Litzenberger <dlitz@dlitz.net>
  4. #
  5. # This program is free software: you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation, either version 3 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. #++
  18. require 'thread'
  19. module MaglevDNS
  20. class StoppableThread < ::Thread
  21. def initialize
  22. @mutex = ::Mutex.new
  23. @stop_requested = false
  24. @stop_pipe_r, @stop_pipe_w = ::IO::pipe # pipe used for breaking out of select() calls
  25. thread_stopper = Thread.current[:thread_stopper]
  26. thread_stopper.add_thread!(self)
  27. thread_stopper.prune!
  28. raise "BUG: #{self.class.name}#alive? returned false" unless self.alive?
  29. super() do
  30. begin
  31. # Inherit ThreadStopper instance from parent thread
  32. Thread.current[:thread_stopper] = thread_stopper
  33. # Invoke thread_main
  34. catch(:STOP_THREAD) { thread_main }
  35. ensure
  36. @stop_pipe_r.close
  37. @stop_pipe_r = nil
  38. end
  39. end
  40. end
  41. # Ask the thread to exit
  42. def request_stop
  43. @mutex.synchronize {
  44. @stop_requested = true
  45. @stop_pipe_w.close unless @stop_pipe_w.closed? # send a 'signal' to the thread
  46. yield if block_given?
  47. }
  48. end
  49. # Throw :STOP_THREAD if request_stop has been called.
  50. def check_stop
  51. @mutex.synchronize { throw :STOP_THREAD if @stop_requested }
  52. end
  53. protected
  54. def thread_main
  55. raise "thread_main not implemented"
  56. end
  57. end
  58. end