此函数注册一个函数,当前线程进入某个特殊状态时会调用此函数。
void cciRegisterForThreadStateChange( int *returnCode, CciThreadContext *threadContext, CciDataContext *userContext, CciRegCallback callback, CciCallbackType type);
当前线程的输入节点主动轮询输入源的数据,但是没有数据可用。在数据可用于输入节点之前,消息不沿着消息流向下传播。
当前线程的输入节点已停止轮询数据,并且该线程已被释放。通过同一个消息流中的同一个输入节点或任何其他输入节点,再次分配该线程。当利用了为消息流部署的附加实例来应付现已停止的输入数据的流入时,进入此状态。输入节点继续轮询单线程处理方式的输入数据和其他已释放的线程。
正在结束当前线程。当代理关闭时、控制方式中的执行组访问结束或删除消息流时,会发生此情况。删除了消息流中的所有节点和解析器后会发生此情况。
或者,type 参数可以是两个或多个这些值的 bit wise OR 操作的结果。 在这种情况下,当线程进入每个单独的 type 值的相关状态时,调用指定的函数:
声明 struct 和函数:
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 struct 的实例的指针。该指针与传回回调的指针相同。要确保该指针在传递到回调时仍然有效,将 struct 的实例声明为静态。另一个确保指针有效的技术是在堆上分配存储。
在回调函数中,可以将 userContext 参数类型强制转换成 (MyContext*)。可以通过此地址引用原始的 MyContext struct。这允许数据从注册回调的代码传递到该回调函数。