diff options
author | andreas_kupries <akupries@shaw.ca> | 2008-04-07 22:53:07 (GMT) |
---|---|---|
committer | andreas_kupries <akupries@shaw.ca> | 2008-04-07 22:53:07 (GMT) |
commit | 2c13070f5fd97ee4c28c1843f2a551538185b453 (patch) | |
tree | 1ff321a7f8c010dfc7bee7ae53a10d5ec5a7aef5 /generic | |
parent | 2a54793003d2d7f9d4919377bdc9a1fffdeb6c45 (diff) | |
download | tcl-2c13070f5fd97ee4c28c1843f2a551538185b453.zip tcl-2c13070f5fd97ee4c28c1843f2a551538185b453.tar.gz tcl-2c13070f5fd97ee4c28c1843f2a551538185b453.tar.bz2 |
* tests/io.test (io-53.10): Testcase for bi-directionaly fcopy.
* tests/chanio.test:
* 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 60d60ea..2b6138c 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.140 2008/04/07 19:42:59 andreas_kupries Exp $ + * RCS: @(#) $Id: tclIO.c,v 1.141 2008/04/07 22:53:08 andreas_kupries Exp $ */ #include "tclInt.h" @@ -222,9 +222,8 @@ static Tcl_ObjType tclChannelType = { ((objPtr)->internalRep.otherValuePtr = (void *) (storePtr)) #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))) /* *--------------------------------------------------------------------------- @@ -1317,7 +1316,8 @@ Tcl_CreateChannel( statePtr->scriptRecordPtr = 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)) { @@ -1478,13 +1478,18 @@ Tcl_StackChannel( */ if ((mask & TCL_WRITABLE) != 0) { - CopyState *csPtr; + CopyState *csPtrR; + CopyState *csPtrW; - csPtr = statePtr->csPtr; - statePtr->csPtr = NULL; + csPtrR = statePtr->csPtrR; + statePtr->csPtrR = NULL; + + csPtrW = statePtr->csPtrW; + statePtr->csPtrW = 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), "\"", NULL); @@ -1492,7 +1497,8 @@ Tcl_StackChannel( return NULL; } - statePtr->csPtr = csPtr; + statePtr->csPtrR = csPtrR; + statePtr->csPtrW = csPtrW; } /* @@ -1624,13 +1630,18 @@ Tcl_UnstackChannel( */ if (statePtr->flags & TCL_WRITABLE) { - CopyState *csPtr; + CopyState *csPtrR; + CopyState *csPtrW; + + csPtrR = statePtr->csPtrR; + statePtr->csPtrR = NULL; - csPtr = statePtr->csPtr; - statePtr->csPtr = NULL; + csPtrW = statePtr->csPtrW; + statePtr->csPtrW = NULL; if (Tcl_Flush((Tcl_Channel) chanPtr) != TCL_OK) { - statePtr->csPtr = csPtr; + statePtr->csPtrR = csPtrR; + statePtr->csPtrW = csPtrW; /* * TIP #219, Tcl Channel Reflection API. @@ -1648,7 +1659,8 @@ Tcl_UnstackChannel( return TCL_ERROR; } - statePtr->csPtr = csPtr; + statePtr->csPtrR = csPtrR; + statePtr->csPtrW = csPtrW; } /* @@ -3091,7 +3103,8 @@ Tcl_ClearChannelHandlers( * 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 @@ -7096,12 +7109,10 @@ Tcl_GetChannelOption( * 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; } @@ -7311,7 +7322,7 @@ Tcl_SetChannelOption( * 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", NULL); @@ -8498,8 +8509,9 @@ TclCopyChannel( Tcl_IncrRefCount(cmdPtr); } csPtr->cmdPtr = cmdPtr; - inStatePtr->csPtr = csPtr; - outStatePtr->csPtr = csPtr; + + inStatePtr->csPtrR = csPtr; + outStatePtr->csPtrW = csPtr; /* * Start copying data between the channels. @@ -9451,8 +9463,8 @@ StopCopy( } TclDecrRefCount(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 411f48d..662d631 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.11 2007/12/13 15:23:18 dgp Exp $ + * RCS: @(#) $Id: tclIO.h,v 1.12 2008/04/07 22:53:08 andreas_kupries Exp $ */ /* @@ -219,7 +219,8 @@ typedef struct ChannelState { * handlers ("fileevent") on this channel. */ 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. |