[MLton-commit] r4379

Stephen Weeks MLton@mlton.org
Mon, 13 Mar 2006 14:27:23 -0800


Made Int.{fmt,toString} thread safe.

----------------------------------------------------------------------

U   mlton/trunk/basis-library/integer/int.sml
U   mlton/trunk/basis-library/libs/basis-extra/basis-extra.mlb
A   mlton/trunk/basis-library/misc/one.sml

----------------------------------------------------------------------

Modified: mlton/trunk/basis-library/integer/int.sml
===================================================================
--- mlton/trunk/basis-library/integer/int.sml	2006-03-13 00:42:43 UTC (rev 4378)
+++ mlton/trunk/basis-library/integer/int.sml	2006-03-13 22:27:22 UTC (rev 4379)
@@ -119,40 +119,42 @@
     * The most that will be required is for minInt in binary.
     *)
    val maxNumDigits = PI.+ (precision', 1)
-   val buf = CharArray.array (maxNumDigits, #"\000")
+   val one = One.make (fn () => CharArray.array (maxNumDigits, #"\000"))
 in
    fun fmt radix (n: int): string =
-      let
-         val radix = fromInt (StringCvt.radixToInt radix)
-         fun loop (q, i: Int.int) =
-            let
-               val _ =
-                  CharArray.update
-                  (buf, i, StringCvt.digitToChar (toInt (~? (rem (q, radix)))))
-               val q = quot (q, radix)
-            in
-               if q = zero
-                  then
-                     let
-                        val start =
-                           if n < zero
-                              then
-                                 let
-                                    val i = PI.- (i, 1)
-                                    val () = CharArray.update (buf, i, #"~")
-                                 in
-                                    i
-                                 end
-                           else i
-                     in
-                        CharArraySlice.vector
-                        (CharArraySlice.slice (buf, start, NONE))
-                     end
-               else loop (q, PI.- (i, 1))
-            end
-      in
-         loop (if n < zero then n else ~? n, PI.- (maxNumDigits, 1))
-      end
+      One.use
+      (one, fn buf =>
+       let
+          val radix = fromInt (StringCvt.radixToInt radix)
+          fun loop (q, i: Int.int) =
+             let
+                val _ =
+                   CharArray.update
+                   (buf, i, StringCvt.digitToChar (toInt (~? (rem (q, radix)))))
+                val q = quot (q, radix)
+             in
+                if q = zero
+                   then
+                      let
+                         val start =
+                            if n < zero
+                               then
+                                  let
+                                     val i = PI.- (i, 1)
+                                     val () = CharArray.update (buf, i, #"~")
+                                  in
+                                     i
+                                  end
+                            else i
+                      in
+                         CharArraySlice.vector
+                         (CharArraySlice.slice (buf, start, NONE))
+                      end
+                else loop (q, PI.- (i, 1))
+             end
+       in
+          loop (if n < zero then n else ~? n, PI.- (maxNumDigits, 1))
+       end)
 end      
 
 val toString = fmt StringCvt.DEC

Modified: mlton/trunk/basis-library/libs/basis-extra/basis-extra.mlb
===================================================================
--- mlton/trunk/basis-library/libs/basis-extra/basis-extra.mlb	2006-03-13 00:42:43 UTC (rev 4378)
+++ mlton/trunk/basis-library/libs/basis-extra/basis-extra.mlb	2006-03-13 22:27:22 UTC (rev 4379)
@@ -20,6 +20,7 @@
       ../../misc/dynamic-wind.sml
       ../../general/general.sig
       ../../general/general.sml
+      ../../misc/one.sml
       ../../misc/util.sml
       ../../general/option.sig
       ../../general/option.sml

Added: mlton/trunk/basis-library/misc/one.sml
===================================================================
--- mlton/trunk/basis-library/misc/one.sml	2006-03-13 00:42:43 UTC (rev 4378)
+++ mlton/trunk/basis-library/misc/one.sml	2006-03-13 22:27:22 UTC (rev 4379)
@@ -0,0 +1,35 @@
+structure One:
+   sig
+      type 'a t
+
+      val make: (unit -> 'a) -> 'a t
+      val use: 'a t * ('a -> 'b) -> 'b
+   end =
+   struct
+      datatype 'a t = T of {more: unit -> 'a,
+                            static: 'a,
+                            staticIsInUse: bool ref}
+
+      fun make f = T {more = f,
+                      static = f (),
+                      staticIsInUse = ref false}
+
+      fun use (T {more, static, staticIsInUse}, f) =
+         let
+            val () = Primitive.Thread.atomicBegin ()
+            val b = ! staticIsInUse
+            val d =
+               if b then
+                  (Primitive.Thread.atomicEnd ();
+                   more ())
+               else
+                  (staticIsInUse := true;
+                   Primitive.Thread.atomicEnd ();
+                   static)
+        in
+           DynamicWind.wind (fn () => f d,
+                             fn () => if b then () else staticIsInUse := false)
+        end
+
+   end
+