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 ofBaseRandomcan't implement naturally.- See Also:
- Serialized Form
-
-
Field Summary
Fields Modifier and Type Field Description protected ThreadLocal<BaseRandom>threadLocalHolds 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.ToStringHelperaddSubclassFields(MoreObjects.ToStringHelper original)Adds the fields that were not inherited from BaseRandom to the givenMoreObjects.ToStringHelperfor dumping.protected voiddebitEntropy(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.longgetEntropyBits()Returns an estimate of the current amount of entropy.intgetNewSeedLength()Returns the preferred length of a new byte-array seed.SimpleRandomSeedergetRandomSeeder()Returns the current seed generator for this PRNG.byte[]getSeed()Returns the wrapped PRNG's seed, if we know it.BaseRandomgetWrapped()Returns the PRNG this RandomWrapper is currently wrapping.booleannextBoolean()voidnextBytes(byte[] bytes)Generates random bytes and places them into a user-supplied byte array.doublenextDouble()doublenextDoubleNoEntropyDebit()Returns the next randomdoublebetween 0.0 (inclusive) and 1.0 (exclusive), but does not debit entropy.floatnextFloat()doublenextGaussian()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.intnextInt()intnextInt(int bound)intnextInt(int origin, int bound)Returns a pseudorandomintvalue between the specified origin (inclusive) and the specified bound (exclusive).longnextLong()Returns the next pseudorandom, uniformly distributed long value from this random number generator's sequence.longnextLong(long bound)Returns a pseudorandomlongvalue between zero (inclusive) and the specified bound (exclusive).longnextLong(long origin, long bound)Returns a pseudorandomlongvalue between the specified origin (inclusive) and the specified bound (exclusive).protected longnextLongNoEntropyDebit()Returns the next randomlong, but does not debit entropy.booleanpreferSeedWithLong()Indicates whetherRandom.setSeed(long)is recommended overByteArrayReseedableRandom.setSeed(byte[])when the seed is already in the form of along.voidsetRandomSeeder(SimpleRandomSeeder randomSeeder)Not supported, because this class uses a thread-local seed.voidsetSeed(long seed)Sets the seed of this random number generator using a single long seed, if this implementation supports that.protected voidsetSeedInternal(byte[] seed)Delegates to one ofByteArrayReseedableRandom.setSeed(byte[]),SecureRandom.setSeed(byte[])orRandom.setSeed(long).booleanwithProbability(double probability)Returns true with the given probability, and records that only 1 bit of entropy is being spent.protected booleanwithProbabilityInternal(double probability)Called byBaseRandom.withProbability(double)to generate a boolean with a specified probability of returning true, after checking thatprobabilityis strictly between 0 and 1.static ThreadLocalRandomWrapperwrapLegacy(java8.util.function.LongFunction<Random> legacyCreator, SeedGenerator seedGenerator)Uses this class andRandomWrapperto decorate any implementation ofRandomthat can be constructed from alongseed 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 theSupplieris serializable.- Parameters:
initializer- a supplier that will be called to provide the initialBaseRandomfor 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 theFunctionis 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- aFunctionthat creates aBaseRandomfrom each seed. Probably a constructor reference.
-
-
Method Detail
-
wrapLegacy
public static ThreadLocalRandomWrapper wrapLegacy(java8.util.function.LongFunction<Random> legacyCreator, SeedGenerator seedGenerator)
Uses this class andRandomWrapperto decorate any implementation ofRandomthat can be constructed from alongseed into a fully-concurrent one.- Parameters:
legacyCreator- a function that provides theRandomthat 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:BaseRandomReturns the current seed generator for this PRNG.- Overrides:
getRandomSeederin 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:
setRandomSeederin classBaseRandom- Parameters:
randomSeeder- ignored.- Throws:
UnsupportedOperationException- always.
-
withProbabilityInternal
protected boolean withProbabilityInternal(double probability)
Description copied from class:BaseRandomCalled byBaseRandom.withProbability(double)to generate a boolean with a specified probability of returning true, after checking thatprobabilityis strictly between 0 and 1.- Overrides:
withProbabilityInternalin classBaseRandom- Parameters:
probability- The probability (between 0 and 1 exclusive) of returning true.- Returns:
- True with probability equal to the
probabilityparameter; false otherwise.
-
withProbability
public boolean withProbability(double probability)
Description copied from class:BaseRandomReturns 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:
withProbabilityin classBaseRandom- Parameters:
probability- The probability of returning true.- Returns:
- True with probability equal to the
probabilityparameter; false otherwise.
-
nextLong
public long nextLong()
Description copied from class:BaseRandomReturns 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:
nextLongin interfaceJava8CompatRandom- Overrides:
nextLongin classBaseRandom
-
nextLong
public long nextLong(long bound)
Description copied from class:BaseRandomReturns a pseudorandomlongvalue between zero (inclusive) and the specified bound (exclusive).- Overrides:
nextLongin classBaseRandom- Parameters:
bound- the upper bound (exclusive). Must be positive.- Returns:
- a pseudorandom
longvalue between zero (inclusive) and the bound (exclusive)
-
nextInt
public int nextInt(int origin, int bound)Description copied from class:BaseRandomReturns a pseudorandomintvalue between the specified origin (inclusive) and the specified bound (exclusive).- Overrides:
nextIntin classBaseRandom- Parameters:
origin- the least value returnedbound- the upper bound (exclusive)- Returns:
- a pseudorandom
intvalue between the origin (inclusive) and the bound (exclusive)
-
nextLong
public long nextLong(long origin, long bound)Description copied from class:BaseRandomReturns a pseudorandomlongvalue 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:
nextLongin classBaseRandom- Parameters:
origin- the least value returnedbound- the upper bound (exclusive)- Returns:
- a pseudorandom
longvalue between the origin (inclusive) and the bound (exclusive)
-
getWrapped
public BaseRandom getWrapped()
Description copied from class:RandomWrapperReturns the PRNG this RandomWrapper is currently wrapping.- Overrides:
getWrappedin classRandomWrapper- Returns:
- the wrapped
Randominstance
-
nextBytes
public void nextBytes(byte[] bytes)
Description copied from class:BaseRandomGenerates 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:
nextBytesin interfaceJava8CompatRandom- Overrides:
nextBytesin classRandomWrapper
-
nextInt
public int nextInt()
- Specified by:
nextIntin interfaceJava8CompatRandom- Overrides:
nextIntin classRandomWrapper
-
nextInt
public int nextInt(int bound)
- Specified by:
nextIntin interfaceJava8CompatRandom- Overrides:
nextIntin classRandomWrapper
-
nextLongNoEntropyDebit
protected long nextLongNoEntropyDebit()
Description copied from class:BaseRandomReturns the next randomlong, but does not debit entropy.- Overrides:
nextLongNoEntropyDebitin classRandomWrapper- Returns:
- a pseudorandom
longwith all possible values equally likely.
-
nextBoolean
public boolean nextBoolean()
- Specified by:
nextBooleanin interfaceJava8CompatRandom- Overrides:
nextBooleanin classRandomWrapper
-
nextFloat
public float nextFloat()
- Specified by:
nextFloatin interfaceJava8CompatRandom- Overrides:
nextFloatin classRandomWrapper
-
nextDoubleNoEntropyDebit
public double nextDoubleNoEntropyDebit()
Description copied from class:BaseRandomReturns the next randomdoublebetween 0.0 (inclusive) and 1.0 (exclusive), but does not debit entropy.- Overrides:
nextDoubleNoEntropyDebitin classRandomWrapper- Returns:
- a pseudorandom
double.
-
nextGaussian
public double nextGaussian()
Description copied from class:BaseRandomReturns 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:
nextGaussianin interfaceJava8CompatRandom- Overrides:
nextGaussianin classRandomWrapper
-
nextDouble
public double nextDouble()
- Specified by:
nextDoublein interfaceJava8CompatRandom- Overrides:
nextDoublein classBaseRandom
-
addSubclassFields
protected MoreObjects.ToStringHelper addSubclassFields(MoreObjects.ToStringHelper original)
Description copied from class:BaseRandomAdds the fields that were not inherited from BaseRandom to the givenMoreObjects.ToStringHelperfor dumping.- Overrides:
addSubclassFieldsin classRandomWrapper- Parameters:
original- aMoreObjects.ToStringHelperobject.- Returns:
originalwith the fields not inherited from BaseRandom written to it.
-
preferSeedWithLong
public boolean preferSeedWithLong()
Description copied from interface:ByteArrayReseedableRandomIndicates whetherRandom.setSeed(long)is recommended overByteArrayReseedableRandom.setSeed(byte[])when the seed is already in the form of along.- Specified by:
preferSeedWithLongin interfaceByteArrayReseedableRandom- Overrides:
preferSeedWithLongin classRandomWrapper- Returns:
- true if
Random.setSeed(long)will tend to perform better thanByteArrayReseedableRandom.setSeed(byte[]).
-
getSeed
public byte[] getSeed()
Description copied from class:RandomWrapperReturns the wrapped PRNG's seed, if we know it. When this RandomWrapper is wrapping a passed-inRandomthat'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 anUnsupportedOperationExceptionwill be thrown until then.- Specified by:
getSeedin interfaceRepeatableRandom- Overrides:
getSeedin classRandomWrapper- Returns:
- The seed data used to initialize this pseudo-random number generator.
-
setSeed
public void setSeed(long seed)
Description copied from class:BaseRandomSets 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:
setSeedin interfaceJava8CompatRandom- Overrides:
setSeedin classRandomWrapper
-
setSeedInternal
protected void setSeedInternal(byte[] seed)
Description copied from class:RandomWrapperDelegates to one ofByteArrayReseedableRandom.setSeed(byte[]),SecureRandom.setSeed(byte[])orRandom.setSeed(long).- Overrides:
setSeedInternalin classRandomWrapper- Parameters:
seed- The new seed.
-
debitEntropy
protected void debitEntropy(long bits)
Description copied from class:BaseRandomRecord that entropy has been spent, and schedule a reseeding if this PRNG has now spent as much as it's been seeded with.- Overrides:
debitEntropyin classBaseRandom- Parameters:
bits- The number of bits of entropy spent.
-
getEntropyBits
public long getEntropyBits()
Description copied from interface:EntropyCountingRandomReturns 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:
getEntropyBitsin interfaceEntropyCountingRandom- Overrides:
getEntropyBitsin classBaseRandom- Returns:
- The current estimated amount of entropy.
-
getNewSeedLength
public int getNewSeedLength()
Description copied from interface:ByteArrayReseedableRandomReturns 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:
getNewSeedLengthin interfaceByteArrayReseedableRandom- Overrides:
getNewSeedLengthin classRandomWrapper- Returns:
- The desired length of a new byte-array seed.
-
-