diff --git a/lila/src/main/scala/Maths.scala b/lila/src/main/scala/Maths.scala index e460eb4..f5e129b 100644 --- a/lila/src/main/scala/Maths.scala +++ b/lila/src/main/scala/Maths.scala @@ -1,7 +1,5 @@ package scalalib -import scalalib.ThreadLocalRandom - import scala.Numeric.Implicits.* import scala.reflect.ClassTag import scala.util.Sorting diff --git a/lila/src/main/scala/Random.scala b/lila/src/main/scala/Random.scala index 1291289..bbdabec 100644 --- a/lila/src/main/scala/Random.scala +++ b/lila/src/main/scala/Random.scala @@ -2,16 +2,23 @@ package scalalib import scala.collection.mutable.StringBuilder -private final val store = - java.lang.ThreadLocal.withInitial(() => RandomApi(java.util.concurrent.ThreadLocalRandom.current)) +object ThreadLocalRandom extends RandomApi: + protected def impl = java.util.concurrent.ThreadLocalRandom.current() -def ThreadLocalRandom = store.get +object SecureRandom extends RandomApi: + protected val impl = java.security.SecureRandom.getInstanceStrong() -val SecureRandom = RandomApi(java.security.SecureRandom()) +private abstract class RandomApi: + protected def impl: java.util.Random -final class RandomApi(impl: java.util.Random): - - export impl.{ nextBoolean, nextDouble, nextFloat, nextGaussian, nextInt, nextLong } + def nextBoolean() = impl.nextBoolean + def nextDouble() = impl.nextDouble + def nextFloat() = impl.nextFloat + def nextGaussian() = impl.nextGaussian + def nextInt() = impl.nextInt + def nextInt(n: Int) = impl.nextInt(n) + def nextLong() = impl.nextLong + def nextLong(l: Long) = impl.nextLong(l) def nextBytes(len: Int): Array[Byte] = val bytes = new Array[Byte](len) @@ -20,7 +27,7 @@ final class RandomApi(impl: java.util.Random): private val chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" private inline def nextAlphanumeric(): Char = - chars.charAt(nextInt(chars.length)) // Constant time + chars.charAt(impl.nextInt(chars.length)) // Constant time def nextString(len: Int): String = val sb = StringBuilder(len) @@ -31,9 +38,9 @@ final class RandomApi(impl: java.util.Random): scala.util.Random(impl).shuffle(xs) def oneOf[A](vec: Vector[A]): Option[A] = - if vec.nonEmpty then vec.lift(nextInt(vec.size)) else None + if vec.nonEmpty then vec.lift(impl.nextInt(vec.size)) else None // odds(1) = 100% true // odds(2) = 50% true // odds(3) = 33% true - def odds(n: Int): Boolean = nextInt(n) == 0 + def odds(n: Int): Boolean = impl.nextInt(n) == 0 diff --git a/lila/src/main/scala/cuteName.scala b/lila/src/main/scala/cuteName.scala index 1e1ae9b..3830ac3 100644 --- a/lila/src/main/scala/cuteName.scala +++ b/lila/src/main/scala/cuteName.scala @@ -1,8 +1,6 @@ package scalalib package cuteName -import scalalib.ThreadLocalRandom - // children friendly names only // this is used by /class object CuteNameGenerator: diff --git a/lila/src/test/scala/RandomTest.scala b/lila/src/test/scala/RandomTest.scala deleted file mode 100644 index 2b2095d..0000000 --- a/lila/src/test/scala/RandomTest.scala +++ /dev/null @@ -1,12 +0,0 @@ -package scalalib - -class RandomTest extends munit.FunSuite: - - test("different threads get different randoms"): - val r1 = ThreadLocalRandom - - @volatile var r2: RandomApi = null - val thread2 = new Thread(() => r2 = ThreadLocalRandom) - thread2.start() - thread2.join() - assertNotEquals(r1, r2)