Tcl8.3.4のソースコードで、マルチスレッド版のtclshとwishをビルドするには、
まず、Tcl coreを--enable-threadsオプションでconfigureしてmakeした後に、
tcltestとtktestをmakeします。
tcltest.exeとtktest.exeは、tclsh.exeとwish.exeのマルチスレッド版になります。
$ cd tcl8.3.4/win $ ./configure --enable-gcc --enable-threads $ make $ make tcltest.exe $ cd tk8.3.4/win $ ./configure --enable-gcc --enable-threads $ make $ make tktest.exe |
一方、Thread拡張をビルドするのも、configureをしてmakeするだけですが、
configureで生成されるMakefileが不完全のため、若干手直しが必要です。
手っ取り早く使いたい方は、TclアーカイブからThread2.2のバイナリが取れます。
package require Thread ::thread::create => 3308 |
スレッドが生成されるとスレッドIDが返却されます。
引数にスクリプトを指定すると、生成したスレッドでスクリプトを実行します。
package require Thread ::thread::create {set a 5} => 3309 |
スクリプトの実行が終わると、スレッドは破棄されます。
スクリプトの実行が終っても、スレッドを破棄したくなければ、
スレッドをイベント待ち状態にしておきます。
この時にvwaitを使ってもよいですが、waitコマンドが使えます。
package require Thread ::thread::create {set a 5; ::thread::wait} => 3310 |
別スレッドから待ち状態のスレッドにsendコマンドでスクリプトを送信できます。
sendコマンドの引数には、送信先のスレッドのスレッドIDとスクリプトを指定します。
通常、sendコマンドで送信したスクリプトの結果は同期して返却されます。
sendに-asyncオプションを付けると処理は非同期になり、スクリプトの結果は返却されません。
package require Thread ::thread::create {set a 5; ::thread::wait} => 3311 ::thread::send 3311 {set a} => 5 ::thread::send -async 3311 {set a} |
この例は、別スレッドから別スレッドの変数の値を参照しています。
全スレッドのスレッドIDを一覧するには、namesコマンドを使います。
package require Thread ::thread::names => 3308 3310 3311 |
スレッドが存在するかのチェックはexistsコマンドを使います。
スレッドIDで指定したスレッドが存在する場合は1を、それ以外は0が返却されます。
package require Thread ::thread::exists 3308 => 1 |
カレントスレッドのスレッドIDを取るには、idコマンドを使います。
package require Thread ::thread::id => 3307 |
スレッドを破棄するには、exitまたはunwindコマンドを使います。
(Thread 2.2から::thread::exitは::thread::unwindに変更されています)
package require Thread ::thread::create => 3312 ::thread::send 3312 {::thread::unwind} => target thread died |
createコマンドで生成したスレッドでスクリプトを実行中にエラーが発生し、
かつ、そのエラーがcatchで捕獲されていない場合、アプリが異常終了します。
スレッドで発生したエラーは、errorprocで指定したプロシジャで捕獲できます。
エラープロシジャを定義しておけば、アプリが異常終了するのを回避できます。
package require Thread proc myerrproc {id info} { puts stderr [list $id $info] } ::thread::errorproc myerrproc ::thread::create {hoge} => 3313 => 3313 {invalid command name "hoge" while executing "hoge"} |
エラープロシジャの引数は、エラーの発生したスレッドのスレッドIDとエラー情報になります。
この情報からスクリプトのバグを見つけ出すこともできるでしょう。
thread::joinとthread::transferは、Tcl8.4との組み合わせでないと使えません。
joinは、指定したスレッドが終了するまで呼び出しスレッドの実行を一時停止するコマンドです。
transferは、オープンしたファイルハンドルを別スレッドに転送するコマンドです。
その他、マニュアルに載っていないのですが、以下の様な
各スレッドで変数を共有して扱うための隠しコマンドがあります。
sv_condとsv_mutexは変数アクセスの排他制御をするためのコマンドです。
詳細は下記の参考文献を参照してください。説明は省略します。(^^;)
それ以外のsv_コマンドは、コマンド名から機能が創造できると思います。
sv_get, sv_lappend, sv_incr, sv_append, sv_set, sv_unset, sv_array, sv_cond, sv_mutex |
以下の例は各スレッドで変数を共有する例です。
共有する変数はすべて配列変数として扱い変数名と添え字名で指定します。
package require Thread ::thread::sv_set a 1 5 => 5 ::thread::create => 3314 ::thread::send 3314 {::thread::sv_set a 1} => 5 ::thread::send 3314 {::thread::sv_incr a 1} => 6 |