summaryrefslogtreecommitdiffstats
path: root/src/FastRandom.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/FastRandom.cpp')
-rw-r--r--src/FastRandom.cpp119
1 files changed, 30 insertions, 89 deletions
diff --git a/src/FastRandom.cpp b/src/FastRandom.cpp
index 718092aee..de33a112c 100644
--- a/src/FastRandom.cpp
+++ b/src/FastRandom.cpp
@@ -1,11 +1,11 @@
// FastRandom.cpp
-// Implements the cFastRandom class representing a fast random number generator
#include "Globals.h"
#include "FastRandom.h"
+#include <mutex>
#include <random>
#if defined (__GNUC__)
@@ -13,109 +13,50 @@
#elif defined (_MSC_VER)
#define ATTRIBUTE_TLS static __declspec(thread)
#else
- #error "Unknown thread local storage qualifier"
+ #define ATTRIBUTE_TLS thread_local
#endif
-static unsigned int GetRandomSeed()
-{
- ATTRIBUTE_TLS bool SeedCounterInitialized = 0;
- ATTRIBUTE_TLS unsigned int SeedCounter = 0;
-
- if (!SeedCounterInitialized)
- {
- std::random_device rd;
- std::uniform_int_distribution<unsigned int> dist;
- SeedCounter = dist(rd);
- SeedCounterInitialized = true;
- }
- return ++SeedCounter;
-}
-
-
-
-
-////////////////////////////////////////////////////////////////////////////////
-// cFastRandom:
-
-
-
-
-
-cFastRandom::cFastRandom(void) :
- m_LinearRand(GetRandomSeed())
-{
-}
-
-
-
-
-
-int cFastRandom::NextInt(int a_Range)
-{
- std::uniform_int_distribution<> distribution(0, a_Range - 1);
- return distribution(m_LinearRand);
-}
-
-
-
-
-
-
-float cFastRandom::NextFloat(float a_Range)
-{
- std::uniform_real_distribution<float> distribution(0, a_Range);
- return distribution(m_LinearRand);
-}
-
-
-int cFastRandom::GenerateRandomInteger(int a_Begin, int a_End)
+MTRand & GetRandomProvider()
{
- std::uniform_int_distribution<> distribution(a_Begin, a_End);
- return distribution(m_LinearRand);
-}
-
-
-
-
-
-////////////////////////////////////////////////////////////////////////////////
-// MTRand:
-
-MTRand::MTRand() :
- m_MersenneRand(GetRandomSeed())
-{
-}
-
-
-
+ // Some compilers don't support thread_local for non-POD types, this is purely a work around for that restriction.
+ // There should be minimal overhead for the non-initializing case and all thread's instances are deleted properly.
+ ATTRIBUTE_TLS MTRand * LocalPtr = nullptr;
+ if (LocalPtr == nullptr)
+ {
+ // This list allows deletion of elements as if they had static storage duration
+ static std::mutex CSDeleteList;
+ static std::list<std::unique_ptr<MTRand>> DeleteList;
+ cRandomDeviceSeeder seeder;
+ auto NewInstance = cpp14::make_unique<MTRand>(seeder);
+ auto TempPtr = NewInstance.get();
-int MTRand::randInt(int a_Range)
-{
- std::uniform_int_distribution<> distribution(0, a_Range);
- return distribution(m_MersenneRand);
+ std::lock_guard<std::mutex> Lock(CSDeleteList);
+ DeleteList.push_front(std::move(NewInstance));
+ LocalPtr = TempPtr; // Set after push_back so LocalPtr won't dangle if it throws
+ }
+ return *LocalPtr;
}
-int MTRand::randInt()
+UInt32 Detail::GetRandomSeed()
{
- std::uniform_int_distribution<> distribution(0, std::numeric_limits<int>::max());
- return distribution(m_MersenneRand);
-}
-
-
-
-
+ ATTRIBUTE_TLS bool SeedCounterInitialized = false;
+ ATTRIBUTE_TLS UInt32 SeedCounter = 0;
-double MTRand::rand(double a_Range)
-{
- std::uniform_real_distribution<> distribution(0, a_Range);
- return distribution(m_MersenneRand);
+ if (!SeedCounterInitialized)
+ {
+ std::random_device rd;
+ std::uniform_int_distribution<UInt32> dist;
+ SeedCounter = dist(rd);
+ SeedCounterInitialized = true;
+ }
+ return ++SeedCounter;
}