diff options
author | sebres <sebres@users.sourceforge.net> | 2017-07-03 13:24:04 (GMT) |
---|---|---|
committer | sebres <sebres@users.sourceforge.net> | 2017-07-03 13:24:04 (GMT) |
commit | 8a1d9a3be57af976d24c218db14975378927f125 (patch) | |
tree | f5ba35170e5f2a3ee16e5b126a174c35b114ac52 /generic/tclTimer.c | |
parent | df949554f991f8fb4a399bdd248437012deebe40 (diff) | |
download | tcl-8a1d9a3be57af976d24c218db14975378927f125.zip tcl-8a1d9a3be57af976d24c218db14975378927f125.tar.gz tcl-8a1d9a3be57af976d24c218db14975378927f125.tar.bz2 |
[performance] much better handling for timer events within Tcl_ServiceEvent using timer marker in the queue and direct call of TclServiceTimerEvents if marker reached (instead of continuous adding handler event, polling it in the queue and removing hereafter);
this provides double performance increase in the service cycle;
Diffstat (limited to 'generic/tclTimer.c')
-rw-r--r-- | generic/tclTimer.c | 118 |
1 files changed, 28 insertions, 90 deletions
diff --git a/generic/tclTimer.c b/generic/tclTimer.c index d3aa5aa..12b039f 100644 --- a/generic/tclTimer.c +++ b/generic/tclTimer.c @@ -121,7 +121,6 @@ static void FreeAfterPtr(ClientData clientData); static AfterInfo * GetAfterEvent(AfterAssocData *assocPtr, Tcl_Obj *objPtr); static ThreadSpecificData *InitTimer(void); static void TimerExitProc(ClientData clientData); -static void TimerCheckProc(ClientData clientData, int flags); static void TimerSetupProc(ClientData clientData, int flags); static void AfterObj_DupInternalRep(Tcl_Obj *, Tcl_Obj *); @@ -259,7 +258,7 @@ InitTimer(void) if (tsdPtr == NULL) { tsdPtr = TCL_TSD_INIT(&dataKey); - Tcl_CreateEventSource(TimerSetupProc, TimerCheckProc, tsdPtr); + Tcl_CreateEventSource(TimerSetupProc, NULL, tsdPtr); Tcl_CreateThreadExitHandler(TimerExitProc, NULL); } return tsdPtr; @@ -290,7 +289,7 @@ TimerExitProc( TclThreadDataKeyGet(&dataKey); if (tsdPtr != NULL) { - Tcl_DeleteEventSource(TimerSetupProc, TimerCheckProc, tsdPtr); + Tcl_DeleteEventSource(TimerSetupProc, NULL, tsdPtr); while ((tsdPtr->lastPromptPtr) != NULL) { TclDeleteTimerEntry(tsdPtr->lastPromptPtr); @@ -583,7 +582,7 @@ TclDeleteTimerEntry( static void TimerSetupProc( - ClientData data, /* Specific data. */ + ClientData data, /* Not used. */ int flags) /* Event flags as passed to Tcl_DoOneEvent. */ { Tcl_Time blockTime, *firstTime; @@ -591,11 +590,10 @@ TimerSetupProc( if (tsdPtr == NULL) { tsdPtr = InitTimer(); }; - if ( ((flags & TCL_TIMER_EVENTS) && tsdPtr->timerPending) - || ((flags & TCL_IDLE_EVENTS) && tsdPtr->idleList ) - ) { + if (((flags & TCL_IDLE_EVENTS) && tsdPtr->idleList ) + || ((flags & TCL_TIMER_EVENTS) && tsdPtr->timerPending)) { /* - * There is a pending timer event or an idle handler, so just poll. + * There is an idle handler or a pending timer event, so just poll. */ blockTime.sec = 0; @@ -618,6 +616,15 @@ TimerSetupProc( blockTime.sec = 0; blockTime.usec = 0; } + + /* + * If the first timer has expired, stick an event on the queue. + */ + + if (!tsdPtr->timerPending && blockTime.sec == 0 && blockTime.usec == 0) { + TclSetTimerEventMarker(); + tsdPtr->timerPending = 1; + } } else { return; @@ -629,67 +636,6 @@ TimerSetupProc( /* *---------------------------------------------------------------------- * - * TimerCheckProc -- - * - * This function is called by Tcl_DoOneEvent to check the timer event - * source for events. This routine checks the first timer in the list. - * - * Results: - * None. - * - * Side effects: - * May queue an event and update the maximum notifier block time. - * - *---------------------------------------------------------------------- - */ - -static void -TimerCheckProc( - ClientData data, /* Specific data. */ - int flags) /* Event flags as passed to Tcl_DoOneEvent. */ -{ - Tcl_Time blockTime, *firstTime; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *)data; - - if (!(flags & TCL_TIMER_EVENTS)) { - return; - } - - if (tsdPtr == NULL) { tsdPtr = InitTimer(); }; - - /* If already pending */ - if (!tsdPtr->timerList || tsdPtr->timerPending) { - return; - } - - /* - * Verify the first timer on the queue. - */ - Tcl_GetTime(&blockTime); - firstTime = &(TimerEntry2TimerHandler(tsdPtr->timerList)->time); - blockTime.sec = firstTime->sec - blockTime.sec; - blockTime.usec = firstTime->usec - blockTime.usec; - if (blockTime.usec < 0) { - blockTime.sec -= 1; - blockTime.usec += 1000000; - } - if (blockTime.sec < 0) { - blockTime.sec = 0; - blockTime.usec = 0; - } - - /* - * If the first timer has expired, stick an event on the queue. - */ - if (blockTime.sec == 0 && blockTime.usec == 0) { - TclSetTimerEventMarker(); - tsdPtr->timerPending = 1; - } -} - -/* - *---------------------------------------------------------------------- - * * TclServiceTimerEvents -- * * This function is called by Tcl_ServiceEvent when a timer events should @@ -839,7 +785,7 @@ done: /* Compute the next timeout (later via TimerSetupProc using the first timer). */ tsdPtr->timerPending = 0; - return 1; /* processing done, again later via TimerCheckProc */ + return 1; /* processing done, again later via TimerSetupProc */ } /* @@ -982,7 +928,7 @@ Tcl_CancelIdleCall( /* *---------------------------------------------------------------------- * - * TclServiceIdle -- , TclServiceIdleEx -- + * TclServiceIdle -- * * This function is invoked by the notifier when it becomes idle. It will * invoke all idle handlers that are present at the time the call is @@ -999,14 +945,14 @@ Tcl_CancelIdleCall( */ int -TclServiceIdleEx( - int count) +TclServiceIdle(void) { TimerEntry *idlePtr; size_t currentGeneration; + Tcl_Time blockTime; ThreadSpecificData *tsdPtr = InitTimer(); - if ((idlePtr = tsdPtr->idleList) == NULL) { + if (tsdPtr->idleList == NULL) { return 0; } @@ -1029,7 +975,9 @@ TclServiceIdleEx( * during the call. */ - while (idlePtr->generation <= currentGeneration) { + while ((idlePtr = tsdPtr->idleList) != NULL + && idlePtr->generation <= currentGeneration + ) { /* detach entry from the owner's list */ TclSpliceOutEx(idlePtr, tsdPtr->idleList, tsdPtr->lastIdlePtr); @@ -1041,28 +989,18 @@ TclServiceIdleEx( (*idlePtr->deleteProc)(idlePtr->clientData); } ckfree((char *) idlePtr); - - /* stop processing idle if no more idle, count reached or other queued */ - if ( (idlePtr = tsdPtr->idleList) == NULL - || !--count - || TclPeekEventQueued(TCL_ALL_EVENTS) - ) { - break; - } } - + if (tsdPtr->idleList) { + blockTime.sec = 0; + blockTime.usec = 0; + Tcl_SetMaxBlockTime(&blockTime); + } /* Reset generation */ if (!tsdPtr->idleList) { tsdPtr->idleGeneration = 0; } return 1; } - -int -TclServiceIdle(void) -{ - return TclServiceIdleEx(INT_MAX); -} /* *---------------------------------------------------------------------- |