CBL_THREAD_CREATE で作成されたスレッドは、CBL_THREAD_KILL ルーチンで取り消すことができます。別の方法で作成されたスレッドを、CBL_THREAD_KILL を使用して強制終了することはできません。この場合には、COBOL スレッドはただちに異常終了されますが、通常は、CBL_THREAD_KILL を一般的なアプリケーション スレッド コントロールの一部として使用しないでください。主な理由は、スレッドの終了時に、ユーザーとシステムの同期リソースが、正しくロック解除または解放されないためです。そのため、ユーザー アプリケーションとランタイム システム間の同期が影響を受け、アプリケーションで重大な問題が発生することがあります。
CBL_THREAD_KILL は、主スレッドの重大エラー ハンドラーでは、適切に使用できます。このエラー ハンドラーでは、スレッド ハンドルを CBL_THREAD_LIST_n ルーチンによって獲得できます。スレッドをすべて取り消し、STOP RUN でアプリケーションを終了します。この方法は、同期プリミティブのロックが必要となる可能性を最小限にするため、CBL_THREAD_KILL のランダム使用ほどの危険性はありません。ただし実行単位の終了時に、ファイルの破損やデッドロックが生じる可能性はあります。
いずれにせよ、ほとんどのアプリケーションでは CBL_THREAD_KILL を使用しないようにしてください。そのためには、終了フラグをもつスレッド識別データを作成 (CBL_THREAD_IDDATA_ALLOC ルーチンを使用) します。そのデータは、ロックが保持されていないレベルの各スレッドでポーリングできます。終了フラグが設定されている場合は、ポーリング スレッドを正常に終了できます。
例 - スレッド識別データと終了フラグの作成
******************** MAINPROG.CBL ******************** identification division. program-id. mainprog. Data Division. Local-Storage Section. 01 ret-ptr usage pointer. 01 iddata-ptr usage pointer. 01 sub-iddata-ptr usage pointer. 01 sub-handle usage thread-pointer. Linkage Section. 01 iddata-record. 05 iddata-name pic x(20). 05 iddata-term pic x comp-x value 0. Procedure Division. * Establish identification data - don't provide * initialization data when it is allocated, instead * initialize it after the pointer is retrieved. call 'CBL_THREAD_IDDATA_ALLOC' using by value zero length of iddata-record call 'CBL_THREAD_IDDATA_GET' using iddata-ptr omitted set address of iddata-record to iddata-ptr move 'main' to iddata-name * Create sub-thread * Starting point call 'CBL_THREAD_CREATE' using 'SUBPROG ' by value 0 *> No parameters 0 *> Optional - parameter size 0 *> Flag to create detached 0 *> Default priority 0 *> Default stack by reference sub-handle if return-code not = 0 display 'unable to create thread' stop run end-if * Wait until child creates its iddata and then flag * termination set sub-iddata-ptr to NULL perform until 1 = 0 call 'CBL_THREAD_IDDATA_GET' using sub-iddata-ptr by value sub-handle end-call if sub-iddata-ptr not = null exit perform end-if call 'CBL_THREAD_YIELD' end-perform set address of iddata-record to sub-iddata-ptr move "stop" to iddata-name move 1 to iddata-term * Wait till the child exits wait for sub-handle display 'All synchronization is complete on ' & 'RTS termination' stop run. end program mainprog. *************** SUBPROG.CBL ******************************** identification division. program-id. subprog. Data Division. Working-Storage Section. 01 sub-iddata. 05 sub-name pic x(20) value 'sub'. 05 sub-term pic x comp-x value 0. Local-Storage Section. 01 iddata-ptr usage pointer. 01 thread-handle usage pointer. 01 thread-state pic x(4) comp-x. 01 parent-handle usage pointer. Linkage Section. 01 iddata-record. 05 iddata-name pic x(20). 05 iddata-term pic x comp-x value 0. Procedure Division. * Establish identification data - provide initialization data call 'CBL_THREAD_IDDATA_ALLOC' using sub-iddata by value length of sub-iddata * Find our parent thread and resume him * call 'CBL_THREAD_LIST_START' using thread-handle thread-state iddata-ptr set parent-handle to NULL perform until thread-handle = null or return-code not = 0 if iddata-ptr not = null set address of iddata-record to iddata-ptr if iddata-name = 'main' set parent-handle to thread-handle exit perform end-if end-if call 'CBL_THREAD_LIST_NEXT' using thread-handle thread-state iddata-ptr end-perform call 'CBL_THREAD_LIST_END' if parent-handle = NULL display 'synchronization error' stop run end-if call 'CBL_THREAD_IDDATA_GET' using iddata-ptr omitted set address of iddata-record to iddata-ptr perform until iddata-term = 1 call 'CBL_THREAD_YIELD' end-perform exit program. end program subprog.
この長めのコード例は、実際にはほとんど何も行わず、スレッドおよびアプリケーションを終了するためのハンドシェイクの確立のみを行います。これについて説明する前に、主スレッドのハンドルをパラメーターとして子スレッドに渡すと、このようなハンドシェイクをより簡単に確立できることに注目してください。この方法を使用すると、識別データに依存したり、スレッド リストをステップ実行したりする必要はありません。
サンプル アプリケーションについては、以下の点を考慮してください。
アプリケーションで使用する方法は、識別データで予測される競合のレベルによって異なります。
スレッドが CBL_THREAD_LIST ルーチンを使用する場合、
このため、以下を行うことをお勧めします。
この制限は、CBL_THREAD_LIST_END 呼び出しによりステップ実行が終了した場合にのみ解除されます。