cciRegisterForThreadStateChange
This function registers a function to be called when the current thread enters a particular state.
Syntax
void cciRegisterForThreadStateChange(
int *returnCode,
CciThreadContext *threadContext,
CciDataContext *userContext,
CciRegCallback callback,
CciCallbackType type);
Parameters
- returnCode
- The return code from the function (output). An input value of
NULL signifies that errors are silently handled, or are ignored by
the integration node. If the input value is not NULL, the output value
signifies the success status of the call. If the
threadContext
parameter is not valid,*returnCode
is set to CCI_INV_THREAD_CONTEXT, and the callback is not registered. - threadContext
- This parameter provides the thread context in which to register
the callback function and associated data. It is assumed that this
parameter is obtained by calling cniGetThreadContext() on
the current thread. If NULL is supplied as
threadContext
, the thread context is determined by the framework. This method is less efficient than calling cniGetThreadContext. - userContext
- This parameter allows the caller to provide a context pointer that is passed to the callback function when it is called. This parameter can be NULL.
- callback
- This parameter is a pointer to the callback function that is to
be called. This function must be of the type
CciRegCallback
. - type
- This parameter specifies whether the callback is to be called
at the time when the thread is ending, or when the thread is in one
of the idle states. The idle states can be one of the following values:
- CCI_THREAD_STATE_IDLE:
The input node for the current thread is actively polling for data from the input source, but no data is available. Messages are not propagated through the message flow until data becomes available for the input node.
- CCI_THREAD_STATE_INSTANCE_END
The input node for the current thread has stopped polling for data and the thread has been released. The thread is dispatched again either by the same input node or by another input node in the same message flow. This state is entered when additional instances, which have been deployed for a message flow, have been configured to cope with an influx of input data that has now ceased. The input node continues to poll for input data on a single thread, and the other threads are released.
- CCI_THREAD_STATE_TERMINATION
The current thread is ending. This action can happen when the integration node is shut down, the integration server process is ending in a controlled manner, or when the message flow is being deleted. This state can occur after all nodes and parsers in the flow are deleted.
Alternatively, the
type
parameter can be the result of a bit-wiseOR
operation on two or more of these values. In this case, the specified function is called when the thread enters the relevant state for each individualtype
value. - CCI_THREAD_STATE_IDLE:
Return values
None. If an error occurs, the returnCode parameter indicates the reason for the error.
Example
Declaring the 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 to 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 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 technique permits the passing of data from the code where the callback is registered to the callback function.