diff options
author | Christian Strømme <christian.stromme@digia.com> | 2013-10-11 14:55:33 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-10-17 01:49:19 +0200 |
commit | 021c79f038c218a55b145fafcda5c59cf3a309d8 (patch) | |
tree | 7fad7d283bafcc49a43c6e6836d5e04b3c9a4314 | |
parent | d0b419e35521d50f1409de84f99ded3b9a7ab01d (diff) |
Android: Use java.util.Random in qrand()
Android does not provide rand_r(), so we would fall back to rand()
and srand() which means we where not keeping the promise of qrand
and qsrand being thread-safe. As a replacement we can use the Java
api and have one Random object for each thread.
Task-number: QTBUG-32814
Change-Id: Id46d195a0bb122bc7a5a8de43bdf088e11a9c42e
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com>
-rw-r--r-- | src/corelib/global/qglobal.cpp | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index ff2c4bbe5e..1dd77c5859 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -76,6 +76,10 @@ #include <CoreServices/CoreServices.h> #endif +#if defined(Q_OS_ANDROID) +#include <private/qjni_p.h> +#endif + QT_BEGIN_NAMESPACE #if !QT_DEPRECATED_SINCE(5, 0) @@ -2335,6 +2339,9 @@ typedef uint SeedStorageType; typedef QThreadStorage<SeedStorageType *> SeedStorage; Q_GLOBAL_STATIC(SeedStorage, randTLS) // Thread Local Storage for seed value +#elif defined(Q_OS_ANDROID) +typedef QThreadStorage<QJNIObjectPrivate> AndroidRandomStorage; +Q_GLOBAL_STATIC(AndroidRandomStorage, randomTLS) #endif /*! @@ -2368,6 +2375,16 @@ void qsrand(uint seed) //global static object, fallback to srand(seed) srand(seed); } +#elif defined(Q_OS_ANDROID) + QJNIObjectPrivate random = QJNIObjectPrivate("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 @@ -2409,6 +2426,25 @@ int qrand() //global static object, fallback to rand() return rand(); } +#elif defined(Q_OS_ANDROID) + AndroidRandomStorage *randomStorage = randomTLS(); + if (!randomStorage) + return rand(); + + QJNIObjectPrivate random; + if (!randomStorage->hasLocalData()) { + random = QJNIObjectPrivate("java/util/Random", + "(J)V", + jlong(1)); + if (!random.isValid()) + return rand(); + + randomStorage->setLocalData(random); + } else { + random = randomStorage->localData(); + } + + return random.callMethod<jint>("nextInt", "(I)I", RAND_MAX); #else // On Windows srand() and rand() already use Thread-Local-Storage // to store the seed between calls |