diff options
author | andreas_kupries <akupries@shaw.ca> | 2008-04-07 22:17:36 (GMT) |
---|---|---|
committer | andreas_kupries <akupries@shaw.ca> | 2008-04-07 22:17:36 (GMT) |
commit | 56497ff7346fa776215fc25fd154ee60d5422e2b (patch) | |
tree | 153cea45c09d973240fba5c1b70cd4c09cb693b0 /generic | |
parent | 2a9d0c7d0ca876dc97db9373e820c520ad293b7b (diff) | |
download | tcl-56497ff7346fa776215fc25fd154ee60d5422e2b.zip tcl-56497ff7346fa776215fc25fd154ee60d5422e2b.tar.gz tcl-56497ff7346fa776215fc25fd154ee60d5422e2b.tar.bz2 |
* tests/io.test (io-53.10): Testcase for bi-directionaly fcopy.
* generic/tclIO.c: Additional changes to data structures for fcopy
* generic/tclIO.h: and channels to perform proper cleanup in case
of a channel having two background copy operations running as is
now possible.
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tclIO.c | 66 | ||||
-rw-r--r-- | generic/tclIO.h | 5 |
2 files changed, 42 insertions, 29 deletions
diff --git a/generic/tclIO.c b/generic/tclIO.c index 739b644..3f79021 100644 --- a/generic/tclIO.c +++ b/generic/tclIO.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclIO.c,v 1.61.2.26 2008/04/07 19:40:58 andreas_kupries Exp $ + * RCS: @(#) $Id: tclIO.c,v 1.61.2.27 2008/04/07 22:17:37 andreas_kupries Exp $ */ #include "tclInt.h" @@ -157,9 +157,8 @@ static int WriteChars _ANSI_ARGS_((Channel *chanPtr, CONST char *src, int srcLen)); #define BUSY_STATE(st,fl) \ - ((st)->csPtr && \ - ( (((fl)&TCL_READABLE)&&((st)->csPtr->readPtr ==(st)->topChanPtr)) || \ - (((fl)&TCL_WRITABLE)&&((st)->csPtr->writePtr==(st)->topChanPtr)))) + ((((st)->csPtrR) && ((fl) & TCL_READABLE)) || \ + (((st)->csPtrW) && ((fl) & TCL_WRITABLE))) /* *--------------------------------------------------------------------------- @@ -1218,7 +1217,8 @@ Tcl_CreateChannel(typePtr, chanName, instanceData, mask) statePtr->scriptRecordPtr = (EventScriptRecord *) NULL; statePtr->bufSize = CHANNELBUFFER_DEFAULT_SIZE; statePtr->timer = NULL; - statePtr->csPtr = NULL; + statePtr->csPtrR = NULL; + statePtr->csPtrW = NULL; statePtr->outputStage = NULL; if ((statePtr->encoding != NULL) && (statePtr->flags & TCL_WRITABLE)) { @@ -1374,13 +1374,18 @@ Tcl_StackChannel(interp, typePtr, instanceData, mask, prevChan) */ if ((mask & TCL_WRITABLE) != 0) { - CopyState *csPtr; + CopyState *csPtrR; + CopyState *csPtrW; - csPtr = statePtr->csPtr; - statePtr->csPtr = (CopyState*) NULL; + csPtrR = statePtr->csPtrR; + statePtr->csPtrR = (CopyState*) NULL; + + csPtrW = statePtr->csPtrW; + statePtr->csPtrW = (CopyState*) NULL; if (Tcl_Flush((Tcl_Channel) prevChanPtr) != TCL_OK) { - statePtr->csPtr = csPtr; + statePtr->csPtrR = csPtrR; + statePtr->csPtrW = csPtrW; if (interp) { Tcl_AppendResult(interp, "could not flush channel \"", Tcl_GetChannelName(prevChan), "\"", (char *) NULL); @@ -1388,7 +1393,8 @@ Tcl_StackChannel(interp, typePtr, instanceData, mask, prevChan) return (Tcl_Channel) NULL; } - statePtr->csPtr = csPtr; + statePtr->csPtrR = csPtrR; + statePtr->csPtrW = csPtrW; } /* * Discard any input in the buffers. They are not yet read by the @@ -1503,13 +1509,18 @@ Tcl_UnstackChannel (interp, chan) */ if (statePtr->flags & TCL_WRITABLE) { - CopyState* csPtr; + CopyState *csPtrR; + CopyState *csPtrW; + + csPtrR = statePtr->csPtrR; + statePtr->csPtrR = (CopyState*) NULL; - csPtr = statePtr->csPtr; - statePtr->csPtr = (CopyState*) NULL; + csPtrW = statePtr->csPtrW; + statePtr->csPtrW = (CopyState*) NULL; if (Tcl_Flush((Tcl_Channel) chanPtr) != TCL_OK) { - statePtr->csPtr = csPtr; + statePtr->csPtrR = csPtrR; + statePtr->csPtrW = csPtrW; if (interp) { Tcl_AppendResult(interp, "could not flush channel \"", Tcl_GetChannelName((Tcl_Channel) chanPtr), "\"", @@ -1518,7 +1529,8 @@ Tcl_UnstackChannel (interp, chan) return TCL_ERROR; } - statePtr->csPtr = csPtr; + statePtr->csPtrR = csPtrR; + statePtr->csPtrW = csPtrW; } /* @@ -2739,7 +2751,8 @@ Tcl_ClearChannelHandlers (channel) * Cancel any pending copy operation. */ - StopCopy(statePtr->csPtr); + StopCopy(statePtr->csPtrR); + StopCopy(statePtr->csPtrW); /* * Must set the interest mask now to 0, otherwise infinite loops @@ -6319,12 +6332,10 @@ Tcl_GetChannelOption(interp, chan, optionName, dsPtr) * If we are in the middle of a background copy, use the saved flags. */ - if (statePtr->csPtr) { - if (chanPtr == statePtr->csPtr->readPtr) { - flags = statePtr->csPtr->readFlags; - } else { - flags = statePtr->csPtr->writeFlags; - } + if (statePtr->csPtrR) { + flags = statePtr->csPtrR->readFlags; + } else if (statePtr->csPtrW) { + flags = statePtr->csPtrW->writeFlags; } else { flags = statePtr->flags; } @@ -6534,7 +6545,7 @@ Tcl_SetChannelOption(interp, chan, optionName, newValue) * If the channel is in the middle of a background copy, fail. */ - if (statePtr->csPtr) { + if (statePtr->csPtrR || statePtr->csPtrW) { if (interp) { Tcl_AppendResult(interp, "unable to set channel options: background copy in progress", @@ -7757,8 +7768,9 @@ TclCopyChannel(interp, inChan, outChan, toRead, cmdPtr) Tcl_IncrRefCount(cmdPtr); } csPtr->cmdPtr = cmdPtr; - inStatePtr->csPtr = csPtr; - outStatePtr->csPtr = csPtr; + + inStatePtr->csPtrR = csPtr; + outStatePtr->csPtrW = csPtr; /* * Start copying data between the channels. @@ -8698,8 +8710,8 @@ StopCopy(csPtr) } Tcl_DecrRefCount(csPtr->cmdPtr); } - inStatePtr->csPtr = NULL; - outStatePtr->csPtr = NULL; + inStatePtr->csPtrR = NULL; + outStatePtr->csPtrW = NULL; ckfree((char*) csPtr); } diff --git a/generic/tclIO.h b/generic/tclIO.h index ea3c6e4..4564f32 100644 --- a/generic/tclIO.h +++ b/generic/tclIO.h @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclIO.h,v 1.5.4.2 2004/07/15 20:46:19 andreas_kupries Exp $ + * RCS: @(#) $Id: tclIO.h,v 1.5.4.3 2008/04/07 22:17:37 andreas_kupries Exp $ */ /* @@ -225,7 +225,8 @@ typedef struct ChannelState { int bufSize; /* What size buffers to allocate? */ Tcl_TimerToken timer; /* Handle to wakeup timer for this channel. */ - CopyState *csPtr; /* State of background copy, or NULL. */ + CopyState *csPtrR; /* State of background copy for which channel is input, or NULL. */ + CopyState *csPtrW; /* State of background copy for which channel is output, or NULL. */ Channel *topChanPtr; /* Refers to topmost channel in a stack. * Never NULL. */ Channel *bottomChanPtr; /* Refers to bottommost channel in a stack. |