This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH, RFC] Fixing money_put::do_put vs MT


Hi,

in order to better explain my proposal for libstdc++/6015, I have
prepared a fix for the money_put::do_put use of (the MT unsafe)
__convert_from_v.

Overall, there are three places where __convert_from_v is used: one
is in num_put::_M_convert_int and, having to do with integers, is
not troublesome at all. Another, the most important one is in
num_put::_M_convert_float, which is also the most tough since we
have to deal with many possible formats.

The easiest, useful to explain the approach, is that in
money_put::do_put, because we know at the outset that the format
is %.01Lf and therefore the exact position along the string of the
decimal point. Right after having printed the number with
__convert_from_v into __cs, the only wrong thing which may have
happened due to MT is that the decimal point in the string is not
the expected '.'. Therefore we fix it.

The approach for num_put::_M_convert_float is identical in
principle (it's only more tricky to find the actual decimal point,
which, in principle, may be /any/ char) and, if I'm not wrong
(I think Uli agrees with me), is able to fix number formatting in
MT environment, which currently is broken. Therefore, we can afford,
IMO, the slightly higher computational cost of the search for the
decimal point.

Of course the preliminary patch below was fully tested on
i686-pc-linux-gnu with no regressions.

Does it look reasonable? In that case, I will proceed with the more
important num_put::_M_convert_float case.

Ciao,
Paolo.

///////////////

--- locale_facets.tcc.~1.74.~    2002-04-01 10:55:04.000000000 +0200
+++ locale_facets.tcc    2002-04-05 00:58:23.000000000 +0200
@@ -1168,6 +1168,16 @@
       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
       int __len = __convert_from_v(__cs, 0, "%.01Lf", __units, 
_S_c_locale);
 #endif
+
+      // In general, in a MT environment, a different thread can change
+      // unpredictably the locale actually used by s(n)printf in
+      // __convert_from_v from "C" to another one, having the decimal
+      // point != '.'.
+#if (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
+#else
+      __cs[__len - 2] = '.';
+#endif
+
       _CharT* __ws = 
static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __cs_size));
       __ctype.widen(__cs, __cs + __len, __ws);
       string_type __digits(__ws);




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]