*** doc/CrtChannel.3 1 Jul 2002 18:24:39 -0000 1.16 --- doc/CrtChannel.3 14 Jan 2004 02:18:02 -0000 *************** *** 7,17 **** '\" '\" RCS: @(#) $Id: CrtChannel.3,v 1.16 2002/07/01 18:24:39 jenglish Exp $ .so man.macros ! .TH Tcl_CreateChannel 3 8.3 Tcl "Tcl Library Procedures" .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME ! Tcl_CreateChannel, Tcl_GetChannelInstanceData, Tcl_GetChannelType, Tcl_GetChannelName, Tcl_GetChannelHandle, Tcl_GetChannelMode, Tcl_GetChannelBufferSize, Tcl_SetChannelBufferSize, Tcl_NotifyChannel, Tcl_BadChannelOption, Tcl_ChannelName, Tcl_ChannelVersion, Tcl_ChannelBlockModeProc, Tcl_ChannelCloseProc, Tcl_ChannelClose2Proc, Tcl_ChannelInputProc, Tcl_ChannelOutputProc, Tcl_ChannelSeekProc, Tcl_ChannelWideSeekProc, Tcl_ChannelSetOptionProc, Tcl_ChannelGetOptionProc, Tcl_ChannelWatchProc, Tcl_ChannelGetHandleProc, Tcl_ChannelFlushProc, Tcl_ChannelHandlerProc, Tcl_IsChannelShared, Tcl_IsChannelRegistered, Tcl_CutChannel, Tcl_SpliceChannel, Tcl_IsChannelExisting, Tcl_ClearChannelHandlers, Tcl_GetChannelThread, Tcl_ChannelBuffered \- procedures for creating and manipulating channels .SH SYNOPSIS .nf \fB#include \fR --- 7,17 ---- '\" '\" RCS: @(#) $Id: CrtChannel.3,v 1.16 2002/07/01 18:24:39 jenglish Exp $ .so man.macros ! .TH Tcl_CreateChannel 3 8.5 Tcl "Tcl Library Procedures" .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME ! Tcl_CreateChannel, Tcl_GetChannelInstanceData, Tcl_GetChannelType, Tcl_GetChannelName, Tcl_GetChannelHandle, Tcl_GetChannelMode, Tcl_GetChannelBufferSize, Tcl_SetChannelBufferSize, Tcl_NotifyChannel, Tcl_BadChannelOption, Tcl_ChannelName, Tcl_ChannelVersion, Tcl_ChannelBlockModeProc, Tcl_ChannelCloseProc, Tcl_ChannelClose2Proc, Tcl_ChannelInputProc, Tcl_ChannelOutputProc, Tcl_ChannelSeekProc, Tcl_ChannelWideSeekProc, Tcl_ChannelSetOptionProc, Tcl_ChannelGetOptionProc, Tcl_ChannelWatchProc, Tcl_ChannelGetHandleProc, Tcl_ChannelFlushProc, Tcl_ChannelHandlerProc, Tcl_ChannelCutProc, Tcl_ChannelSpliceProc, Tcl_IsChannelShared, Tcl_IsChannelRegistered, Tcl_CutChannel, Tcl_SpliceChannel, Tcl_IsChannelExisting, Tcl_ClearChannelHandlers, Tcl_GetChannelThread, Tcl_ChannelBuffered \- procedures for creating and manipulating channels .SH SYNOPSIS .nf \fB#include \fR *************** *** 98,103 **** --- 98,113 ---- \fBTcl_ChannelWideSeekProc\fR(\fItypePtr\fR) .VE 8.4 .sp + .VS 8.5 + Tcl_DriverCutProc * + \fBTcl_ChannelCutProc\fR(\fItypePtr\fR) + .VE 8.5 + .sp + .VS 8.5 + Tcl_DriverSpliceProc * + \fBTcl_ChannelSpliceProc\fR(\fItypePtr\fR) + .VE 8.5 + .sp Tcl_DriverSetOptionProc * \fBTcl_ChannelSetOptionProc\fR(\fItypePtr\fR) .sp *************** *** 286,295 **** --- 296,313 ---- (thread)global list of all channels (of the current thread). Application to a channel still registered in some interpreter is not allowed. + .VS 8.5 + Also notifiers the driver if the \fBTcl_ChannelType\fR version is + \fBTCL_CHANNEL_VERSION_4\fR (or higher). + .VE 8.5 .PP \fBTcl_SpliceChannel\fR adds the specified \fIchannel\fR to the (thread)global list of all channels (of the current thread). Application to a channel registered in some interpreter is not allowed. + .VS 8.5 + Also notifiers the driver if the \fBTcl_ChannelType\fR version is + \fBTCL_CHANNEL_VERSION_4\fR (or higher). + .VE 8.5 .PP \fBTcl_ClearChannelHandlers\fR removes all channelhandlers and event scripts associated with the specified \fIchannel\fR, thus shutting *************** *** 323,328 **** --- 341,348 ---- Tcl_DriverFlushProc *\fIflushProc\fR; Tcl_DriverHandlerProc *\fIhandlerProc\fR; Tcl_DriverWideSeekProc *\fIwideSeekProc\fR; + Tcl_DriverCutProc *\fIcutProc\fR; + Tcl_DriverSpliceProc *\fIspliceProc\fR; } Tcl_ChannelType; .CE .PP *************** *** 344,349 **** --- 364,372 ---- .VS 8.4 \fBTcl_ChannelWideSeekProc\fR, .VE 8.4 + .VS 8.5 + \fBTcl_ChannelCutProc\fR, \fBTcl_ChannelSpliceProc\fR, + .VE 8.5 \fBTcl_ChannelSetOptionProc\fR, \fBTcl_ChannelGetOptionProc\fR, \fBTcl_ChannelWatchProc\fR, \fBTcl_ChannelGetHandleProc\fR, \fBTcl_ChannelFlushProc\fR, or \fBTcl_ChannelHandlerProc\fR. *************** *** 364,377 **** .SH VERSION .PP ! The \fIversion\fR field should be set to \fBTCL_CHANNEL_VERSION_2\fR. ! If it is not set to this value \fBTCL_CHANNEL_VERSION_3\fR, then this ! \fBTcl_ChannelType\fR is assumed to have the older structure. See \fBOLD CHANNEL TYPES\fR for more details. While Tcl will recognize ! and function with either structure, stacked channels must be of at least \fBTCL_CHANNEL_VERSION_2\fR to function correctly. .PP This value can be retrieved with \fBTcl_ChannelVersion\fR, which returns .VS 8.4 one of \fBTCL_CHANNEL_VERSION_3\fR, .VE 8.4 --- 387,411 ---- .SH VERSION .PP ! The \fIversion\fR field should be set to the version of the structure ! that you require. \fBTCL_CHANNEL_VERSION_2\fR is the minimum recommended. ! .VS 8.4 ! \fBTCL_CHANNEL_VERSION_3\fR must be set to specifiy the \fIwideSeekProc\fR member. ! .VE 8.4 ! .VS 8.5 ! \fBTCL_CHANNEL_VERSION_4\fR must be set to specifiy the \fIcutProc\fR and ! \fIspliceProc\fR members (includes \fIwideSeekProc\fR). ! .VE 8.5 ! If it is not set to any of these, then this ! \fBTcl_ChannelType\fR is assumed to have the original structure. See \fBOLD CHANNEL TYPES\fR for more details. While Tcl will recognize ! and function with either structures, stacked channels must be of at least \fBTCL_CHANNEL_VERSION_2\fR to function correctly. .PP This value can be retrieved with \fBTcl_ChannelVersion\fR, which returns + .VS 8.5 + one of \fBTCL_CHANNEL_VERSION_4\fR, + .VE 8.5 .VS 8.4 one of \fBTCL_CHANNEL_VERSION_3\fR, .VE 8.4 *************** *** 779,784 **** --- 813,847 ---- This value can be retrieved with \fBTcl_ChannelHandlerProc\fR, which returns a pointer to the function. + .VS 8.5 + .SH "CUTPROC AND SPLICEPROC" + .PP + The \fIcutProc\fR and \fIspliceProc\fR fields contain the addresses of + the functions called by the generic layer when a channel is to move to + a different thread and can be NULL. \fIcutProc\fR is used to notify the + driver that it should remove any thread-specific references it might be + maintaining. \fIcutProc\fR can also be called when the channel is closing, + too. \fIspliceProc\fR is used to notify the driver that it should update + any thread-specific references it might be maintaining using the calling + thread as the associate. See \fBTcl_CutChannel\fR and \fBTcl_SpliceChannel\fR + for more detail. + .PP + .CS + typedef void Tcl_DriverCutProc( + ClientData \fIinstanceData\fR); + .CE + .CS + typedef void Tcl_DriverSpliceProc( + ClientData \fIinstanceData\fR); + .CE + .PP + \fIInstanceData\fR is the same as the value passed to \fBTcl_CreateChannel\fR + when this channel was created. + .PP + These values can be retrieved with \fBTcl_ChannelCutProc\fR and + \fBTcl_ChannelCutProc\fR, which returns a pointer to the function. + .VE 8.5 + .SH TCL_BADCHANNELOPTION .PP This procedure generates a "bad option" error message in an *** generic/tcl.decls 29 Sep 2003 21:38:49 -0000 1.101 --- generic/tcl.decls 14 Jan 2004 02:18:05 -0000 *************** *** 1860,1865 **** --- 1860,1873 ---- Tcl_ExitProc *Tcl_SetExitProc(Tcl_ExitProc *proc) } + # davygrvy channelType ver 4 TIP#{unassigned} + declare 520 generic { + Tcl_DriverCutProc *Tcl_ChannelCutProc(Tcl_ChannelType *chanTypePtr) + } + declare 521 generic { + Tcl_DriverSpliceProc *Tcl_ChannelSpliceProc(Tcl_ChannelType *chanTypePtr) + } + ############################################################################## # Define the platform specific public Tcl interface. These functions are *** generic/tcl.h 9 Jan 2004 20:55:26 -0000 1.170 --- generic/tcl.h 14 Jan 2004 02:18:09 -0000 *************** *** 1434,1440 **** * should be closed. */ #define TCL_CLOSE_READ (1<<1) ! #define TCL_CLOSE_WRITE (1<<2) /* * Value to use as the closeProc for a channel that supports the --- 1434,1440 ---- * should be closed. */ #define TCL_CLOSE_READ (1<<1) ! #define TCL_CLOSE_WRITE (1<<2) /* * Value to use as the closeProc for a channel that supports the *************** *** 1448,1453 **** --- 1448,1454 ---- #define TCL_CHANNEL_VERSION_1 ((Tcl_ChannelTypeVersion) 0x1) #define TCL_CHANNEL_VERSION_2 ((Tcl_ChannelTypeVersion) 0x2) #define TCL_CHANNEL_VERSION_3 ((Tcl_ChannelTypeVersion) 0x3) + #define TCL_CHANNEL_VERSION_4 ((Tcl_ChannelTypeVersion) 0x4) /* * Typedefs for the various operations in a channel type: *************** *** 1482,1487 **** --- 1483,1492 ---- typedef Tcl_WideInt (Tcl_DriverWideSeekProc) _ANSI_ARGS_(( ClientData instanceData, Tcl_WideInt offset, int mode, int *errorCodePtr)); + typedef void (Tcl_DriverCutProc) _ANSI_ARGS_(( + ClientData instanceData)); + typedef void (Tcl_DriverSpliceProc) _ANSI_ARGS_(( + ClientData instanceData)); /* *************** *** 1573,1578 **** --- 1578,1594 ---- * handle 64-bit offsets. May be * NULL, and must be NULL if * seekProc is NULL. */ + /* + * Only valid in TCL_CHANNEL_VERSION_4 channels or later + */ + Tcl_DriverCutProc *cutProc; /* Procedure to call to allow the + * driver to remove any thread + * specific data. */ + Tcl_DriverSpliceProc *spliceProc; /* Procedure to call to allow the + * driver to insert new thread + * specific data on the moved + * channel. */ + } Tcl_ChannelType; /* *************** *** 1580,1587 **** * set the channel into blocking or nonblocking mode. They are passed * as arguments to the blockModeProc procedure in the above structure. */ ! #define TCL_MODE_BLOCKING 0 /* Put channel into blocking mode. */ ! #define TCL_MODE_NONBLOCKING 1 /* Put channel into nonblocking * mode. */ /* --- 1596,1603 ---- * set the channel into blocking or nonblocking mode. They are passed * as arguments to the blockModeProc procedure in the above structure. */ ! #define TCL_MODE_BLOCKING 0 /* Put channel into blocking mode. */ ! #define TCL_MODE_NONBLOCKING 1 /* Put channel into nonblocking * mode. */ /* *** generic/tclInt.h 13 Jan 2004 23:15:03 -0000 1.140 --- generic/tclInt.h 14 Jan 2004 02:18:17 -0000 *************** *** 1786,1795 **** EXTERN Tcl_Channel TclpOpenFileChannel _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *pathPtr, int mode, int permissions)); - EXTERN void TclpCutFileChannel _ANSI_ARGS_((Tcl_Channel chan)); - EXTERN void TclpCutSockChannel _ANSI_ARGS_((Tcl_Channel chan)); - EXTERN void TclpSpliceFileChannel _ANSI_ARGS_((Tcl_Channel chan)); - EXTERN void TclpSpliceSockChannel _ANSI_ARGS_((Tcl_Channel chan)); EXTERN void TclpPanic _ANSI_ARGS_(TCL_VARARGS(CONST char *, format)); EXTERN char * TclpReadlink _ANSI_ARGS_((CONST char *fileName, --- 1786,1791 ---- *** generic/tclIO.c 24 Dec 2003 04:18:19 -0000 1.69 --- generic/tclIO.c 14 Jan 2004 02:18:24 -0000 *************** *** 2388,2393 **** --- 2388,2394 ---- * channel out of the list on close. */ ChannelState *statePtr = ((Channel *) chan)->state; /* state of the channel stack. */ + Tcl_DriverCutProc *cutProc; /* * Remove this channel from of the list of all channels *************** *** 2410,2417 **** statePtr->nextCSPtr = (ChannelState *) NULL; ! TclpCutFileChannel(chan); ! TclpCutSockChannel(chan); } /* --- 2411,2420 ---- statePtr->nextCSPtr = (ChannelState *) NULL; ! cutProc = Tcl_ChannelCutProc(Tcl_GetChannelType(chan)); ! if (cutProc != NULL) { ! (*cutProc)(Tcl_GetChannelInstanceData(chan)); ! } } /* *************** *** 2448,2453 **** --- 2451,2457 ---- { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); ChannelState *statePtr = ((Channel *) chan)->state; + Tcl_DriverSpliceProc *spliceProc; if (statePtr->nextCSPtr != (ChannelState *) NULL) { Tcl_Panic("Tcl_SpliceChannel: trying to add channel used in different list"); *************** *** 2462,2471 **** * values even for a non-threaded core. */ ! statePtr->managingThread = Tcl_GetCurrentThread (); ! ! TclpSpliceFileChannel(chan); ! TclpSpliceSockChannel(chan); } /* --- 2466,2476 ---- * values even for a non-threaded core. */ ! statePtr->managingThread = Tcl_GetCurrentThread(); ! spliceProc = Tcl_ChannelSpliceProc(Tcl_GetChannelType(chan)); ! if (spliceProc != NULL) { ! (*spliceProc)(Tcl_GetChannelInstanceData(chan)); ! } } /* *************** *** 8826,8831 **** --- 8831,8838 ---- return TCL_CHANNEL_VERSION_2; } else if (chanTypePtr->version == TCL_CHANNEL_VERSION_3) { return TCL_CHANNEL_VERSION_3; + } else if (chanTypePtr->version == TCL_CHANNEL_VERSION_4) { + return TCL_CHANNEL_VERSION_4; } else { /* * In cutProc; + } else { + return NULL; + } + } + + /* + *---------------------------------------------------------------------- + * + * Tcl_ChannelSpliceProc -- + * + * Return the Tcl_DriverSpliceProc of the channel type. + * + * Results: + * A pointer to the proc. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + + Tcl_DriverSpliceProc * + Tcl_ChannelSpliceProc(chanTypePtr) + Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */ + { + if (HaveVersion(chanTypePtr, TCL_CHANNEL_VERSION_4)) { + return chanTypePtr->spliceProc; + } else { + return NULL; + } + } *** generic/tclIOGT.c 24 May 2002 21:19:06 -0000 1.7 --- generic/tclIOGT.c 14 Jan 2004 02:18:26 -0000 *************** *** 131,137 **** static Tcl_ChannelType transformChannelType = { "transform", /* Type name. */ ! TCL_CHANNEL_VERSION_2, TransformCloseProc, /* Close proc. */ TransformInputProc, /* Input proc. */ TransformOutputProc, /* Output proc. */ --- 131,137 ---- static Tcl_ChannelType transformChannelType = { "transform", /* Type name. */ ! TCL_CHANNEL_VERSION_3, TransformCloseProc, /* Close proc. */ TransformInputProc, /* Input proc. */ TransformOutputProc, /* Output proc. */ *** mac/tclMacChan.c 24 Dec 2003 04:18:21 -0000 1.22 --- mac/tclMacChan.c 14 Jan 2004 02:18:30 -0000 *************** *** 79,129 **** * Static routines for this file: */ ! static int CommonGetHandle _ANSI_ARGS_((ClientData instanceData, ! int direction, ClientData *handlePtr)); ! static void CommonWatch _ANSI_ARGS_((ClientData instanceData, ! int mask)); ! static int FileBlockMode _ANSI_ARGS_((ClientData instanceData, ! int mode)); ! static void FileChannelExitHandler _ANSI_ARGS_(( ! ClientData clientData)); ! static void FileCheckProc _ANSI_ARGS_((ClientData clientData, ! int flags)); ! static int FileClose _ANSI_ARGS_((ClientData instanceData, ! Tcl_Interp *interp)); ! static int FileEventProc _ANSI_ARGS_((Tcl_Event *evPtr, ! int flags)); ! static ThreadSpecificData *FileInit _ANSI_ARGS_((void)); ! static int FileInput _ANSI_ARGS_((ClientData instanceData, ! char *buf, int toRead, int *errorCode)); ! static int FileOutput _ANSI_ARGS_((ClientData instanceData, ! CONST char *buf, int toWrite, int *errorCode)); ! static int FileSeek _ANSI_ARGS_((ClientData instanceData, ! long offset, int mode, int *errorCode)); ! static void FileSetupProc _ANSI_ARGS_((ClientData clientData, ! int flags)); ! static Tcl_Channel OpenFileChannel _ANSI_ARGS_((CONST char *fileName, ! int mode, int permissions, int *errorCodePtr)); ! static int StdIOBlockMode _ANSI_ARGS_((ClientData instanceData, ! int mode)); ! static int StdIOClose _ANSI_ARGS_((ClientData instanceData, ! Tcl_Interp *interp)); ! static int StdIOInput _ANSI_ARGS_((ClientData instanceData, ! char *buf, int toRead, int *errorCode)); ! static int StdIOOutput _ANSI_ARGS_((ClientData instanceData, ! CONST char *buf, int toWrite, int *errorCode)); ! static int StdIOSeek _ANSI_ARGS_((ClientData instanceData, ! long offset, int mode, int *errorCode)); ! static int StdReady _ANSI_ARGS_((ClientData instanceData, ! int mask)); /* * This structure describes the channel type structure for file based IO: */ static Tcl_ChannelType consoleChannelType = { ! "file", /* Type name. */ ! (Tcl_ChannelTypeVersion)StdIOBlockMode, /* Set blocking/nonblocking mode.*/ StdIOClose, /* Close proc. */ StdIOInput, /* Input proc. */ StdIOOutput, /* Output proc. */ --- 79,117 ---- * Static routines for this file: */ ! static Tcl_DriverCutProc CommonCutProc; ! static Tcl_DriverGetHandleProc CommonGetHandle; ! static Tcl_DriverSpliceProc CommonSpliceProc; ! static Tcl_DriverWatchProc CommonWatch; ! ! static Tcl_DriverBlockModeProc FileBlockMode; ! static Tcl_ExitProc FileChannelExitHandler; ! static Tcl_EventCheckProc FileCheckProc; ! static Tcl_DriverCloseProc FileClose; ! static Tcl_EventProc FileEventProc; ! static ThreadSpecificData * FileInit _ANSI_ARGS_((void)); ! static Tcl_DriverInputProc FileInput; ! static Tcl_DriverOutputProc FileOutput; ! static Tcl_DriverSeekProc FileSeek; ! static Tcl_EventSetupProc FileSetupProc; ! static Tcl_Channel OpenFileChannel _ANSI_ARGS_(( ! CONST char *fileName, int mode, ! int permissions, int *errorCodePtr)); ! static Tcl_DriverBlockModeProc StdIOBlockMode; ! static Tcl_DriverCloseProc StdIOClose; ! static Tcl_DriverInputProc StdIOInput; ! static Tcl_DriverOutputProc StdIOOutput; ! static Tcl_DriverSeekProc StdIOSeek; ! static int StdReady _ANSI_ARGS_(( ! ClientData instanceData, int mask)); /* * This structure describes the channel type structure for file based IO: */ static Tcl_ChannelType consoleChannelType = { ! "console", /* Type name. */ ! TCL_CHANNEL_VERSION_4, /* v2 channel */ StdIOClose, /* Close proc. */ StdIOInput, /* Input proc. */ StdIOOutput, /* Output proc. */ *************** *** 131,137 **** NULL, /* Set option proc. */ NULL, /* Get option proc. */ CommonWatch, /* Initialize notifier. */ ! CommonGetHandle /* Get OS handles out of channel. */ }; /* --- 119,132 ---- NULL, /* Set option proc. */ NULL, /* Get option proc. */ CommonWatch, /* Initialize notifier. */ ! CommonGetHandle, /* Get OS handles out of channel. */ ! NULL, /* close2 proc. */ ! StdIOBlockMode, /* Set blocking/nonblocking mode.*/ ! NULL, /* flush proc. */ ! NULL, /* handler proc. */ ! NULL, /* wide seek proc. */ ! CommonCutProc, /* cut proc. */ ! CommonSpliceProc, /* splice proc. */ }; /* *************** *** 140,147 **** static Tcl_ChannelType fileChannelType = { "file", /* Type name. */ ! (Tcl_ChannelTypeVersion)FileBlockMode, /* Set blocking or ! * non-blocking mode.*/ FileClose, /* Close proc. */ FileInput, /* Input proc. */ FileOutput, /* Output proc. */ --- 135,141 ---- static Tcl_ChannelType fileChannelType = { "file", /* Type name. */ ! TCL_CHANNEL_VERSION_4, /* v4 channel */ FileClose, /* Close proc. */ FileInput, /* Input proc. */ FileOutput, /* Output proc. */ *************** *** 149,155 **** NULL, /* Set option proc. */ NULL, /* Get option proc. */ CommonWatch, /* Initialize notifier. */ ! CommonGetHandle /* Get OS handles out of channel. */ }; --- 143,156 ---- NULL, /* Set option proc. */ NULL, /* Get option proc. */ CommonWatch, /* Initialize notifier. */ ! CommonGetHandle, /* Get OS handles out of channel. */ ! NULL, /* close2 proc. */ ! FileBlockMode, /* Set blocking or non-blocking mode. */ ! NULL, /* flush proc. */ ! NULL, /* handler proc. */ ! NULL, /* wide seek proc. */ ! CommonCutProc, /* cut proc. */ ! CommonSpliceProc, /* splice proc. */ }; *************** *** 241,247 **** { FileState *infoPtr; Tcl_Time blockTime = { 0, 0 }; ! ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return; --- 242,250 ---- { FileState *infoPtr; Tcl_Time blockTime = { 0, 0 }; ! ThreadSpecificData *tsdPtr; ! ! tsdPtr = FileInit(); if (!(flags & TCL_FILE_EVENTS)) { return; *************** *** 286,292 **** FileState *infoPtr; int sentMsg = 0; Tcl_Time blockTime = { 0, 0 }; ! ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return; --- 289,297 ---- FileState *infoPtr; int sentMsg = 0; Tcl_Time blockTime = { 0, 0 }; ! ThreadSpecificData *tsdPtr; ! ! tsdPtr = FileInit(); if (!(flags & TCL_FILE_EVENTS)) { return; *************** *** 338,344 **** { FileEvent *fileEvPtr = (FileEvent *)evPtr; FileState *infoPtr; ! ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return 0; --- 343,351 ---- { FileEvent *fileEvPtr = (FileEvent *)evPtr; FileState *infoPtr; ! ThreadSpecificData *tsdPtr; ! ! tsdPtr = FileInit(); if (!(flags & TCL_FILE_EVENTS)) { return 0; *************** *** 416,422 **** Tcl_Interp *interp) /* Unused. */ { int fd, errorCode = 0; ! ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); /* * Invalidate the stdio cache if necessary. Note that we assume that --- 423,431 ---- Tcl_Interp *interp) /* Unused. */ { int fd, errorCode = 0; ! ThreadSpecificData *tsdPtr; ! ! tsdPtr = FileInit(); /* * Invalidate the stdio cache if necessary. Note that we assume that *************** *** 673,678 **** --- 682,690 ---- char channelName[16 + TCL_INTEGER_SPACE]; int channelPermissions; FileState *fileState; + ThreadSpecificData *tsdPtr; + + tsdPtr = FileInit(); /* * If the channels were not created yet, create them now and *************** *** 706,711 **** --- 718,725 ---- (ClientData) fileState, channelPermissions); fileState->fileChan = channel; fileState->fileRef = fd; + fileState->nextPtr = tsdPtr->firstFilePtr; + tsdPtr->firstFilePtr = fileState; /* * Set up the normal channel options for stdio handles. *************** *** 1212,1221 **** /* *---------------------------------------------------------------------- * ! * TclpCutFileChannel -- * ! * Remove any thread local refs to this channel. See ! * Tcl_CutChannel for more info. * * Results: * None. --- 1226,1235 ---- /* *---------------------------------------------------------------------- * ! * CommonCutProc -- * ! * Driver procedure to remove any thread local refs to this ! * channel. See Tcl_CutChannel for more info. * * Results: * None. *************** *** 1226,1247 **** *---------------------------------------------------------------------- */ ! void ! TclpCutFileChannel(chan) ! Tcl_Channel chan; /* The channel being removed. Must ! * not be referenced in any ! * interpreter. */ { ! ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); ! Channel *chanPtr = (Channel *) chan; ! FileState *infoPtr; FileState **nextPtrPtr; int removed = 0; ! if (chanPtr->typePtr != &fileChannelType) ! return; ! ! infoPtr = (FileState *) chanPtr->instanceData; for (nextPtrPtr = &(tsdPtr->firstFilePtr); (*nextPtrPtr) != NULL; nextPtrPtr = &((*nextPtrPtr)->nextPtr)) { --- 1240,1255 ---- *---------------------------------------------------------------------- */ ! static void ! CommonCutProc(instanceData) ! ClientData instanceData, /* The file state. */ { ! ThreadSpecificData *tsdPtr; ! FileState *infoPtr = (FileState *) chanPtr->instanceData; FileState **nextPtrPtr; int removed = 0; ! tsdPtr = FileInit(); for (nextPtrPtr = &(tsdPtr->firstFilePtr); (*nextPtrPtr) != NULL; nextPtrPtr = &((*nextPtrPtr)->nextPtr)) { *************** *** 1259,1275 **** */ if (!removed) { ! Tcl_Panic("file info ptr not on thread channel list"); } } /* *---------------------------------------------------------------------- * ! * TclpSpliceFileChannel -- * ! * Insert thread local ref for this channel. ! * Tcl_SpliceChannel for more info. * * Results: * None. --- 1267,1283 ---- */ if (!removed) { ! Tcl_Panic("FileState ptr not on thread channel list"); } } /* *---------------------------------------------------------------------- * ! * CommonSpliceProc -- * ! * Driver procedure to insert thread local ref for this channel. ! * See Tcl_SpliceChannel for more info. * * Results: * None. *************** *** 1280,1299 **** *---------------------------------------------------------------------- */ ! void ! TclpSpliceFileChannel(chan) ! Tcl_Channel chan; /* The channel being removed. Must ! * not be referenced in any ! * interpreter. */ { ! ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); ! Channel *chanPtr = (Channel *) chan; ! FileState *infoPtr; ! ! if (chanPtr->typePtr != &fileChannelType) ! return; ! infoPtr = (FileState *) chanPtr->instanceData; infoPtr->nextPtr = tsdPtr->firstFilePtr; tsdPtr->firstFilePtr = infoPtr; --- 1288,1301 ---- *---------------------------------------------------------------------- */ ! static void ! CommonSpliceProc(instanceData) ! ClientData instanceData, /* The file state. */ { ! ThreadSpecificData *tsdPtr; ! FileState *infoPtr = (FileState *) chanPtr->instanceData; ! tsdPtr = FileInit(); infoPtr->nextPtr = tsdPtr->firstFilePtr; tsdPtr->firstFilePtr = infoPtr; *** mac/tclMacSock.c 24 Dec 2003 04:18:21 -0000 1.16 --- mac/tclMacSock.c 14 Jan 2004 02:18:34 -0000 *************** *** 130,186 **** StreamPtr tcpStream; /* Low level Macintosh stream. */ } SocketEvent; /* * Static routines for this file: */ ! static pascal void CleanUpExitProc _ANSI_ARGS_((void)); ! static void ClearZombieSockets _ANSI_ARGS_((void)); ! static void CloseCompletionRoutine _ANSI_ARGS_((TCPiopb *pb)); ! static TcpState * CreateSocket _ANSI_ARGS_((Tcl_Interp *interp, ! int port, CONST char *host, CONST char *myAddr, ! int myPort, int server, int async)); ! static pascal void DNRCompletionRoutine _ANSI_ARGS_(( ! struct hostInfo *hostinfoPtr, ! DNRState *dnrStatePtr)); ! static void FreeSocketInfo _ANSI_ARGS_((TcpState *statePtr)); ! static long GetBufferSize _ANSI_ARGS_((void)); ! static OSErr GetHostFromString _ANSI_ARGS_((CONST char *name, ! ip_addr *address)); ! static OSErr GetLocalAddress _ANSI_ARGS_((unsigned long *addr)); ! static void IOCompletionRoutine _ANSI_ARGS_((TCPiopb *pb)); ! static void InitMacTCPParamBlock _ANSI_ARGS_((TCPiopb *pBlock, ! int csCode)); ! static void InitSockets _ANSI_ARGS_((void)); ! static TcpState * NewSocketInfo _ANSI_ARGS_((StreamPtr stream)); ! static OSErr ResolveAddress _ANSI_ARGS_((ip_addr tcpAddress, ! Tcl_DString *dsPtr)); ! static void SocketCheckProc _ANSI_ARGS_((ClientData clientData, ! int flags)); ! static int SocketEventProc _ANSI_ARGS_((Tcl_Event *evPtr, ! int flags)); ! static void SocketExitHandler _ANSI_ARGS_((ClientData clientData)); ! static void SocketFreeProc _ANSI_ARGS_((ClientData clientData)); ! static int SocketReady _ANSI_ARGS_((TcpState *statePtr)); ! static void SocketSetupProc _ANSI_ARGS_((ClientData clientData, ! int flags)); ! static void TcpAccept _ANSI_ARGS_((TcpState *statePtr)); ! static int TcpBlockMode _ANSI_ARGS_((ClientData instanceData, int mode)); ! static int TcpClose _ANSI_ARGS_((ClientData instanceData, ! Tcl_Interp *interp)); ! static int TcpGetHandle _ANSI_ARGS_((ClientData instanceData, ! int direction, ClientData *handlePtr)); ! static int TcpGetOptionProc _ANSI_ARGS_((ClientData instanceData, ! Tcl_Interp *interp, CONST char *optionName, ! Tcl_DString *dsPtr)); ! static int TcpInput _ANSI_ARGS_((ClientData instanceData, ! char *buf, int toRead, int *errorCodePtr)); ! static int TcpOutput _ANSI_ARGS_((ClientData instanceData, ! CONST char *buf, int toWrite, int *errorCodePtr)); ! static void TcpWatch _ANSI_ARGS_((ClientData instanceData, ! int mask)); ! static int WaitForSocketEvent _ANSI_ARGS_((TcpState *infoPtr, ! int mask, int *errorCodePtr)); pascal void NotifyRoutine ( StreamPtr tcpStream, --- 130,201 ---- StreamPtr tcpStream; /* Low level Macintosh stream. */ } SocketEvent; + typedef struct ThreadSpecificData { + /* + * Every open socket has an entry on the following list. + */ + + TcpState *socketList; + } ThreadSpecificData; + + static Tcl_ThreadDataKey dataKey; + /* * Static routines for this file: */ ! static pascal void CleanUpExitProc _ANSI_ARGS_((void)); ! static void ClearZombieSockets _ANSI_ARGS_((void)); ! static void CloseCompletionRoutine _ANSI_ARGS_(( ! TCPiopb *pb)); ! static TcpState * CreateSocket _ANSI_ARGS_(( ! Tcl_Interp *interp, int port, ! CONST char *host, CONST char *myAddr, ! int myPort, int server, int async)); ! static pascal void DNRCompletionRoutine _ANSI_ARGS_(( ! struct hostInfo *hostinfoPtr, ! DNRState *dnrStatePtr)); ! static void FreeSocketInfo _ANSI_ARGS_(( ! TcpState *statePtr)); ! static long GetBufferSize _ANSI_ARGS_((void)); ! static OSErr GetHostFromString _ANSI_ARGS_(( ! CONST char *name, ip_addr *address)); ! static OSErr GetLocalAddress _ANSI_ARGS_(( ! unsigned long *addr)); ! static void IOCompletionRoutine _ANSI_ARGS_(( ! TCPiopb *pb)); ! static void InitMacTCPParamBlock _ANSI_ARGS_(( ! TCPiopb *pBlock, int csCode)); ! static ThreadSpecificData * InitSockets _ANSI_ARGS_((void)); ! static TcpState * NewSocketInfo _ANSI_ARGS_(( ! StreamPtr stream)); ! static OSErr ResolveAddress _ANSI_ARGS_(( ! ip_addr tcpAddress, ! Tcl_DString *dsPtr)); ! static Tcl_EventCheckProc SocketCheckProc; ! static Tcl_EventProc SocketEventProc; ! static Tcl_ExitProc SocketExitHandler; ! static void SocketFreeProc _ANSI_ARGS_(( ! ClientData clientData)); ! static int SocketReady _ANSI_ARGS_(( ! TcpState *statePtr)); ! static void SocketSetupProc _ANSI_ARGS_(( ! ClientData clientData, int flags)); ! static void TcpAccept _ANSI_ARGS_(( ! TcpState *statePtr)); ! static Tcl_DriverBlockModeProc TcpBlockMode; ! static Tcl_DriverCloseProc TcpClose; ! static Tcl_DriverCutProc TcpCutProc; ! static Tcl_DriverGetHandleProc TcpGetHandle; ! static Tcl_DriverGetOptionProc TcpGetOptionProc; ! static Tcl_DriverInputProc TcpInput; ! static Tcl_DriverOutputProc TcpOutput; ! static Tcl_DriverSpliceProc TcpSpliceProc; ! static Tcl_DriverWatchProc TcpWatch; ! ! static int WaitForSocketEvent _ANSI_ARGS_(( ! TcpState *infoPtr, int mask, ! int *errorCodePtr)); pascal void NotifyRoutine ( StreamPtr tcpStream, *************** *** 196,203 **** static Tcl_ChannelType tcpChannelType = { "tcp", /* Type name. */ ! (Tcl_ChannelTypeVersion)TcpBlockMode, /* Set blocking or ! * non-blocking mode.*/ TcpClose, /* Close proc. */ TcpInput, /* Input proc. */ TcpOutput, /* Output proc. */ --- 211,217 ---- static Tcl_ChannelType tcpChannelType = { "tcp", /* Type name. */ ! TCL_CHANNEL_VERSION_4, TcpClose, /* Close proc. */ TcpInput, /* Input proc. */ TcpOutput, /* Output proc. */ *************** *** 205,211 **** NULL, /* Set option proc. */ TcpGetOptionProc, /* Get option proc. */ TcpWatch, /* Initialize notifier. */ ! TcpGetHandle /* Get handles out of channel. */ }; /* --- 219,232 ---- NULL, /* Set option proc. */ TcpGetOptionProc, /* Get option proc. */ TcpWatch, /* Initialize notifier. */ ! TcpGetHandle, /* Get handles out of channel. */ ! NULL, /* close2 proc. */ ! TcpBlockMode, /* Set blocking or non-blocking mode.*/ ! NULL, /* flush proc. */ ! NULL, /* handler proc. */ ! NULL, /* wide seek proc. */ ! TcpCutProc, /* cut proc. */ ! TcpSpliceProc, /* splice proc. */ }; /* *************** *** 251,266 **** {NULL, 0}, }; - typedef struct ThreadSpecificData { - /* - * Every open socket has an entry on the following list. - */ - - TcpState *socketList; - } ThreadSpecificData; - - static Tcl_ThreadDataKey dataKey; - /* * Globals for holding information about OS support for sockets. */ --- 272,277 ---- *************** *** 293,299 **** */ #define gestaltMacTCPVersion 'mtcp' ! static void InitSockets() { ParamBlockRec pb; --- 304,310 ---- */ #define gestaltMacTCPVersion 'mtcp' ! static ThreadSpecificData * InitSockets() { ParamBlockRec pb; *************** *** 371,376 **** --- 382,388 ---- Tcl_CreateEventSource(SocketSetupProc, SocketCheckProc, NULL); Tcl_CreateThreadExitHandler(SocketExitHandler, (ClientData) NULL); } + return tsdPtr; } /* *************** *** 460,466 **** { TcpState *statePtr; Tcl_Time blockTime = { 0, 0 }; ! ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return; --- 472,480 ---- { TcpState *statePtr; Tcl_Time blockTime = { 0, 0 }; ! ThreadSpecificData *tsdPtr; ! ! tsdPtr = InitSockets(); if (!(flags & TCL_FILE_EVENTS)) { return; *************** *** 507,513 **** TcpState *statePtr; SocketEvent *evPtr; TcpState dummyState; ! ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return; --- 521,529 ---- TcpState *statePtr; SocketEvent *evPtr; TcpState dummyState; ! ThreadSpecificData *tsdPtr; ! ! tsdPtr = InitSockets(); if (!(flags & TCL_FILE_EVENTS)) { return; *************** *** 869,875 **** } /* ! * It's very bad if the statePtr is nNULL - we should probably panic... */ if (statePtr == NULL) { --- 885,891 ---- } /* ! * It's very bad if the statePtr is NULL - we should probably panic... */ if (statePtr == NULL) { *************** *** 1096,1102 **** switch (err) { case noErr: /* ! * The channel remains readable only if this read succeds * and we had more data then the size of the buffer we were * trying to fill. Use the info from the call to status to * determine this. --- 1112,1118 ---- switch (err) { case noErr: /* ! * The channel remains readable only if this read succeeds * and we had more data then the size of the buffer we were * trying to fill. Use the info from the call to status to * determine this. *************** *** 1542,1547 **** --- 1558,1640 ---- /* *---------------------------------------------------------------------- * + * TcpCutProc -- + * + * Driver procedure to remove any thread local refs to this + * channel. See Tcl_CutChannel for more info. + * + * Results: + * None. + * + * Side effects: + * Changes thread local list of valid channels. + * + *---------------------------------------------------------------------- + */ + + static void + TcpCutProc(instanceData) + ClientData instanceData; /* Socket state. */ + { + ThreadSpecificData *tsdPtr; + TcpState *infoPtr = (TcpState *) instanceData; + TcpState **nextPtrPtr; + int removed = 0; + + tsdPtr = InitSockets(); + + for (nextPtrPtr = &(tsdPtr->socketList); (*nextPtrPtr) != NULL; + nextPtrPtr = &((*nextPtrPtr)->nextPtr)) { + if ((*nextPtrPtr) == infoPtr) { + (*nextPtrPtr) = infoPtr->nextPtr; + removed = 1; + break; + } + } + + /* + * This could happen if the channel was created in one thread + * and then moved to another without updating the thread + * local data in each thread. + */ + + if (!removed) + Tcl_Panic("TcpState info ptr not on thread channel list"); + } + + /* + *---------------------------------------------------------------------- + * + * TcpSpliceProc -- + * + * Driver procedure to insert thread local ref for this channel. + * See Tcl_SpliceChannel for more info. + * + * Results: + * None. + * + * Side effects: + * Changes thread local list of valid channels. + * + *---------------------------------------------------------------------- + */ + + static void + TcpSpliceProc(instanceData) + ClientData instanceData; /* Socket state. */ + { + ThreadSpecificData *tsdPtr; + TcpState *infoPtr = (TcpState *) instanceData; + + tsdPtr = InitSockets(); + + infoPtr->nextPtr = tsdPtr->socketList; + tsdPtr->socketList = infoPtr; + } + + /* + *---------------------------------------------------------------------- + * * NewSocketInfo -- * * This function allocates and initializes a new SocketInfo *************** *** 1561,1567 **** StreamPtr tcpStream) { TcpState *statePtr; ! ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); statePtr = (TcpState *) ckalloc((unsigned) sizeof(TcpState)); statePtr->tcpStream = tcpStream; --- 1654,1662 ---- StreamPtr tcpStream) { TcpState *statePtr; ! ThreadSpecificData *tsdPtr; ! ! tsdPtr = InitSockets(); statePtr = (TcpState *) ckalloc((unsigned) sizeof(TcpState)); statePtr->tcpStream = tcpStream; *************** *** 1599,1605 **** FreeSocketInfo( TcpState *statePtr) /* The state pointer to free. */ { ! ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (statePtr == tsdPtr->socketList) { tsdPtr->socketList = statePtr->nextPtr; --- 1694,1702 ---- FreeSocketInfo( TcpState *statePtr) /* The state pointer to free. */ { ! ThreadSpecificData *tsdPtr; ! ! tsdPtr = InitSockets(); if (statePtr == tsdPtr->socketList) { tsdPtr->socketList = statePtr->nextPtr; *************** *** 1987,1993 **** TcpState *statePtr; SocketEvent *eventPtr = (SocketEvent *) evPtr; int mask = 0; ! ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return 0; --- 2084,2092 ---- TcpState *statePtr; SocketEvent *eventPtr = (SocketEvent *) evPtr; int mask = 0; ! ThreadSpecificData *tsdPtr; ! ! tsdPtr = InitSockets(); if (!(flags & TCL_FILE_EVENTS)) { return 0; *************** *** 2743,2749 **** ClearZombieSockets() { TcpState *statePtr; ! ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); for (statePtr = tsdPtr->socketList; statePtr != NULL; statePtr = statePtr->nextPtr) { --- 2842,2850 ---- ClearZombieSockets() { TcpState *statePtr; ! ThreadSpecificData *tsdPtr; ! ! tsdPtr = InitSockets(); for (statePtr = tsdPtr->socketList; statePtr != NULL; statePtr = statePtr->nextPtr) { *************** *** 2790,2881 **** localIcmpMsg = *icmpMsg; } - - /* - *---------------------------------------------------------------------- - * - * TclpCutSockChannel -- - * - * Remove any thread local refs to this channel. See - * Tcl_CutChannel for more info. - * - * Results: - * None. - * - * Side effects: - * Changes thread local list of valid channels. - * - *---------------------------------------------------------------------- - */ - - void - TclpCutSockChannel(chan) - Tcl_Channel chan; - { - ThreadSpecificData *tsdPtr; - TcpState *infoPtr; - TcpState **nextPtrPtr; - int removed = 0; - - if (Tcl_GetChannelType(chan) != &tcpChannelType) - return; - - tsdPtr = TCL_TSD_INIT(&dataKey); - infoPtr = (TcpState *) Tcl_GetChannelInstanceData (chan); - - for (nextPtrPtr = &(tsdPtr->socketList); (*nextPtrPtr) != NULL; - nextPtrPtr = &((*nextPtrPtr)->nextPtr)) { - if ((*nextPtrPtr) == infoPtr) { - (*nextPtrPtr) = infoPtr->nextPtr; - removed = 1; - break; - } - } - - /* - * This could happen if the channel was created in one thread - * and then moved to another without updating the thread - * local data in each thread. - */ - - if (!removed) - Tcl_Panic("file info ptr not on thread channel list"); - return; - } - - /* - *---------------------------------------------------------------------- - * - * TclpSpliceSockChannel -- - * - * Insert thread local ref for this channel. - * Tcl_SpliceChannel for more info. - * - * Results: - * None. - * - * Side effects: - * Changes thread local list of valid channels. - * - *---------------------------------------------------------------------- - */ - - void - TclpSpliceSockChannel(chan) - Tcl_Channel chan; - { - ThreadSpecificData *tsdPtr; - TcpState *infoPtr; - - if (Tcl_GetChannelType(chan) != &tcpChannelType) - return; - - InitSockets (); - - tsdPtr = TCL_TSD_INIT(&dataKey); - infoPtr = (TcpState *) Tcl_GetChannelInstanceData (chan); - - infoPtr->nextPtr = tsdPtr->socketList; - tsdPtr->socketList = infoPtr; - } - --- 2891,2893 ---- *** unix/tclUnixChan.c 24 Dec 2003 04:18:22 -0000 1.45 --- unix/tclUnixChan.c 14 Jan 2004 02:18:37 -0000 *************** *** 231,302 **** * Static routines for this file: */ ! static TcpState * CreateSocket _ANSI_ARGS_((Tcl_Interp *interp, ! int port, CONST char *host, int server, ! CONST char *myaddr, int myport, int async)); ! static int CreateSocketAddress _ANSI_ARGS_( ! (struct sockaddr_in *sockaddrPtr, ! CONST char *host, int port)); ! static int FileBlockModeProc _ANSI_ARGS_(( ! ClientData instanceData, int mode)); ! static int FileCloseProc _ANSI_ARGS_((ClientData instanceData, ! Tcl_Interp *interp)); ! static int FileGetHandleProc _ANSI_ARGS_((ClientData instanceData, ! int direction, ClientData *handlePtr)); ! static int FileInputProc _ANSI_ARGS_((ClientData instanceData, ! char *buf, int toRead, int *errorCode)); ! static int FileOutputProc _ANSI_ARGS_(( ! ClientData instanceData, CONST char *buf, ! int toWrite, int *errorCode)); ! static int FileSeekProc _ANSI_ARGS_((ClientData instanceData, ! long offset, int mode, int *errorCode)); ! static Tcl_WideInt FileWideSeekProc _ANSI_ARGS_((ClientData instanceData, ! Tcl_WideInt offset, int mode, int *errorCode)); ! static void FileWatchProc _ANSI_ARGS_((ClientData instanceData, ! int mask)); ! static void TcpAccept _ANSI_ARGS_((ClientData data, int mask)); ! static int TcpBlockModeProc _ANSI_ARGS_((ClientData data, ! int mode)); ! static int TcpCloseProc _ANSI_ARGS_((ClientData instanceData, ! Tcl_Interp *interp)); ! static int TcpGetHandleProc _ANSI_ARGS_((ClientData instanceData, ! int direction, ClientData *handlePtr)); ! static int TcpGetOptionProc _ANSI_ARGS_((ClientData instanceData, ! Tcl_Interp *interp, CONST char *optionName, ! Tcl_DString *dsPtr)); ! static int TcpInputProc _ANSI_ARGS_((ClientData instanceData, ! char *buf, int toRead, int *errorCode)); ! static int TcpOutputProc _ANSI_ARGS_((ClientData instanceData, ! CONST char *buf, int toWrite, int *errorCode)); ! static void TcpWatchProc _ANSI_ARGS_((ClientData instanceData, ! int mask)); #ifdef SUPPORTS_TTY ! static int TtyCloseProc _ANSI_ARGS_((ClientData instanceData, ! Tcl_Interp *interp)); ! static void TtyGetAttributes _ANSI_ARGS_((int fd, ! TtyAttrs *ttyPtr)); ! static int TtyGetOptionProc _ANSI_ARGS_((ClientData instanceData, ! Tcl_Interp *interp, CONST char *optionName, ! Tcl_DString *dsPtr)); ! static FileState * TtyInit _ANSI_ARGS_((int fd, int initialize)); #if BAD_TIP35_FLUSH ! static int TtyOutputProc _ANSI_ARGS_((ClientData instanceData, ! CONST char *buf, int toWrite, int *errorCode)); #endif /* BAD_TIP35_FLUSH */ ! static int TtyParseMode _ANSI_ARGS_((Tcl_Interp *interp, ! CONST char *mode, int *speedPtr, int *parityPtr, ! int *dataPtr, int *stopPtr)); ! static void TtySetAttributes _ANSI_ARGS_((int fd, ! TtyAttrs *ttyPtr)); ! static int TtySetOptionProc _ANSI_ARGS_((ClientData instanceData, ! Tcl_Interp *interp, CONST char *optionName, ! CONST char *value)); #endif /* SUPPORTS_TTY */ ! static int WaitForConnect _ANSI_ARGS_((TcpState *statePtr, ! int *errorCodePtr)); ! static Tcl_Channel MakeTcpClientChannelMode _ANSI_ARGS_( ! (ClientData tcpSocket, ! int mode)); /* --- 231,286 ---- * Static routines for this file: */ ! static TcpState * CreateSocket _ANSI_ARGS_(( ! Tcl_Interp *interp, int port, ! CONST char *host, int server, ! CONST char *myaddr, int myport, ! int async)); ! static int CreateSocketAddress _ANSI_ARGS_( ! (struct sockaddr_in *sockaddrPtr, ! CONST char *host, int port)); ! static Tcl_DriverBlockModeProc FileBlockModeProc; ! static Tcl_DriverCloseProc FileCloseProc; ! static Tcl_DriverCutProc FileCutProc; ! static Tcl_DriverGetHandleProc FileGetHandleProc; ! static Tcl_DriverInputProc FileInputProc; ! static Tcl_DriverOutputProc FileOutputProc); ! static Tcl_DriverSeekProc FileSeekProc; ! static Tcl_DriverSpliceProc FileSpliceProc; ! static Tcl_DriverWideSeekProc FileWideSeekProc; ! static Tcl_DriverWatchProc FileWatchProc; ! static void TcpAccept _ANSI_ARGS_((ClientData data, ! int mask)); ! static Tcl_DriverBlockModeProc TcpBlockModeProc; ! static Tcl_DriverCloseProc TcpCloseProc; ! static Tcl_DriverGetHandleProc TcpGetHandleProc; ! static Tcl_DriverGetOptionProc TcpGetOptionProc; ! static Tcl_DriverInputProc TcpInputProc; ! static Tcl_DriverOutputProc TcpOutputProc; ! static Tcl_DriverWatchProc TcpWatchProc; #ifdef SUPPORTS_TTY ! static Tcl_DriverCloseProc TtyCloseProc; ! static void TtyGetAttributes _ANSI_ARGS_((int fd, ! TtyAttrs *ttyPtr)); ! static Tcl_DriverGetOptionProc TtyGetOptionProc; ! static FileState * TtyInit _ANSI_ARGS_((int fd, ! int initialize)); #if BAD_TIP35_FLUSH ! static Tcl_DriverOutputProc TtyOutputProc; #endif /* BAD_TIP35_FLUSH */ ! static int TtyParseMode _ANSI_ARGS_(( ! Tcl_Interp *interp, CONST char *mode, ! int *speedPtr, int *parityPtr, ! int *dataPtr, int *stopPtr)); ! static void TtySetAttributes _ANSI_ARGS_((int fd, ! TtyAttrs *ttyPtr)); ! static Tcl_DriverSetOptionProc TtySetOptionProc; #endif /* SUPPORTS_TTY */ ! static int WaitForConnect _ANSI_ARGS_(( ! TcpState *statePtr, ! int *errorCodePtr)); ! static Tcl_Channel MakeTcpClientChannelMode _ANSI_ARGS_(( ! ClientData tcpSocket, int mode)); /* *************** *** 305,311 **** static Tcl_ChannelType fileChannelType = { "file", /* Type name. */ ! TCL_CHANNEL_VERSION_3, /* v3 channel */ FileCloseProc, /* Close proc. */ FileInputProc, /* Input proc. */ FileOutputProc, /* Output proc. */ --- 289,295 ---- static Tcl_ChannelType fileChannelType = { "file", /* Type name. */ ! TCL_CHANNEL_VERSION_4, /* v4 channel */ FileCloseProc, /* Close proc. */ FileInputProc, /* Input proc. */ FileOutputProc, /* Output proc. */ *************** *** 319,324 **** --- 303,310 ---- NULL, /* flush proc. */ NULL, /* handler proc. */ FileWideSeekProc, /* wide seek proc. */ + FileCutProc, /* cut proc. */ + FileSpliceProc, /* splice proc. */ }; #ifdef SUPPORTS_TTY *************** *** 735,740 **** --- 721,805 ---- return TCL_ERROR; } } + + /* + *---------------------------------------------------------------------- + * + * FileCutProc -- + * + * Driver procedure to remove any thread local refs to this + * channel. See Tcl_CutChannel for more info. + * + * Results: + * None. + * + * Side effects: + * Changes thread local list of valid channels. + * + *---------------------------------------------------------------------- + */ + + static void + FileCutProc(instanceData) + ClientData instanceData; /* The file state. */ + { + #ifdef DEPRECATED + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + FileState *fsPtr = (FileState *) instanceData;; + FileState **nextPtrPtr; + int removed = 0; + + for (nextPtrPtr = &(tsdPtr->firstFilePtr); (*nextPtrPtr) != NULL; + nextPtrPtr = &((*nextPtrPtr)->nextPtr)) { + if ((*nextPtrPtr) == fsPtr) { + (*nextPtrPtr) = fsPtr->nextPtr; + removed = 1; + break; + } + } + + /* + * This could happen if the channel was created in one thread + * and then moved to another without updating the thread + * local data in each thread. + */ + + if (!removed) { + Tcl_Panic("FileState ptr not on thread channel list"); + } + + #endif /* DEPRECATED */ + } + + /* + *---------------------------------------------------------------------- + * + * FileSpliceProc -- + * + * Driver procedure to insert thread local ref for this channel. + * Tcl_SpliceChannel for more info. + * + * Results: + * None. + * + * Side effects: + * Changes thread local list of valid channels. + * + *---------------------------------------------------------------------- + */ + + static void + FileSpliceProc(instanceData) + ClientData instanceData; /* The file state. */ + { + #ifdef DEPRECATED + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + FileState *fsPtr = (FileState *) instanceData; + + fsPtr->nextPtr = tsdPtr->firstFilePtr; + tsdPtr->firstFilePtr = fsPtr; + #endif /* DEPRECATED */ + } #ifdef SUPPORTS_TTY *************** *** 3272,3369 **** } return result; } - - /* - *---------------------------------------------------------------------- - * - * TclpCutFileChannel -- - * - * Remove any thread local refs to this channel. See - * Tcl_CutChannel for more info. - * - * Results: - * None. - * - * Side effects: - * Changes thread local list of valid channels. - * - *---------------------------------------------------------------------- - */ - - void - TclpCutFileChannel(chan) - Tcl_Channel chan; /* The channel being removed. Must - * not be referenced in any - * interpreter. */ - { - #ifdef DEPRECATED - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - Channel *chanPtr = (Channel *) chan; - FileState *fsPtr; - FileState **nextPtrPtr; - int removed = 0; - - if (chanPtr->typePtr != &fileChannelType) - return; - - fsPtr = (FileState *) chanPtr->instanceData; - - for (nextPtrPtr = &(tsdPtr->firstFilePtr); (*nextPtrPtr) != NULL; - nextPtrPtr = &((*nextPtrPtr)->nextPtr)) { - if ((*nextPtrPtr) == fsPtr) { - (*nextPtrPtr) = fsPtr->nextPtr; - removed = 1; - break; - } - } - - /* - * This could happen if the channel was created in one thread - * and then moved to another without updating the thread - * local data in each thread. - */ - - if (!removed) { - Tcl_Panic("file info ptr not on thread channel list"); - } - - #endif /* DEPRECATED */ - } - - /* - *---------------------------------------------------------------------- - * - * TclpSpliceFileChannel -- - * - * Insert thread local ref for this channel. - * Tcl_SpliceChannel for more info. - * - * Results: - * None. - * - * Side effects: - * Changes thread local list of valid channels. - * - *---------------------------------------------------------------------- - */ - - void - TclpSpliceFileChannel(chan) - Tcl_Channel chan; /* The channel being removed. Must - * not be referenced in any - * interpreter. */ - { - #ifdef DEPRECATED - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - Channel *chanPtr = (Channel *) chan; - FileState *fsPtr; - - if (chanPtr->typePtr != &fileChannelType) - return; - - fsPtr = (FileState *) chanPtr->instanceData; - - fsPtr->nextPtr = tsdPtr->firstFilePtr; - tsdPtr->firstFilePtr = fsPtr; - #endif /* DEPRECATED */ - } --- 3337,3339 ---- *** unix/tclUnixSock.c 22 Apr 2003 23:20:43 -0000 1.7 --- unix/tclUnixSock.c 14 Jan 2004 02:18:39 -0000 *************** *** 148,196 **** { return TCL_OK; } - - /* - *---------------------------------------------------------------------- - * - * TclpCutSockChannel -- - * - * Remove any thread local refs to this channel. See - * Tcl_CutChannel for more info. Dummy definition. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - - void - TclpCutSockChannel(chan) - Tcl_Channel chan; - { - } - - /* - *---------------------------------------------------------------------- - * - * TclpSpliceSockChannel -- - * - * Insert thread local ref for this channel. - * Tcl_SpliceChannel for more info. Dummy definition. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - - void - TclpSpliceSockChannel(chan) - Tcl_Channel chan; - { - } --- 148,150 ---- *** win/tclWinChan.c 24 Dec 2003 04:18:22 -0000 1.33 --- win/tclWinChan.c 14 Jan 2004 02:18:41 -0000 *************** *** 73,103 **** * Static routines for this file: */ ! static int FileBlockProc _ANSI_ARGS_((ClientData instanceData, ! int mode)); ! static void FileChannelExitHandler _ANSI_ARGS_(( ! ClientData clientData)); ! static void FileCheckProc _ANSI_ARGS_((ClientData clientData, ! int flags)); ! static int FileCloseProc _ANSI_ARGS_((ClientData instanceData, ! Tcl_Interp *interp)); ! static int FileEventProc _ANSI_ARGS_((Tcl_Event *evPtr, ! int flags)); ! static int FileGetHandleProc _ANSI_ARGS_((ClientData instanceData, ! int direction, ClientData *handlePtr)); ! static ThreadSpecificData *FileInit _ANSI_ARGS_((void)); ! static int FileInputProc _ANSI_ARGS_((ClientData instanceData, ! char *buf, int toRead, int *errorCode)); ! static int FileOutputProc _ANSI_ARGS_((ClientData instanceData, ! CONST char *buf, int toWrite, int *errorCode)); ! static int FileSeekProc _ANSI_ARGS_((ClientData instanceData, ! long offset, int mode, int *errorCode)); ! static Tcl_WideInt FileWideSeekProc _ANSI_ARGS_((ClientData instanceData, ! Tcl_WideInt offset, int mode, int *errorCode)); ! static void FileSetupProc _ANSI_ARGS_((ClientData clientData, ! int flags)); ! static void FileWatchProc _ANSI_ARGS_((ClientData instanceData, ! int mask)); /* --- 73,93 ---- * Static routines for this file: */ ! static Tcl_DriverBlockModeProc FileBlockProc; ! static Tcl_ExitProc FileChannelExitHandler; ! static Tcl_EventCheckProc FileCheckProc; ! static Tcl_DriverCloseProc FileCloseProc; ! static Tcl_DriverCutProc FileCutProc; ! static Tcl_EventProc FileEventProc; ! static Tcl_DriverGetHandleProc FileGetHandleProc; ! static ThreadSpecificData * FileInit _ANSI_ARGS_((void)); ! static Tcl_DriverInputProc FileInputProc; ! static Tcl_DriverOutputProc FileOutputProc; ! static Tcl_DriverSeekProc FileSeekProc; ! static Tcl_DriverWideSeekProc FileWideSeekProc; ! static Tcl_EventSetupProc FileSetupProc; ! static Tcl_DriverSpliceProc FileSpliceProc; ! static Tcl_DriverWatchProc FileWatchProc; /* *************** *** 106,112 **** static Tcl_ChannelType fileChannelType = { "file", /* Type name. */ ! TCL_CHANNEL_VERSION_3, /* v3 channel */ FileCloseProc, /* Close proc. */ FileInputProc, /* Input proc. */ FileOutputProc, /* Output proc. */ --- 96,102 ---- static Tcl_ChannelType fileChannelType = { "file", /* Type name. */ ! TCL_CHANNEL_VERSION_4, /* v4 channel */ FileCloseProc, /* Close proc. */ FileInputProc, /* Input proc. */ FileOutputProc, /* Output proc. */ *************** *** 120,125 **** --- 110,117 ---- NULL, /* flush proc. */ NULL, /* handler proc. */ FileWideSeekProc, /* Wide seek proc. */ + FileCutProc, /* cut proc. */ + FileSpliceProc, /* splice proc. */ }; #if defined(HAVE_NO_SEH) && defined(TCL_MEM_DEBUG) *************** *** 181,187 **** static void FileChannelExitHandler(clientData) ! ClientData clientData; /* Old window proc */ { Tcl_DeleteEventSource(FileSetupProc, FileCheckProc, NULL); } --- 173,179 ---- static void FileChannelExitHandler(clientData) ! ClientData clientData; /* Not used. */ { Tcl_DeleteEventSource(FileSetupProc, FileCheckProc, NULL); } *************** *** 210,216 **** { FileInfo *infoPtr; Tcl_Time blockTime = { 0, 0 }; ! ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return; --- 202,210 ---- { FileInfo *infoPtr; Tcl_Time blockTime = { 0, 0 }; ! ThreadSpecificData *tsdPtr; ! ! tsdPtr = FileInit(); if (!(flags & TCL_FILE_EVENTS)) { return; *************** *** 253,259 **** { FileEvent *evPtr; FileInfo *infoPtr; ! ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return; --- 247,255 ---- { FileEvent *evPtr; FileInfo *infoPtr; ! ThreadSpecificData *tsdPtr; ! ! tsdPtr = FileInit(); if (!(flags & TCL_FILE_EVENTS)) { return; *************** *** 305,311 **** { FileEvent *fileEvPtr = (FileEvent *)evPtr; FileInfo *infoPtr; ! ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return 0; --- 301,309 ---- { FileEvent *fileEvPtr = (FileEvent *)evPtr; FileInfo *infoPtr; ! ThreadSpecificData *tsdPtr; ! ! tsdPtr = FileInit(); if (!(flags & TCL_FILE_EVENTS)) { return 0; *************** *** 720,733 **** return TCL_ERROR; } } /* *---------------------------------------------------------------------- * * TclpOpenFileChannel -- * ! * Open an File based channel on Unix systems. * * Results: * The new channel or NULL. If NULL, the output argument --- 718,808 ---- return TCL_ERROR; } } + + /* + *---------------------------------------------------------------------- + * + * FileCutProc -- + * + * Driver procedure to remove any thread local refs to this + * channel. See Tcl_CutChannel for more info. + * + * Results: + * None. + * + * Side effects: + * Changes thread local list of valid channels. + * + *---------------------------------------------------------------------- + */ + + static void + FileCutProc(instanceData) + ClientData instanceData; /* The file state. */ + { + ThreadSpecificData *tsdPtr; + FileInfo *infoPtr = (FileInfo *) instanceData; + FileInfo **nextPtrPtr; + int removed = 0; + + tsdPtr = FileInit(); + + for (nextPtrPtr = &(tsdPtr->firstFilePtr); (*nextPtrPtr) != NULL; + nextPtrPtr = &((*nextPtrPtr)->nextPtr)) { + if ((*nextPtrPtr) == infoPtr) { + (*nextPtrPtr) = infoPtr->nextPtr; + removed = 1; + break; + } + } + + /* + * This could happen if the channel was created in one thread + * and then moved to another without updating the thread + * local data in each thread. + */ + + if (!removed) { + Tcl_Panic("file info ptr not on thread channel list"); + } + } + + /* + *---------------------------------------------------------------------- + * + * FileSpliceProc -- + * + * Insert thread local ref for this channel. + * Tcl_SpliceChannel for more info. + * + * Results: + * None. + * + * Side effects: + * Changes thread local list of valid channels. + * + *---------------------------------------------------------------------- + */ + + static void + FileSpliceProc(instanceData) + ClientData instanceData; /* The file state. */ + { + ThreadSpecificData *tsdPtr; + FileInfo *infoPtr = (FileInfo *) instanceData; + tsdPtr = FileInit(); + + infoPtr->nextPtr = tsdPtr->firstFilePtr; + tsdPtr->firstFilePtr = infoPtr; + } /* *---------------------------------------------------------------------- * * TclpOpenFileChannel -- * ! * Open a file based channel on Win32 systems. * * Results: * The new channel or NULL. If NULL, the output argument *************** *** 1338,1430 **** } } } - - /* - *---------------------------------------------------------------------- - * - * TclpCutFileChannel -- - * - * Remove any thread local refs to this channel. See - * Tcl_CutChannel for more info. - * - * Results: - * None. - * - * Side effects: - * Changes thread local list of valid channels. - * - *---------------------------------------------------------------------- - */ - - void - TclpCutFileChannel(chan) - Tcl_Channel chan; /* The channel being removed. Must - * not be referenced in any - * interpreter. */ - { - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - Channel *chanPtr = (Channel *) chan; - FileInfo *infoPtr; - FileInfo **nextPtrPtr; - int removed = 0; - - if (chanPtr->typePtr != &fileChannelType) - return; - - infoPtr = (FileInfo *) chanPtr->instanceData; - - for (nextPtrPtr = &(tsdPtr->firstFilePtr); (*nextPtrPtr) != NULL; - nextPtrPtr = &((*nextPtrPtr)->nextPtr)) { - if ((*nextPtrPtr) == infoPtr) { - (*nextPtrPtr) = infoPtr->nextPtr; - removed = 1; - break; - } - } - - /* - * This could happen if the channel was created in one thread - * and then moved to another without updating the thread - * local data in each thread. - */ - - if (!removed) { - Tcl_Panic("file info ptr not on thread channel list"); - } - } - - /* - *---------------------------------------------------------------------- - * - * TclpSpliceFileChannel -- - * - * Insert thread local ref for this channel. - * Tcl_SpliceChannel for more info. - * - * Results: - * None. - * - * Side effects: - * Changes thread local list of valid channels. - * - *---------------------------------------------------------------------- - */ - - void - TclpSpliceFileChannel(chan) - Tcl_Channel chan; /* The channel being removed. Must - * not be referenced in any - * interpreter. */ - { - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - Channel *chanPtr = (Channel *) chan; - FileInfo *infoPtr; - - if (chanPtr->typePtr != &fileChannelType) - return; - - infoPtr = (FileInfo *) chanPtr->instanceData; - - infoPtr->nextPtr = tsdPtr->firstFilePtr; - tsdPtr->firstFilePtr = infoPtr; - } --- 1413,1415 ---- *** win/tclWinConsole.c 26 Nov 2002 22:41:58 -0000 1.11 --- win/tclWinConsole.c 14 Jan 2004 02:18:43 -0000 *************** *** 140,164 **** * Declarations for functions used only in this file. */ ! static int ConsoleBlockModeProc(ClientData instanceData, int mode); ! static void ConsoleCheckProc(ClientData clientData, int flags); ! static int ConsoleCloseProc(ClientData instanceData, ! Tcl_Interp *interp); ! static int ConsoleEventProc(Tcl_Event *evPtr, int flags); ! static void ConsoleExitHandler(ClientData clientData); ! static int ConsoleGetHandleProc(ClientData instanceData, ! int direction, ClientData *handlePtr); ! static ThreadSpecificData *ConsoleInit(void); ! static int ConsoleInputProc(ClientData instanceData, char *buf, ! int toRead, int *errorCode); ! static int ConsoleOutputProc(ClientData instanceData, ! CONST char *buf, int toWrite, int *errorCode); ! static DWORD WINAPI ConsoleReaderThread(LPVOID arg); ! static void ConsoleSetupProc(ClientData clientData, int flags); ! static void ConsoleWatchProc(ClientData instanceData, int mask); ! static DWORD WINAPI ConsoleWriterThread(LPVOID arg); ! static void ProcExitHandler(ClientData clientData); ! static int WaitForRead(ConsoleInfo *infoPtr, int blocking); /* * This structure describes the channel type structure for command console --- 140,163 ---- * Declarations for functions used only in this file. */ ! static Tcl_DriverBlockModeProc ConsoleBlockModeProc; ! static Tcl_EventCheckProc ConsoleCheckProc; ! static Tcl_DriverCloseProc ConsoleCloseProc; ! static Tcl_DriverCutProc ConsoleCutProc; ! static Tcl_EventProc ConsoleEventProc; ! static Tcl_ExitProc ConsoleExitHandler; ! static Tcl_DriverGetHandleProc ConsoleGetHandleProc; ! static ThreadSpecificData * ConsoleInit(void); ! static Tcl_DriverInputProc ConsoleInputProc; ! static Tcl_DriverOutputProc ConsoleOutputProc; ! static DWORD WINAPI ConsoleReaderThread(LPVOID arg); ! static Tcl_EventSetupProc ConsoleSetupProc; ! static Tcl_DriverSpliceProc ConsoleSpliceProc; ! static Tcl_DriverWatchProc ConsoleWatchProc; ! static DWORD WINAPI ConsoleWriterThread(LPVOID arg); ! static Tcl_ExitProc ProcExitHandler; ! static int WaitForRead(ConsoleInfo *infoPtr, ! int blocking); /* * This structure describes the channel type structure for command console *************** *** 167,173 **** static Tcl_ChannelType consoleChannelType = { "console", /* Type name. */ ! TCL_CHANNEL_VERSION_2, /* v2 channel */ ConsoleCloseProc, /* Close proc. */ ConsoleInputProc, /* Input proc. */ ConsoleOutputProc, /* Output proc. */ --- 166,172 ---- static Tcl_ChannelType consoleChannelType = { "console", /* Type name. */ ! TCL_CHANNEL_VERSION_4, /* v4 channel */ ConsoleCloseProc, /* Close proc. */ ConsoleInputProc, /* Input proc. */ ConsoleOutputProc, /* Output proc. */ *************** *** 180,185 **** --- 179,187 ---- ConsoleBlockModeProc, /* Set blocking or non-blocking mode.*/ NULL, /* flush proc. */ NULL, /* handler proc. */ + NULL, /* wide seek proc. */ + ConsoleCutProc, /* cut proc. */ + ConsoleSpliceProc, /* splice proc. */ }; /* *************** *** 246,252 **** static void ConsoleExitHandler( ! ClientData clientData) /* Old window proc */ { Tcl_DeleteEventSource(ConsoleSetupProc, ConsoleCheckProc, NULL); } --- 248,254 ---- static void ConsoleExitHandler( ! ClientData clientData) /* Not used. */ { Tcl_DeleteEventSource(ConsoleSetupProc, ConsoleCheckProc, NULL); } *************** *** 270,276 **** static void ProcExitHandler( ! ClientData clientData) /* Old window proc */ { Tcl_MutexLock(&consoleMutex); initialized = 0; --- 272,278 ---- static void ProcExitHandler( ! ClientData clientData) /* Not used. */ { Tcl_MutexLock(&consoleMutex); initialized = 0; *************** *** 302,308 **** ConsoleInfo *infoPtr; Tcl_Time blockTime = { 0, 0 }; int block = 1; ! ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return; --- 304,312 ---- ConsoleInfo *infoPtr; Tcl_Time blockTime = { 0, 0 }; int block = 1; ! ThreadSpecificData *tsdPtr; ! ! tsdPtr = ConsoleInit(); if (!(flags & TCL_FILE_EVENTS)) { return; *************** *** 355,361 **** ConsoleInfo *infoPtr; ConsoleEvent *evPtr; int needEvent; ! ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return; --- 359,367 ---- ConsoleInfo *infoPtr; ConsoleEvent *evPtr; int needEvent; ! ThreadSpecificData *tsdPtr; ! ! tsdPtr = ConsoleInit(); if (!(flags & TCL_FILE_EVENTS)) { return; *************** *** 463,479 **** ConsoleInfo *consolePtr = (ConsoleInfo *) instanceData; int errorCode; ConsoleInfo *infoPtr, **nextPtrPtr; ! ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); DWORD exitCode; errorCode = 0; ! /* * Clean up the background thread if necessary. Note that this * must be done before we can close the file, since the * thread may be blocking trying to read from the console. */ ! if (consolePtr->readThread) { /* --- 469,486 ---- ConsoleInfo *consolePtr = (ConsoleInfo *) instanceData; int errorCode; ConsoleInfo *infoPtr, **nextPtrPtr; ! ThreadSpecificData *tsdPtr; DWORD exitCode; errorCode = 0; ! tsdPtr = ConsoleInit(); ! /* * Clean up the background thread if necessary. Note that this * must be done before we can close the file, since the * thread may be blocking trying to read from the console. */ ! if (consolePtr->readThread) { /* *************** *** 832,838 **** ConsoleEvent *consoleEvPtr = (ConsoleEvent *)evPtr; ConsoleInfo *infoPtr; int mask; ! ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return 0; --- 839,847 ---- ConsoleEvent *consoleEvPtr = (ConsoleEvent *)evPtr; ConsoleInfo *infoPtr; int mask; ! ThreadSpecificData *tsdPtr; ! ! tsdPtr = ConsoleInit(); if (!(flags & TCL_FILE_EVENTS)) { return 0; *************** *** 919,925 **** ConsoleInfo **nextPtrPtr, *ptr; ConsoleInfo *infoPtr = (ConsoleInfo *) instanceData; int oldMask = infoPtr->watchMask; ! ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); /* * Since most of the work is handled by the background threads, --- 928,936 ---- ConsoleInfo **nextPtrPtr, *ptr; ConsoleInfo *infoPtr = (ConsoleInfo *) instanceData; int oldMask = infoPtr->watchMask; ! ThreadSpecificData *tsdPtr; ! ! tsdPtr = ConsoleInit(); /* * Since most of the work is handled by the background threads, *************** *** 986,991 **** --- 997,1080 ---- /* *---------------------------------------------------------------------- * + * ConsoleCutProc -- + * + * Driver procedure to remove any thread local refs to this + * channel. See Tcl_CutChannel for more info. + * + * Results: + * None. + * + * Side effects: + * Changes thread local list of valid channels. + * + *---------------------------------------------------------------------- + */ + + static void + ConsoleCutProc(instanceData) + ClientData instanceData; /* Console state. */ + { + ThreadSpecificData *tsdPtr; + ConsoleInfo *infoPtr = (ConsoleInfo *) instanceData; + ConsoleInfo **nextPtrPtr; + int removed = 0; + + tsdPtr = ConsoleInit(); + + for (nextPtrPtr = &(tsdPtr->firstConsolePtr); (*nextPtrPtr) != NULL; + nextPtrPtr = &((*nextPtrPtr)->nextPtr)) { + if ((*nextPtrPtr) == infoPtr) { + (*nextPtrPtr) = infoPtr->nextPtr; + removed = 1; + break; + } + } + + /* + * This could happen if the channel was created in one thread + * and then moved to another without updating the thread + * local data in each thread. + */ + + if (!removed) { + Tcl_Panic("ConsoleInfo ptr not on thread channel list"); + } + } + + /* + *---------------------------------------------------------------------- + * + * ConsoleSpliceProc -- + * + * Driver procedure to insert thread local ref for this channel. + * See Tcl_SpliceChannel for more info. + * + * Results: + * None. + * + * Side effects: + * Changes thread local list of valid channels. + * + *---------------------------------------------------------------------- + */ + + static void + ConsoleSpliceProc(instanceData) + ClientData instanceData; /* Console state. */ + { + ThreadSpecificData *tsdPtr; + ConsoleInfo *infoPtr = (ConsoleInfo *) instanceData; + + tsdPtr = ConsoleInit(); + + infoPtr->nextPtr = tsdPtr->firstConsolePtr; + tsdPtr->firstConsolePtr = infoPtr; + } + + /* + *---------------------------------------------------------------------- + * * WaitForRead -- * * Wait until some data is available, the console is at *** win/tclWinFile.c 16 Dec 2003 02:55:38 -0000 1.58 --- win/tclWinFile.c 14 Jan 2004 02:18:47 -0000 *************** *** 14,21 **** * RCS: @(#) $Id: tclWinFile.c,v 1.58 2003/12/16 02:55:38 davygrvy Exp $ */ - //#define _WIN32_WINNT 0x0500 - #include "tclWinInt.h" #include #include --- 14,19 ---- *** win/tclWinPipe.c 24 Dec 2003 04:18:23 -0000 1.39 --- win/tclWinPipe.c 14 Jan 2004 02:18:50 -0000 *************** *** 179,209 **** * Declarations for functions used only in this file. */ ! static int ApplicationType(Tcl_Interp *interp, ! const char *fileName, char *fullName); ! static void BuildCommandLine(const char *executable, int argc, ! CONST char **argv, Tcl_DString *linePtr); ! static BOOL HasConsole(void); ! static int PipeBlockModeProc(ClientData instanceData, int mode); ! static void PipeCheckProc(ClientData clientData, int flags); ! static int PipeClose2Proc(ClientData instanceData, ! Tcl_Interp *interp, int flags); ! static int PipeEventProc(Tcl_Event *evPtr, int flags); ! static void PipeExitHandler(ClientData clientData); ! static int PipeGetHandleProc(ClientData instanceData, ! int direction, ClientData *handlePtr); ! static void PipeInit(void); ! static int PipeInputProc(ClientData instanceData, char *buf, ! int toRead, int *errorCode); ! static int PipeOutputProc(ClientData instanceData, ! CONST char *buf, int toWrite, int *errorCode); ! static DWORD WINAPI PipeReaderThread(LPVOID arg); ! static void PipeSetupProc(ClientData clientData, int flags); ! static void PipeWatchProc(ClientData instanceData, int mask); ! static DWORD WINAPI PipeWriterThread(LPVOID arg); ! static void ProcExitHandler(ClientData clientData); ! static int TempFileName(WCHAR name[MAX_PATH]); ! static int WaitForRead(PipeInfo *infoPtr, int blocking); /* * This structure describes the channel type structure for command pipe --- 179,209 ---- * Declarations for functions used only in this file. */ ! static int ApplicationType(Tcl_Interp *interp, ! CONST char *fileName, char *fullName); ! static void BuildCommandLine(const char *executable, ! int argc, CONST char **argv, ! Tcl_DString *linePtr); ! static BOOL HasConsole(void); ! static Tcl_DriverBlockModeProc PipeBlockModeProc; ! static Tcl_EventCheckProc PipeCheckProc; ! static Tcl_DriverClose2Proc PipeClose2Proc; ! static Tcl_DriverCutProc PipeCutProc; ! static Tcl_EventProc PipeEventProc; ! static Tcl_ExitProc PipeExitHandler; ! static Tcl_DriverGetHandleProc PipeGetHandleProc; ! static ThreadSpecificData * PipeInit(void); ! static Tcl_DriverInputProc PipeInputProc; ! static Tcl_DriverOutputProc PipeOutputProc; ! static DWORD WINAPI PipeReaderThread(LPVOID arg); ! static Tcl_EventSetupProc PipeSetupProc; ! static Tcl_DriverSpliceProc PipeSpliceProc; ! static Tcl_DriverWatchProc PipeWatchProc; ! static DWORD WINAPI PipeWriterThread(LPVOID arg); ! static Tcl_ExitProc ProcExitHandler; ! static int TempFileName(WCHAR name[MAX_PATH]); ! static int WaitForRead(PipeInfo *infoPtr, ! int blocking); /* * This structure describes the channel type structure for command pipe *************** *** 212,218 **** static Tcl_ChannelType pipeChannelType = { "pipe", /* Type name. */ ! TCL_CHANNEL_VERSION_2, /* v2 channel */ TCL_CLOSE2PROC, /* Close proc. */ PipeInputProc, /* Input proc. */ PipeOutputProc, /* Output proc. */ --- 212,218 ---- static Tcl_ChannelType pipeChannelType = { "pipe", /* Type name. */ ! TCL_CHANNEL_VERSION_4, /* v4 channel */ TCL_CLOSE2PROC, /* Close proc. */ PipeInputProc, /* Input proc. */ PipeOutputProc, /* Output proc. */ *************** *** 225,230 **** --- 225,233 ---- PipeBlockModeProc, /* Set blocking or non-blocking mode.*/ NULL, /* flush proc. */ NULL, /* handler proc. */ + NULL, /* wide seek proc. */ + PipeCutProc, /* cut proc. */ + PipeSpliceProc, /* splice proc. */ }; /* *************** *** 243,249 **** *---------------------------------------------------------------------- */ ! static void PipeInit() { ThreadSpecificData *tsdPtr; --- 246,252 ---- *---------------------------------------------------------------------- */ ! static ThreadSpecificData * PipeInit() { ThreadSpecificData *tsdPtr; *************** *** 270,275 **** --- 273,279 ---- Tcl_CreateEventSource(PipeSetupProc, PipeCheckProc, NULL); Tcl_CreateThreadExitHandler(PipeExitHandler, NULL); } + return tsdPtr; } /* *************** *** 315,321 **** static void ProcExitHandler( ! ClientData clientData) /* Old window proc */ { Tcl_MutexLock(&pipeMutex); initialized = 0; --- 319,325 ---- static void ProcExitHandler( ! ClientData clientData) /* Not used. */ { Tcl_MutexLock(&pipeMutex); initialized = 0; *************** *** 404,410 **** PipeEvent *evPtr; WinFile *filePtr; int needEvent; ! ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return; --- 408,416 ---- PipeEvent *evPtr; WinFile *filePtr; int needEvent; ! ThreadSpecificData *tsdPtr; ! ! tsdPtr = PipeInit(); if (!(flags & TCL_FILE_EVENTS)) { return; *************** *** 1882,1890 **** Tcl_Channel errChan; int errorCode, result; PipeInfo *infoPtr, **nextPtrPtr; ! ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); DWORD exitCode; errorCode = 0; if ((!flags || (flags == TCL_CLOSE_READ)) && (pipePtr->readFile != NULL)) { --- 1888,1898 ---- Tcl_Channel errChan; int errorCode, result; PipeInfo *infoPtr, **nextPtrPtr; ! ThreadSpecificData *tsdPtr; DWORD exitCode; + tsdPtr = PipeInit(); + errorCode = 0; if ((!flags || (flags == TCL_CLOSE_READ)) && (pipePtr->readFile != NULL)) { *************** *** 2299,2305 **** PipeInfo *infoPtr; WinFile *filePtr; int mask; ! ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return 0; --- 2307,2315 ---- PipeInfo *infoPtr; WinFile *filePtr; int mask; ! ThreadSpecificData *tsdPtr; ! ! tsdPtr = PipeInit(); if (!(flags & TCL_FILE_EVENTS)) { return 0; *************** *** 2386,2392 **** PipeInfo **nextPtrPtr, *ptr; PipeInfo *infoPtr = (PipeInfo *) instanceData; int oldMask = infoPtr->watchMask; ! ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); /* * Since most of the work is handled by the background threads, --- 2396,2404 ---- PipeInfo **nextPtrPtr, *ptr; PipeInfo *infoPtr = (PipeInfo *) instanceData; int oldMask = infoPtr->watchMask; ! ThreadSpecificData *tsdPtr; ! ! tsdPtr = PipeInit(); /* * Since most of the work is handled by the background threads, *************** *** 2463,2468 **** --- 2475,2558 ---- /* *---------------------------------------------------------------------- * + * PipeCutProc -- + * + * Driver procedure to remove any thread local refs to this + * channel. See Tcl_CutChannel for more info. + * + * Results: + * None. + * + * Side effects: + * Changes thread local list of valid channels. + * + *---------------------------------------------------------------------- + */ + + static void + PipeCutProc(instanceData) + ClientData instanceData; /* Pipe state. */ + { + ThreadSpecificData *tsdPtr; + PipeInfo *infoPtr = (PipeInfo *) instanceData; + PipeInfo **nextPtrPtr; + int removed = 0; + + tsdPtr = PipeInit(); + + for (nextPtrPtr = &(tsdPtr->firstPipePtr); (*nextPtrPtr) != NULL; + nextPtrPtr = &((*nextPtrPtr)->nextPtr)) { + if ((*nextPtrPtr) == infoPtr) { + (*nextPtrPtr) = infoPtr->nextPtr; + removed = 1; + break; + } + } + + /* + * This could happen if the channel was created in one thread + * and then moved to another without updating the thread + * local data in each thread. + */ + + if (!removed) { + Tcl_Panic("PipeInfo ptr not on thread channel list"); + } + } + + /* + *---------------------------------------------------------------------- + * + * PipeSpliceProc -- + * + * Driver procedure to insert thread local ref for this channel. + * See Tcl_SpliceChannel for more info. + * + * Results: + * None. + * + * Side effects: + * Changes thread local list of valid channels. + * + *---------------------------------------------------------------------- + */ + + static void + PipeSpliceProc(instanceData) + ClientData instanceData; /* Pipe state. */ + { + ThreadSpecificData *tsdPtr; + PipeInfo *infoPtr = (PipeInfo *) instanceData; + + tsdPtr = PipeInit(); + + infoPtr->nextPtr = tsdPtr->firstPipePtr; + tsdPtr->firstPipePtr = infoPtr; + } + + /* + *---------------------------------------------------------------------- + * * Tcl_WaitPid -- * * Emulates the waitpid system call. *** win/tclWinSerial.c 19 Aug 2003 19:39:56 -0000 1.28 --- win/tclWinSerial.c 14 Jan 2004 02:18:53 -0000 *************** *** 169,203 **** * Declarations for functions used only in this file. */ ! static int SerialBlockProc(ClientData instanceData, ! int mode); ! static void SerialCheckProc(ClientData clientData, ! int flags); ! static int SerialCloseProc(ClientData instanceData, ! Tcl_Interp *interp); ! static int SerialEventProc(Tcl_Event *evPtr, int flags); ! static void SerialExitHandler(ClientData clientData); ! static int SerialGetHandleProc(ClientData instanceData, ! int direction, ClientData *handlePtr); static ThreadSpecificData * SerialInit(void); ! static int SerialInputProc(ClientData instanceData, ! char *buf, int toRead, int *errorCode); ! static int SerialOutputProc(ClientData instanceData, ! CONST char *buf, int toWrite, ! int *errorCode); ! static void SerialSetupProc(ClientData clientData, ! int flags); ! static void SerialWatchProc(ClientData instanceData, ! int mask); ! static void ProcExitHandler(ClientData clientData); ! static int SerialGetOptionProc _ANSI_ARGS_(( ! ClientData instanceData, ! Tcl_Interp *interp, CONST char *optionName, ! Tcl_DString *dsPtr)); ! static int SerialSetOptionProc _ANSI_ARGS_(( ! ClientData instanceData, ! Tcl_Interp *interp, CONST char *optionName, ! CONST char *value)); static DWORD WINAPI SerialWriterThread(LPVOID arg); /* --- 169,190 ---- * Declarations for functions used only in this file. */ ! static Tcl_DriverBlockModeProc SerialBlockProc; ! static Tcl_EventCheckProc SerialCheckProc; ! static Tcl_DriverCloseProc SerialCloseProc; ! static Tcl_DriverCutProc SerialCutProc; ! static Tcl_EventProc SerialEventProc; ! static Tcl_ExitProc SerialExitHandler; ! static Tcl_DriverGetHandleProc SerialGetHandleProc; static ThreadSpecificData * SerialInit(void); ! static Tcl_DriverInputProc SerialInputProc; ! static Tcl_DriverOutputProc SerialOutputProc; ! static Tcl_EventSetupProc SerialSetupProc; ! static Tcl_DriverSpliceProc SerialSpliceProc; ! static Tcl_DriverWatchProc SerialWatchProc; ! static Tcl_ExitProc ProcExitHandler; ! static Tcl_DriverGetOptionProc SerialGetOptionProc; ! static Tcl_DriverSetOptionProc SerialSetOptionProc; static DWORD WINAPI SerialWriterThread(LPVOID arg); /* *************** *** 207,213 **** static Tcl_ChannelType serialChannelType = { "serial", /* Type name. */ ! TCL_CHANNEL_VERSION_2, /* v2 channel */ SerialCloseProc, /* Close proc. */ SerialInputProc, /* Input proc. */ SerialOutputProc, /* Output proc. */ --- 194,200 ---- static Tcl_ChannelType serialChannelType = { "serial", /* Type name. */ ! TCL_CHANNEL_VERSION_4, /* v4 channel */ SerialCloseProc, /* Close proc. */ SerialInputProc, /* Input proc. */ SerialOutputProc, /* Output proc. */ *************** *** 220,225 **** --- 207,215 ---- SerialBlockProc, /* Set blocking or non-blocking mode.*/ NULL, /* flush proc. */ NULL, /* handler proc. */ + NULL, /* wide seek proc. */ + SerialCutProc, /* cut proc. */ + SerialSpliceProc, /* splice proc. */ }; /* *************** *** 1288,1293 **** --- 1278,1361 ---- /* *---------------------------------------------------------------------- * + * SerialCutProc -- + * + * Driver procedure to remove any thread local refs to this + * channel. See Tcl_CutChannel for more info. + * + * Results: + * None. + * + * Side effects: + * Changes thread local list of valid channels. + * + *---------------------------------------------------------------------- + */ + + static void + SerialCutProc(instanceData) + ClientData instanceData; /* Serial state. */ + { + ThreadSpecificData *tsdPtr; + SerialInfo *infoPtr = (SerialInfo *) instanceData; + SerialInfo **nextPtrPtr; + int removed = 0; + + tsdPtr = SerialInit(); + + for (nextPtrPtr = &(tsdPtr->firstSerialPtr); (*nextPtrPtr) != NULL; + nextPtrPtr = &((*nextPtrPtr)->nextPtr)) { + if ((*nextPtrPtr) == infoPtr) { + (*nextPtrPtr) = infoPtr->nextPtr; + removed = 1; + break; + } + } + + /* + * This could happen if the channel was created in one thread + * and then moved to another without updating the thread + * local data in each thread. + */ + + if (!removed) { + Tcl_Panic("SerialInfo ptr not on thread channel list"); + } + } + + /* + *---------------------------------------------------------------------- + * + * SerialSpliceProc -- + * + * Driver procedure to insert thread local ref for this channel. + * See Tcl_SpliceChannel for more info. + * + * Results: + * None. + * + * Side effects: + * Changes thread local list of valid channels. + * + *---------------------------------------------------------------------- + */ + + static void + SerialSpliceProc(instanceData) + ClientData instanceData; /* Serial state. */ + { + ThreadSpecificData *tsdPtr; + SerialInfo *infoPtr = (SerialInfo *) instanceData; + + tsdPtr = SerialInit(); + + infoPtr->nextPtr = tsdPtr->firstSerialPtr; + tsdPtr->firstSerialPtr = infoPtr; + } + + /* + *---------------------------------------------------------------------- + * * SerialWriterThread -- * * This function runs in a separate thread and writes data *** win/tclWinSock.c 24 Dec 2003 04:18:23 -0000 1.41 --- win/tclWinSock.c 14 Jan 2004 02:18:56 -0000 *************** *** 232,257 **** * Static functions defined in this file. */ ! static SocketInfo * CreateSocket _ANSI_ARGS_((Tcl_Interp *interp, int port, CONST char *host, int server, CONST char *myaddr, int myport, int async)); ! static int CreateSocketAddress _ANSI_ARGS_( ! (LPSOCKADDR_IN sockaddrPtr, CONST char *host, int port)); ! static void InitSockets _ANSI_ARGS_((void)); ! static SocketInfo * NewSocketInfo _ANSI_ARGS_((SOCKET socket)); ! static Tcl_EventCheckProc SocketCheckProc; ! static Tcl_EventProc SocketEventProc; ! static void SocketExitHandler _ANSI_ARGS_(( ! ClientData clientData)); ! static LRESULT CALLBACK SocketProc _ANSI_ARGS_((HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)); ! static Tcl_EventSetupProc SocketSetupProc; ! static Tcl_ExitProc SocketThreadExitHandler; ! static int SocketsEnabled _ANSI_ARGS_((void)); ! static void TcpAccept _ANSI_ARGS_((SocketInfo *infoPtr)); static Tcl_DriverBlockModeProc TcpBlockProc; static Tcl_DriverCloseProc TcpCloseProc; static Tcl_DriverSetOptionProc TcpSetOptionProc; --- 232,256 ---- * Static functions defined in this file. */ ! static SocketInfo * CreateSocket _ANSI_ARGS_((Tcl_Interp *interp, int port, CONST char *host, int server, CONST char *myaddr, int myport, int async)); ! static int CreateSocketAddress _ANSI_ARGS_(( ! LPSOCKADDR_IN sockaddrPtr, CONST char *host, int port)); ! static void InitSockets _ANSI_ARGS_((void)); ! static SocketInfo * NewSocketInfo _ANSI_ARGS_((SOCKET socket)); ! static Tcl_EventCheckProc SocketCheckProc; ! static Tcl_EventProc SocketEventProc; ! static Tcl_ExitProc SocketExitHandler; ! static LRESULT CALLBACK SocketProc _ANSI_ARGS_((HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)); ! static Tcl_EventSetupProc SocketSetupProc; ! static Tcl_ExitProc SocketThreadExitHandler; ! static int SocketsEnabled _ANSI_ARGS_((void)); ! static void TcpAccept _ANSI_ARGS_((SocketInfo *infoPtr)); static Tcl_DriverBlockModeProc TcpBlockProc; static Tcl_DriverCloseProc TcpCloseProc; static Tcl_DriverSetOptionProc TcpSetOptionProc; *************** *** 260,269 **** static Tcl_DriverOutputProc TcpOutputProc; static Tcl_DriverWatchProc TcpWatchProc; static Tcl_DriverGetHandleProc TcpGetHandleProc; ! static int WaitForSocketEvent _ANSI_ARGS_(( ! SocketInfo *infoPtr, int events, ! int *errorCodePtr)); ! static DWORD WINAPI SocketThread _ANSI_ARGS_((LPVOID arg)); /* * This structure describes the channel type structure for TCP socket --- 259,271 ---- static Tcl_DriverOutputProc TcpOutputProc; static Tcl_DriverWatchProc TcpWatchProc; static Tcl_DriverGetHandleProc TcpGetHandleProc; ! static Tcl_DriverCutProc TcpCutProc; ! static Tcl_DriverSpliceProc TcpSpliceProc; ! ! static int WaitForSocketEvent _ANSI_ARGS_(( ! SocketInfo *infoPtr, int events, ! int *errorCodePtr)); ! static DWORD WINAPI SocketThread _ANSI_ARGS_((LPVOID arg)); /* * This structure describes the channel type structure for TCP socket *************** *** 272,278 **** static Tcl_ChannelType tcpChannelType = { "tcp", /* Type name. */ ! TCL_CHANNEL_VERSION_2, /* v2 channel */ TcpCloseProc, /* Close proc. */ TcpInputProc, /* Input proc. */ TcpOutputProc, /* Output proc. */ --- 274,280 ---- static Tcl_ChannelType tcpChannelType = { "tcp", /* Type name. */ ! TCL_CHANNEL_VERSION_4, /* v4 channel */ TcpCloseProc, /* Close proc. */ TcpInputProc, /* Input proc. */ TcpOutputProc, /* Output proc. */ *************** *** 285,290 **** --- 287,295 ---- TcpBlockProc, /* Set socket into (non-)blocking mode. */ NULL, /* flush proc. */ NULL, /* handler proc. */ + NULL, /* wideseek proc. */ + TcpCutProc, /* cut proc. */ + TcpSpliceProc, /* splice proc. */ }; *************** *** 2284,2290 **** /* *---------------------------------------------------------------------- * ! * TcpGetProc -- * * Called from Tcl_GetChannelHandle to retrieve an OS handle from inside * a TCP socket based channel. --- 2289,2295 ---- /* *---------------------------------------------------------------------- * ! * TcpGetHandleProc -- * * Called from Tcl_GetChannelHandle to retrieve an OS handle from inside * a TCP socket based channel. *************** *** 2313,2318 **** --- 2318,2431 ---- /* *---------------------------------------------------------------------- * + * TcpCutProc -- + * + * Remove any thread local refs to this channel. See + * Tcl_CutChannel for more info. + * + * Results: + * None. + * + * Side effects: + * Changes thread local list of valid channels. + * + *---------------------------------------------------------------------- + */ + + static void + TcpCutProc(instanceData) + ClientData instanceData; /* The socket state. */ + { + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + SocketInfo *infoPtr = (SocketInfo *) instanceData; + SocketInfo **nextPtrPtr; + int removed = 0; + + for (nextPtrPtr = &(tsdPtr->socketList); (*nextPtrPtr) != NULL; + nextPtrPtr = &((*nextPtrPtr)->nextPtr)) { + if ((*nextPtrPtr) == infoPtr) { + (*nextPtrPtr) = infoPtr->nextPtr; + removed = 1; + break; + } + } + + /* + * This could happen if the channel was created in one thread + * and then moved to another without updating the thread + * local data in each thread. + */ + + if (!removed) { + Tcl_Panic("file info ptr not on thread channel list"); + } + + /* + * Stop notifications for the socket to occur in this thread. + */ + + SendMessage(tsdPtr->hwnd, SOCKET_SELECT, + (WPARAM) UNSELECT, (LPARAM) infoPtr); + } + + /* + *---------------------------------------------------------------------- + * + * TcpSpliceProc -- + * + * Insert thread local ref for this channel. + * Tcl_SpliceChannel for more info. + * + * Results: + * None. + * + * Side effects: + * Changes thread local list of valid channels. + * + *---------------------------------------------------------------------- + */ + + static void + TcpSpliceProc(instanceData) + ClientData instanceData; /* The socket state. */ + { + ThreadSpecificData *tsdPtr; + SocketInfo *infoPtr = (SocketInfo *) instanceData; + + /* + * Ensure that socket subsystem is initialized in this thread, or + * else sockets will not work. + */ + + Tcl_MutexLock(&socketMutex); + InitSockets(); + Tcl_MutexUnlock(&socketMutex); + + /* + * The initializtion of tsdPtr _after_ we have determined that we + * are dealing with socket is necessary. Doing it before causes + * the module to access th tdsPtr when it is not initialized yet, + * causing a lockup. + */ + + tsdPtr = TCL_TSD_INIT(&dataKey); + + WaitForSingleObject(tsdPtr->socketListLock, INFINITE); + infoPtr->nextPtr = tsdPtr->socketList; + tsdPtr->socketList = infoPtr; + SetEvent(tsdPtr->socketListLock); + + /* + * Ensure that notifications for the socket occur in this thread. + */ + + SendMessage(tsdPtr->hwnd, SOCKET_SELECT, + (WPARAM) SELECT, (LPARAM) infoPtr); + } + + /* + *---------------------------------------------------------------------- + * * SocketThread -- * * Helper thread used to manage the socket event handling window. *************** *** 2666,2799 **** return winSock.getservbyname(name, proto); } - - - - /* - *---------------------------------------------------------------------- - * - * TclpCutSockChannel -- - * - * Remove any thread local refs to this channel. See - * Tcl_CutChannel for more info. - * - * Results: - * None. - * - * Side effects: - * Changes thread local list of valid channels. - * - *---------------------------------------------------------------------- - */ - - void - TclpCutSockChannel(chan) - Tcl_Channel chan; /* The channel being removed. Must - * not be referenced in any - * interpreter. */ - { - ThreadSpecificData *tsdPtr; - SocketInfo *infoPtr; - SocketInfo **nextPtrPtr; - int removed = 0; - - if (Tcl_GetChannelType(chan) != &tcpChannelType) - return; - - /* - * The initializtion of tsdPtr _after_ we have determined that we - * are dealing with socket is necessary. Doing it before causes - * the module to access th tdsPtr when it is not initialized yet, - * causing a lockup. - */ - - tsdPtr = TCL_TSD_INIT(&dataKey); - infoPtr = (SocketInfo *) Tcl_GetChannelInstanceData (chan); - - for (nextPtrPtr = &(tsdPtr->socketList); (*nextPtrPtr) != NULL; - nextPtrPtr = &((*nextPtrPtr)->nextPtr)) { - if ((*nextPtrPtr) == infoPtr) { - (*nextPtrPtr) = infoPtr->nextPtr; - removed = 1; - break; - } - } - - /* - * This could happen if the channel was created in one thread - * and then moved to another without updating the thread - * local data in each thread. - */ - - if (!removed) { - Tcl_Panic("file info ptr not on thread channel list"); - } - - /* - * Stop notifications for the socket to occur in this thread. - */ - - SendMessage(tsdPtr->hwnd, SOCKET_SELECT, - (WPARAM) UNSELECT, (LPARAM) infoPtr); - } - - /* - *---------------------------------------------------------------------- - * - * TclpSpliceSockChannel -- - * - * Insert thread local ref for this channel. - * Tcl_SpliceChannel for more info. - * - * Results: - * None. - * - * Side effects: - * Changes thread local list of valid channels. - * - *---------------------------------------------------------------------- - */ - - void - TclpSpliceSockChannel(chan) - Tcl_Channel chan; /* The channel being removed. Must - * not be referenced in any - * interpreter. */ - { - ThreadSpecificData *tsdPtr; - SocketInfo *infoPtr; - - if (Tcl_GetChannelType(chan) != &tcpChannelType) - return; - - /* - * Ensure that socket subsystem is initialized in this thread, or - * else sockets will not work. - */ - - Tcl_MutexLock(&socketMutex); - InitSockets(); - Tcl_MutexUnlock(&socketMutex); - - /* - * The initializtion of tsdPtr _after_ we have determined that we - * are dealing with socket is necessary. Doing it before causes - * the module to access th tdsPtr when it is not initialized yet, - * causing a lockup. - */ - - tsdPtr = TCL_TSD_INIT(&dataKey); - infoPtr = (SocketInfo *) Tcl_GetChannelInstanceData (chan); - - WaitForSingleObject(tsdPtr->socketListLock, INFINITE); - infoPtr->nextPtr = tsdPtr->socketList; - tsdPtr->socketList = infoPtr; - SetEvent(tsdPtr->socketListLock); - - /* - * Ensure that notifications for the socket occur in this thread. - */ - - SendMessage(tsdPtr->hwnd, SOCKET_SELECT, - (WPARAM) SELECT, (LPARAM) infoPtr); - } --- 2779,2781 ----