mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Random: Make the system random object safer to use from multiple threads
This commit is contained in:
parent
a50292f50d
commit
8fe8717ebc
2 changed files with 37 additions and 14 deletions
|
|
@ -46,26 +46,29 @@ Random::Random() : seed (1)
|
|||
|
||||
void Random::setSeed (const int64 newSeed) noexcept
|
||||
{
|
||||
if (this == &getSystemRandom())
|
||||
{
|
||||
// Resetting the system Random risks messing up
|
||||
// JUCE's internal state. If you need a predictable
|
||||
// stream of random numbers you should use a local
|
||||
// Random object.
|
||||
jassertfalse;
|
||||
return;
|
||||
}
|
||||
// Resetting the system Random risks messing up JUCE's internal state.
|
||||
// If you need a predictable stream of random numbers you should use a
|
||||
// local Random object.
|
||||
jassert (! isSystemRandom);
|
||||
|
||||
seed = newSeed;
|
||||
}
|
||||
|
||||
void Random::combineSeed (const int64 seedValue) noexcept
|
||||
{
|
||||
// Resetting the system Random risks messing up JUCE's internal state.
|
||||
// Consider using a local Random object instead.
|
||||
jassert (! isSystemRandom);
|
||||
|
||||
seed ^= nextInt64() ^ seedValue;
|
||||
}
|
||||
|
||||
void Random::setSeedRandomly()
|
||||
{
|
||||
// Resetting the system Random risks messing up JUCE's internal state.
|
||||
// Consider using a local Random object instead.
|
||||
jassert (! isSystemRandom);
|
||||
|
||||
static std::atomic<int64> globalSeed { 0 };
|
||||
|
||||
combineSeed (globalSeed ^ (int64) (pointer_sized_int) this);
|
||||
|
|
@ -78,13 +81,28 @@ void Random::setSeedRandomly()
|
|||
|
||||
Random& Random::getSystemRandom() noexcept
|
||||
{
|
||||
static Random sysRand;
|
||||
thread_local Random sysRand = std::invoke ([]
|
||||
{
|
||||
Random r;
|
||||
#if JUCE_ASSERTIONS_ENABLED_OR_LOGGED
|
||||
r.isSystemRandom = true;
|
||||
#endif
|
||||
return r;
|
||||
});
|
||||
|
||||
return sysRand;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
int Random::nextInt() noexcept
|
||||
{
|
||||
// If you encounter this assertion you've likely stored a reference to the
|
||||
// system random object and are accessing it from a thread other than the
|
||||
// one it was first created on. This may lead to race conditions on the
|
||||
// random object. To avoid this assertion call Random::getSystemRandom()
|
||||
// directly instead of storing a reference.
|
||||
jassert (! isSystemRandom || this == &getSystemRandom());
|
||||
|
||||
seed = (int64) (((((uint64) seed) * 0x5deece66dLL) + 11) & 0xffffffffffffLL);
|
||||
|
||||
return (int) (seed >> 16);
|
||||
|
|
|
|||
|
|
@ -128,11 +128,12 @@ 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.
|
||||
/** 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..
|
||||
Note this will return a different object per thread it's accessed from,
|
||||
making it thread safe. However, it's therefore important not store a reference
|
||||
to this object that will later be accessed from other threads.
|
||||
*/
|
||||
static Random& getSystemRandom() noexcept;
|
||||
|
||||
|
|
@ -140,6 +141,10 @@ private:
|
|||
//==============================================================================
|
||||
int64 seed;
|
||||
|
||||
#if JUCE_ASSERTIONS_ENABLED_OR_LOGGED
|
||||
bool isSystemRandom = false;
|
||||
#endif
|
||||
|
||||
JUCE_LEAK_DETECTOR (Random)
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue