diff options
author | dgp <dgp@users.sourceforge.net> | 2021-06-17 15:52:08 (GMT) |
---|---|---|
committer | dgp <dgp@users.sourceforge.net> | 2021-06-17 15:52:08 (GMT) |
commit | a6a453f3b858089f9ffab17a781a8098f2ad7747 (patch) | |
tree | b07e5c947ee9613f5e9e2dac0d781beba7c1e448 /generic | |
parent | 8cfc0278110ec7362f8c61c6c78ffe855b256542 (diff) | |
parent | 79b57974dc692ad554c9c4679d4b8dccb5eab963 (diff) | |
download | tcl-a6a453f3b858089f9ffab17a781a8098f2ad7747.zip tcl-a6a453f3b858089f9ffab17a781a8098f2ad7747.tar.gz tcl-a6a453f3b858089f9ffab17a781a8098f2ad7747.tar.bz2 |
Revert to the code of RC2, so that only timestamps and changes file entries
are different.
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tclIORChan.c | 66 |
1 files changed, 60 insertions, 6 deletions
diff --git a/generic/tclIORChan.c b/generic/tclIORChan.c index 65f166b..9097bf4 100644 --- a/generic/tclIORChan.c +++ b/generic/tclIORChan.c @@ -58,6 +58,8 @@ static int ReflectSetOption(ClientData clientData, const char *newValue); static int ReflectTruncate(ClientData clientData, long long length); +static void TimerRunRead(ClientData clientData); +static void TimerRunWrite(ClientData clientData); /* * The C layer channel type/driver definition used by the reflection. @@ -119,6 +121,17 @@ typedef struct { int dead; /* Boolean signal that some operations * should no longer be attempted. */ + Tcl_TimerToken readTimer; /* + A token for the timer that is scheduled in + order to call Tcl_NotifyChannel when the + channel is readable + */ + Tcl_TimerToken writeTimer; /* + A token for the timer that is scheduled in + order to call Tcl_NotifyChannel when the + channel is writable + */ + /* * Note regarding the usage of timers. * @@ -128,11 +141,9 @@ typedef struct { * * See 'rechan', 'memchan', etc. * - * Here this is _not_ required. Interest in events is posted to the Tcl - * level via 'watch'. And posting of events is possible from the Tcl level - * as well, via 'chan postevent'. This means that the generation of all - * events, fake or not, timer based or not, is completely in the hands of - * the Tcl level. Therefore no timer here. + * A timer is used here as well in order to ensure at least on pass through + * the event loop when a channel becomes ready. See issues 67a5eabbd3d1 and + * ef28eb1f1516. */ } ReflectedChannel; @@ -940,7 +951,18 @@ TclChanPostEventObjCmd( #if TCL_THREADS if (rcPtr->owner == rcPtr->thread) { #endif - Tcl_NotifyChannel(chan, events); + if (events & TCL_READABLE) { + if (rcPtr->readTimer == NULL) { + rcPtr->readTimer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME, + TimerRunRead, rcPtr); + } + } + if (events & TCL_WRITABLE) { + if (rcPtr->writeTimer == NULL) { + rcPtr->writeTimer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME, + TimerRunWrite, rcPtr); + } + } #if TCL_THREADS } else { ReflectEvent *ev = (ReflectEvent *)ckalloc(sizeof(ReflectEvent)); @@ -988,6 +1010,24 @@ TclChanPostEventObjCmd( #undef EVENT } +static void +TimerRunRead( + ClientData clientData) +{ + ReflectedChannel *rcPtr = (ReflectedChannel *)clientData; + rcPtr->readTimer = NULL; + Tcl_NotifyChannel(rcPtr->chan, TCL_READABLE); +} + +static void +TimerRunWrite( + ClientData clientData) +{ + ReflectedChannel *rcPtr = (ReflectedChannel *)clientData; + rcPtr->writeTimer = NULL; + Tcl_NotifyChannel(rcPtr->chan, TCL_WRITABLE); +} + /* * Channel error message marshalling utilities. */ @@ -1186,6 +1226,12 @@ ReflectClose( ckfree(tctPtr); ((Channel *)rcPtr->chan)->typePtr = NULL; } + if (rcPtr->readTimer != NULL) { + Tcl_DeleteTimerHandler(rcPtr->readTimer); + } + if (rcPtr->writeTimer != NULL) { + Tcl_DeleteTimerHandler(rcPtr->writeTimer); + } Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *) FreeReflectedChannel); return EOK; } @@ -1255,6 +1301,12 @@ ReflectClose( ckfree(tctPtr); ((Channel *)rcPtr->chan)->typePtr = NULL; } + if (rcPtr->readTimer != NULL) { + Tcl_DeleteTimerHandler(rcPtr->readTimer); + } + if (rcPtr->writeTimer != NULL) { + Tcl_DeleteTimerHandler(rcPtr->writeTimer); + } Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *) FreeReflectedChannel); return (result == TCL_OK) ? EOK : EINVAL; } @@ -2225,6 +2277,8 @@ NewReflectedChannel( rcPtr->chan = NULL; rcPtr->interp = interp; rcPtr->dead = 0; + rcPtr->readTimer = 0; + rcPtr->writeTimer = 0; #if TCL_THREADS rcPtr->thread = Tcl_GetCurrentThread(); #endif |