[Anthy-dev 2422] Re: reentrant uim?

アーカイブの一覧に戻る

TOKUNAGA Hiroyuki tkng****@xem*****
2005年 9月 24日 (土) 23:07:54 JST


On Sat, 24 Sep 2005 14:16:32 +0900
YamaKen <yamak****@bp*****> wrote:

> ヤマケンです。
> 
> しばらく前から徳永さんがuimをthread safeにするための作業を行って
> らっしゃいますが、r1558のコードには疑問があったので一時的に
> revertさせてもらいました。
> 
> 問題を感じているのはuimを単にthread safeにするだけでなく
> reentrantにするという方針です。

私はthread safeとreentrantに関して、あまり深く考えずに使っています。
Thread safeであればそれで十分です。

> r1558のcommit logには"to make uim reentrant"とあり、
> UIM_EVAL_FSTRINGn_WITH_MUTEX()というmutex付きevalマクロが導入さ
> れています。しかし、uimの中核であるSchemeインタプリタは現在trunk 
> で使用されているSIODにしても近く導入予定のSigSchemeにしても
> reentrantではありません。よって、これを変えない限りはuimのC部分
> がいくらmutex lockの粒度を小さくしても肝心のScheme部分ですぐに待
> たされる事になり無意味です。

 libuimの関数は全て短時間で返ることが期待されるので、Thread safeにさえ
なれば、これ以上mutexの粒度を下げても大してメリットは無いと思っていま
す。というわけで、mutexの粒度を下げる予定はありません。というか、これで
うまくいったら、mutex回りはもういじりたくないです。

> このような事情から現在のuimではAPI関数毎にgiant lockをかけるのが
> 現実的な落としどころだと思いますし、徳永さんの日記でもそういった
> 意図でアドバイスをさせてもらいました。表現が悪くて伝わらなかった
> かもしれませんが。

 ThreadまわりはAPI関数毎にgiant lockをかける、というのはひとつのmutexを
libuim内部で共有する、という事でいいのでしょうか?そういう仮定で話を進め
ます。

この場合、uim_switch_imで問題が出てきます。uim_switch_imは
uim_reset_contextを呼びますが、uim_reset_contextは外部から呼ばれる可能性
があるので、API毎にロックをかけると、二重でロックしてしまうことになりま
す。

これを解決するには

 a. 再帰的なロックを使う
 b. staticなuim_reset_context_internalという関数を作り、uim_reset_context
    はロックをかけてからuim_reset_context_internalを呼ぶだけの関数にする

の2つの解決法が考えられますが、aは移植性に疑問を持ったので断念しました。
(LinuxではPTHREAD_MUTEX_RECURSIVEは#ifdef __USE_UNIX98でないと使えない
が、#define __USE_UNIX98するとコンパイルできなかった。かといって
FreeBSDではPTHREAD_MUTEX_RECURSIVE_NPは使えない。)実際にやってみたら、
Linux以外はFreeBSDのやりかたでいけるのかもしれませんが…。

他のソフトウェアはどうなっているのかも調べてみましたが、glibは再帰的な
ロックは自分でロックカウントを計算して実装していました。gaucheも
PTHREAD_MUTEX_RECURSIVEは使わず、ポートの再帰的なロックは自力での実装
になっていました。身近なアプリケーションではPTHREAD_MUTEX_RECURSIVEを
使っているものはみつけられなかったわけで、これも移植性に問題があるので
は、と私に疑わせている一因です。

 b. は個人的に気に入らないやり方なのでやりません。やるなら全ての関数で
やるべきだと思いますがそれはあまりに手間だし、uim_reset_contextだけ
別途非ロック版を用意するのは面白くない。

> [Anthy-dev 2337]のようにthread safeにする責任をlibuimより上の層
> に委ねるというのも一つの手ですが、私は上述のようなgiant lockぐら
> いならlibuimで提供してもよいと思います。ただしconfigure時の指定
> でthread safe版と通常版の両方をビルドできるようにし、ブリッジや
> プラットフォーム毎にどちらをリンクするか選択できるようにする必要
> はありますが(pthreadの存在検出だけでは不十分)。

[Anthy-dev 2337] は「単純なポインターの読み書きにロックをかける必要は無
い」という話で、thread safeにする責任については扱ってないと思うのです
が、「thread safeにする責任をlibuimより上の層に委ねる」というのはどうい
う事でしょうか?Bridge側でロックをかけるようにするとか?

それと、pthreadの存在検出だけでは不十分、というのは、どういう場合に問題
が起こるのでしょう?pthreadが存在する場合はそれをリンクするようにすれば
それで動作上は問題ない(シングルスレッドなアプリケーションでパフォーマン
スが少し無駄に落ちるだけ)ように思えます。

-- 
徳永拓之
tkng at xem jp



Anthy-dev メーリングリストの案内
アーカイブの一覧に戻る