diff options
author | Bradley T. Hughes <bradley.hughes@nokia.com> | 2009-10-09 10:13:47 (GMT) |
---|---|---|
committer | Bradley T. Hughes <bradley.hughes@nokia.com> | 2009-10-12 07:16:06 (GMT) |
commit | 90a082c9076f35dcca092ade019891e92692710e (patch) | |
tree | f35f8333b84fd8c2323d596eacef71a88749bffd /src/corelib/global | |
parent | 52aef13521af2137db15ee878893f5c5150471e5 (diff) | |
download | Qt-90a082c9076f35dcca092ade019891e92692710e.zip Qt-90a082c9076f35dcca092ade019891e92692710e.tar.gz Qt-90a082c9076f35dcca092ade019891e92692710e.tar.bz2 |
QUuid::createUuid() not unique when using threads on Unix
QUuid::createUuid() only seeds the PRNG on the first entry, but since
it's using qsrand() and qrand(), all other threads will use the
default seed, and thus generate the exact same UUIDs.
Fix this by adding an internal function (qsrand() overload with no
args) which seeds the PRNG if it hasn't been done already, and use a
seed that is based on current time, a stack address and a global
serial counter (so that the chances of 2 threads using the same seed
are as low as possible).
Task-number: QTBUG-3543
Reviewed-by: Marius Storm-Olsen
Diffstat (limited to 'src/corelib/global')
-rw-r--r-- | src/corelib/global/qglobal.cpp | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 742f4ec..9fc3c8d 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -46,6 +46,7 @@ #include "qthreadstorage.h" #include "qdir.h" #include "qstringlist.h" +#include "qdatetime.h" #ifndef QT_NO_QOBJECT #include <private/qthread_p.h> @@ -2523,6 +2524,33 @@ void qsrand(uint seed) #endif } +/*! \internal + \relates <QtGlobal> + \since 4.6 + + Seed the PRNG, but only if it has not already been seeded. + + The default seed is a combination of current time, a stack address and a + serial counter (since thread stack addresses are re-used). +*/ +void qsrand() +{ +#if defined(Q_OS_UNIX) && !defined(QT_NO_THREAD) && !defined(Q_OS_SYMBIAN) + SeedStorageType *pseed = randTLS()->localData(); + if (pseed) { + // already seeded + return; + } + randTLS()->setLocalData(pseed = new SeedStorageType); + static QBasicAtomicInt serial = Q_BASIC_ATOMIC_INITIALIZER(0); + *pseed = QDateTime::currentDateTime().toTime_t() + + quintptr(&pseed) + + serial.fetchAndAddRelaxed(1); +#else + // On Windows, we assume that rand() already does the right thing +#endif +} + /*! \relates <QtGlobal> \since 4.2 |