Rabbit Slide Show

Rubyでつくるスレッド

Description

* [スライド原稿](implement-thread-in-ruby.md) * [スライドPDF](pdf/MatsueRubyKaigi09-implement-thread-in-ruby.pdf) * [ベース実装](minthread.rb) * [TracePoint版実装](minthread2.rb) * [モンキーパッチ版実装](minthread3.rb)

Text

Page: 1

Rubyでつくる
スレッド
Shugo Maeda
NaCl
2018-06-30

Page: 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

Page: 3

継続(Continuation)
次に実行される計算を表す
グローバルgoto
オブジェクトの状態は戻らない
Ruby 1.8のスレッドの実装を利用
[ruby-dev:4083]
継続でスレッドをつくれるのでは?

Page: 4

わかる人にはわかる説明(1)
Ruby 1.8のスレッドはsetjmp()/
longjmp()で切り替える
スタックは自前で保存して書き戻す
継続も同じ仕組み

Page: 5

わかる人にはわかる説明(2)
スレッド
継続
並行宇宙
世界線

Page: 6

継続の例
require "continuation"
callcc {|c| $cont = c}
print "Hello, World!\n"
$cont.call

Page: 7

実装

Page: 8

スレッドの作成
module MinThread
QUEUE = []
def self.start(&block)
QUEUE.push(block)
end

Page: 9

スレッドの実行
def self.resume
proc = QUEUE.shift
if proc
proc.call
end
end
at_exit do
MinThread.resume
end

Page: 10

スレッドの切替
def self.pass
callcc do |c|
QUEUE.push(c)
resume
end
end

Page: 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

Page: 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

Page: 13

勝手にスレッドを切り替えたい

Page: 14

TracePoint
Ruby実行中のイベントをフック
フックで切り替えればいいのでは?

Page: 15

実装
at_exit do
MinThread.set_next_switch_time
TracePoint.trace(:line) do |tp|
MinThread.schedule # 一定時間毎に Thread.pass
end
MinThread.resume
end

Page: 16

1回しか切り替わらない!

Page: 17

理由
フックの中ではTracePointが無効
化される
フック中で継続を呼ぶと無効化され
たまま

Page: 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

Page: 19

デモ

Page: 20

課題
IOなどでブロックすると全部止まる
IO#readなどをノンブロッキングIOで再実
装すればいい

Page: 21

まとめ
スレッドはつくれる

Other slides