Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Rubyでつくるスレッド

124 views

Published on

松江Ruby会議09の発表資料です。

Rubyでスレッドをつくってみました。

Published in: Engineering
  • Be the first to comment

  • Be the first to like this

Rubyでつくるスレッド

  1. 1. Rubyでつくる スレッド Shugo Maeda NaCl 2018-06-30
  2. 2. やりたいこと MinThread.start do 20.times do |i| puts "Thread#1: #{i}" sleep(0.1) end end MinThread.start do 20.times do |i| puts "Thread#2: #{i}" sleep(0.1) end end
  3. 3. 継続(Continuation) 次に実行される計算を表す グローバルgoto オブジェクトの状態は戻らない Ruby 1.8のスレッドの実装を利用 [ruby-dev:4083] 継続でスレッドをつくれるのでは?
  4. 4. わかる人にはわかる説明(1) Ruby 1.8のスレッドはsetjmp()/ longjmp()で切り替える スタックは自前で保存して書き戻す 継続も同じ仕組み
  5. 5. わかる人にはわかる説明(2) スレッド 並行宇宙 継続 世界線
  6. 6. 継続の例 require "continuation" callcc {|c| $cont = c} print "Hello, World!n" $cont.call
  7. 7. 実装
  8. 8. スレッドの作成 module MinThread QUEUE = [] def self.start(&block) QUEUE.push(block) end
  9. 9. スレッドの実行 def self.resume proc = QUEUE.shift if proc proc.call end end at_exit do MinThread.resume end
  10. 10. スレッドの切替 def self.pass callcc do |c| QUEUE.push(c) resume end end
  11. 11. 動いた! MinThread.start do 20.times do |i| puts "Thread#1: #{i}" sleep(0.1) MinThread.pass end end MinThread.start do 20.times do |i| puts "Thread#2: #{i}" sleep(0.1) MinThread.pass end end
  12. 12. でも何か違う MinThread.start do 20.times do |i| puts "Thread#1: #{i}" sleep(0.1) MinThread.pass # これが必要 end end MinThread.start do 20.times do |i| puts "Thread#2: #{i}" sleep(0.1) MinThread.pass # これが必要 end end
  13. 13. 勝手にスレッドを切り替えたい
  14. 14. TracePoint Ruby実行中のイベントをフック フックで切り替えればいいのでは?
  15. 15. 実装 at_exit do MinThread.set_next_switch_time TracePoint.trace(:line) do |tp| MinThread.schedule # 一定時間毎にThread.pass end MinThread.resume end
  16. 16. 1回しか切り替わらない!
  17. 17. 理由 フックの中ではTracePointが無効 化される フック中で継続を呼ぶと無効化され たまま
  18. 18. じゃあモンキーパッチで at_exit do MinThread.set_next_switch_time [Integer, String, Array, Hash, IO, File].each do |mod| mod.prepend Module.new { mod.instance_methods(false).each do |method| define_method(method) do |*args, &block| MinThread.schedule super(*args, &block) end end } end MinThread.resume end
  19. 19. デモ
  20. 20. 課題 IOなどでブロックすると全部止まる IO#readなどをノンブロッキングIOで再実 装すればいい
  21. 21. まとめ スレッドはつくれる

×