summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2021-06-17 15:52:08 (GMT)
committerdgp <dgp@users.sourceforge.net>2021-06-17 15:52:08 (GMT)
commita6a453f3b858089f9ffab17a781a8098f2ad7747 (patch)
treeb07e5c947ee9613f5e9e2dac0d781beba7c1e448 /generic
parent8cfc0278110ec7362f8c61c6c78ffe855b256542 (diff)
parent79b57974dc692ad554c9c4679d4b8dccb5eab963 (diff)
downloadtcl-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.c66
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