This is a function that can be registered as a callback and is invoked when the registered event occurs. The function is registered by providing a function pointer which matches the following typedef:
type CciRegCallbackStatus (defined in BipCci.h)
For each of these five trace utility functions, the CciObject parameter must be NULL.
Declare the following struct and function:
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; }
Place the following code into the _Switch_evaluate function in the samples to enable you to read service trace and see when the message processing thread changes state:
/*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; }
This example registers only on the first thread that receives a message. If it is necessary to register every thread that receives a message, the user-defined extensions must remember on which threads they have registered.
By using the userContext parameter you can see how data is passed from the code where the callback is registered to the actual callback function.
When registering the callback, a pointer to an instance of the MyContext struct is passed in. This is the same pointer as is passed back to the callback. To ensure that the pointer is still valid when it is passed back to the callback, an instance of the struct is declared as static. Another technique to ensure that the pointer is valid is to allocate storage on the heap.
In the callback function, the userContext parameter can be cast to a (MyContext*). The original MyContext struct can be referenced through this address. This permits the passing of data from the code where the callback is registered to the callback function.