From 360d8eade0332f2c1aa5c205ca772cd506c35b26 Mon Sep 17 00:00:00 2001 From: peterbell10 Date: Tue, 13 Jun 2017 20:35:30 +0100 Subject: FastRandom rewrite (#3754) --- src/FastRandom.cpp | 119 ++++++++++++++--------------------------------------- 1 file changed, 30 insertions(+), 89 deletions(-) (limited to 'src/FastRandom.cpp') 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 #include #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 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 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> DeleteList; + cRandomDeviceSeeder seeder; + auto NewInstance = cpp14::make_unique(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 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::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 dist; + SeedCounter = dist(rd); + SeedCounterInitialized = true; + } + return ++SeedCounter; } -- cgit v1.2.3