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:
parent
d0b419e355
commit
021c79f038
@ -76,6 +76,10 @@
|
|||||||
#include <CoreServices/CoreServices.h>
|
#include <CoreServices/CoreServices.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(Q_OS_ANDROID)
|
||||||
|
#include <private/qjni_p.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
#if !QT_DEPRECATED_SINCE(5, 0)
|
#if !QT_DEPRECATED_SINCE(5, 0)
|
||||||
@ -2335,6 +2339,9 @@ typedef uint SeedStorageType;
|
|||||||
typedef QThreadStorage<SeedStorageType *> SeedStorage;
|
typedef QThreadStorage<SeedStorageType *> SeedStorage;
|
||||||
Q_GLOBAL_STATIC(SeedStorage, randTLS) // Thread Local Storage for seed value
|
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
|
#endif
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -2368,6 +2375,16 @@ void qsrand(uint seed)
|
|||||||
//global static object, fallback to srand(seed)
|
//global static object, fallback to srand(seed)
|
||||||
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
|
#else
|
||||||
// On Windows srand() and rand() already use Thread-Local-Storage
|
// On Windows srand() and rand() already use Thread-Local-Storage
|
||||||
// to store the seed between calls
|
// to store the seed between calls
|
||||||
@ -2409,6 +2426,25 @@ int qrand()
|
|||||||
//global static object, fallback to rand()
|
//global static object, fallback to rand()
|
||||||
return 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
|
#else
|
||||||
// On Windows srand() and rand() already use Thread-Local-Storage
|
// On Windows srand() and rand() already use Thread-Local-Storage
|
||||||
// to store the seed between calls
|
// to store the seed between calls
|
||||||
|
Loading…
x
Reference in New Issue
Block a user