Slide 1

Slide 1 text

わりこまれるはなし [email protected] Ractorの中では限定的な操作しかできないぞ!の補足として話そうとしたが没にした

Slide 2

Slide 2 text

まとめ わりこまれたことを知るのは相当めんどくさいぞ 結局イベントループ的な構造が必要になるぞ イベントとかコールバックとかめんどくさいからスレッ ドにやらせればいいや!と思うかもしれないけど、その スレッドのためにイベントループが必要でなにも解決し ないぞ! 2

Slide 3

Slide 3 text

プログラムがわりこまれる? 実行中のプログラムがわりこまれるって なにか特別なイベントが発生したら 中断、変更、サービス開始... どうやって? 3

Slide 4

Slide 4 text

実行主体 プログラムが走ってるな!って感じるアレ コンテキストとかいうときもある? プロセス、スレッド、ファイバ(コルーチン) そういう概念あるでしょ? 4

Slide 5

Slide 5 text

昔のこと 1982 - 8bit PC(MZ-80系列) 1992 - RealTime OSとデバイスドライバ、pthread 1999 - dRuby 5

Slide 6

Slide 6 text

OSҎલ OSとかないころ

Slide 7

Slide 7 text

SHARP MZ-80 BASICのテキストだよ

Slide 8

Slide 8 text

BREAKキーとは! BASICインタプリタ ≒ REPL BREAKキーを押すとプログラムの実行を停止して、対話 モードに戻る BREAKキーに特別な能力があると信じていたがマシン語 で書いたサブルーチンは止まってくれない...なんでだ!? 当時BASICで書くと遅いルーチンはハンドアセンブルで 作ったサブルーチンをコールする、という宗派があった shでいうとCtrl-Cとか? 8

Slide 9

Slide 9 text

関西弁...

Slide 10

Slide 10 text

BREAK

Slide 11

Slide 11 text

BREAKキーの実装 実際にはこんな感じ!RUNすると構文木を処理するぞ 11 BREAK RUN

Slide 12

Slide 12 text

BREAKキーの実装 OPコードを一つ処理する 12 BREAK

Slide 13

Slide 13 text

BREAKキーの実装 BREAKキーが押されているか見る 13 BREAK

Slide 14

Slide 14 text

BREAKキーの実装 OPコードを一つ処理する 14 BREAK

Slide 15

Slide 15 text

BREAKキーの実装 また見る 15 BREAK

Slide 16

Slide 16 text

BREAKキーの実装 OPコードを一つ処理する 16 BREAK

Slide 17

Slide 17 text

BREAKキーの実装 また見る...押されてた!! 17 BREAK

Slide 18

Slide 18 text

BREAKキーの実装 実行やめてプロンプトへ戻る 18 BREAK READY _

Slide 19

Slide 19 text

処理の合間にキーを見る 処理を小さな単位に分けて、その合間にBREAKキーが押 されているか調べてる 都合のよいときにチラ見する→ポーリング これは割り込み機能がないからなの!? OSがあればこんな苦労しなくて良いのに(妄想 それはどうかな... 19

Slide 20

Slide 20 text

signal UNIXのケース 20

Slide 21

Slide 21 text

signal Ctrl-Cで停止させるのは? 止めてるのはOS側 じゃあプロセスがうけとるときは? 21 signal

Slide 22

Slide 22 text

signal シグナルがきた!実行主体は横取りされるぞ 22 signal

Slide 23

Slide 23 text

signal 割り込みサービスルーチン 本体とは別人格 async-signal-safe関数のみ preemptiveとかいう 23 signal

Slide 24

Slide 24 text

async-signal-safe 本体がどのような状態でも別人格に切り替わる mallocなどのメモリ管理中や再入可能でない関数の中、ト ランザクション的な処理の途中であっても別人格になる 本体を壊さないように限られた処理だけが許されている async-signal-safeと言われる操作だけだよ 「許されている」っていうのは約束を守れば動くけど、 守っていないことをコンパイラが教えてくれたりはしな いぞ みんなもシグナルハンドラでログを書いていた先人のコードで困ったことがあるはず 24

Slide 25

Slide 25 text

signal 割り込みサービスルーチン 本体とは別人格 async-signal-safe関数のみ 大域変数に遺言を残して終了 たいしたことはできないので、割り込まれたよーというメモを残して終わる 25 signal

Slide 26

Slide 26 text

signal 割り込みサービスルーチン 本体とは別人格 async-signal-safe関数のみ 大域変数に遺言を残して終了 本体は... 割り込まれたことを知らないので... 残されたメモを定期的に見に行くことに Rubyでsignalつかってもこういうことは身につかないかもしれん 26 signal

Slide 27

Slide 27 text

signal 割り込まれたときに気づけない 長いシステムコール中ならEINTR わかることもあるがわからないこともある 割り込まれたときに気づけないので、都合の良いときに メモがないか調べることになる なんらかのイベントループを構成しとく必要がある またか! 27

Slide 28

Slide 28 text

pthreadのcancel RubyでいうところのThread#killのはなし スレッドを任意の瞬間に止めることはできない malloc中とかトランザクション中とかさっきのasync- signal-safeと同じようなもの 次の都合のよいときに止まってくださいな pthread_cancel() cancel要求受けました、というメモをしておく 標準ライブラリは呼ばれたときにメモを見て自殺する めっちゃ使いにくい!! Rubyのスレッドは楽すぎて堕落する 28

Slide 29

Slide 29 text

select族が便利 シグナルハンドラやスレッド間の通信が必要な局面で socket_pairやpipeなどを用いるテクニックも多い FDとして扱える select族で多元待ちも簡単 一度に複数の事象を待てる select()使えるようになって歓喜した人たちがいた(旧世紀) 29

Slide 30

Slide 30 text

都合のよいときにメモを見る 割り込まれた!は自分で見る 確認する単位はいろいろ OSがあるとメモを効率よく書いてくれる でも本質的な形はかわらない 実行主体には割り込めない 30

Slide 31

Slide 31 text

「処理の合間に見る」を反転 チラ見するたびに処理をする イベントドリブンのスタイル 巧みに隠されているけどWebのJSとか コールバックを呼ぶ人はだれなのか?を想像しよう 31

Slide 32

Slide 32 text

コールバックめんどくさいから めんどくさいからマルチスレッドにしてみたー めんどくささは解決していない スレッド間通信もチラ見のループになる よくある勘違い 32

Slide 33

Slide 33 text

まとめ わりこまれたことを知るのは相当めんどくさいぞ 結局イベントループ的な構造が必要になるぞ イベントとかコールバックとかめんどくさいからスレッ ドにやらせればいいや!と思うかもしれないけど、その スレッドのためにイベントループが必要でなにも解決し ないぞ! 33