tooから引っ越し2017-05-18BartenderのAPIで練習するFiberの使い方Fiberの使い道を考えるために、selectと組み合わせて処理を単純に記述できる(のではないか、ということを確かめるために)部品を作ってみました。FiberselectのラッパーまずFiberと関係ない部分です。selectの簡単なラッパーです。今後、Ruby本体にもっと良いものが載り、このレイヤーは後で捨てられるだろう、と考えています。:write)とfdに、コールバックを登録します。一つの組みに、一つのコールバックだけ登録できます。endendXtのころの経験から一つの事象に一つだけコールバックを登録できるようにしました。複数でもいいんだけど、複数入れられるものはこの上に被せれば良いだろうから、コア部分は一つだけにしました。複数登録できる場合の発火する順序などにまつわるイヤなバグの思い出があったので、アプリケーション層で管理してもらう方がいいかなって判断しました。サーバーのコールバックは次のように登録します。context.runFiberと組み合わせたAPIそれぞれのコールバックにFiber.current.method(:resume)を与えることで、Fiberの実行権をブロックしそうな時に手放すことができるだろう、というのを確認するAPIです。sec秒間、止まります。スレッドは止まらず、別のFiberが実行されます。writableになるまで止まります。スレッドは止まらず、別のFiberが実行されます。timeoutがあるwait_ioです。ブロッキング風、ノンブロッキングなreadです。ブロッキング風、ノンブロッキングなwriteです。endendしつこいけど、sleepの実装を説明します。sleepはalarmでできています。end2行でできています。sec秒後にFiber.current.method(:resume)を呼ぶようにalarmを登録します。Fiber.yieldで実行権を手放します。時刻を過ぎたらresumeが呼ばれて、yieldしところから再開します。結果、sec秒間止まることができます。その他のAPIの実装もほとんど一緒です。sleepは後から作ったから)なので、そのうちtimeoutが指定できるようにするかもしれません。最後に、この中で一番長いwait_io_timeoutを説明します。自信がないAPIです。endsleepと同様にalarmを設定します。fd]の組みにresumeを登録Fiber.yieldします。戻り値が:timeoutだったら例外を発生させますensureでそれぞれのコールバックを削除します。alarmのコールバックは発火した後は削除されるのだけど、IO待ちのコールバックで再開したあとに、またalarmのコールバックが発生すると困るので明示的に削除してます。削除してあったら何も起きないので雑にdelete_alarmしてます。スレッドだったら、IO待ち起因のコールバックとalarm起因のコールバックが同時に発生したらどうしよう、とか、イベント取り外し中にいやなこと起きないかなあ、とか、心配するところですが、Fiberだから大丈夫。あわせて読みたいパーフェクトRubyの改訂版でもFiberの記述は増えていないとのこと。dRubyサーバーの説明こわいのでタイトルからFiberを抜いてみました。注目記事リンクgithubウィッシュリスト待ってます最新記事n月刊ラムダノートに寄稿しました。gemを動くようにした話(誰か引き取って月別アーカイブはてなブログをはじめよう!m_sekiさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。