From 41ae541c110c5729d4467ce0c5c0a5bc9aa24d48 Mon Sep 17 00:00:00 2001 From: dgp Date: Wed, 27 Jul 2005 18:23:58 +0000 Subject: * 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. --- ChangeLog | 10 ++++++++++ generic/tclUtil.c | 44 ++++++++++++++------------------------------ 2 files changed, 24 insertions(+), 30 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4233574..bb91299 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,10 +1,20 @@ 2005-07-27 Don Porter + * 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 diff --git a/generic/tclUtil.c b/generic/tclUtil.c index 1031334..30cf775 100644 --- a/generic/tclUtil.c +++ b/generic/tclUtil.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclUtil.c,v 1.62 2005/07/24 22:56:44 dkf Exp $ + * RCS: @(#) $Id: tclUtil.c,v 1.63 2005/07/27 18:24:02 dgp Exp $ */ #include "tclInt.h" @@ -72,16 +72,11 @@ static ProcessGlobalValue executableName = {0, 0, NULL, NULL, NULL, NULL, NULL}; #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 @@ Tcl_PrintDouble(interp, value, dst) * 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 @@ Tcl_PrintDouble(interp, value, dst) if (signum) { *dst++ = '-'; } - prec = strlen(buffer); p = buffer; if (exp < -3 || exp > 17) { /* @@ -1989,7 +1980,7 @@ Tcl_PrintDouble(interp, value, dst) * 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 @@ TclPrecTraceProc(clientData, interp, name1, name2, flags) { 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 @@ TclPrecTraceProc(clientData, interp, name1, name2, flags) 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 @@ TclPrecTraceProc(clientData, interp, name1, name2, flags) */ 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 @@ TclPrecTraceProc(clientData, interp, name1, name2, flags) || prec < 0 || prec > TCL_MAX_PREC) { return "improper value for precision"; } - Tcl_MutexLock(&precisionMutex); - precision = prec; - Tcl_MutexUnlock(&precisionMutex); + *precisionPtr = prec; return (char *) NULL; } -- cgit v0.12