summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authorandreas_kupries <akupries@shaw.ca>2008-04-07 22:53:07 (GMT)
committerandreas_kupries <akupries@shaw.ca>2008-04-07 22:53:07 (GMT)
commit2c13070f5fd97ee4c28c1843f2a551538185b453 (patch)
tree1ff321a7f8c010dfc7bee7ae53a10d5ec5a7aef5 /generic
parent2a54793003d2d7f9d4919377bdc9a1fffdeb6c45 (diff)
downloadtcl-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.c66
-rw-r--r--generic/tclIO.h5
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.