void Tcl_DoWhenIdle( Tcl_IdleProc *proc, /* Function to invoke. */ ClientData clientData) /* Arbitrary value to pass to proc. */ { register IdleHandler *idlePtr; Tcl_Time blockTime; ThreadSpecificData *tsdPtr = InitTimer(); idlePtr = ckalloc(sizeof(IdleHandler)); idlePtr->proc = proc; idlePtr->clientData = clientData; idlePtr->generation = tsdPtr->idleGeneration; idlePtr->nextPtr = NULL; if (tsdPtr->lastIdlePtr == NULL) { tsdPtr->idleList = idlePtr; } else { tsdPtr->lastIdlePtr->nextPtr = idlePtr; } tsdPtr->lastIdlePtr = idlePtr; blockTime.sec = 0; blockTime.usec = 0; Tcl_SetMaxBlockTime(&blockTime); }
static void DisplaySetupProc( ClientData clientData, /* Not used. */ int flags) { TkDisplay *dispPtr; static Tcl_Time blockTime = { 0, 0 }; if (!(flags & TCL_WINDOW_EVENTS)) { return; } for (dispPtr = TkGetDisplayList(); dispPtr != NULL; dispPtr = dispPtr->nextPtr) { /* * Flush the display. If data is pending on the X queue, set the block * time to zero. This ensures that we won't block in the notifier if * there is data in the X queue, but not on the server socket. */ XFlush(dispPtr->display); if (QLength(dispPtr->display) > 0) { Tcl_SetMaxBlockTime(&blockTime); } } }
void ConsoleSetupProc( ClientData data, /* Not used. */ int flags) /* Event flags as passed to Tcl_DoOneEvent. */ { ConsoleInfo *infoPtr; Tcl_Time blockTime = { 0, 0 }; int block = 1; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return; } /* * Look to see if any events are already pending. If they are, poll. */ for (infoPtr = tsdPtr->firstConsolePtr; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { if (infoPtr->watchMask & TCL_WRITABLE) { if (WaitForSingleObject(infoPtr->writable, 0) != WAIT_TIMEOUT) { block = 0; } } if (infoPtr->watchMask & TCL_READABLE) { if (WaitForRead(infoPtr, 0) >= 0) { block = 0; } } } if (!block) { Tcl_SetMaxBlockTime(&blockTime); } }
int TclServiceIdle(void) { IdleHandler *idlePtr; int oldGeneration; Tcl_Time blockTime; ThreadSpecificData *tsdPtr = InitTimer(); if (tsdPtr->idleList == NULL) { return 0; } oldGeneration = tsdPtr->idleGeneration; tsdPtr->idleGeneration++; /* * The code below is trickier than it may look, for the following reasons: * * 1. New handlers can get added to the list while the current one is * being processed. If new ones get added, we don't want to process * them during this pass through the list (want to check for other work * to do first). This is implemented using the generation number in the * handler: new handlers will have a different generation than any of * the ones currently on the list. * 2. The handler can call Tcl_DoOneEvent, so we have to remove the * handler from the list before calling it. Otherwise an infinite loop * could result. * 3. Tcl_CancelIdleCall can be called to remove an element from the list * while a handler is executing, so the list could change structure * during the call. */ for (idlePtr = tsdPtr->idleList; ((idlePtr != NULL) && ((oldGeneration - idlePtr->generation) >= 0)); idlePtr = tsdPtr->idleList) { tsdPtr->idleList = idlePtr->nextPtr; if (tsdPtr->idleList == NULL) { tsdPtr->lastIdlePtr = NULL; } idlePtr->proc(idlePtr->clientData); ckfree(idlePtr); } if (tsdPtr->idleList) { blockTime.sec = 0; blockTime.usec = 0; Tcl_SetMaxBlockTime(&blockTime); } return 1; }
static void ConsoleWatchProc( ClientData instanceData, /* Console state. */ int mask) /* What events to watch for, OR-ed * combination of TCL_READABLE, * TCL_WRITABLE and TCL_EXCEPTION. */ { ConsoleInfo **nextPtrPtr, *ptr; ConsoleInfo *infoPtr = (ConsoleInfo *) instanceData; int oldMask = infoPtr->watchMask; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); /* * Since most of the work is handled by the background threads, * we just need to update the watchMask and then force the notifier * to poll once. */ infoPtr->watchMask = mask & infoPtr->validMask; if (infoPtr->watchMask) { Tcl_Time blockTime = { 0, 0 }; if (!oldMask) { infoPtr->nextPtr = tsdPtr->firstConsolePtr; tsdPtr->firstConsolePtr = infoPtr; } Tcl_SetMaxBlockTime(&blockTime); } else { if (oldMask) { /* * Remove the console from the list of watched consoles. */ for (nextPtrPtr = &(tsdPtr->firstConsolePtr), ptr = *nextPtrPtr; ptr != NULL; nextPtrPtr = &ptr->nextPtr, ptr = *nextPtrPtr) { if (infoPtr == ptr) { *nextPtrPtr = ptr->nextPtr; break; } } } } }
static void TimerSetupProc( ClientData data, /* Not used. */ int flags) /* Event flags as passed to Tcl_DoOneEvent. */ { Tcl_Time blockTime; ThreadSpecificData *tsdPtr = InitTimer(); if (((flags & TCL_IDLE_EVENTS) && tsdPtr->idleList) || ((flags & TCL_TIMER_EVENTS) && tsdPtr->timerPending)) { /* * There is an idle handler or a pending timer event, so just poll. */ blockTime.sec = 0; blockTime.usec = 0; } else if ((flags & TCL_TIMER_EVENTS) && tsdPtr->firstTimerHandlerPtr) { /* * Compute the timeout for the next timer on the list. */ Tcl_GetTime(&blockTime); blockTime.sec = tsdPtr->firstTimerHandlerPtr->time.sec - blockTime.sec; blockTime.usec = tsdPtr->firstTimerHandlerPtr->time.usec - blockTime.usec; if (blockTime.usec < 0) { blockTime.sec -= 1; blockTime.usec += 1000000; } if (blockTime.sec < 0) { blockTime.sec = 0; blockTime.usec = 0; } } else { return; } Tcl_SetMaxBlockTime(&blockTime); }
void DBus_SetupProc(ClientData data, int flags) { Tcl_Time blockTime; DBusDispatchStatus status; Tcl_HashEntry *hPtr; Tcl_HashSearch search; Tcl_DBusBus *dbus; blockTime.sec = 0; blockTime.usec = 100000; /* Check the incoming message queues */ for (hPtr = Tcl_FirstHashEntry(&bus, &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { dbus = (Tcl_DBusBus *) Tcl_GetHashValue(hPtr); dbus_connection_read_write(dbus->conn, 0); status = dbus_connection_get_dispatch_status(dbus->conn); if (status == DBUS_DISPATCH_DATA_REMAINS) { blockTime.sec = 0; blockTime.usec = 0; break; } } Tcl_SetMaxBlockTime(&blockTime); }