Essa função registra uma função a ser chamada quando o encadeamento atual informa um estado específico.
void cciRegisterForThreadStateChange( int *returnCode, CciThreadContext *threadContext, CciDataContext *userContext, CciRegCallback callback, CciCallbackType type);
O nó input para o encadeamento atual está ativamente efetuando o polling de dados da origem de entrada, mas nenhum dado está disponível. As mensagens não são propagadas abaixo do fluxo de mensagens, até que os dados fiquem disponíveis para o nó input.
O nó input para o encadeamento atual parou o polling de dados e o encadeamento foi liberado. O encadeamento é enviado novamente pelo mesmo nó input ou por outro nó input no mesmo fluxo de mensagens. Esse estado é informado quando instâncias adicionais, que foram implementadas para um fluxo de mensagens, foram utilizadas para arcar com um influxo de dados de entrada que foi agora parado. O nó input continua a controlar os dados de entrada em um único encadeamento e os outros encadeamentos são liberados.
O encadeamento atual é finalizado. Isso pode acontecer quando o intermediário é encerrado, o processo do grupo de execução está sendo finalizado de maneira controlada ou quando o fluxo de mensagens está sendo excluído. Isso pode acontecer após a exclusão de todos os nós e analisadores no fluxo.
Ou então, o parâmetro type pode ser o resultado de uma operação OR de bit a bit em dois ou mais desses valores. Nesse caso, a função especificada é chamada quando o encadeamento informa o estado relevante para cada valor de type individual.
Declarando a estrutura e a função:
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; }
Coloque o código a seguir na função _Switch_evaluate nas amostras, para permitir a leitura do rastreio de serviço e para ver quando o encadeamento de processamento de mensagens altera o estado:
/*registrar para alteração no estado de encadeamento*/ 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; }
Esse exemplo é registrado apenas no primeiro encadeamento que recebe uma mensagem. Se for necessário registrar cada encadeamento que recebe uma mensagem, as extensões definidas pelo usuário devem lembrar em quais encadeamentos elas foram registradas.
Utilizando o parâmetro userContext, você pode ver como os dados são transmitidos do código, no qual o retorno de chamada é registrado para a função de retorno de chamada real.
Ao registrar o retorno de chamada, é transmitido um ponteiro para uma instância da estrutura MyContext. Esse é o mesmo ponteiro, pois é transmitido novamente para o retorno de chamada. Para assegurar que o ponteiro ainda é válido quando transmitido novamente para o retorno de chamada, uma instância da estrutura é declarada como estática. Outra técnica é assegurar que o ponteiro é válido para alocar o armazenamento no heap.
Na função de retorno de chamada, o parâmetro userContext pode ser convertido em um (MyContext*). A estrutura MyContext original pode ser referenciada através desse endereço. Isso permite a transmissão de dados do código no qual o retorno de chamada é registrado para a função de retorno de chamada.