void tclSendThread(Tcl_ThreadId thread, Tcl_Interp *interpreter, CONST char *script) { ThreadEvent *event; Tcl_Channel errorChannel; Tcl_Obj *object; int boolean; object = Tcl_GetVar2Ex(interpreter, "::tcl_platform", "threaded", 0); if ((object == 0) || (Tcl_GetBooleanFromObj(interpreter, object, &boolean) != TCL_OK) || !boolean) { errorChannel = Tcl_GetStdChannel(TCL_STDERR); if (errorChannel == NULL) return; Tcl_WriteChars( errorChannel, "error: Python thread requested script evaluation on Tcl core not compiled for multithreading.\n", -1 ); return; } event = (ThreadEvent *)Tcl_Alloc(sizeof(ThreadEvent)); event->event.proc = ThreadEventProc; event->interpreter = interpreter; event->script = strcpy(Tcl_Alloc(strlen(script) + 1), script); Tcl_MutexLock(&threadMutex); Tcl_ThreadQueueEvent(thread, (Tcl_Event *)event, TCL_QUEUE_TAIL); Tcl_ThreadAlert(thread); Tcl_MutexUnlock(&threadMutex); }
/* *---------------------------------------------------------------------- * * casstcl_logging_callback -- * * this routine is called by the cassandra cpp-driver as a callback * when a log message has been received and cass_log_set_callback * has been done to register this callback * * Results: * an event is queued to the thread that started our conversation with * cassandra * *---------------------------------------------------------------------- */ void casstcl_logging_callback (const CassLogMessage *message, void *data) { casstcl_loggingEvent *evPtr; Tcl_Interp *interp = data; evPtr = (casstcl_loggingEvent *)ckalloc (sizeof(casstcl_loggingEvent)); evPtr->event.proc = casstcl_logging_eventProc; evPtr->interp = interp; evPtr->message = *message; /* structure copy */ Tcl_ThreadQueueEvent(casstcl_loggingCallbackThreadId, (Tcl_Event *)evPtr, TCL_QUEUE_TAIL); }
static void stateHandler (struct connection_handler_args chargs) { /* callback */ pvInfo *info = ca_puser(chargs.chid); if (info->connectprefix) { /* queue event to handle the Tcl callback */ connectionEvent * cev = ckalloc(sizeof(connectionEvent)); cev->ev.proc = stateHandlerInvoke; cev->info = info; cev->op = chargs.op; Tcl_ThreadQueueEvent(info->thrid, (Tcl_Event*)cev, TCL_QUEUE_TAIL); Tcl_ThreadAlert(info->thrid); } }
/* ** Register an EvalEvent to evaluate the script pScript in the ** parent interpreter/thread of SqlThread p. */ static void postToParent(SqlThread *p, Tcl_Obj *pScript){ EvalEvent *pEvent; char *zMsg; int nMsg; zMsg = Tcl_GetStringFromObj(pScript, &nMsg); pEvent = (EvalEvent *)ckalloc(sizeof(EvalEvent)+nMsg+1); pEvent->base.nextPtr = 0; pEvent->base.proc = tclScriptEvent; pEvent->zScript = (char *)&pEvent[1]; memcpy(pEvent->zScript, zMsg, nMsg+1); pEvent->interp = p->interp; Tcl_ThreadQueueEvent(p->parent, (Tcl_Event *)pEvent, TCL_QUEUE_TAIL); Tcl_ThreadAlert(p->parent); }
int TclThreadSend( Tcl_Interp *interp, /* The current interpreter. */ Tcl_ThreadId id, /* Thread Id of other interpreter. */ char *script, /* The script to evaluate. */ int wait) /* If 1, we block for the result. */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); ThreadEvent *threadEventPtr; ThreadEventResult *resultPtr; int found, code; Tcl_ThreadId threadId = (Tcl_ThreadId) id; /* * Verify the thread exists. */ Tcl_MutexLock(&threadMutex); found = 0; for (tsdPtr = threadList ; tsdPtr ; tsdPtr = tsdPtr->nextPtr) { if (tsdPtr->threadId == threadId) { found = 1; break; } } if (!found) { Tcl_MutexUnlock(&threadMutex); Tcl_AppendResult(interp, "invalid thread id", NULL); return TCL_ERROR; } /* * Short circut sends to ourself. Ought to do something with -async, like * run in an idle handler. */ if (threadId == Tcl_GetCurrentThread()) { Tcl_MutexUnlock(&threadMutex); return Tcl_GlobalEval(interp, script); } /* * Create the event for its event queue. */ threadEventPtr = (ThreadEvent *) ckalloc(sizeof(ThreadEvent)); threadEventPtr->script = ckalloc(strlen(script) + 1); strcpy(threadEventPtr->script, script); if (!wait) { resultPtr = threadEventPtr->resultPtr = NULL; } else { resultPtr = (ThreadEventResult *) ckalloc(sizeof(ThreadEventResult)); threadEventPtr->resultPtr = resultPtr; /* * Initialize the result fields. */ resultPtr->done = NULL; resultPtr->code = 0; resultPtr->result = NULL; resultPtr->errorInfo = NULL; resultPtr->errorCode = NULL; /* * Maintain the cleanup list. */ resultPtr->srcThreadId = Tcl_GetCurrentThread(); resultPtr->dstThreadId = threadId; resultPtr->eventPtr = threadEventPtr; resultPtr->nextPtr = resultList; if (resultList) { resultList->prevPtr = resultPtr; } resultPtr->prevPtr = NULL; resultList = resultPtr; } /* * Queue the event and poke the other thread's notifier. */ threadEventPtr->event.proc = ThreadEventProc; Tcl_ThreadQueueEvent(threadId, (Tcl_Event *)threadEventPtr, TCL_QUEUE_TAIL); Tcl_ThreadAlert(threadId); if (!wait) { Tcl_MutexUnlock(&threadMutex); return TCL_OK; } /* * Block on the results and then get them. */ Tcl_ResetResult(interp); while (resultPtr->result == NULL) { Tcl_ConditionWait(&resultPtr->done, &threadMutex, NULL); } /* * Unlink result from the result list. */ if (resultPtr->prevPtr) { resultPtr->prevPtr->nextPtr = resultPtr->nextPtr; } else { resultList = resultPtr->nextPtr; } if (resultPtr->nextPtr) { resultPtr->nextPtr->prevPtr = resultPtr->prevPtr; } resultPtr->eventPtr = NULL; resultPtr->nextPtr = NULL; resultPtr->prevPtr = NULL; Tcl_MutexUnlock(&threadMutex); if (resultPtr->code != TCL_OK) { if (resultPtr->errorCode) { Tcl_SetErrorCode(interp, resultPtr->errorCode, NULL); ckfree(resultPtr->errorCode); } if (resultPtr->errorInfo) { Tcl_AddErrorInfo(interp, resultPtr->errorInfo); ckfree(resultPtr->errorInfo); } } Tcl_SetResult(interp, resultPtr->result, TCL_DYNAMIC); Tcl_ConditionFinalize(&resultPtr->done); code = resultPtr->code; ckfree((char *) resultPtr); return code; }
static void ManagerThreadProc ( ClientData clientData ) { BlockAllSignals(); Tcl_MutexLock(&spointsLock); /* Notify creator thread we're ready */ threadReady = 1; Tcl_ConditionNotify(&spointsCV); while (1) { Queue eventQueue; SignalMapSearch iterator; SyncPoint *spointPtr; while (condReady == 0) { Tcl_ConditionWait(&spointsCV, &spointsLock, NULL); } condReady = 0; if (shutdownRequested) { break; } InitEventList(&eventQueue); HarvestDanglingSyncpoints(&danglingSpoints, &eventQueue); spointPtr = FirstSigMapEntry(&syncpoints, &iterator); while (spointPtr != NULL) { HarvestSyncpoint(spointPtr, &eventQueue); spointPtr = NextSigMapEntry(&iterator); } Tcl_MutexUnlock(&spointsLock); { SignalEvent *evPtr; Tcl_ThreadId lastId; evPtr = QueuePop(&eventQueue); lastId = evPtr->threadId; do { SignalEvent *nextEvPtr; Tcl_ThreadId threadId; nextEvPtr = QueuePop(&eventQueue); threadId = evPtr->threadId; Tcl_ThreadQueueEvent(threadId, (Tcl_Event*) evPtr, TCL_QUEUE_TAIL); if (threadId != lastId) { Tcl_ThreadAlert(lastId); } printf("Sent %d to %x\n", evPtr->signum, evPtr->threadId); evPtr = nextEvPtr; lastId = threadId; } while (evPtr != NULL); Tcl_ThreadAlert(lastId); } Tcl_MutexLock(&spointsLock); } /* Notify creator thread we're finished. * Note that the spointsLock is held at this point. */ threadReady = 1; Tcl_ConditionNotify(&spointsCV); Tcl_MutexUnlock(&spointsLock); }