Class ThreadLocalRandomWrapper
- java.lang.Object
-
- java.util.Random
-
- io.github.pr0methean.betterrandom.prng.BaseRandom
-
- io.github.pr0methean.betterrandom.prng.adapter.RandomWrapper
-
- io.github.pr0methean.betterrandom.prng.adapter.ThreadLocalRandomWrapper
-
- All Implemented Interfaces:
ByteArrayReseedableRandom
,EntropyCountingRandom
,Java8CompatRandom
,RepeatableRandom
,Dumpable
,Serializable
- Direct Known Subclasses:
ReseedingThreadLocalRandomWrapper
public class ThreadLocalRandomWrapper extends RandomWrapper
Wraps aThreadLocal
<BaseRandom
> in order to provide concurrency that most implementations ofBaseRandom
can't implement naturally.- See Also:
- Serialized Form
-
-
Field Summary
Fields Modifier and Type Field Description protected ThreadLocal<BaseRandom>
threadLocal
Holds the delegate for each thread.-
Fields inherited from class io.github.pr0methean.betterrandom.prng.BaseRandom
ENTROPY_OF_DOUBLE, ENTROPY_OF_FLOAT, entropyBits, lock, randomSeeder, seed, superConstructorFinished
-
-
Constructor Summary
Constructors Constructor Description ThreadLocalRandomWrapper(int seedSize, SeedGenerator seedGenerator, java8.util.function.Function<byte[],? extends BaseRandom> creator)
Wraps a seed generator and a function that takes a seed byte array as input.ThreadLocalRandomWrapper(java8.util.function.Supplier<? extends BaseRandom> initializer)
Wraps the givenSupplier
.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description protected MoreObjects.ToStringHelper
addSubclassFields(MoreObjects.ToStringHelper original)
Adds the fields that were not inherited from BaseRandom to the givenMoreObjects.ToStringHelper
for dumping.protected void
debitEntropy(long bits)
Record that entropy has been spent, and schedule a reseeding if this PRNG has now spent as much as it's been seeded with.long
getEntropyBits()
Returns an estimate of the current amount of entropy.int
getNewSeedLength()
Returns the preferred length of a new byte-array seed.SimpleRandomSeeder
getRandomSeeder()
Returns the current seed generator for this PRNG.byte[]
getSeed()
Returns the wrapped PRNG's seed, if we know it.BaseRandom
getWrapped()
Returns the PRNG this RandomWrapper is currently wrapping.boolean
nextBoolean()
void
nextBytes(byte[] bytes)
Generates random bytes and places them into a user-supplied byte array.double
nextDouble()
double
nextDoubleNoEntropyDebit()
Returns the next randomdouble
between 0.0 (inclusive) and 1.0 (exclusive), but does not debit entropy.float
nextFloat()
double
nextGaussian()
Returns the next pseudorandom, Gaussian ("normally") distributed double value with mean 0.0 and standard deviation 1.0 from this random number generator's sequence.int
nextInt()
int
nextInt(int bound)
int
nextInt(int origin, int bound)
Returns a pseudorandomint
value between the specified origin (inclusive) and the specified bound (exclusive).long
nextLong()
Returns the next pseudorandom, uniformly distributed long value from this random number generator's sequence.long
nextLong(long bound)
Returns a pseudorandomlong
value between zero (inclusive) and the specified bound (exclusive).long
nextLong(long origin, long bound)
Returns a pseudorandomlong
value between the specified origin (inclusive) and the specified bound (exclusive).protected long
nextLongNoEntropyDebit()
Returns the next randomlong
, but does not debit entropy.boolean
preferSeedWithLong()
Indicates whetherRandom.setSeed(long)
is recommended overByteArrayReseedableRandom.setSeed(byte[])
when the seed is already in the form of along
.void
setRandomSeeder(SimpleRandomSeeder randomSeeder)
Not supported, because this class uses a thread-local seed.void
setSeed(long seed)
Sets the seed of this random number generator using a single long seed, if this implementation supports that.protected void
setSeedInternal(byte[] seed)
Delegates to one ofByteArrayReseedableRandom.setSeed(byte[])
,SecureRandom.setSeed(byte[])
orRandom.setSeed(long)
.boolean
withProbability(double probability)
Returns true with the given probability, and records that only 1 bit of entropy is being spent.protected boolean
withProbabilityInternal(double probability)
Called byBaseRandom.withProbability(double)
to generate a boolean with a specified probability of returning true, after checking thatprobability
is strictly between 0 and 1.static ThreadLocalRandomWrapper
wrapLegacy(java8.util.function.LongFunction<Random> legacyCreator, SeedGenerator seedGenerator)
Uses this class andRandomWrapper
to decorate any implementation ofRandom
that can be constructed from along
seed into a fully-concurrent one.protected static java8.util.function.Function<byte[],BaseRandom>
wrapLongCreatorAsByteArrayCreator(java8.util.function.LongFunction<Random> legacyCreator)
-
Methods inherited from class io.github.pr0methean.betterrandom.prng.adapter.RandomWrapper
next, setWrapped, supportsMultipleSeedLengths, toString, usesParallelStreams
-
Methods inherited from class io.github.pr0methean.betterrandom.prng.BaseRandom
checkLength, creditEntropyForNewSeed, doubles, doubles, doubles, doubles, dump, entropyOfInt, entropyOfLong, fallbackSetSeedIfInitialized, gaussians, gaussians, initTransientFields, internalNextGaussian, ints, ints, ints, ints, lockForNextGaussian, longs, longs, longs, longs, needsReseedingEarly, nextDouble, nextDouble, nextElement, nextElement, nextEnum, setSeed, unlockForNextGaussian
-
-
-
-
Field Detail
-
threadLocal
protected transient ThreadLocal<BaseRandom> threadLocal
Holds the delegate for each thread.
-
-
Constructor Detail
-
ThreadLocalRandomWrapper
public ThreadLocalRandomWrapper(java8.util.function.Supplier<? extends BaseRandom> initializer)
Wraps the givenSupplier
. This ThreadLocalRandomWrapper will be serializable if theSupplier
is serializable.- Parameters:
initializer
- a supplier that will be called to provide the initialBaseRandom
for each thread.
-
ThreadLocalRandomWrapper
public ThreadLocalRandomWrapper(int seedSize, SeedGenerator seedGenerator, java8.util.function.Function<byte[],? extends BaseRandom> creator)
Wraps a seed generator and a function that takes a seed byte array as input. This ThreadLocalRandomWrapper will be serializable if theFunction
is serializable.- Parameters:
seedSize
- the size of seed arrays to generate.seedGenerator
- The seed generation strategy that will provide the seed value for each thread'sBaseRandom
.creator
- aFunction
that creates aBaseRandom
from each seed. Probably a constructor reference.
-
-
Method Detail
-
wrapLegacy
public static ThreadLocalRandomWrapper wrapLegacy(java8.util.function.LongFunction<Random> legacyCreator, SeedGenerator seedGenerator)
Uses this class andRandomWrapper
to decorate any implementation ofRandom
that can be constructed from along
seed into a fully-concurrent one.- Parameters:
legacyCreator
- a function that provides theRandom
that underlies the returned wrapper on each thread, taking a seed as input.seedGenerator
- the seed generator whose output will be fed tolegacyCreator
.- Returns:
- a ThreadLocalRandomWrapper decorating instances created by
legacyCreator
.
-
wrapLongCreatorAsByteArrayCreator
protected static java8.util.function.Function<byte[],BaseRandom> wrapLongCreatorAsByteArrayCreator(java8.util.function.LongFunction<Random> legacyCreator)
-
getRandomSeeder
@Nullable public SimpleRandomSeeder getRandomSeeder()
Description copied from class:BaseRandom
Returns the current seed generator for this PRNG.- Overrides:
getRandomSeeder
in classBaseRandom
- Returns:
- the current seed generator, or null if there is none
-
setRandomSeeder
public void setRandomSeeder(@Nullable SimpleRandomSeeder randomSeeder)
Not supported, because this class uses a thread-local seed.- Overrides:
setRandomSeeder
in classBaseRandom
- Parameters:
randomSeeder
- ignored.- Throws:
UnsupportedOperationException
- always.
-
withProbabilityInternal
protected boolean withProbabilityInternal(double probability)
Description copied from class:BaseRandom
Called byBaseRandom.withProbability(double)
to generate a boolean with a specified probability of returning true, after checking thatprobability
is strictly between 0 and 1.- Overrides:
withProbabilityInternal
in classBaseRandom
- Parameters:
probability
- The probability (between 0 and 1 exclusive) of returning true.- Returns:
- True with probability equal to the
probability
parameter; false otherwise.
-
withProbability
public boolean withProbability(double probability)
Description copied from class:BaseRandom
Returns true with the given probability, and records that only 1 bit of entropy is being spent.
When
probability <= 0
, instantly returns false without recording any entropy spent. Likewise, instantly returns true whenprobability >= 1
.- Overrides:
withProbability
in classBaseRandom
- Parameters:
probability
- The probability of returning true.- Returns:
- True with probability equal to the
probability
parameter; false otherwise.
-
nextLong
public long nextLong()
Description copied from class:BaseRandom
Returns the next pseudorandom, uniformly distributed long value from this random number generator's sequence. Unlike the inherited implementation inRandom.nextLong()
, ones in BetterRandom generally can be expected to return all 264 possible values.- Specified by:
nextLong
in interfaceJava8CompatRandom
- Overrides:
nextLong
in classBaseRandom
-
nextLong
public long nextLong(long bound)
Description copied from class:BaseRandom
Returns a pseudorandomlong
value between zero (inclusive) and the specified bound (exclusive).- Overrides:
nextLong
in classBaseRandom
- Parameters:
bound
- the upper bound (exclusive). Must be positive.- Returns:
- a pseudorandom
long
value between zero (inclusive) and the bound (exclusive)
-
nextInt
public int nextInt(int origin, int bound)
Description copied from class:BaseRandom
Returns a pseudorandomint
value between the specified origin (inclusive) and the specified bound (exclusive).- Overrides:
nextInt
in classBaseRandom
- Parameters:
origin
- the least value returnedbound
- the upper bound (exclusive)- Returns:
- a pseudorandom
int
value between the origin (inclusive) and the bound (exclusive)
-
nextLong
public long nextLong(long origin, long bound)
Description copied from class:BaseRandom
Returns a pseudorandomlong
value between the specified origin (inclusive) and the specified bound (exclusive). This implementation is adapted from the reference implementation of Random.longs(long, long) from JDK 8.- Overrides:
nextLong
in classBaseRandom
- Parameters:
origin
- the least value returnedbound
- the upper bound (exclusive)- Returns:
- a pseudorandom
long
value between the origin (inclusive) and the bound (exclusive)
-
getWrapped
public BaseRandom getWrapped()
Description copied from class:RandomWrapper
Returns the PRNG this RandomWrapper is currently wrapping.- Overrides:
getWrapped
in classRandomWrapper
- Returns:
- the wrapped
Random
instance
-
nextBytes
public void nextBytes(byte[] bytes)
Description copied from class:BaseRandom
Generates random bytes and places them into a user-supplied byte array. The number of random bytes produced is equal to the length of the byte array. Reimplemented for entropy-counting purposes.- Specified by:
nextBytes
in interfaceJava8CompatRandom
- Overrides:
nextBytes
in classRandomWrapper
-
nextInt
public int nextInt()
- Specified by:
nextInt
in interfaceJava8CompatRandom
- Overrides:
nextInt
in classRandomWrapper
-
nextInt
public int nextInt(int bound)
- Specified by:
nextInt
in interfaceJava8CompatRandom
- Overrides:
nextInt
in classRandomWrapper
-
nextLongNoEntropyDebit
protected long nextLongNoEntropyDebit()
Description copied from class:BaseRandom
Returns the next randomlong
, but does not debit entropy.- Overrides:
nextLongNoEntropyDebit
in classRandomWrapper
- Returns:
- a pseudorandom
long
with all possible values equally likely.
-
nextBoolean
public boolean nextBoolean()
- Specified by:
nextBoolean
in interfaceJava8CompatRandom
- Overrides:
nextBoolean
in classRandomWrapper
-
nextFloat
public float nextFloat()
- Specified by:
nextFloat
in interfaceJava8CompatRandom
- Overrides:
nextFloat
in classRandomWrapper
-
nextDoubleNoEntropyDebit
public double nextDoubleNoEntropyDebit()
Description copied from class:BaseRandom
Returns the next randomdouble
between 0.0 (inclusive) and 1.0 (exclusive), but does not debit entropy.- Overrides:
nextDoubleNoEntropyDebit
in classRandomWrapper
- Returns:
- a pseudorandom
double
.
-
nextGaussian
public double nextGaussian()
Description copied from class:BaseRandom
Returns the next pseudorandom, Gaussian ("normally") distributed double value with mean 0.0 and standard deviation 1.0 from this random number generator's sequence. Unlike the one inRandom
, this implementation is lockless.- Specified by:
nextGaussian
in interfaceJava8CompatRandom
- Overrides:
nextGaussian
in classRandomWrapper
-
nextDouble
public double nextDouble()
- Specified by:
nextDouble
in interfaceJava8CompatRandom
- Overrides:
nextDouble
in classBaseRandom
-
addSubclassFields
protected MoreObjects.ToStringHelper addSubclassFields(MoreObjects.ToStringHelper original)
Description copied from class:BaseRandom
Adds the fields that were not inherited from BaseRandom to the givenMoreObjects.ToStringHelper
for dumping.- Overrides:
addSubclassFields
in classRandomWrapper
- Parameters:
original
- aMoreObjects.ToStringHelper
object.- Returns:
original
with the fields not inherited from BaseRandom written to it.
-
preferSeedWithLong
public boolean preferSeedWithLong()
Description copied from interface:ByteArrayReseedableRandom
Indicates whetherRandom.setSeed(long)
is recommended overByteArrayReseedableRandom.setSeed(byte[])
when the seed is already in the form of along
.- Specified by:
preferSeedWithLong
in interfaceByteArrayReseedableRandom
- Overrides:
preferSeedWithLong
in classRandomWrapper
- Returns:
- true if
Random.setSeed(long)
will tend to perform better thanByteArrayReseedableRandom.setSeed(byte[])
.
-
getSeed
public byte[] getSeed()
Description copied from class:RandomWrapper
Returns the wrapped PRNG's seed, if we know it. When this RandomWrapper is wrapping a passed-inRandom
that's not aRepeatableRandom
, we won't know the seed until the nextBaseRandom.setSeed(byte[])
orRandomWrapper.setSeed(long)
call lets us set it ourselves, and so anUnsupportedOperationException
will be thrown until then.- Specified by:
getSeed
in interfaceRepeatableRandom
- Overrides:
getSeed
in classRandomWrapper
- Returns:
- The seed data used to initialize this pseudo-random number generator.
-
setSeed
public void setSeed(long seed)
Description copied from class:BaseRandom
Sets the seed of this random number generator using a single long seed, if this implementation supports that. If it is capable of using 64 bits or less of seed data (i.e. if{@link #getNewSeedLength()} <= {@link Long#BYTES}
), then this method shall replace the entire seed asRandom.setSeed(long)
does; otherwise, it shall either combine the input with the existing seed asSecureRandom.setSeed(long)
does, or it shall generate a new seed using theDefaultSeedGenerator
. The latter is a backward-compatibility measure and can be very slow.- Specified by:
setSeed
in interfaceJava8CompatRandom
- Overrides:
setSeed
in classRandomWrapper
-
setSeedInternal
protected void setSeedInternal(byte[] seed)
Description copied from class:RandomWrapper
Delegates to one ofByteArrayReseedableRandom.setSeed(byte[])
,SecureRandom.setSeed(byte[])
orRandom.setSeed(long)
.- Overrides:
setSeedInternal
in classRandomWrapper
- Parameters:
seed
- The new seed.
-
debitEntropy
protected void debitEntropy(long bits)
Description copied from class:BaseRandom
Record that entropy has been spent, and schedule a reseeding if this PRNG has now spent as much as it's been seeded with.- Overrides:
debitEntropy
in classBaseRandom
- Parameters:
bits
- The number of bits of entropy spent.
-
getEntropyBits
public long getEntropyBits()
Description copied from interface:EntropyCountingRandom
Returns an estimate of the current amount of entropy. Every time the PRNG is reseeded, the entropy count is set to the new seed's length; and every time it is used, it is decreased by the number of random bits in the output rounded up. The amount of entropy can go below zero, giving an indication of how far the entropy has been stretched. This estimate is a lower bound if the seed is perfectly random and is not being reused.- Specified by:
getEntropyBits
in interfaceEntropyCountingRandom
- Overrides:
getEntropyBits
in classBaseRandom
- Returns:
- The current estimated amount of entropy.
-
getNewSeedLength
public int getNewSeedLength()
Description copied from interface:ByteArrayReseedableRandom
Returns the preferred length of a new byte-array seed. "Preferred" is implementation-defined when multiple seed lengths are supported, but should probably usually mean the longest one, since the longer the seed, the more random the output.- Specified by:
getNewSeedLength
in interfaceByteArrayReseedableRandom
- Overrides:
getNewSeedLength
in classRandomWrapper
- Returns:
- The desired length of a new byte-array seed.
-
-