この関数はコールバック関数として登録でき、登録されたイベントが発生すると呼び出されます。 この関数は特定の typedef と一致する関数ポインターを指定することにより登録されます。
typedef int (*CciRegCallback)(CciDataContext *, cciCallbackType);
type CciRegCallbackStatus (BipCci.h で定義される)
これら 5 つのトレース・ユーティリティー関数のそれぞれで、CciObject パラメーターは NULL でなければなりません。
以下の構造と関数を宣言します。
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 構造は、このアドレスを介して参照可能です。 この技法により、コールバックが登録されているコードからコールバック関数にデータを渡すことが可能になります。