Index: ChangeLog
===================================================================
RCS file: /cvsroot/tcl/tcl/ChangeLog,v
retrieving revision 1.2723
diff -u -r1.2723 ChangeLog
--- ChangeLog	27 Jul 2005 18:12:24 -0000	1.2723
+++ ChangeLog	27 Jul 2005 18:16:52 -0000
@@ -1,10 +1,20 @@
 2005-07-27  Don Porter  <dgp@users.sourceforge.net>
 
+	* generic/tclUtil.c:	Converted the $::tcl_precision value to be
+	kept per-thread to prevent different threads from stomping on each
+	others' formatting prescriptions.
+
+	***POTENTIAL INCOMPATIBILITY*** Multi-threaded programs that set
+	the value of ::tcl_precision will now have to set it in each thread.
+
 	* tests/expr.test:	Consolidated equivalent constraints into
 	* tests/fileName.test:	single definitions and (more precise) names:
 	* tests/get.test:	longis32bit, 32bit, !intsAre64bit => longIs32bit
 	* tests/listObj.test:	empty => emptyTest; winOnly => win
 	* tests/obj.test:	intsAre64bit => longIs64bit
+	Also updated some "nonPortable" tests to use constraints that mark
+	precisely what about them isn't portable, so the tests can run where
+	they work.
 
 	* library/init.tcl ([unknown]):	Corrected return code handling
 	in the portions of [unknown] that expand incomplete commands
Index: generic/tclUtil.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclUtil.c,v
retrieving revision 1.62
diff -u -r1.62 tclUtil.c
--- generic/tclUtil.c	24 Jul 2005 22:56:44 -0000	1.62
+++ generic/tclUtil.c	27 Jul 2005 18:16:53 -0000
@@ -72,16 +72,11 @@
 #define BRACES_UNMATCHED	4
 
 /*
- * The following values determine the precision used when converting
- * floating-point values to strings. This information is linked to all of the
- * tcl_precision variables in all interpreters via the function
- * TclPrecTraceProc.
+ * The following key is used by Tcl_PrintDouble and TclPrecTraceProc to
+ * access the precision to be used for double formatting.
  */
 
-static int precision = 0;	/* Precision of floating point conversions, in
-				 * the range 0-17 inclusive. */
-
-TCL_DECLARE_MUTEX(precisionMutex)
+static Tcl_ThreadDataKey precisionKey;
 
 /*
  * Prototypes for functions defined later in this file.
@@ -1887,24 +1882,21 @@
 				 * at least TCL_DOUBLE_SPACE characters. */
 {
     char *p, c;
-    int prec;
     int exp;
     int signum;
     char buffer[TCL_DOUBLE_SPACE];
     Tcl_UniChar ch;
 
-    Tcl_MutexLock(&precisionMutex);
-    prec = precision;
-    Tcl_MutexUnlock(&precisionMutex);
+    int *precisionPtr = Tcl_GetThreadData(&precisionKey, (int)sizeof(int));
 
     /*
-     * If prec == 0, then use TclDoubleDigits to develop a decimal significand
-     * and exponent, then format it in E or F format as appropriate. If prec
-     * != 0, use the native sprintf and then add a trailing ".0" if there is
-     * no decimal point in the rep.
+     * If *precisionPtr == 0, then use TclDoubleDigits to develop a decimal
+     * significand and exponent, then format it in E or F format as
+     * appropriate.  If *precisionPtr != 0, use the native sprintf and then
+     * add a trailing ".0" if there is no decimal point in the rep.
      */
 
-    if ( prec == 0 ) {
+    if ( *precisionPtr == 0 ) {
 	/*
 	 * Handle NaN.
 	 */
@@ -1935,7 +1927,6 @@
 	if (signum) {
 	    *dst++ = '-';
 	}
-	prec = strlen(buffer);
 	p = buffer;
 	if (exp < -3 || exp > 17) {
 	    /*
@@ -1989,7 +1980,7 @@
 	 * tcl_precision is supplied, pass it to the native sprintf.
 	 */
 
-	sprintf(dst, "%.*g", prec, value);
+	sprintf(dst, "%.*g", *precisionPtr, value);
 
 	/*
 	 * If the ASCII result looks like an integer, add ".0" so that it
@@ -2047,6 +2038,7 @@
 {
     Tcl_Obj* value;
     int prec;
+    int *precisionPtr = Tcl_GetThreadData(&precisionKey, (int)sizeof(int));
 
     /*
      * If the variable is unset, then recreate the trace.
@@ -2069,10 +2061,8 @@
 
 
     if (flags & TCL_TRACE_READS) {
-	Tcl_MutexLock(&precisionMutex);
-	Tcl_SetVar2Ex(interp, name1, name2, Tcl_NewIntObj(precision),
+	Tcl_SetVar2Ex(interp, name1, name2, Tcl_NewIntObj(*precisionPtr),
 		flags & TCL_GLOBAL_ONLY);
-	Tcl_MutexUnlock(&precisionMutex);
 	return (char *) NULL;
     }
 
@@ -2083,10 +2073,6 @@
      */
 
     if (Tcl_IsSafe(interp)) {
-	Tcl_MutexLock(&precisionMutex);
-	Tcl_SetVar2Ex(interp, name1, name2, Tcl_NewIntObj(precision),
-		flags & TCL_GLOBAL_ONLY);
-	Tcl_MutexUnlock(&precisionMutex);
 	return "can't modify precision from a safe interpreter";
     }
     value = Tcl_GetVar2Ex(interp, name1, name2, flags & TCL_GLOBAL_ONLY);
@@ -2095,9 +2081,7 @@
 	    || prec < 0 || prec > TCL_MAX_PREC) {
 	return "improper value for precision";
     }
-    Tcl_MutexLock(&precisionMutex);
-    precision = prec;
-    Tcl_MutexUnlock(&precisionMutex);
+    *precisionPtr = prec;
     return (char *) NULL;
 }
 
