From 030782e1a8c44c6be2a95c88d5a4a3a37b3b6173 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 13 Apr 2017 17:50:05 -0700 Subject: Move qrand() & qsrand() to qrandom.cpp Now that we have the file, may as well consolidate Change-Id: Icd0e0d4b27cb4e5eb892fffd14b51d3e701c6a94 Reviewed-by: Lars Knoll --- src/corelib/global/qglobal.cpp | 135 --------------------------------------- src/corelib/global/qrandom.cpp | 141 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 140 insertions(+), 136 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index a718689064..4c1b210489 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -42,7 +42,6 @@ #include "qstring.h" #include "qvector.h" #include "qlist.h" -#include "qthreadstorage.h" #include "qdir.h" #include "qdatetime.h" #include "qoperatingsystemversion.h" @@ -3472,140 +3471,6 @@ bool qunsetenv(const char *varName) #endif } -#if defined(Q_OS_UNIX) && !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && (_POSIX_THREAD_SAFE_FUNCTIONS - 0 > 0) - -# if defined(Q_OS_INTEGRITY) && defined(__GHS_VERSION_NUMBER) && (__GHS_VERSION_NUMBER < 500) -// older versions of INTEGRITY used a long instead of a uint for the seed. -typedef long SeedStorageType; -# else -typedef uint SeedStorageType; -# endif - -typedef QThreadStorage SeedStorage; -Q_GLOBAL_STATIC(SeedStorage, randTLS) // Thread Local Storage for seed value - -#elif defined(Q_OS_ANDROID) -typedef QThreadStorage AndroidRandomStorage; -Q_GLOBAL_STATIC(AndroidRandomStorage, randomTLS) -#endif - -/*! - \relates - \since 4.2 - - Thread-safe version of the standard C++ \c srand() function. - - Sets the argument \a seed to be used to generate a new random number sequence of - pseudo random integers to be returned by qrand(). - - The sequence of random numbers generated is deterministic per thread. For example, - if two threads call qsrand(1) and subsequently call qrand(), the threads will get - the same random number sequence. - - \sa qrand(), QRandomGenerator -*/ -void qsrand(uint seed) -{ -#if defined(Q_OS_UNIX) && !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && (_POSIX_THREAD_SAFE_FUNCTIONS - 0 > 0) - SeedStorage *seedStorage = randTLS(); - if (seedStorage) { - SeedStorageType *pseed = seedStorage->localData(); - if (!pseed) - seedStorage->setLocalData(pseed = new SeedStorageType); - *pseed = seed; - } else { - //global static seed storage should always exist, - //except after being deleted by QGlobalStaticDeleter. - //But since it still can be called from destructor of another - //global static object, fallback to srand(seed) - srand(seed); - } -#elif defined(Q_OS_ANDROID) - if (randomTLS->hasLocalData()) { - randomTLS->localData().callMethod("setSeed", "(J)V", jlong(seed)); - return; - } - - QJNIObjectPrivate random("java/util/Random", - "(J)V", - jlong(seed)); - if (!random.isValid()) { - srand(seed); - return; - } - - randomTLS->setLocalData(random); -#else - // On Windows srand() and rand() already use Thread-Local-Storage - // to store the seed between calls - // this is also valid for QT_NO_THREAD - srand(seed); -#endif -} - -/*! - \relates - \since 4.2 - - Thread-safe version of the standard C++ \c rand() function. - - Returns a value between 0 and \c RAND_MAX (defined in \c and - \c ), the next number in the current sequence of pseudo-random - integers. - - Use \c qsrand() to initialize the pseudo-random number generator with a - seed value. Seeding must be performed at least once on each thread. If that - step is skipped, then the sequence will be pre-seeded with a constant - value. - - \sa qsrand(), QRandomGenerator -*/ -int qrand() -{ -#if defined(Q_OS_UNIX) && !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && (_POSIX_THREAD_SAFE_FUNCTIONS - 0 > 0) - SeedStorage *seedStorage = randTLS(); - if (seedStorage) { - SeedStorageType *pseed = seedStorage->localData(); - if (!pseed) { - seedStorage->setLocalData(pseed = new SeedStorageType); - *pseed = 1; - } - return rand_r(pseed); - } else { - //global static seed storage should always exist, - //except after being deleted by QGlobalStaticDeleter. - //But since it still can be called from destructor of another - //global static object, fallback to rand() - return rand(); - } -#elif defined(Q_OS_ANDROID) - AndroidRandomStorage *randomStorage = randomTLS(); - if (!randomStorage) - return rand(); - - if (randomStorage->hasLocalData()) { - return randomStorage->localData().callMethod("nextInt", - "(I)I", - RAND_MAX); - } - - QJNIObjectPrivate random("java/util/Random", - "(J)V", - jlong(1)); - - if (!random.isValid()) - return rand(); - - randomStorage->setLocalData(random); - return random.callMethod("nextInt", "(I)I", RAND_MAX); -#else - // On Windows srand() and rand() already use Thread-Local-Storage - // to store the seed between calls - // this is also valid for QT_NO_THREAD - return rand(); -#endif -} - /*! \macro forever \relates diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp index 74fdf9f318..573e762fc9 100644 --- a/src/corelib/global/qrandom.cpp +++ b/src/corelib/global/qrandom.cpp @@ -42,6 +42,7 @@ #include "qrandom.h" #include "qrandom_p.h" +#include #if QT_HAS_INCLUDE() # include @@ -62,6 +63,10 @@ DECLSPEC_IMPORT BOOLEAN WINAPI SystemFunction036(PVOID RandomBuffer, ULONG Rando } #endif +#if defined(Q_OS_ANDROID) +# include +#endif + QT_BEGIN_NAMESPACE namespace { @@ -231,7 +236,7 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd) quint32 *ptr = reinterpret_cast(buffer); quint32 * const end = reinterpret_cast(bufferEnd); -#if defined(Q_COMPILER_THREAD_LOCAL) +#if defined(Q_COMPILER_THREAD_LOCAL) && !defined(QT_BOOTSTRAPPED) if (SystemRandom::EfficientBufferFill && (end - ptr) < ThreadState::BufferCount && uint(qt_randomdevice_control) == 0) { thread_local ThreadState state; @@ -724,4 +729,138 @@ void QRandomGenerator::fillRange_helper(void *buffer, void *bufferEnd) fill(buffer, bufferEnd); } +#if defined(Q_OS_UNIX) && !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && (_POSIX_THREAD_SAFE_FUNCTIONS - 0 > 0) + +# if defined(Q_OS_INTEGRITY) && defined(__GHS_VERSION_NUMBER) && (__GHS_VERSION_NUMBER < 500) +// older versions of INTEGRITY used a long instead of a uint for the seed. +typedef long SeedStorageType; +# else +typedef uint SeedStorageType; +# endif + +typedef QThreadStorage SeedStorage; +Q_GLOBAL_STATIC(SeedStorage, randTLS) // Thread Local Storage for seed value + +#elif defined(Q_OS_ANDROID) +typedef QThreadStorage AndroidRandomStorage; +Q_GLOBAL_STATIC(AndroidRandomStorage, randomTLS) +#endif + +/*! + \relates + \since 4.2 + + Thread-safe version of the standard C++ \c srand() function. + + Sets the argument \a seed to be used to generate a new random number sequence of + pseudo random integers to be returned by qrand(). + + The sequence of random numbers generated is deterministic per thread. For example, + if two threads call qsrand(1) and subsequently call qrand(), the threads will get + the same random number sequence. + + \sa qrand(), QRandomGenerator +*/ +void qsrand(uint seed) +{ +#if defined(Q_OS_UNIX) && !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && (_POSIX_THREAD_SAFE_FUNCTIONS - 0 > 0) + SeedStorage *seedStorage = randTLS(); + if (seedStorage) { + SeedStorageType *pseed = seedStorage->localData(); + if (!pseed) + seedStorage->setLocalData(pseed = new SeedStorageType); + *pseed = seed; + } else { + //global static seed storage should always exist, + //except after being deleted by QGlobalStaticDeleter. + //But since it still can be called from destructor of another + //global static object, fallback to srand(seed) + srand(seed); + } +#elif defined(Q_OS_ANDROID) + if (randomTLS->hasLocalData()) { + randomTLS->localData().callMethod("setSeed", "(J)V", jlong(seed)); + return; + } + + QJNIObjectPrivate random("java/util/Random", + "(J)V", + jlong(seed)); + if (!random.isValid()) { + srand(seed); + return; + } + + randomTLS->setLocalData(random); +#else + // On Windows srand() and rand() already use Thread-Local-Storage + // to store the seed between calls + // this is also valid for QT_NO_THREAD + srand(seed); +#endif +} + +/*! + \relates + \since 4.2 + + Thread-safe version of the standard C++ \c rand() function. + + Returns a value between 0 and \c RAND_MAX (defined in \c and + \c ), the next number in the current sequence of pseudo-random + integers. + + Use \c qsrand() to initialize the pseudo-random number generator with a + seed value. Seeding must be performed at least once on each thread. If that + step is skipped, then the sequence will be pre-seeded with a constant + value. + + \sa qsrand(), QRandomGenerator +*/ +int qrand() +{ +#if defined(Q_OS_UNIX) && !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && (_POSIX_THREAD_SAFE_FUNCTIONS - 0 > 0) + SeedStorage *seedStorage = randTLS(); + if (seedStorage) { + SeedStorageType *pseed = seedStorage->localData(); + if (!pseed) { + seedStorage->setLocalData(pseed = new SeedStorageType); + *pseed = 1; + } + return rand_r(pseed); + } else { + //global static seed storage should always exist, + //except after being deleted by QGlobalStaticDeleter. + //But since it still can be called from destructor of another + //global static object, fallback to rand() + return rand(); + } +#elif defined(Q_OS_ANDROID) + AndroidRandomStorage *randomStorage = randomTLS(); + if (!randomStorage) + return rand(); + + if (randomStorage->hasLocalData()) { + return randomStorage->localData().callMethod("nextInt", + "(I)I", + RAND_MAX); + } + + QJNIObjectPrivate random("java/util/Random", + "(J)V", + jlong(1)); + + if (!random.isValid()) + return rand(); + + randomStorage->setLocalData(random); + return random.callMethod("nextInt", "(I)I", RAND_MAX); +#else + // On Windows srand() and rand() already use Thread-Local-Storage + // to store the seed between calls + // this is also valid for QT_NO_THREAD + return rand(); +#endif +} + QT_END_NAMESPACE -- cgit v1.2.3