summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-10-24 10:37:17 +0200
committerLiang Qi <liang.qi@qt.io>2017-10-24 13:40:55 +0200
commitfa9d12f4a20d618caedc77880459fa1af75fd50d (patch)
tree11bd3cb4541afb924b3ee17f867133e71eb0e090 /src/corelib
parent895cb4681ee78caaf9b99c88390a74ff1d79ae61 (diff)
parentf174d31667dca184439f520b9624a1471d9556a6 (diff)
Merge remote-tracking branch 'origin/5.10' into dev
Conflicts: src/plugins/platforms/windows/qwindowsmousehandler.cpp src/plugins/platforms/xcb/qxcbimage.cpp tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp tests/manual/qtabletevent/regular_widgets/main.cpp Done-with: Friedemann Kleint<Friedemann.Kleint@qt.io> Done-with: MÃ¥rten Nordheim<marten.nordheim@qt.io> Change-Id: I5b2499513a92c590ed0756f7d2e93c35a64b7f30
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/corelib.pro2
-rw-r--r--src/corelib/global/global.pri23
-rw-r--r--src/corelib/global/qglobal.cpp4
-rw-r--r--src/corelib/global/qrandom.cpp8
-rw-r--r--src/corelib/global/qrandom.h12
-rw-r--r--src/corelib/global/qt_windows.h4
-rw-r--r--src/corelib/io/qfilesystemengine_win.cpp3
-rw-r--r--src/corelib/io/qloggingcategory.cpp8
-rw-r--r--src/corelib/io/qurl.cpp31
-rw-r--r--src/corelib/kernel/qcoreevent.cpp8
-rw-r--r--src/corelib/thread/qmutex.h2
-rw-r--r--src/corelib/thread/qthreadpool.cpp87
-rw-r--r--src/corelib/thread/qthreadpool_p.h84
13 files changed, 210 insertions, 66 deletions
diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro
index 3ab7794f2e..4d67e5837f 100644
--- a/src/corelib/corelib.pro
+++ b/src/corelib/corelib.pro
@@ -48,8 +48,6 @@ win32 {
mingw {
# otherwise mingw headers do not declare common functions like putenv
CONFIG -= strict_c++
- # Override MinGW's definition in _mingw.h
- DEFINES += WINVER=0x600 _WIN32_WINNT=0x0600
}
LIBS_PRIVATE += -lws2_32
!winrt {
diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri
index 78b37755a4..7c31df4d6a 100644
--- a/src/corelib/global/global.pri
+++ b/src/corelib/global/global.pri
@@ -99,16 +99,13 @@ gcc:ltcg {
SOURCES += $$VERSIONTAGGING_SOURCES
}
-# On AARCH64 the fp16 extension is mandatory, so we don't need the conversion tables.
-!contains(QT_ARCH, "arm64") {
- QMAKE_QFLOAT16_TABLES_GENERATE = global/qfloat16.h
-
- qtPrepareTool(QMAKE_QFLOAT16_TABLES, qfloat16-tables)
-
- qfloat16_tables.commands = $$QMAKE_QFLOAT16_TABLES ${QMAKE_FILE_OUT}
- qfloat16_tables.output = global/qfloat16tables.cpp
- qfloat16_tables.depends = $$QMAKE_QFLOAT16_TABLES
- qfloat16_tables.input = QMAKE_QFLOAT16_TABLES_GENERATE
- qfloat16_tables.variable_out = SOURCES
- QMAKE_EXTRA_COMPILERS += qfloat16_tables
-}
+QMAKE_QFLOAT16_TABLES_GENERATE = global/qfloat16.h
+
+qtPrepareTool(QMAKE_QFLOAT16_TABLES, qfloat16-tables)
+
+qfloat16_tables.commands = $$QMAKE_QFLOAT16_TABLES ${QMAKE_FILE_OUT}
+qfloat16_tables.output = global/qfloat16tables.cpp
+qfloat16_tables.depends = $$QMAKE_QFLOAT16_TABLES
+qfloat16_tables.input = QMAKE_QFLOAT16_TABLES_GENERATE
+qfloat16_tables.variable_out = SOURCES
+QMAKE_EXTRA_COMPILERS += qfloat16_tables
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index f2f807e1d9..36b7560398 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -4296,6 +4296,7 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters)
/*!
\macro qDebug(const char *message, ...)
\relates <QtGlobal>
+ \threadsafe
Calls the message handler with the debug message \a message. If no
message handler has been installed, the message is printed to
@@ -4332,6 +4333,7 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters)
/*!
\macro qInfo(const char *message, ...)
\relates <QtGlobal>
+ \threadsafe
\since 5.5
Calls the message handler with the informational message \a message. If no
@@ -4369,6 +4371,7 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters)
/*!
\macro qWarning(const char *message, ...)
\relates <QtGlobal>
+ \threadsafe
Calls the message handler with the warning message \a message. If no
message handler has been installed, the message is printed to
@@ -4406,6 +4409,7 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters)
/*!
\macro qCritical(const char *message, ...)
\relates <QtGlobal>
+ \threadsafe
Calls the message handler with the critical message \a message. If no
message handler has been installed, the message is printed to
diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp
index d77ec8075a..9abb9ece7f 100644
--- a/src/corelib/global/qrandom.cpp
+++ b/src/corelib/global/qrandom.cpp
@@ -154,15 +154,19 @@ class SystemRandom
{
static QBasicAtomicInt s_fdp1; // "file descriptor plus 1"
static int openDevice();
+#ifdef Q_CC_GNU
+ // If it's not GCC or GCC-like, then we'll leak the file descriptor
+ __attribute__((destructor))
+#endif
+ static void closeDevice();
SystemRandom() {}
- ~SystemRandom();
public:
enum { EfficientBufferFill = true };
static qssize_t fillBuffer(void *buffer, qssize_t count);
};
QBasicAtomicInt SystemRandom::s_fdp1 = Q_BASIC_ATOMIC_INITIALIZER(0);
-SystemRandom::~SystemRandom()
+void SystemRandom::closeDevice()
{
int fd = s_fdp1.loadAcquire() - 1;
if (fd >= 0)
diff --git a/src/corelib/global/qrandom.h b/src/corelib/global/qrandom.h
index 7f96cd6749..2259f2657a 100644
--- a/src/corelib/global/qrandom.h
+++ b/src/corelib/global/qrandom.h
@@ -62,8 +62,16 @@ public:
static Q_CORE_EXPORT quint64 generate64();
static double generateDouble()
{
- // use get64() to get enough bits
- return double(generate64()) / ((std::numeric_limits<quint64>::max)() + double(1.0));
+ // IEEE 754 double precision has:
+ // 1 bit sign
+ // 10 bits exponent
+ // 53 bits mantissa
+ // In order for our result to be normalized in the range [0, 1), we
+ // need exactly 53 bits of random data. Use generate64() to get enough.
+ quint64 x = generate64();
+ quint64 limit = Q_UINT64_C(1) << std::numeric_limits<double>::digits;
+ x >>= std::numeric_limits<quint64>::digits - std::numeric_limits<double>::digits;
+ return double(x) / double(limit);
}
static qreal bounded(qreal sup)
diff --git a/src/corelib/global/qt_windows.h b/src/corelib/global/qt_windows.h
index bc48104edc..67ba27f072 100644
--- a/src/corelib/global/qt_windows.h
+++ b/src/corelib/global/qt_windows.h
@@ -48,10 +48,10 @@
#if defined(Q_CC_MINGW)
// mingw's windows.h does not set _WIN32_WINNT, resulting breaking compilation
# ifndef WINVER
-# define WINVER 0x600
+# define WINVER 0x601
# endif
# ifndef _WIN32_WINNT
-# define _WIN32_WINNT 0x600
+# define _WIN32_WINNT 0x601
# endif
# ifndef NTDDI_VERSION
# define NTDDI_VERSION 0x06000000
diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp
index 35ddb41215..944ca232ee 100644
--- a/src/corelib/io/qfilesystemengine_win.cpp
+++ b/src/corelib/io/qfilesystemengine_win.cpp
@@ -595,6 +595,9 @@ QByteArray QFileSystemEngine::id(const QFileSystemEntry &entry)
params.dwSize = sizeof(params);
params.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
params.dwFileFlags = FILE_FLAG_BACKUP_SEMANTICS;
+ params.dwSecurityQosFlags = SECURITY_ANONYMOUS;
+ params.lpSecurityAttributes = NULL;
+ params.hTemplateFile = NULL;
const HANDLE handle =
CreateFile2((const wchar_t*)entry.nativeFilePath().utf16(), 0,
FILE_SHARE_READ, OPEN_EXISTING, &params);
diff --git a/src/corelib/io/qloggingcategory.cpp b/src/corelib/io/qloggingcategory.cpp
index 4256d4b6e1..b029274329 100644
--- a/src/corelib/io/qloggingcategory.cpp
+++ b/src/corelib/io/qloggingcategory.cpp
@@ -445,6 +445,7 @@ void QLoggingCategory::setFilterRules(const QString &rules)
/*!
\macro qCDebug(category)
\relates QLoggingCategory
+ \threadsafe
\since 5.2
Returns an output stream for debug messages in the logging category
@@ -469,6 +470,7 @@ void QLoggingCategory::setFilterRules(const QString &rules)
/*!
\macro qCDebug(category, const char *message, ...)
\relates QLoggingCategory
+ \threadsafe
\since 5.3
Logs a debug message \a message in the logging category \a category.
@@ -490,6 +492,7 @@ void QLoggingCategory::setFilterRules(const QString &rules)
/*!
\macro qCInfo(category)
\relates QLoggingCategory
+ \threadsafe
\since 5.5
Returns an output stream for informational messages in the logging category
@@ -514,6 +517,7 @@ void QLoggingCategory::setFilterRules(const QString &rules)
/*!
\macro qCInfo(category, const char *message, ...)
\relates QLoggingCategory
+ \threadsafe
\since 5.5
Logs an informational message \a message in the logging category \a category.
@@ -535,6 +539,7 @@ void QLoggingCategory::setFilterRules(const QString &rules)
/*!
\macro qCWarning(category)
\relates QLoggingCategory
+ \threadsafe
\since 5.2
Returns an output stream for warning messages in the logging category
@@ -559,6 +564,7 @@ void QLoggingCategory::setFilterRules(const QString &rules)
/*!
\macro qCWarning(category, const char *message, ...)
\relates QLoggingCategory
+ \threadsafe
\since 5.3
Logs a warning message \a message in the logging category \a category.
@@ -580,6 +586,7 @@ void QLoggingCategory::setFilterRules(const QString &rules)
/*!
\macro qCCritical(category)
\relates QLoggingCategory
+ \threadsafe
\since 5.2
Returns an output stream for critical messages in the logging category
@@ -604,6 +611,7 @@ void QLoggingCategory::setFilterRules(const QString &rules)
/*!
\macro qCCritical(category, const char *message, ...)
\relates QLoggingCategory
+ \threadsafe
\since 5.3
Logs a critical message \a message in the logging category \a category.
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp
index ac694a464a..a499dc2d30 100644
--- a/src/corelib/io/qurl.cpp
+++ b/src/corelib/io/qurl.cpp
@@ -499,9 +499,10 @@ public:
InvalidFragmentError = Fragment << 8,
- // the following two cases are only possible in combination
- // with presence/absence of the authority and scheme. See validityError().
+ // the following three cases are only possible in combination with
+ // presence/absence of the path, authority and scheme. See validityError().
AuthorityPresentAndPathIsRelative = Authority << 8 | Path << 8 | 0x10000,
+ AuthorityAbsentAndPathIsDoubleSlash,
RelativeUrlPathContainsColonBeforeSlash = Scheme << 8 | Authority << 8 | Path << 8 | 0x10000,
NoError = 0
@@ -1627,19 +1628,32 @@ inline QUrlPrivate::ErrorCode QUrlPrivate::validityError(QString *source, int *p
return error->code;
}
- // There are two more cases of invalid URLs that QUrl recognizes and they
+ // There are three more cases of invalid URLs that QUrl recognizes and they
// are only possible with constructed URLs (setXXX methods), not with
// parsing. Therefore, they are tested here.
//
- // The two cases are a non-empty path that doesn't start with a slash and:
+ // Two cases are a non-empty path that doesn't start with a slash and:
// - with an authority
// - without an authority, without scheme but the path with a colon before
// the first slash
+ // The third case is an empty authority and a non-empty path that starts
+ // with "//".
// Those cases are considered invalid because toString() would produce a URL
// that wouldn't be parsed back to the same QUrl.
- if (path.isEmpty() || path.at(0) == QLatin1Char('/'))
+ if (path.isEmpty())
return NoError;
+ if (path.at(0) == QLatin1Char('/')) {
+ if (sectionIsPresent & QUrlPrivate::Authority || port != -1 ||
+ path.length() == 1 || path.at(1) != QLatin1Char('/'))
+ return NoError;
+ if (source) {
+ *source = path;
+ *position = 0;
+ }
+ return AuthorityAbsentAndPathIsDoubleSlash;
+ }
+
if (sectionIsPresent & QUrlPrivate::Host) {
if (source) {
*source = path;
@@ -2514,10 +2528,7 @@ void QUrl::setPath(const QString &path, ParsingMode mode)
mode = TolerantMode;
}
- int from = 0;
- while (from < data.length() - 2 && data.midRef(from, 2) == QLatin1String("//"))
- ++from;
- d->setPath(data, from, data.length());
+ d->setPath(data, 0, data.length());
// optimized out, since there is no path delimiter
// if (path.isNull())
@@ -3989,6 +4000,8 @@ static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &err
case QUrlPrivate::AuthorityPresentAndPathIsRelative:
return QStringLiteral("Path component is relative and authority is present");
+ case QUrlPrivate::AuthorityAbsentAndPathIsDoubleSlash:
+ return QStringLiteral("Path component starts with '//' and authority is absent");
case QUrlPrivate::RelativeUrlPathContainsColonBeforeSlash:
return QStringLiteral("Relative URL's path component contains ':' before any '/'");
}
diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp
index e90cd842ab..1e6b328c75 100644
--- a/src/corelib/kernel/qcoreevent.cpp
+++ b/src/corelib/kernel/qcoreevent.cpp
@@ -170,10 +170,10 @@ QT_BEGIN_NAMESPACE
\value LeaveEditFocus An editor widget loses focus for editing. QT_KEYPAD_NAVIGATION must be defined.
\value LeaveWhatsThisMode Send to toplevel widgets when the application leaves "What's This?" mode.
\value LocaleChange The system locale has changed.
- \value NonClientAreaMouseButtonDblClick A mouse double click occurred outside the client area.
- \value NonClientAreaMouseButtonPress A mouse button press occurred outside the client area.
- \value NonClientAreaMouseButtonRelease A mouse button release occurred outside the client area.
- \value NonClientAreaMouseMove A mouse move occurred outside the client area.
+ \value NonClientAreaMouseButtonDblClick A mouse double click occurred outside the client area (QMouseEvent).
+ \value NonClientAreaMouseButtonPress A mouse button press occurred outside the client area (QMouseEvent).
+ \value NonClientAreaMouseButtonRelease A mouse button release occurred outside the client area (QMouseEvent).
+ \value NonClientAreaMouseMove A mouse move occurred outside the client area (QMouseEvent).
\value MacSizeChange The user changed his widget sizes (\macos only).
\value MetaCall An asynchronous method invocation via QMetaObject::invokeMethod().
\value ModifiedChange Widgets modification state has been changed.
diff --git a/src/corelib/thread/qmutex.h b/src/corelib/thread/qmutex.h
index f40dd3c814..541f6af546 100644
--- a/src/corelib/thread/qmutex.h
+++ b/src/corelib/thread/qmutex.h
@@ -251,7 +251,7 @@ class Q_CORE_EXPORT QMutex
public:
enum RecursionMode { NonRecursive, Recursive };
- inline explicit QMutex(RecursionMode mode = NonRecursive) Q_DECL_NOTHROW { Q_UNUSED(mode); }
+ inline Q_DECL_CONSTEXPR explicit QMutex(RecursionMode = NonRecursive) Q_DECL_NOTHROW { }
inline void lock() Q_DECL_NOTHROW {}
inline bool tryLock(int timeout = 0) Q_DECL_NOTHROW { Q_UNUSED(timeout); return true; }
diff --git a/src/corelib/thread/qthreadpool.cpp b/src/corelib/thread/qthreadpool.cpp
index fd5a1106a0..157cbeaf4d 100644
--- a/src/corelib/thread/qthreadpool.cpp
+++ b/src/corelib/thread/qthreadpool.cpp
@@ -73,7 +73,7 @@ public:
\internal
*/
QThreadPoolThread::QThreadPoolThread(QThreadPoolPrivate *manager)
- :manager(manager), runnable(0)
+ :manager(manager), runnable(nullptr)
{
setStackSize(manager->stackSize);
}
@@ -86,7 +86,7 @@ void QThreadPoolThread::run()
QMutexLocker locker(&manager->mutex);
for(;;) {
QRunnable *r = runnable;
- runnable = 0;
+ runnable = nullptr;
do {
if (r) {
@@ -118,8 +118,19 @@ void QThreadPoolThread::run()
if (manager->tooManyThreadsActive())
break;
- r = !manager->queue.isEmpty() ? manager->queue.takeFirst().first : 0;
- } while (r != 0);
+ if (manager->queue.isEmpty()) {
+ r = nullptr;
+ break;
+ }
+
+ QueuePage *page = manager->queue.first();
+ r = page->pop();
+
+ if (page->isFinished()) {
+ manager->queue.removeFirst();
+ delete page;
+ }
+ } while (true);
if (manager->isExiting) {
registerThreadInactive();
@@ -160,6 +171,7 @@ QThreadPoolPrivate:: QThreadPoolPrivate()
bool QThreadPoolPrivate::tryStart(QRunnable *task)
{
+ Q_ASSERT(task != nullptr);
if (allThreads.isEmpty()) {
// always create at least one thread
startThread(task);
@@ -180,7 +192,7 @@ bool QThreadPoolPrivate::tryStart(QRunnable *task)
if (!expiredThreads.isEmpty()) {
// restart an expired thread
QThreadPoolThread *thread = expiredThreads.dequeue();
- Q_ASSERT(thread->runnable == 0);
+ Q_ASSERT(thread->runnable == nullptr);
++activeThreads;
@@ -196,22 +208,25 @@ bool QThreadPoolPrivate::tryStart(QRunnable *task)
return true;
}
-inline bool operator<(int priority, const QPair<QRunnable *, int> &p)
-{ return p.second < priority; }
-inline bool operator<(const QPair<QRunnable *, int> &p, int priority)
-{ return priority < p.second; }
+inline bool comparePriority(int priority, const QueuePage *p)
+{
+ return p->priority() < priority;
+}
void QThreadPoolPrivate::enqueueTask(QRunnable *runnable, int priority)
{
+ Q_ASSERT(runnable != nullptr);
if (runnable->autoDelete())
++runnable->ref;
- // put it on the queue
- QVector<QPair<QRunnable *, int> >::const_iterator begin = queue.constBegin();
- QVector<QPair<QRunnable *, int> >::const_iterator it = queue.constEnd();
- if (it != begin && priority > (*(it - 1)).second)
- it = std::upper_bound(begin, --it, priority);
- queue.insert(it - begin, qMakePair(runnable, priority));
+ for (QueuePage *page : qAsConst(queue)) {
+ if (page->priority() == priority && !page->isFull()) {
+ page->push(runnable);
+ return;
+ }
+ }
+ auto it = std::upper_bound(queue.constBegin(), queue.constEnd(), priority, comparePriority);
+ queue.insert(std::distance(queue.constBegin(), it), new QueuePage(runnable, priority));
}
int QThreadPoolPrivate::activeThreadCount() const
@@ -225,8 +240,18 @@ int QThreadPoolPrivate::activeThreadCount() const
void QThreadPoolPrivate::tryToStartMoreThreads()
{
// try to push tasks on the queue to any available threads
- while (!queue.isEmpty() && tryStart(queue.constFirst().first))
- queue.removeFirst();
+ while (!queue.isEmpty()) {
+ QueuePage *page = queue.first();
+ if (!tryStart(page->first()))
+ break;
+
+ page->pop();
+
+ if (page->isFinished()) {
+ queue.removeFirst();
+ delete page;
+ }
+ }
}
bool QThreadPoolPrivate::tooManyThreadsActive() const
@@ -240,6 +265,7 @@ bool QThreadPoolPrivate::tooManyThreadsActive() const
*/
void QThreadPoolPrivate::startThread(QRunnable *runnable)
{
+ Q_ASSERT(runnable != nullptr);
QScopedPointer <QThreadPoolThread> thread(new QThreadPoolThread(this));
thread->setObjectName(QLatin1String("Thread (pooled)"));
Q_ASSERT(!allThreads.contains(thread.data())); // if this assert hits, we have an ABA problem (deleted threads don't get removed here)
@@ -303,12 +329,14 @@ bool QThreadPoolPrivate::waitForDone(int msecs)
void QThreadPoolPrivate::clear()
{
QMutexLocker locker(&mutex);
- for (QVector<QPair<QRunnable *, int> >::const_iterator it = queue.constBegin();
- it != queue.constEnd(); ++it) {
- QRunnable* r = it->first;
- if (r->autoDelete() && !--r->ref)
- delete r;
+ for (QueuePage *page : qAsConst(queue)) {
+ while (!page->isFinished()) {
+ QRunnable *r = page->pop();
+ if (r && r->autoDelete() && !--r->ref)
+ delete r;
+ }
}
+ qDeleteAll(queue);
queue.clear();
}
@@ -333,22 +361,21 @@ bool QThreadPool::tryTake(QRunnable *runnable)
{
Q_D(QThreadPool);
- if (runnable == 0)
+ if (runnable == nullptr)
return false;
{
QMutexLocker locker(&d->mutex);
- auto it = d->queue.begin();
- auto end = d->queue.end();
-
- while (it != end) {
- if (it->first == runnable) {
- d->queue.erase(it);
+ for (QueuePage *page : qAsConst(d->queue)) {
+ if (page->tryTake(runnable)) {
+ if (page->isFinished()) {
+ d->queue.removeOne(page);
+ delete page;
+ }
if (runnable->autoDelete())
--runnable->ref; // undo ++ref in start()
return true;
}
- ++it;
}
}
diff --git a/src/corelib/thread/qthreadpool_p.h b/src/corelib/thread/qthreadpool_p.h
index 8b6a8cc476..d03ba9d77f 100644
--- a/src/corelib/thread/qthreadpool_p.h
+++ b/src/corelib/thread/qthreadpool_p.h
@@ -63,6 +63,87 @@
QT_BEGIN_NAMESPACE
+class QueuePage {
+public:
+ enum {
+ MaxPageSize = 256
+ };
+
+ QueuePage(QRunnable *runnable, int pri)
+ : m_priority(pri)
+ {
+ push(runnable);
+ }
+
+ bool isFull() {
+ return m_lastIndex >= MaxPageSize - 1;
+ }
+
+ bool isFinished() {
+ return m_firstIndex > m_lastIndex;
+ }
+
+ void push(QRunnable *runnable) {
+ Q_ASSERT(runnable != nullptr);
+ Q_ASSERT(!isFull());
+ m_lastIndex += 1;
+ m_entries[m_lastIndex] = runnable;
+ }
+
+ void skipToNextOrEnd() {
+ while (!isFinished() && m_entries[m_firstIndex] == nullptr) {
+ m_firstIndex += 1;
+ }
+ }
+
+ QRunnable *first() {
+ Q_ASSERT(!isFinished());
+ QRunnable *runnable = m_entries[m_firstIndex];
+ Q_ASSERT(runnable);
+ return runnable;
+ }
+
+ QRunnable *pop() {
+ Q_ASSERT(!isFinished());
+ QRunnable *runnable = first();
+ Q_ASSERT(runnable);
+
+ // clear the entry although this should not be necessary
+ m_entries[m_firstIndex] = nullptr;
+ m_firstIndex += 1;
+
+ // make sure the next runnable returned by first() is not a nullptr
+ skipToNextOrEnd();
+
+ return runnable;
+ }
+
+ bool tryTake(QRunnable *runnable) {
+ Q_ASSERT(!isFinished());
+ for (int i = m_firstIndex; i <= m_lastIndex; i++) {
+ if (m_entries[i] == runnable) {
+ m_entries[i] = nullptr;
+ if (i == m_firstIndex) {
+ // make sure first() does not return a nullptr
+ skipToNextOrEnd();
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ int priority() const {
+ return m_priority;
+ }
+
+private:
+ int m_priority = 0;
+ int m_firstIndex = 0;
+ int m_lastIndex = -1;
+ QRunnable *m_entries[MaxPageSize];
+};
+
class QThreadPoolThread;
class Q_CORE_EXPORT QThreadPoolPrivate : public QObjectPrivate
{
@@ -84,12 +165,13 @@ public:
bool waitForDone(int msecs);
void clear();
void stealAndRunRunnable(QRunnable *runnable);
+ void deletePageIfFinished(QueuePage *page);
mutable QMutex mutex;
QList<QThreadPoolThread *> allThreads;
QQueue<QThreadPoolThread *> waitingThreads;
QQueue<QThreadPoolThread *> expiredThreads;
- QVector<QPair<QRunnable *, int> > queue;
+ QVector<QueuePage*> queue;
QWaitCondition noActiveThreads;
int expiryTimeout = 30000;