diff --git a/src/audio/dsp/juce_AudioDataConverters.cpp b/src/audio/dsp/juce_AudioDataConverters.cpp index ff547b1469..76c820913e 100644 --- a/src/audio/dsp/juce_AudioDataConverters.cpp +++ b/src/audio/dsp/juce_AudioDataConverters.cpp @@ -504,6 +504,7 @@ public: { const int numSamples = 2048; int32 original [numSamples], converted [numSamples], reversed [numSamples]; + Random r; { AudioData::Pointer d (original); @@ -511,13 +512,13 @@ public: for (int i = 0; i < numSamples / 2; ++i) { - d.setAsFloat (Random::getSystemRandom().nextFloat() * 2.2f - 1.1f); + d.setAsFloat (r.nextFloat() * 2.2f - 1.1f); if (! d.isFloatingPoint()) clippingFailed = d.getAsFloat() > 1.0f || d.getAsFloat() < -1.0f || clippingFailed; ++d; - d.setAsInt32 (Random::getSystemRandom().nextInt()); + d.setAsInt32 (r.nextInt()); ++d; } diff --git a/src/containers/juce_AbstractFifo.cpp b/src/containers/juce_AbstractFifo.cpp index 91286752eb..6ccac77c9a 100644 --- a/src/containers/juce_AbstractFifo.cpp +++ b/src/containers/juce_AbstractFifo.cpp @@ -165,10 +165,11 @@ public: void run() { int n = 0; + Random r; while (! threadShouldExit()) { - int num = Random::getSystemRandom().nextInt (2000) + 1; + int num = r.nextInt (2000) + 1; int start1, size1, start2, size2; fifo.prepareToWrite (num, start1, size1, start2, size2); @@ -203,10 +204,11 @@ public: WriteThread writer (fifo, buffer); int n = 0; + Random r; for (int count = 1000000; --count >= 0;) { - int num = Random::getSystemRandom().nextInt (6000) + 1; + int num = r.nextInt (6000) + 1; int start1, size1, start2, size2; fifo.prepareToRead (num, start1, size1, start2, size2); diff --git a/src/core/juce_Uuid.cpp b/src/core/juce_Uuid.cpp index 257ffdb17b..6b6fe3bc58 100644 --- a/src/core/juce_Uuid.cpp +++ b/src/core/juce_Uuid.cpp @@ -33,42 +33,36 @@ BEGIN_JUCE_NAMESPACE #include "../io/network/juce_MACAddress.h" #include "../memory/juce_MemoryBlock.h" +namespace +{ + int64 getRandomSeedFromMACAddresses() + { + Array result; + MACAddress::findAllAddresses (result); + + Random r; + for (int i = 0; i < result.size(); ++i) + r.combineSeed (result[i].toInt64()); + + return r.nextInt64(); + } +} //============================================================================== Uuid::Uuid() { - // Mix up any available MAC addresses with some time-based pseudo-random numbers - // to make it very very unlikely that two UUIDs will ever be the same.. + // The normal random seeding is pretty good, but we'll throw some MAC addresses + // into the mix too, to make it very very unlikely that two UUIDs will ever be the same.. - static int64 macAddresses[2]; - static bool hasCheckedMacAddresses = false; + static Random r1 (getRandomSeedFromMACAddresses()); - if (! hasCheckedMacAddresses) - { - hasCheckedMacAddresses = true; + value.asInt64[0] = r1.nextInt64(); + value.asInt64[1] = r1.nextInt64(); - Array result; - MACAddress::findAllAddresses (result); - - for (int i = 0; i < numElementsInArray (macAddresses); ++i) - macAddresses[i] = result[i].toInt64(); - } - - value.asInt64[0] = macAddresses[0]; - value.asInt64[1] = macAddresses[1]; - - // We'll use both a local RNG that is re-seeded, plus the shared RNG, - // whose seed will carry over between calls to this method. - - Random r (macAddresses[0] ^ macAddresses[1] - ^ Random::getSystemRandom().nextInt64()); + Random r2; for (int i = 4; --i >= 0;) - { - r.setSeedRandomly(); // calling this repeatedly improves randomness - value.asInt[i] ^= r.nextInt(); - value.asInt[i] ^= Random::getSystemRandom().nextInt(); - } + value.asInt[i] ^= r2.nextInt(); } Uuid::~Uuid() noexcept diff --git a/src/cryptography/juce_Primes.cpp b/src/cryptography/juce_Primes.cpp index 64e6e7c9b5..4bcce8818a 100644 --- a/src/cryptography/juce_Primes.cpp +++ b/src/cryptography/juce_Primes.cpp @@ -171,14 +171,14 @@ BigInteger Primes::createProbablePrime (const int bitLength, { randomSeeds = defaultSeeds; numRandomSeeds = numElementsInArray (defaultSeeds); - Random r; + Random r1, r2; for (int j = 10; --j >= 0;) { - r.setSeedRandomly(); + r1.setSeedRandomly(); for (int i = numRandomSeeds; --i >= 0;) - defaultSeeds[i] ^= r.nextInt() ^ Random::getSystemRandom().nextInt(); + defaultSeeds[i] ^= r1.nextInt() ^ r2.nextInt(); } } diff --git a/src/gui/components/mouse/juce_DragAndDropContainer.cpp b/src/gui/components/mouse/juce_DragAndDropContainer.cpp index e4da477447..0efb43ae27 100644 --- a/src/gui/components/mouse/juce_DragAndDropContainer.cpp +++ b/src/gui/components/mouse/juce_DragAndDropContainer.cpp @@ -359,6 +359,7 @@ void DragAndDropContainer::startDragging (const var& sourceDescription, Point relPos (sourceComponent->getLocalPoint (nullptr, lastMouseDown)); Point clipped (dragImage.getBounds().getConstrainedPoint (relPos)); + Random random; for (int y = dragImage.getHeight(); --y >= 0;) { @@ -373,7 +374,7 @@ void DragAndDropContainer::startDragging (const var& sourceDescription, { const float alpha = (distance > hi) ? 0 : (hi - distance) / (float) (hi - lo) - + Random::getSystemRandom().nextFloat() * 0.008f; + + random.nextFloat() * 0.008f; dragImage.multiplyAlphaAt (x, y, alpha); } diff --git a/src/gui/components/windows/juce_ComponentPeer.cpp b/src/gui/components/windows/juce_ComponentPeer.cpp index 3d6f26dd11..25ec7f2b89 100644 --- a/src/gui/components/windows/juce_ComponentPeer.cpp +++ b/src/gui/components/windows/juce_ComponentPeer.cpp @@ -135,9 +135,11 @@ void ComponentPeer::handlePaint (LowLevelGraphicsContext& contextToPaintTo) // clearly when things are being repainted. g.restoreState(); - g.fillAll (Colour ((uint8) Random::getSystemRandom().nextInt (255), - (uint8) Random::getSystemRandom().nextInt (255), - (uint8) Random::getSystemRandom().nextInt (255), + static Random rng; + + g.fillAll (Colour ((uint8) rng.nextInt (255), + (uint8) rng.nextInt (255), + (uint8) rng.nextInt (255), (uint8) 0x50)); #endif diff --git a/src/io/files/juce_File.cpp b/src/io/files/juce_File.cpp index 738e76f43f..fb5954746b 100644 --- a/src/io/files/juce_File.cpp +++ b/src/io/files/juce_File.cpp @@ -890,7 +890,7 @@ String File::getRelativePathFrom (const File& dir) const File File::createTempFile (const String& fileNameEnding) { const File tempFile (getSpecialLocation (tempDirectory) - .getChildFile ("temp_" + String (Random::getSystemRandom().nextInt())) + .getChildFile ("temp_" + String::toHexString (Random::getSystemRandom().nextInt())) .withFileExtension (fileNameEnding)); if (tempFile.exists()) diff --git a/src/io/files/juce_TemporaryFile.cpp b/src/io/files/juce_TemporaryFile.cpp index 3d1f609a86..da3fadb706 100644 --- a/src/io/files/juce_TemporaryFile.cpp +++ b/src/io/files/juce_TemporaryFile.cpp @@ -36,7 +36,7 @@ BEGIN_JUCE_NAMESPACE TemporaryFile::TemporaryFile (const String& suffix, const int optionFlags) { createTempFile (File::getSpecialLocation (File::tempDirectory), - "temp_" + String (Random::getSystemRandom().nextInt()), + "temp_" + String::toHexString (Random::getSystemRandom().nextInt()), suffix, optionFlags); } @@ -48,7 +48,8 @@ TemporaryFile::TemporaryFile (const File& targetFile_, const int optionFlags) jassert (targetFile != File::nonexistent); createTempFile (targetFile.getParentDirectory(), - targetFile.getFileNameWithoutExtension() + "_temp" + String (Random::getSystemRandom().nextInt()), + targetFile.getFileNameWithoutExtension() + + "_temp" + String::toHexString (Random::getSystemRandom().nextInt()), targetFile.getFileExtension(), optionFlags); } diff --git a/src/io/streams/juce_MemoryInputStream.cpp b/src/io/streams/juce_MemoryInputStream.cpp index 231457890c..4d9c72c95b 100644 --- a/src/io/streams/juce_MemoryInputStream.cpp +++ b/src/io/streams/juce_MemoryInputStream.cpp @@ -113,10 +113,11 @@ public: void runTest() { beginTest ("Basics"); + Random r; - int randomInt = Random::getSystemRandom().nextInt(); - int64 randomInt64 = Random::getSystemRandom().nextInt64(); - double randomDouble = Random::getSystemRandom().nextDouble(); + int randomInt = r.nextInt(); + int64 randomInt64 = r.nextInt64(); + double randomDouble = r.nextDouble(); String randomString (createRandomWideCharString()); MemoryOutputStream mo; @@ -146,16 +147,16 @@ public: for (int i = 0; i < numElementsInArray (buffer) - 1; ++i) { - if (Random::getSystemRandom().nextBool()) + if (r.nextBool()) { do { - buffer[i] = (juce_wchar) (1 + Random::getSystemRandom().nextInt (0x10ffff - 1)); + buffer[i] = (juce_wchar) (1 + r.nextInt (0x10ffff - 1)); } while (! CharPointer_UTF16::canRepresent (buffer[i])); } else - buffer[i] = (juce_wchar) (1 + Random::getSystemRandom().nextInt (0xff)); + buffer[i] = (juce_wchar) (1 + r.nextInt (0xff)); } return CharPointer_UTF32 (buffer); diff --git a/src/maths/juce_Random.cpp b/src/maths/juce_Random.cpp index b599f11b2b..c13163da87 100644 --- a/src/maths/juce_Random.cpp +++ b/src/maths/juce_Random.cpp @@ -59,11 +59,14 @@ void Random::combineSeed (const int64 seedValue) noexcept void Random::setSeedRandomly() { - combineSeed ((int64) (pointer_sized_int) this); + static int64 globalSeed = 0; + + combineSeed (globalSeed ^ (int64) (pointer_sized_int) this); combineSeed (Time::getMillisecondCounter()); combineSeed (Time::getHighResolutionTicks()); combineSeed (Time::getHighResolutionTicksPerSecond()); combineSeed (Time::currentTimeMillis()); + globalSeed ^= seed; } Random& Random::getSystemRandom() noexcept @@ -83,7 +86,7 @@ int Random::nextInt() noexcept int Random::nextInt (const int maxValue) noexcept { jassert (maxValue > 0); - return (nextInt() & 0x7fffffff) % maxValue; + return (((unsigned int) nextInt()) * (uint64) maxValue) >> 32; } int64 Random::nextInt64() noexcept diff --git a/src/maths/juce_Random.h b/src/maths/juce_Random.h index d8bf1be2db..b2cc04f9ab 100644 --- a/src/maths/juce_Random.h +++ b/src/maths/juce_Random.h @@ -34,9 +34,6 @@ A random number generator. You can create a Random object and use it to generate a sequence of random numbers. - As a handy shortcut to avoid having to create and seed one yourself, you can call - Random::getSystemRandom() to return a global RNG that is seeded randomly when the - app launches. */ class JUCE_API Random { @@ -67,7 +64,7 @@ public: int nextInt() noexcept; /** Returns the next random number, limited to a given range. - + The maxValue parameter may not be negative, or zero. @returns a random integer between 0 (inclusive) and maxValue (exclusive). */ int nextInt (int maxValue) noexcept; @@ -104,14 +101,6 @@ public: void fillBitsRandomly (BigInteger& arrayToChange, int startBit, int numBits); //============================================================================== - /** To avoid the overhead of having to create a new Random object whenever - you need a number, this is a shared application-wide object that - can be used. - - It's not thread-safe though, so threads should use their own Random object. - */ - static Random& getSystemRandom() noexcept; - /** Resets this Random object to a given seed value. */ void setSeed (int64 newSeed) noexcept; @@ -129,6 +118,14 @@ public: */ void setSeedRandomly(); + /** The overhead of creating a new Random object is fairly small, but if you want to avoid + it, you can call this method to get a global shared Random object. + + It's not thread-safe though, so threads should use their own Random object, otherwise + you run the risk of your random numbers becoming.. erm.. randomly corrupted.. + */ + static Random& getSystemRandom() noexcept; + private: //============================================================================== int64 seed; diff --git a/src/text/juce_String.cpp b/src/text/juce_String.cpp index 7e3b7ebf0f..4aa6e275d4 100644 --- a/src/text/juce_String.cpp +++ b/src/text/juce_String.cpp @@ -2161,19 +2161,20 @@ public: static String createRandomWideCharString() { juce_wchar buffer[50] = { 0 }; + Random r; for (int i = 0; i < numElementsInArray (buffer) - 1; ++i) { - if (Random::getSystemRandom().nextBool()) + if (r.nextBool()) { do { - buffer[i] = (juce_wchar) (1 + Random::getSystemRandom().nextInt (0x10ffff - 1)); + buffer[i] = (juce_wchar) (1 + r.nextInt (0x10ffff - 1)); } while (! CharPointer_UTF16::canRepresent (buffer[i])); } else - buffer[i] = (juce_wchar) (1 + Random::getSystemRandom().nextInt (0xff)); + buffer[i] = (juce_wchar) (1 + r.nextInt (0xff)); } return CharPointer_UTF32 (buffer);