[前へ] [目次へ] [次へ]

スレッド


FGESのスレッドはソフトウェアスレッドとして実装されており、
ネイティブレベルではシングルスレッドで動作します。

●スケジューリング

FGES VMはあくまでホストプログラムの下で動作するため、
FGESスレッドの実行もホストプログラム側から呼び出された場合のみ行い、
規定時間の実行後中断してホストプログラム側に処理が戻されます。
(コンソール版FGESではホストプログラム側はひたすらFGESスレッドを
実行するようになっており、他の言語と同じような動作をします)

また、スレッドスケジューリングについてもホストプログラム側で制御できます。
デフォルトのスレッドスケジューリングを使用する場合、
優先度の高いものから順に実行され、規定時間が過ぎると一時停止されます。
優先度の低いFGESスレッドはより優先度の高いFGESスレッドが動作していると
いつまでも実行されなくなる可能性があることに注意してください。
また、優先度0のスレッドはマニュアルスレッドと定義されており、
スレッドハンドルから Execute を呼び出されるか、
C++レベルで FGESThread::ThreadExec を呼び出されない限り実行されません。

マニュアルスレッドにタスク(実行待ちの処理)がある状態でそのスレッドへの全てのハンドルを消滅させた場合、
そのマニュアルスレッドのタスクを完了する手段がなくなり、リソースリークとなります。
マニュアルスレッドのハンドルを消滅させる場合はスレッドのタスクに注意してください。

●スレッド制御

FGESのスレッドは一般的なスレッドの仕組みとは以下の点で異なります。
●スレッドの作成時にスタートアップルーチンを指定しない
   FGESスレッドは何も実行していない状態で作成されます。
●何も実行していなくてもスレッドは消えない
   FGESスレッドは何も実行していなくても消滅しません。
   FGESスレッドは参照カウント方式で管理されており、
   そのFGESスレッドを示すスレッドハンドルが全て消滅し、
   FGESスレッドが何も実行していない状態になって初めて消滅します。
●スレッドハンドルを使って他のスレッドコンテキストでメソッドを呼び出せる
   スレッドハンドルから Call を呼び出すことにより、
   対象のスレッドコンテキストでメソッドを呼び出すことが出来ます。
   対象のスレッドが何か実行していた場合、割り込みのように動作します。
   この方法で呼び出したメソッドの戻り値を受け取ることはできません。
   また、メソッドの実行はスレッドが切り替わるまで開始されないので、
   一時オブジェクトやローカル変数をスレッド越しに引数として渡すと
   実行開始時点で既に消滅しており例外が発生するので注意が必要です。
●自スレッドの時間を使って他のスレッドを駆動できる
   スレッドハンドルから Execute を呼び出すことにより、
   自スレッドに割り当てられた実行時間を使って対象のスレッドを実行できます。
   マニュアルスレッドはこの方法でなければ実行されません。
   また、この方法であれば確実に指定したスレッドを実行できるので、
   スレッド間の関係に起因する問題をある程度制御できます。
   ただし、この方法で実行すると例外発生時にデバッガは
   Execute を呼び出した側のスレッドを検出する場合があります。
●実行中のメソッドを外部から中断できる
   メソッド内で中断可能宣言をしている場合、
   スレッドハンドル経由でそのメソッドを直ちに中断することができます。
   この動作の詳細は 後述 します。
●親子関係を設定できる
   FGESスレッドは親子関係を持つスレッドを作成することができます。
   この動作の詳細は 後述 します。

●メソッドの中断

FGESでは通常とは異なるパスでメソッドを中断し、処理を終わらせることができます。
この操作はメソッド側で中断可能宣言をしている間のみ可能で、
中断可能宣言をしていないメソッドに対する中断要求は無視されます。

中断可能宣言は実行される文であり、条件分岐などで実行しなかった場合は行ったことになりません。
中断可能宣言をしている間、メソッドは任意のタイミングで終了できなければいけません。
中断する時、ローカル変数はFGES VMの責任で解放され、クリアラーも呼び出されます。
ただしメソッド外に対して依存関係を持たないことは、プログラマの側で保証しなければいけません。

中断可能宣言は以下の構文で行います。
この時、メソッドの戻り値型が void Integer Bool のいずれかでなければいけないという制限があります。

●戻り値型が void の場合
   haltmode 中断識別子 ;

●戻り値型が Integer/Bool の場合
   haltmode 中断時の戻り値 中断識別子 ;

「中断時の戻り値」は戻り値型と同じ型の定数でなければいけません。
この値はこのメソッドが中断された時、戻り値として使用されます。
「中断識別子」は中断要求を受け取る識別子で、式で指定します。
中断要求が行われた時、指定された中断識別子のメソッドまでを中断します。

また、中断可能宣言は次の構文で取り消すことができます。
この取り消しも実行される文であり、実行されると中断可能宣言をしていない状態になります。
   haltmode;

中断を要求するには、中断したいスレッドハンドルに対して Halt を呼び出します。
この時、対象のスレッドで実行中のメソッド内に、
指定した中断識別子と同じ中断識別子に対する中断可能宣言がない場合、中断要求は失敗します。
指定した中断識別子と同じ中断識別子に対する中断可能宣言が複数ある場合、
実行位置に最も近いメソッドに対して中断要求が行われます。

中断要求が成立した場合、実行位置から中断要求したメソッドまでの間に実行中のメソッド
(通常、これは中断要求したメソッドが呼び出しているメソッドです)のうち、
中断可能宣言をしているメソッド全ても同様に中断されます。
中断可能宣言をしていないメソッドは通常通り実行されますが、
実行中に中断可能宣言が行われた場合はその時点で中断されます。
これらの中断は宣言している中断可能識別子とは関係なく行われます。

中断が実行された場合、中断されたメソッドは直ちにローカル変数のクリアラーが呼び出され、終了します。
この時、呼び出し元には中断可能宣言時に指定した戻り値が返されます。
これにより、中断に対応するメソッドの呼び出し元はメソッドが中断されたことを検知できます。

中断の実行は対象のスレッドが実行される時に行われます。
異なるスレッドに対して中断要求を行った場合、次に対象のスレッドが実行されるまで中断は開始されません。

●スレッドの親子関係

FGESでは親子関係を持つスレッドを作成できます。
原則として、子スレッドはFGES VMではなく、親スレッドからタイムスライスを受け取ります。
子スレッドが親スレッドのタイムスライスを使い切った場合、親スレッドは動作しません。
これにより、子スレッドは以下の特性を持ちます。
   ●親スレッドよりも実質優先度が高くなる。
   ●親スレッドが一時停止などでタイムスライスを受け取らない場合、子スレッドも動作しない。

また、子スレッドのタスクは親スレッドの持つタスクの一部として扱われます。
子スレッドにタスクがある場合、親スレッドもタスクがあるものとして扱われます。

加えて、スレッドが子スレッドを持つ場合、
子スレッドへのハンドルやタスクが存在する限り、親スレッドもまた消滅しません。

[前へ] [目次へ] [次へ]

最終更新 2018/07/31