diff --git a/qmake/Makefile.unix b/qmake/Makefile.unix index 768cc0248e..56b9f7e847 100644 --- a/qmake/Makefile.unix +++ b/qmake/Makefile.unix @@ -18,7 +18,7 @@ OBJS = \ #qt code (please keep in order matching DEPEND_SRC) QOBJS = \ qtextcodec.o qutfcodec.o \ - qglobal.o qlogging.o qmalloc.o qnumeric.o qoperatingsystemversion.o \ + qglobal.o qlogging.o qmalloc.o qnumeric.o qoperatingsystemversion.o qrandom.o \ qabstractfileengine.o qbuffer.o qdatastream.o qdebug.o \ qdir.o qdiriterator.o \ qfile.o qfiledevice.o qfileinfo.o qfilesystemengine.o \ @@ -74,6 +74,7 @@ DEPEND_SRC = \ $(SOURCE_PATH)/src/corelib/global/qmalloc.cpp \ $(SOURCE_PATH)/src/corelib/global/qnumeric.cpp \ $(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion.cpp \ + $(SOURCE_PATH)/src/corelib/global/qrandom.cpp \ $(SOURCE_PATH)/src/corelib/io/qabstractfileengine.cpp \ $(SOURCE_PATH)/src/corelib/io/qbuffer.cpp \ $(SOURCE_PATH)/src/corelib/io/qdatastream.cpp \ @@ -83,6 +84,7 @@ DEPEND_SRC = \ $(SOURCE_PATH)/src/corelib/io/qfile.cpp \ $(SOURCE_PATH)/src/corelib/io/qfiledevice.cpp \ $(SOURCE_PATH)/src/corelib/io/qfileinfo.cpp \ + $(SOURCE_PATH)/src/corelib/global/qrandom.cpp \ $(SOURCE_PATH)/src/corelib/io/qfilesystemengine.cpp \ $(SOURCE_PATH)/src/corelib/io/qfilesystementry.cpp \ $(SOURCE_PATH)/src/corelib/io/qfsfileengine.cpp \ @@ -276,6 +278,9 @@ qlibraryinfo_final.o: $(SOURCE_PATH)/src/corelib/global/qlibraryinfo.cpp $(BUILD qnumeric.o: $(SOURCE_PATH)/src/corelib/global/qnumeric.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< +qrandom.o: $(SOURCE_PATH)/src/corelib/global/qrandom.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< + qsettings_mac.o: $(SOURCE_PATH)/src/corelib/io/qsettings_mac.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< @@ -297,6 +302,9 @@ qmalloc.o: $(SOURCE_PATH)/src/corelib/global/qmalloc.cpp qglobal.o: $(SOURCE_PATH)/src/corelib/global/qglobal.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< +qrandom.o: $(SOURCE_PATH)/src/corelib/global/qrandom.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qrandom.cpp + qarraydata.o: $(SOURCE_PATH)/src/corelib/tools/qarraydata.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< diff --git a/qmake/Makefile.win32 b/qmake/Makefile.win32 index f62b4cfeba..385493b582 100644 --- a/qmake/Makefile.win32 +++ b/qmake/Makefile.win32 @@ -109,6 +109,7 @@ QTOBJS= \ qtextstream.obj \ qdatastream.obj \ quuid.obj \ + qrandom.obj \ qsettings.obj \ qvariant.obj \ qsettings_win.obj \ 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 diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro index 521dd5f0f2..b92e5bb82b 100644 --- a/src/tools/bootstrap/bootstrap.pro +++ b/src/tools/bootstrap/bootstrap.pro @@ -29,6 +29,7 @@ SOURCES += \ ../../corelib/global/qmalloc.cpp \ ../../corelib/global/qnumeric.cpp \ ../../corelib/global/qoperatingsystemversion.cpp \ + ../../corelib/global/qrandom.cpp \ ../../corelib/io/qabstractfileengine.cpp \ ../../corelib/io/qbuffer.cpp \ ../../corelib/io/qdatastream.cpp \