*** generic/tcl.decls 31 Aug 2002 06:09:45 -0000 1.94 --- generic/tcl.decls 10 Nov 2002 20:31:06 -0000 *************** *** 1754,1759 **** --- 1754,1765 ---- Tcl_ChannelType *chanTypePtr) } + # new for channel version 4 + declare 494 generic { + Tcl_DriverRegisterInitProc * Tcl_ChannelRegisterInitProc( + Tcl_ChannelType *chanTypePtr) + } + ############################################################################## # Define the platform specific public Tcl interface. These functions are *** generic/tcl.h 21 Oct 2002 04:35:50 -0000 1.147 --- generic/tcl.h 10 Nov 2002 20:31:33 -0000 *************** *** 1423,1428 **** --- 1423,1429 ---- #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: *************** *** 1457,1462 **** --- 1458,1464 ---- typedef Tcl_WideInt (Tcl_DriverWideSeekProc) _ANSI_ARGS_(( ClientData instanceData, Tcl_WideInt offset, int mode, int *errorCodePtr)); + typedef void (Tcl_DriverRegisterInitProc) _ANSI_ARGS_((void)); /* *************** *** 1548,1553 **** --- 1550,1566 ---- * 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_DriverRegisterInitProc *regProc; + /* Procedure to call when + * registering a channel into an + * interp. This allows the + * driver to do any needed per + * thread initialization should + * the channel have come from + * another thread. */ } Tcl_ChannelType; /* *** generic/tclIO.c 30 Jul 2002 18:36:25 -0000 1.57 --- generic/tclIO.c 10 Nov 2002 20:34:05 -0000 *************** *** 748,753 **** --- 748,755 ---- int new; /* Is the hash entry new or does it exist? */ Channel *chanPtr; /* The actual channel. */ ChannelState *statePtr; /* State of the actual channel. */ + Tcl_DriverRegisterInitProc *regProc; + /* the regProc for the channel type */ /* * Always (un)register bottom-most channel in the stack. This makes *************** *** 771,776 **** --- 773,788 ---- panic("Tcl_RegisterChannel: duplicate channel names"); } Tcl_SetHashValue(hPtr, (ClientData) chanPtr); + + /* + * Make sure any needed per thread initialization the actual + * driver needs has been done on channel drivers that support + * this feature. + */ + regProc = Tcl_ChannelRegisterInitProc(chanPtr->typePtr); + if (regProc != NULL) { + (*regProc)(); + } } statePtr->refCount++; } *************** *** 8751,8756 **** --- 8763,8770 ---- 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 wideSeekProc; + } else { + return NULL; + } + } + + /* + *---------------------------------------------------------------------- + * + * Tcl_ChannelRegisterInitProc -- + * + * Return the Tcl_DriverRegisterInitProc of the channel type. + * + * Results: + * A pointer to the proc. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + + Tcl_DriverRegisterInitProc * + Tcl_ChannelRegisterInitProc(chanTypePtr) + Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */ + { + if (HaveVersion(chanTypePtr, TCL_CHANNEL_VERSION_4)) { + return chanTypePtr->regProc; } else { return NULL; } *** win/tclWinSock.c 24 May 2002 18:57:09 -0000 1.26 --- win/tclWinSock.c 10 Nov 2002 20:35:41 -0000 *************** *** 205,210 **** --- 205,211 ---- int mask)); static int TcpGetHandleProc _ANSI_ARGS_((ClientData instanceData, int direction, ClientData *handlePtr)); + static void TcpRegInitProc _ANSI_ARGS_((void)); static int WaitForSocketEvent _ANSI_ARGS_((SocketInfo *infoPtr, int events, int *errorCodePtr)); static DWORD WINAPI SocketThread _ANSI_ARGS_((LPVOID arg)); *************** *** 216,222 **** static Tcl_ChannelType tcpChannelType = { "tcp", /* Type name. */ ! TCL_CHANNEL_VERSION_2, /* v2 channel */ TcpCloseProc, /* Close proc. */ TcpInputProc, /* Input proc. */ TcpOutputProc, /* Output proc. */ --- 217,223 ---- static Tcl_ChannelType tcpChannelType = { "tcp", /* Type name. */ ! TCL_CHANNEL_VERSION_4, /* v4 channel */ TcpCloseProc, /* Close proc. */ TcpInputProc, /* Input proc. */ TcpOutputProc, /* Output proc. */ *************** *** 229,234 **** --- 230,237 ---- TcpBlockProc, /* Set socket into (non-)blocking mode. */ NULL, /* flush proc. */ NULL, /* handler proc. */ + NULL, /* wide seek proc. */ + TcpRegInitProc /* register init proc.*/ }; /* *************** *** 277,283 **** * Initialize the function table. */ ! if (!SocketsEnabled()) { return; } --- 280,286 ---- * Initialize the function table. */ ! if (winSock.hInstance == NULL) { return; } *************** *** 2117,2122 **** --- 2120,2152 ---- return TCL_OK; } + /* + *---------------------------------------------------------------------- + * + * TcpRegInitProc -- + * + * Makes sure per-thread initialization happens when a channel + * is registered into an interp that might be in a different + * thread than where the socket was created. + * + * Results: + * none. + * + * Side effects: + * Creates a new TSD structure and the socket handler thread + * if one does not already exist for the calling thread. + * + *---------------------------------------------------------------------- + */ + + static void + TcpRegInitProc (void) + { + Tcl_MutexLock(&socketMutex); + InitSockets(); + Tcl_MutexUnlock(&socketMutex); + } + /* *---------------------------------------------------------------------- *