summaryrefslogtreecommitdiffstats
path: root/generic/tclTimer.c
diff options
context:
space:
mode:
authorsebres <sebres@users.sourceforge.net>2017-07-03 13:25:01 (GMT)
committersebres <sebres@users.sourceforge.net>2017-07-03 13:25:01 (GMT)
commitc63851a26ab53586d457dfcaf73a9afda52092ec (patch)
treeb0c490f746654ad13133f91ca1819fc35df5a278 /generic/tclTimer.c
parentd2d76748809298daff2f10a63b2999d559d129dd (diff)
downloadtcl-c63851a26ab53586d457dfcaf73a9afda52092ec.zip
tcl-c63851a26ab53586d457dfcaf73a9afda52092ec.tar.gz
tcl-c63851a26ab53586d457dfcaf73a9afda52092ec.tar.bz2
dynamic increase of timer resolution corresponding wait-time;
non-blocking wait for event - if block-time set outside an event source traversal, use it as timeout, so can return with result 0 (no events);
Diffstat (limited to 'generic/tclTimer.c')
-rw-r--r--generic/tclTimer.c44
1 files changed, 24 insertions, 20 deletions
diff --git a/generic/tclTimer.c b/generic/tclTimer.c
index 63346a1..aa78b22 100644
--- a/generic/tclTimer.c
+++ b/generic/tclTimer.c
@@ -115,7 +115,7 @@ static Tcl_ThreadDataKey dataKey;
static void AfterCleanupProc(ClientData clientData,
Tcl_Interp *interp);
-static int AfterDelay(Tcl_Interp *interp, Tcl_WideInt ms);
+static int AfterDelay(Tcl_Interp *interp, double ms);
static void AfterProc(ClientData clientData);
static void FreeAfterPtr(ClientData clientData);
static AfterInfo * GetAfterEvent(AfterAssocData *assocPtr, Tcl_Obj *objPtr);
@@ -623,7 +623,7 @@ TimerSetupProc(
* If the first timer has expired, stick an event on the queue right now.
*/
if (!tsdPtr->timerPending && blockTime.sec == 0 && blockTime.usec == 0) {
- TclSetTimerEventMarker();
+ TclSetTimerEventMarker(0);
tsdPtr->timerPending = 1;
}
@@ -690,7 +690,7 @@ TimerCheckProc(
* If the first timer has expired, stick an event on the queue.
*/
if (blockTime.sec == 0 && blockTime.usec == 0) {
- TclSetTimerEventMarker();
+ TclSetTimerEventMarker(0);
tsdPtr->timerPending = 1;
}
}
@@ -709,7 +709,7 @@ TimerCheckProc(
* the queue.
* Returns 0 if the event was not handled (no timer events).
* Returns -1 if pending timer events available, meaning the marker should
- * stay on the queue.
+ * stay on the head of queue.
*
* Side effects:
* Whatever the timer handler callback functions do.
@@ -723,6 +723,7 @@ TclServiceTimerEvents(void)
TimerEntry *entryPtr, *nextPtr;
Tcl_Time time;
size_t currentGeneration, currentEpoch;
+ int prevTmrPending;
ThreadSpecificData *tsdPtr = InitTimer();
@@ -762,8 +763,13 @@ TclServiceTimerEvents(void)
/* detach entry from the owner's list */
TclSpliceOutEx(entryPtr, tsdPtr->promptList, tsdPtr->lastPromptPtr);
+ /* reset current timer pending (correct process nested wait event) */
+ prevTmrPending = tsdPtr->timerPending;
+ tsdPtr->timerPending = 0;
/* execute event */
(*entryPtr->proc)(entryPtr->clientData);
+ /* restore current timer pending */
+ tsdPtr->timerPending += prevTmrPending;
/* free it via deleteProc and ckfree */
if (entryPtr->deleteProc) {
@@ -775,6 +781,7 @@ TclServiceTimerEvents(void)
/* if stil pending prompt events (new generation) - repeat event cycle as
* soon as possible */
if (tsdPtr->promptList) {
+ tsdPtr->timerPending = 1;
return -1;
}
@@ -815,8 +822,14 @@ TclServiceTimerEvents(void)
currentEpoch = tsdPtr->timerListEpoch;
+ /* reset current timer pending (correct process nested wait event) */
+ prevTmrPending = tsdPtr->timerPending;
+ tsdPtr->timerPending = 0;
/* invoke timer proc */
(*entryPtr->proc)(entryPtr->clientData);
+ /* restore current timer pending */
+ tsdPtr->timerPending += prevTmrPending;
+
/* free it via deleteProc or ckfree */
if (entryPtr->deleteProc) {
(*entryPtr->deleteProc)(entryPtr->clientData);
@@ -836,6 +849,7 @@ done:
/* pending timer events, so mark (queue) timer events */
if (tsdPtr->timerPending > 1) {
tsdPtr->timerPending = 1;
+
return -1;
}
@@ -901,7 +915,7 @@ TclCreateTimerEntryEx(
/* execute immediately: signal pending and set timer marker */
tsdPtr->timerPending++;
- TclSetTimerEventMarker();
+ TclSetTimerEventMarker(0);
} else {
/* idle generation */
entryPtr->generation = tsdPtr->idleGeneration;
@@ -1103,7 +1117,7 @@ Tcl_AfterObjCmd(
int objc, /* Number of arguments. */
Tcl_Obj *CONST objv[]) /* Argument objects. */
{
- Tcl_WideInt ms; /* Number of milliseconds to wait */
+ double ms; /* Number of milliseconds to wait */
AfterInfo *afterPtr;
AfterAssocData *assocPtr;
int length;
@@ -1140,7 +1154,7 @@ Tcl_AfterObjCmd(
index = -1;
if ( ( TclObjIsIndexOfTable(objv[1], afterSubCmds)
- || Tcl_GetWideIntFromObj(NULL, objv[1], &ms) != TCL_OK
+ || Tcl_GetDoubleFromObj(NULL, objv[1], &ms) != TCL_OK
)
&& Tcl_GetIndexFromObj(NULL, objv[1], afterSubCmds, "", 0,
&index) != TCL_OK
@@ -1169,12 +1183,7 @@ Tcl_AfterObjCmd(
if (ms) {
Tcl_Time wakeup;
Tcl_GetTime(&wakeup);
- wakeup.sec += (long)(ms / 1000);
- wakeup.usec += ((long)(ms % 1000)) * 1000;
- if (wakeup.usec > 1000000) {
- wakeup.sec++;
- wakeup.usec -= 1000000;
- }
+ TclTimeAddMilliseconds(&wakeup, ms);
entryPtr = TclCreateAbsoluteTimerHandlerEx(&wakeup, AfterProc,
FreeAfterPtr, sizeof(AfterInfo));
} else {
@@ -1359,7 +1368,7 @@ Tcl_AfterObjCmd(
static int
AfterDelay(
Tcl_Interp *interp,
- Tcl_WideInt ms)
+ double ms)
{
Interp *iPtr = (Interp *) interp;
@@ -1367,12 +1376,7 @@ AfterDelay(
Tcl_WideInt diff;
Tcl_GetTime(&endTime);
- endTime.sec += (long)(ms/1000);
- endTime.usec += ((int)(ms%1000))*1000;
- if (endTime.usec >= 1000000) {
- endTime.sec++;
- endTime.usec -= 1000000;
- }
+ TclTimeAddMilliseconds(&endTime, ms);
do {
Tcl_GetTime(&now);