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>
This commit is contained in:
Christian Strømme 2013-10-11 14:55:33 +02:00 committed by The Qt Project
parent d0b419e355
commit 021c79f038

View File

@ -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