Class EntropyBlockingRandomWrapper<T extends Random>
- java.lang.Object
-
- java.util.Random
-
- io.github.pr0methean.betterrandom.prng.BaseRandom
-
- io.github.pr0methean.betterrandom.prng.adapter.RandomWrapper<T>
-
- io.github.pr0methean.betterrandom.prng.adapter.EntropyBlockingRandomWrapper<T>
-
- All Implemented Interfaces:
ByteArrayReseedableRandom
,EntropyCountingRandom
,RepeatableRandom
,Dumpable
,Serializable
public class EntropyBlockingRandomWrapper<T extends Random> extends RandomWrapper<T>
ARandomWrapper
with the additional property that it won't return any output that would take its entropy below a minimum amount, and will instead either wait to be reseeded by aRandomSeeder
or, if none is installed, reseed itself on the calling thread with aSeedGenerator
. If neither is present, the caller is responsible for reseeding, and any call that would reduce entropy below the minimum will throwIllegalStateException
.- See Also:
- Serialized Form
-
-
Field Summary
-
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 EntropyBlockingRandomWrapper(T wrapped, long minimumEntropy, SeedGenerator sameThreadSeedGen)
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description protected void
checkMaxOutputAtOnce()
Ensures that the attached PRNG can output 64 bits between reseedings, given that its current entropy is the maximum possible.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.SeedGenerator
getSameThreadSeedGen()
Returns the seed generator that is used on the calling thread if not registered with a runningRandomSeeder
.boolean
needsReseedingEarly()
If true, this PRNG needs reseeding even though its entropy is positive.void
nextBytes(byte[] bytes)
Generates random bytes and places them into a user-supplied byte array.protected void
onSeedingStateChanged(boolean reseeded)
Called when a new seed generator orRandomSeeder
is attached or a new seed is generated, so that operations can unblock.void
setRandomSeeder(RandomSeeder randomSeeder)
Registers this PRNG with theRandomSeeder
for the correspondingSeedGenerator
, to schedule reseeding when we run out of entropy.void
setSameThreadSeedGen(SeedGenerator newSeedGen)
Sets the seed generator that is used on the calling thread if not registered with a runningRandomSeeder
.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)
.void
setWrapped(T wrapped)
Replaces the wrapped PRNG with the given one on subsequent calls.static EntropyBlockingRandomWrapper<Random>
wrapJavaUtilRandom(long minimumEntropy, byte[] seed, SeedGenerator sameThreadSeedGen)
Creates an instance wrapping a basicRandom
.static EntropyBlockingRandomWrapper<Random>
wrapJavaUtilRandom(long minimumEntropy, SeedGenerator seedGenerator)
Creates an instance wrapping a basicRandom
.-
Methods inherited from class io.github.pr0methean.betterrandom.prng.adapter.RandomWrapper
addSubclassFields, getNewSeedLength, getSeed, getWrapped, next, nextBoolean, nextDoubleNoEntropyDebit, nextFloat, nextGaussian, nextInt, nextInt, nextLongNoEntropyDebit, preferSeedWithLong, setInitiallyKnownSeed, supportsMultipleSeedLengths, toString, usesParallelStreams, wrapJavaUtilRandom, wrapJavaUtilRandom, wrapJavaUtilRandom, wrapSecureRandom
-
Methods inherited from class io.github.pr0methean.betterrandom.prng.BaseRandom
checkLength, checkValidRange, creditEntropyForNewSeed, doubles, doubles, doubles, doubles, dump, entropyOfInt, entropyOfLong, fallbackSetSeedIfInitialized, gaussians, gaussians, getEntropyBits, getRandomSeeder, initTransientFields, internalNextGaussian, ints, ints, ints, ints, lockForNextGaussian, longs, longs, longs, longs, nextDouble, nextDouble, nextDouble, nextElement, nextElement, nextEnum, nextInt, nextLong, nextLong, nextLong, setSeed, unlockForNextGaussian, withProbability, withProbabilityInternal
-
-
-
-
Constructor Detail
-
EntropyBlockingRandomWrapper
public EntropyBlockingRandomWrapper(T wrapped, long minimumEntropy, @Nullable SeedGenerator sameThreadSeedGen)
- Parameters:
wrapped
- theRandom
to wrapminimumEntropy
- the minimum entropy, below which requests for pseudorandom numbers will block until the PRNG is reseededsameThreadSeedGen
- aSeedGenerator
, if any, to use on the calling thread if this PRNG does not have a runningRandomSeeder
-
-
Method Detail
-
wrapJavaUtilRandom
public static EntropyBlockingRandomWrapper<Random> wrapJavaUtilRandom(long minimumEntropy, SeedGenerator seedGenerator) throws SeedException
Creates an instance wrapping a basicRandom
.- Parameters:
minimumEntropy
- the minimum entropy, below which requests for pseudorandom numbers will block until the PRNG is reseededseedGenerator
- aSeedGenerator
to generate the initial seed; also used for reseeding if this PRNG does not have a runningRandomSeeder
- Returns:
- an instance
- Throws:
SeedException
- if theSeedGenerator
fails to generate an initial seed
-
wrapJavaUtilRandom
public static EntropyBlockingRandomWrapper<Random> wrapJavaUtilRandom(long minimumEntropy, byte[] seed, @Nullable SeedGenerator sameThreadSeedGen)
Creates an instance wrapping a basicRandom
.- Parameters:
seed
- the seedminimumEntropy
- the minimum entropy, below which requests for pseudorandom numbers will block until the PRNG is reseededsameThreadSeedGen
- aSeedGenerator
, if any, to use on the calling thread if this PRNG does not have a runningRandomSeeder
- Returns:
- an instance
-
setWrapped
public void setWrapped(T wrapped)
Description copied from class:RandomWrapper
Replaces the wrapped PRNG with the given one on subsequent calls.- Overrides:
setWrapped
in classRandomWrapper<T extends Random>
- Parameters:
wrapped
- anRandom
instance to wrap
-
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.- Overrides:
nextBytes
in classRandomWrapper<T extends Random>
-
getSameThreadSeedGen
@Nullable public SeedGenerator getSameThreadSeedGen()
Returns the seed generator that is used on the calling thread if not registered with a runningRandomSeeder
.- Returns:
- the seed generator
-
setSameThreadSeedGen
public void setSameThreadSeedGen(@Nullable SeedGenerator newSeedGen)
Sets the seed generator that is used on the calling thread if not registered with a runningRandomSeeder
.- Parameters:
newSeedGen
- the new seed generator
-
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<T extends Random>
- Parameters:
seed
- The new seed.
-
setRandomSeeder
public void setRandomSeeder(@Nullable RandomSeeder randomSeeder)
Description copied from class:BaseRandom
Registers this PRNG with theRandomSeeder
for the correspondingSeedGenerator
, to schedule reseeding when we run out of entropy. Unregisters this PRNG with the previousRandomSeeder
if it had a different one.- Overrides:
setRandomSeeder
in classBaseRandom
- Parameters:
randomSeeder
- aSeedGenerator
whoseRandomSeeder
will be used to reseed this PRNG, or null to stop using one.
-
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.
-
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.- Overrides:
setSeed
in classRandomWrapper<T extends Random>
- See Also:
ByteArrayReseedableRandom.preferSeedWithLong()
-
needsReseedingEarly
public boolean needsReseedingEarly()
Description copied from interface:EntropyCountingRandom
If true, this PRNG needs reseeding even though its entropy is positive. Added to deal withEntropyBlockingRandomWrapper
.- Returns:
- true if this PRNG needs reseeding regardless of entropy count; false otherwise
-
checkMaxOutputAtOnce
protected void checkMaxOutputAtOnce()
Ensures that the attached PRNG can output 64 bits between reseedings, given that its current entropy is the maximum possible. Methods such asRandom.nextLong()
andRandom.nextDouble()
would become much slower and more complex if we didn't require this.- Throws:
IllegalArgumentException
- if the PRNG cannot output 64 bits between reseedings
-
onSeedingStateChanged
protected void onSeedingStateChanged(boolean reseeded)
Called when a new seed generator orRandomSeeder
is attached or a new seed is generated, so that operations can unblock.- Parameters:
reseeded
- true if the seed has changed; false otherwise
-
-