diff options
author | dkf <donal.k.fellows@manchester.ac.uk> | 2004-12-16 19:36:14 (GMT) |
---|---|---|
committer | dkf <donal.k.fellows@manchester.ac.uk> | 2004-12-16 19:36:14 (GMT) |
commit | a0655d89bbe9e5b91b703509126ed1c48a1cf405 (patch) | |
tree | de437c399d4304e768cda1abe7dada3b80e3c57f /generic/tclTimer.c | |
parent | 96a4475c4aa4e7f173d328e2a6f37770ae35f497 (diff) | |
download | tcl-a0655d89bbe9e5b91b703509126ed1c48a1cf405.zip tcl-a0655d89bbe9e5b91b703509126ed1c48a1cf405.tar.gz tcl-a0655d89bbe9e5b91b703509126ed1c48a1cf405.tar.bz2 |
Upgrade the capabilities of time limits by allowing them to fire in the midst
of the processing of the event loop or during a blocking [after]. [Bug 1085023]
Diffstat (limited to 'generic/tclTimer.c')
-rw-r--r-- | generic/tclTimer.c | 88 |
1 files changed, 74 insertions, 14 deletions
diff --git a/generic/tclTimer.c b/generic/tclTimer.c index 8c5a210..12c2ce9 100644 --- a/generic/tclTimer.c +++ b/generic/tclTimer.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclTimer.c,v 1.12 2004/10/06 15:59:25 dgp Exp $ + * RCS: @(#) $Id: tclTimer.c,v 1.13 2004/12/16 19:36:35 dkf Exp $ */ #include "tclInt.h" @@ -223,30 +223,58 @@ Tcl_CreateTimerHandler(milliseconds, proc, clientData) Tcl_TimerProc *proc; /* Procedure to invoke. */ ClientData clientData; /* Arbitrary data to pass to proc. */ { - register TimerHandler *timerHandlerPtr, *tPtr2, *prevPtr; Tcl_Time time; - ThreadSpecificData *tsdPtr; - - tsdPtr = InitTimer(); - - timerHandlerPtr = (TimerHandler *) ckalloc(sizeof(TimerHandler)); /* * Compute when the event should fire. */ Tcl_GetTime(&time); - timerHandlerPtr->time.sec = time.sec + milliseconds/1000; - timerHandlerPtr->time.usec = time.usec + (milliseconds%1000)*1000; - if (timerHandlerPtr->time.usec >= 1000000) { - timerHandlerPtr->time.usec -= 1000000; - timerHandlerPtr->time.sec += 1; + time.sec += milliseconds/1000; + time.usec += (milliseconds%1000)*1000; + if (time.usec >= 1000000) { + time.usec -= 1000000; + time.sec += 1; } + return TclCreateAbsoluteTimerHandler(&time, proc, clientData); +} + +/* + *-------------------------------------------------------------- + * + * TclCreateAbsoluteTimerHandler -- + * + * Arrange for a given procedure to be invoked at a particular + * time in the future. + * + * Results: + * The return value is a token for the timer event, which + * may be used to delete the event before it fires. + * + * Side effects: + * When the time in timePtr has been reached, proc will be invoked + * exactly once. + * + *-------------------------------------------------------------- + */ + +Tcl_TimerToken +TclCreateAbsoluteTimerHandler(timePtr, proc, clientData) + Tcl_Time *timePtr; + Tcl_TimerProc *proc; + ClientData clientData; +{ + register TimerHandler *timerHandlerPtr, *tPtr2, *prevPtr; + ThreadSpecificData *tsdPtr; + + tsdPtr = InitTimer(); + timerHandlerPtr = (TimerHandler *) ckalloc(sizeof(TimerHandler)); /* - * Fill in other fields for the event. + * Fill in fields for the event. */ + memcpy((void *)&timerHandlerPtr->time, (void *)timePtr, sizeof(Tcl_Time)); timerHandlerPtr->proc = proc; timerHandlerPtr->clientData = clientData; tsdPtr->lastTimerId++; @@ -788,7 +816,39 @@ processInteger: ms = 0; } if (objc == 2) { - Tcl_Sleep(ms); + Interp *iPtr = (Interp *) interp; + + if (iPtr->limit.timeEvent != NULL) { + Tcl_Time endTime, now; + + Tcl_GetTime(&endTime); + endTime.sec += ms/1000; + endTime.usec += (ms%1000)*1000; + if (endTime.usec >= 1000000) { + endTime.sec++; + endTime.usec -= 1000000; + } + + do { + Tcl_GetTime(&now); + if (endTime.sec < iPtr->limit.time.sec || + (endTime.sec == iPtr->limit.time.sec && + endTime.usec < iPtr->limit.time.usec)) { + Tcl_Sleep(1000*(endTime.sec - now.sec) + + (endTime.usec - now.usec)/1000); + break; + } else { + Tcl_Sleep(1000*(iPtr->limit.time.sec - now.sec) + + (iPtr->limit.time.usec - now.usec)/1000); + if (Tcl_LimitCheck(interp) != TCL_OK) { + return TCL_ERROR; + } + } + } while (endTime.sec > now.sec || + (endTime.sec == now.sec && endTime.usec > now.usec)); + } else { + Tcl_Sleep(ms); + } return TCL_OK; } afterPtr = (AfterInfo *) ckalloc((unsigned) (sizeof(AfterInfo))); |