See information about the latest product version
cciRegCallback
This function can be registered as a callback function, and is called when the registered event occurs. The function is registered by providing a function pointer which matches a particular typedef.
Syntax
typedef int (*CciRegCallback)(CciDataContext *, cciCallbackType);
Parameters
- type CciDataContext*
- This parameter is the pointer that is provided by the caller to the registration function.
- type CciCallbackType
- This parameter indicates the reason for the callback. The reason is always one of the CciCallbackType values that is specified on the registration call corresponding to this callback.
Return values
type CciRegCallbackStatus (defined in BipCci.h)
- CCI_THREAD_STATE_REGISTRATION_RETAIN: This return code is used for a callback that is to remain registered as a callback function on a particular thread.
- CCI_THREAD_STATE_REGISTRATION_REMOVE: This return code is used to signify that the callback is to be de-registered, and that it must not be called again on this thread unless it is reregistered.
- If another value is returned, a warning is written to a log, and CCI_THREAD_STATE_REGISTRATION_RETAIN is assumed.
- cciLog
- cciUserTrace
- cciServiceTrace
- cciUserDebugTrace
- cciServiceDebugTrace
- cciIsTraceActive
For each of these five trace utility functions, the CciObject parameter must be NULL.
Example
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 pointer is the pointer that 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 technique permits the passing of data from the code where the callback is registered to the callback function.