Gauche:MTとrequire
multi threadな場合にrequire/provideを実装するのが結構ややこしい。
とりあえず、複数のthreadから同じfeatureに対するrequireが来た場合に対応するには:
- provideされたfeatureのリストだけでなく、「requireされてload中」のfeatureの
リストもキープしておく (providing リスト)。
- requireはprovidingリストを見て、featureがprovidingであれば
その状態が変わるまでcondition variableで待つ。
一見、これだけで何とかなりそうだが、
requireの依存関係が循環しているとデッドロックになる可能性がある。
(もちろんそのような循環関係は不正なんだが、うっかりそのような状態に
入った時に止まるのではなくエラーにするようにしといたほうが良かろう)。
release 0.5.5での解決。load.c参照。
- システムは、globalな情報として以下のリストを持つ。
- provideされたfeatureのリスト (ldinfo.provided)
- 現在ロード中のfeatureと、それをロードしているスレッドのconsのリスト(ldinfo.providing)
- 要求されたfeatureがprovidingであるために待ちに入っているスレッドと、それが要求したfeatureのconsのリスト (ldinfo.waiting)
- あるfeatureがrequireされたら、以下のチェックを行う。
globalな情報へのアクセスは全てアトミックに行われる。
- まずldinfo.providedがサーチされる。
その中にfeatureが見つかればロードせずにreturn。
- そうでなければldinfo.providingをサーチ。そこにもfeatureが無ければ、
(cons <feature> (current-thread))をldinfo.providingにpushして、
ファイルをロードしに行く。
- そうでなければ、featureをprovidingしているthread -> がwaitingしているfeature -> がprovidingしているthread ... というチェインを辿って、
自分自身のthreadに出会うかどうか調べる。出会ったらrequireの依存関係に
ループがあるということなのでエラー。
- ループが無ければ、(cons (current-thread) <feature>) をldinfo.waiting
にpushしてprovidingが変化するcondition variableを待つ。
- んで、loadが正常終了するか異常終了するかしたらldinfo.providingから
自分のエントリを削除してcondition variableをsignal。
Last modified : 2002/05/25 09:15:08 UTC