diff options
author | peterbell10 <peterbell10@live.co.uk> | 2017-06-13 21:35:30 +0200 |
---|---|---|
committer | Lukas Pioch <lukas@zgow.de> | 2017-06-13 21:35:30 +0200 |
commit | 360d8eade0332f2c1aa5c205ca772cd506c35b26 (patch) | |
tree | 066fde557310742a39020bad9bc4aa2a5ef8d51a /src/FastRandom.cpp | |
parent | Corrected check for level of subcommand and fixed multiple levels not working (#3758) (diff) | |
download | cuberite-360d8eade0332f2c1aa5c205ca772cd506c35b26.tar cuberite-360d8eade0332f2c1aa5c205ca772cd506c35b26.tar.gz cuberite-360d8eade0332f2c1aa5c205ca772cd506c35b26.tar.bz2 cuberite-360d8eade0332f2c1aa5c205ca772cd506c35b26.tar.lz cuberite-360d8eade0332f2c1aa5c205ca772cd506c35b26.tar.xz cuberite-360d8eade0332f2c1aa5c205ca772cd506c35b26.tar.zst cuberite-360d8eade0332f2c1aa5c205ca772cd506c35b26.zip |
Diffstat (limited to 'src/FastRandom.cpp')
-rw-r--r-- | src/FastRandom.cpp | 119 |
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; } |