この関数は、現行のスレッドが特定の状態になったときに呼び出される関数を登録します。
void cciRegisterForThreadStateChange( int *returnCode, CciThreadContext *threadContext, CciDataContext *userContext, CciRegCallback callback, CciCallbackType type);
現行のスレッドの入力ノードは入力ソースからのデータを求めてアクティブにポーリングを行っていますが、使用可能なデータがありません。 入力ノードでデータが使用可能になるまで、メッセージはメッセージ・フローの下流に伝搬されません。
現行のスレッドの入力ノードはデータのポーリングを停止しており、スレッドは解放されました。 スレッドは、同じ入力ノード、または同じメッセージ・フロー内の別の入力ノードにより、再度ディスパッチされています。 この状態になるのは、メッセージ・フローのためにデプロイされた追加のインスタンスが入力データの殺到を処理するために利用され、この入力データの殺到が現在は途絶えている場合です。入力ノードは、単一スレッド上で入力データのポーリングを継続して、他のスレッドは解放されます。
現行のスレッドは終了します。これは、ブローカーがシャットダウンする時、実行グループ・プロセスが制御された方法で終了する時、またはメッセージ・フローが削除される時に発生することがあります。 これは、フロー内のすべてのノードおよびパーサーが削除された後に発生することがあります。
あるいは、type パラメーターを、上記の複数の値に対するビット単位の OR 演算の結果とすることもできます。 この場合、スレッドが個々の type 値に関連する状態になると、指定された関数が呼び出されます。
以下のように構造と関数を宣言します。
typedef struct { int id; }MyContext; static int registered=0; CciRegCallbackStatus switchThreadStateChange( CciDataContext *context, CciCallbackType type) { char traceText[256]; char* typeStr=0; MyContext* myContext = (MyContext*)context; if (type==CCI_THREAD_STATE_IDLE){ typeStr = "idle"; }else if(type==CCI_THREAD_STATE_INSTANCE_END){ typeStr = "instance end"; }else if (type==CCI_THREAD_STATE_TERMINATION){ typeStr = "termination"; }else{ typeStr = "unknown"; } memset(traceText,0,256); sprintf(traceText,"switchThreadStateChange: context id = %d, thread state %s",myContext->id,typeStr); cciServiceTrace(NULL, NULL, traceText); return CCI_THREAD_STATE_REGISTRATION_RETAIN; }
以下のコードをサンプルの _Switch_evaluate 関数に入れると、サービス・トレースを読んで、メッセージ処理スレッドの状態がいつ変わったかを調べることができるようになります。
/*register for thread state change*/ CciMessageContext* messageContext = cniGetMessageContext(NULL,message); CciThreadContext* threadContext = cniGetThreadContext(NULL,messageContext); static MyContext myContext={1}; if(registered==0){ cciRegisterForThreadStateChange( NULL, threadContext, & myContext, switchThreadStateChange, CCI_THREAD_STATE_IDLE | CCI_THREAD_STATE_INSTANCE_END | CCI_THREAD_STATE_TERMINATION); registered=1; }
この例は、メッセージを受け取る最初のスレッドでのみ登録を行います。 メッセージを受け取るすべてのスレッドで登録を行う必要がある場合は、ユーザー定義拡張機能に、どのスレッドで登録を行ったかを記憶させておく必要があります。
userContext パラメーターを使用すると、コールバックが登録されているコードから、実際のコールバック関数へどのようにデータが渡されるかを調べることができます。
コールバックを登録する際、MyContext 構造のインスタンスへのポインターが渡されます。これは、コールバックに戻されるポインターと同じです。 コールバックに戻されるときまで確実にポインターを有効にしておくために、構造のインスタンスが静的インスタンスとして宣言されます。 確実にポインターを有効にしておくための別の手法として、ヒープにストレージを割り振る方法があります。
コールバック関数で、userContext パラメーターを (MyContext*) にキャストできます。元の MyContext 構造は、このアドレスを介して参照可能です。 これにより、コールバックが登録されているコードからコールバック関数にデータを渡すことが可能になります。