*** 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 <v2 channel versions, the version field is occupied
***************
*** 9099,9104 ****
--- 9113,9145 ----
  {
      if (HaveVersion(chanTypePtr, TCL_CHANNEL_VERSION_3)) {
  	return chanTypePtr->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);
+ }
+ 
  /*
   *----------------------------------------------------------------------
   *
