diff options
Diffstat (limited to 'src/corelib/thread')
-rw-r--r-- | src/corelib/thread/qfuture.h | 1 | ||||
-rw-r--r-- | src/corelib/thread/qfutureinterface.h | 2 | ||||
-rw-r--r-- | src/corelib/thread/qmutex_p.h | 3 | ||||
-rw-r--r-- | src/corelib/thread/qmutex_unix.cpp | 2 | ||||
-rw-r--r-- | src/corelib/thread/qreadwritelock_p.h | 2 | ||||
-rw-r--r-- | src/corelib/thread/qsemaphore.cpp | 6 | ||||
-rw-r--r-- | src/corelib/thread/qthread.cpp | 48 | ||||
-rw-r--r-- | src/corelib/thread/qthread.h | 7 | ||||
-rw-r--r-- | src/corelib/thread/qthread_p.h | 17 | ||||
-rw-r--r-- | src/corelib/thread/qthread_unix.cpp | 12 | ||||
-rw-r--r-- | src/corelib/thread/qthread_win.cpp | 18 | ||||
-rw-r--r-- | src/corelib/thread/qwaitcondition.h | 4 | ||||
-rw-r--r-- | src/corelib/thread/qwaitcondition_unix.cpp | 53 | ||||
-rw-r--r-- | src/corelib/thread/qwaitcondition_win.cpp | 11 |
14 files changed, 133 insertions, 53 deletions
diff --git a/src/corelib/thread/qfuture.h b/src/corelib/thread/qfuture.h index af599c26db..a456dd9139 100644 --- a/src/corelib/thread/qfuture.h +++ b/src/corelib/thread/qfuture.h @@ -136,6 +136,7 @@ public: inline const_iterator operator-(int j) const { return const_iterator(future, index - j); } inline const_iterator &operator+=(int j) { index += j; return *this; } inline const_iterator &operator-=(int j) { index -= j; return *this; } + friend inline const_iterator operator+(int j, const_iterator k) { return k + j; } private: QFuture const * future; int index; diff --git a/src/corelib/thread/qfutureinterface.h b/src/corelib/thread/qfutureinterface.h index 3dd236752c..d5e2401eee 100644 --- a/src/corelib/thread/qfutureinterface.h +++ b/src/corelib/thread/qfutureinterface.h @@ -178,7 +178,7 @@ public: inline void reportResult(const T *result, int index = -1); inline void reportResult(const T &result, int index = -1); inline void reportResults(const QVector<T> &results, int beginIndex = -1, int count = -1); - inline void reportFinished(const T *result = 0); + inline void reportFinished(const T *result = nullptr); inline const T &resultReference(int index) const; inline const T *resultPointer(int index) const; diff --git a/src/corelib/thread/qmutex_p.h b/src/corelib/thread/qmutex_p.h index 4e6f522a37..ec9bfc1152 100644 --- a/src/corelib/thread/qmutex_p.h +++ b/src/corelib/thread/qmutex_p.h @@ -58,6 +58,7 @@ #include <QtCore/qnamespace.h> #include <QtCore/qmutex.h> #include <QtCore/qatomic.h> +#include <QtCore/qdeadlinetimer.h> #if defined(Q_OS_MAC) # include <mach/semaphore.h> @@ -146,7 +147,7 @@ public: // helper functions for qmutex_unix.cpp and qwaitcondition_unix.cpp // they are in qwaitcondition_unix.cpp actually void qt_initialize_pthread_cond(pthread_cond_t *cond, const char *where); -void qt_abstime_for_timeout(struct timespec *ts, int timeout); +void qt_abstime_for_timeout(struct timespec *ts, QDeadlineTimer deadline); #endif QT_END_NAMESPACE diff --git a/src/corelib/thread/qmutex_unix.cpp b/src/corelib/thread/qmutex_unix.cpp index 3e1e531be4..91f02ba3ec 100644 --- a/src/corelib/thread/qmutex_unix.cpp +++ b/src/corelib/thread/qmutex_unix.cpp @@ -130,7 +130,7 @@ bool QMutexPrivate::wait(int timeout) errorCode = pthread_cond_wait(&cond, &mutex); } else { timespec ti; - qt_abstime_for_timeout(&ti, timeout); + qt_abstime_for_timeout(&ti, QDeadlineTimer(timeout)); errorCode = pthread_cond_timedwait(&cond, &mutex, &ti); } if (errorCode) { diff --git a/src/corelib/thread/qreadwritelock_p.h b/src/corelib/thread/qreadwritelock_p.h index 04dd45a2e1..a01d010043 100644 --- a/src/corelib/thread/qreadwritelock_p.h +++ b/src/corelib/thread/qreadwritelock_p.h @@ -54,7 +54,7 @@ #include <QtCore/private/qglobal_p.h> #include <QtCore/qhash.h> -#include <QtCore/QWaitCondition> +#include <QtCore/qwaitcondition.h> #ifndef QT_NO_THREAD diff --git a/src/corelib/thread/qsemaphore.cpp b/src/corelib/thread/qsemaphore.cpp index 74e0746f43..82d439a728 100644 --- a/src/corelib/thread/qsemaphore.cpp +++ b/src/corelib/thread/qsemaphore.cpp @@ -487,11 +487,9 @@ bool QSemaphore::tryAcquire(int n, int timeout) QDeadlineTimer timer(timeout); QMutexLocker locker(&d->mutex); - qint64 remainingTime = timer.remainingTime(); - while (n > d->avail && remainingTime != 0) { - if (!d->cond.wait(locker.mutex(), remainingTime)) + while (n > d->avail && !timer.hasExpired()) { + if (!d->cond.wait(locker.mutex(), timer)) return false; - remainingTime = timer.remainingTime(); } if (n > d->avail) return false; diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index 23606411ff..472c6f6795 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -117,6 +117,14 @@ void QThreadData::deref() #endif } +QAbstractEventDispatcher *QThreadData::createEventDispatcher() +{ + QAbstractEventDispatcher *ed = QThreadPrivate::createEventDispatcher(this); + eventDispatcher.storeRelease(ed); + ed->startingUp(); + return ed; +} + /* QAdoptedThread */ @@ -140,12 +148,13 @@ QAdoptedThread::~QAdoptedThread() // fprintf(stderr, "~QAdoptedThread = %p\n", this); } +#ifndef QT_NO_THREAD void QAdoptedThread::run() { // this function should never be called qFatal("QAdoptedThread::run(): Internal error, this implementation should never be called."); } -#ifndef QT_NO_THREAD + /* QThreadPrivate */ @@ -750,7 +759,8 @@ int QThread::loopLevel() const #else // QT_NO_THREAD QThread::QThread(QObject *parent) - : QObject(*(new QThreadPrivate), (QObject*)0){ + : QObject(*(new QThreadPrivate), parent) +{ Q_D(QThread); d->data->thread = this; } @@ -760,18 +770,27 @@ QThread *QThread::currentThread() return QThreadData::current()->thread; } -QThreadData* QThreadData::current() +// No threads: so we can just use static variables +static QThreadData *data = 0; + +QThreadData *QThreadData::current(bool createIfNecessary) { - static QThreadData *data = 0; // reinterpret_cast<QThreadData *>(pthread_getspecific(current_thread_data_key)); - if (!data) { - QScopedPointer<QThreadData> newdata(new QThreadData); - newdata->thread = new QAdoptedThread(newdata.data()); - data = newdata.take(); + if (!data && createIfNecessary) { + data = new QThreadData; + data->thread = new QAdoptedThread(data); data->deref(); + if (!QCoreApplicationPrivate::theMainThread) + QCoreApplicationPrivate::theMainThread = data->thread.load(); } return data; } +void QThreadData::clearCurrentThreadData() +{ + delete data; + data = 0; +} + /*! \internal */ @@ -783,6 +802,15 @@ QThread::QThread(QThreadPrivate &dd, QObject *parent) d->data->thread = this; } +QThreadPrivate::QThreadPrivate(QThreadData *d) : data(d ? d : new QThreadData) +{ +} + +QThreadPrivate::~QThreadPrivate() +{ + delete data; +} + #endif // QT_NO_THREAD /*! @@ -820,6 +848,8 @@ void QThread::setEventDispatcher(QAbstractEventDispatcher *eventDispatcher) } } +#ifndef QT_NO_THREAD + /*! \reimp */ @@ -983,6 +1013,8 @@ QDaemonThread::~QDaemonThread() { } +#endif // QT_NO_THREAD + QT_END_NAMESPACE #include "moc_qthread.cpp" diff --git a/src/corelib/thread/qthread.h b/src/corelib/thread/qthread.h index 3df76077e1..83c3329cc0 100644 --- a/src/corelib/thread/qthread.h +++ b/src/corelib/thread/qthread.h @@ -247,6 +247,13 @@ public: static Qt::HANDLE currentThreadId() { return Qt::HANDLE(currentThread()); } static QThread* currentThread(); + static void sleep(unsigned long); + static void msleep(unsigned long); + static void usleep(unsigned long); + + QAbstractEventDispatcher *eventDispatcher() const; + void setEventDispatcher(QAbstractEventDispatcher *eventDispatcher); + protected: QThread(QThreadPrivate &dd, QObject *parent = nullptr); diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h index 46294a5fc8..93f245ff6e 100644 --- a/src/corelib/thread/qthread_p.h +++ b/src/corelib/thread/qthread_p.h @@ -215,9 +215,10 @@ public: class QThreadPrivate : public QObjectPrivate { public: - QThreadPrivate(QThreadData *d = 0) : data(d ? d : new QThreadData) {} - ~QThreadPrivate() { delete data; } + QThreadPrivate(QThreadData *d = 0); + ~QThreadPrivate(); + mutable QMutex mutex; QThreadData *data; static void setCurrentThread(QThread*) {} @@ -247,7 +248,15 @@ public: void ref(); void deref(); inline bool hasEventDispatcher() const - { return eventDispatcher.load() != 0; } + { return eventDispatcher.load() != nullptr; } + QAbstractEventDispatcher *createEventDispatcher(); + QAbstractEventDispatcher *ensureEventDispatcher() + { + QAbstractEventDispatcher *ed = eventDispatcher.load(); + if (Q_LIKELY(ed)) + return ed; + return createEventDispatcher(); + } bool canWaitLocked() { @@ -318,7 +327,9 @@ public: void init(); private: +#ifndef QT_NO_THREAD void run() override; +#endif }; QT_END_NAMESPACE diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index 9ad32b162d..0b3c7ddf10 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -339,13 +339,7 @@ void *QThreadPrivate::start(void *arg) data->quitNow = thr->d_func()->exited; } - QAbstractEventDispatcher *eventDispatcher = data->eventDispatcher.load(); - if (!eventDispatcher) { - eventDispatcher = createEventDispatcher(data); - data->eventDispatcher.storeRelease(eventDispatcher); - } - - eventDispatcher->startingUp(); + data->ensureEventDispatcher(); #if (defined(Q_OS_LINUX) || defined(Q_OS_MAC) || defined(Q_OS_QNX)) { @@ -519,6 +513,8 @@ void QThread::yieldCurrentThread() sched_yield(); } +#endif // QT_NO_THREAD + static timespec makeTimespec(time_t secs, long nsecs) { struct timespec ts; @@ -542,6 +538,8 @@ void QThread::usleep(unsigned long usecs) qt_nanosleep(makeTimespec(usecs / 1000 / 1000, usecs % (1000*1000) * 1000)); } +#ifndef QT_NO_THREAD + #ifdef QT_HAS_THREAD_PRIORITY_SCHEDULING #if defined(Q_OS_QNX) static bool calculateUnixPriority(int priority, int *sched_policy, int *sched_priority) diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp index 4459ae87af..83bcb7d751 100644 --- a/src/corelib/thread/qthread_win.cpp +++ b/src/corelib/thread/qthread_win.cpp @@ -61,9 +61,10 @@ # include <process.h> #endif // Q_OS_WINRT -#ifndef QT_NO_THREAD QT_BEGIN_NAMESPACE +#ifndef QT_NO_THREAD + #ifdef Q_OS_WINRT inline DWORD qWinRTTlsAlloc() { return FlsAlloc(0); @@ -359,13 +360,7 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi data->quitNow = thr->d_func()->exited; } - QAbstractEventDispatcher *eventDispatcher = data->eventDispatcher.load(); - if (!eventDispatcher) { - eventDispatcher = createEventDispatcher(data); - data->eventDispatcher.storeRelease(eventDispatcher); - } - - eventDispatcher->startingUp(); + data->ensureEventDispatcher(); #if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC) && !defined(Q_OS_WINRT) // sets the name of the current thread. @@ -449,6 +444,8 @@ void QThread::yieldCurrentThread() #endif } +#endif // QT_NO_THREAD + void QThread::sleep(unsigned long secs) { ::Sleep(secs * 1000); @@ -464,6 +461,8 @@ void QThread::usleep(unsigned long usecs) ::Sleep((usecs / 1000) + 1); } +#ifndef QT_NO_THREAD + void QThread::start(Priority priority) { Q_D(QThread); @@ -700,5 +699,6 @@ void QThreadPrivate::setPriority(QThread::Priority threadPriority) } } -QT_END_NAMESPACE #endif // QT_NO_THREAD + +QT_END_NAMESPACE diff --git a/src/corelib/thread/qwaitcondition.h b/src/corelib/thread/qwaitcondition.h index a0c6766833..e42efbdfca 100644 --- a/src/corelib/thread/qwaitcondition.h +++ b/src/corelib/thread/qwaitcondition.h @@ -49,6 +49,7 @@ QT_BEGIN_NAMESPACE #ifndef QT_NO_THREAD +class QDeadlineTimer; class QWaitConditionPrivate; class QMutex; class QReadWriteLock; @@ -59,8 +60,11 @@ public: QWaitCondition(); ~QWaitCondition(); + // ### Qt 6: remove unsigned long overloads bool wait(QMutex *lockedMutex, unsigned long time = ULONG_MAX); + bool wait(QMutex *lockedMutex, QDeadlineTimer deadline); bool wait(QReadWriteLock *lockedReadWriteLock, unsigned long time = ULONG_MAX); + bool wait(QReadWriteLock *lockedReadWriteLock, QDeadlineTimer deadline); void wakeOne(); void wakeAll(); diff --git a/src/corelib/thread/qwaitcondition_unix.cpp b/src/corelib/thread/qwaitcondition_unix.cpp index 6adee5412e..9706be1504 100644 --- a/src/corelib/thread/qwaitcondition_unix.cpp +++ b/src/corelib/thread/qwaitcondition_unix.cpp @@ -44,6 +44,8 @@ #include "qreadwritelock.h" #include "qatomic.h" #include "qstring.h" +#include "qdeadlinetimer.h" +#include "private/qdeadlinetimer_p.h" #include "qelapsedtimer.h" #include "private/qcore_unix_p.h" @@ -93,23 +95,25 @@ void qt_initialize_pthread_cond(pthread_cond_t *cond, const char *where) pthread_condattr_destroy(&condattr); } -void qt_abstime_for_timeout(timespec *ts, int timeout) +void qt_abstime_for_timeout(timespec *ts, QDeadlineTimer deadline) { #ifdef Q_OS_MAC // on Mac, qt_gettime() (on qelapsedtimer_mac.cpp) returns ticks related to the Mach absolute time // that doesn't work with pthread // Mac also doesn't have clock_gettime struct timeval tv; + qint64 nsec = deadline.remainingTimeNSecs(); gettimeofday(&tv, 0); - ts->tv_sec = tv.tv_sec; - ts->tv_nsec = tv.tv_usec * 1000; -#else - *ts = qt_gettime(); -#endif + ts->tv_sec = tv.tv_sec + nsec / (1000 * 1000 * 1000); + ts->tv_nsec = tv.tv_usec * 1000 + nsec % (1000 * 1000 * 1000); - ts->tv_sec += timeout / 1000; - ts->tv_nsec += timeout % 1000 * Q_UINT64_C(1000) * 1000; normalizedTimespec(*ts); +#else + // depends on QDeadlineTimer's internals!! + Q_STATIC_ASSERT(QDeadlineTimerNanosecondsInT2); + ts->tv_sec = deadline._q_data().first; + ts->tv_nsec = deadline._q_data().second; +#endif } class QWaitConditionPrivate { @@ -119,26 +123,27 @@ public: int waiters; int wakeups; - int wait_relative(unsigned long time) + int wait_relative(QDeadlineTimer deadline) { timespec ti; #ifdef Q_OS_ANDROID - if (local_cond_timedwait_relative) { - ti.tv_sec = time / 1000; - ti.tv_nsec = time % 1000 * Q_UINT64_C(1000) * 1000; + if (!local_condattr_setclock && local_cond_timedwait_relative) { + qint64 nsec = deadline.remainingTimeNSecs(); + ti.tv_sec = nsec / (1000 * 1000 * 1000); + ti.tv_nsec = nsec - ti.tv_sec * 1000 * 1000 * 1000; return local_cond_timedwait_relative(&cond, &mutex, &ti); } #endif - qt_abstime_for_timeout(&ti, time); + qt_abstime_for_timeout(&ti, deadline); return pthread_cond_timedwait(&cond, &mutex, &ti); } - bool wait(unsigned long time) + bool wait(QDeadlineTimer deadline) { int code; forever { - if (time != ULONG_MAX) { - code = wait_relative(time); + if (!deadline.isForever()) { + code = wait_relative(deadline); } else { code = pthread_cond_wait(&cond, &mutex); } @@ -201,6 +206,13 @@ void QWaitCondition::wakeAll() bool QWaitCondition::wait(QMutex *mutex, unsigned long time) { + if (quint64(time) > quint64(std::numeric_limits<qint64>::max())) + return wait(mutex, QDeadlineTimer(QDeadlineTimer::Forever)); + return wait(mutex, QDeadlineTimer(time)); +} + +bool QWaitCondition::wait(QMutex *mutex, QDeadlineTimer deadline) +{ if (! mutex) return false; if (mutex->isRecursive()) { @@ -212,7 +224,7 @@ bool QWaitCondition::wait(QMutex *mutex, unsigned long time) ++d->waiters; mutex->unlock(); - bool returnValue = d->wait(time); + bool returnValue = d->wait(deadline); mutex->lock(); @@ -221,6 +233,11 @@ bool QWaitCondition::wait(QMutex *mutex, unsigned long time) bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time) { + return wait(readWriteLock, QDeadlineTimer(time)); +} + +bool QWaitCondition::wait(QReadWriteLock *readWriteLock, QDeadlineTimer deadline) +{ if (!readWriteLock) return false; auto previousState = readWriteLock->stateForWaitCondition(); @@ -236,7 +253,7 @@ bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time) readWriteLock->unlock(); - bool returnValue = d->wait(time); + bool returnValue = d->wait(deadline); if (previousState == QReadWriteLock::LockedForWrite) readWriteLock->lockForWrite(); diff --git a/src/corelib/thread/qwaitcondition_win.cpp b/src/corelib/thread/qwaitcondition_win.cpp index e6610f18c8..61e4c2bcb1 100644 --- a/src/corelib/thread/qwaitcondition_win.cpp +++ b/src/corelib/thread/qwaitcondition_win.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qwaitcondition.h" +#include "qdeadlinetimer.h" #include "qnamespace.h" #include "qmutex.h" #include "qreadwritelock.h" @@ -184,6 +185,11 @@ bool QWaitCondition::wait(QMutex *mutex, unsigned long time) return returnValue; } +bool QWaitCondition::wait(QMutex *mutex, QDeadlineTimer deadline) +{ + return wait(mutex, deadline.remainingTime()); +} + bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time) { if (!readWriteLock) @@ -210,6 +216,11 @@ bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time) return returnValue; } +bool QWaitCondition::wait(QReadWriteLock *readWriteLock, QDeadlineTimer deadline) +{ + return wait(readWriteLock, deadline.remainingTime()); +} + void QWaitCondition::wakeOne() { // wake up the first waiting thread in the queue |