qt6-bb10/src/corelib/thread/qthreadpool_p.h

158 lines
3.9 KiB
C++

// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTHREADPOOL_P_H
#define QTHREADPOOL_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
//
#include "QtCore/qmutex.h"
#include "QtCore/qthread.h"
#include "QtCore/qwaitcondition.h"
#include "QtCore/qthreadpool.h"
#include "QtCore/qset.h"
#include "QtCore/qqueue.h"
#include "private/qobject_p.h"
QT_REQUIRE_CONFIG(thread);
QT_BEGIN_NAMESPACE
class QDeadlineTimer;
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
{
Q_DECLARE_PUBLIC(QThreadPool)
friend class QThreadPoolThread;
public:
QThreadPoolPrivate();
bool tryStart(QRunnable *task);
void enqueueTask(QRunnable *task, int priority = 0);
int activeThreadCount() const;
void tryToStartMoreThreads();
bool areAllThreadsActive() const;
bool tooManyThreadsActive() const;
int maxThreadCount() const
{ return qMax(requestedMaxThreadCount, 1); } // documentation says we start at least one
void startThread(QRunnable *runnable = nullptr);
void reset();
bool waitForDone(int msecs);
bool waitForDone(const QDeadlineTimer &timer);
void clear();
void stealAndRunRunnable(QRunnable *runnable);
void deletePageIfFinished(QueuePage *page);
static QThreadPool *qtGuiInstance();
mutable QMutex mutex;
QSet<QThreadPoolThread *> allThreads;
QQueue<QThreadPoolThread *> waitingThreads;
QQueue<QThreadPoolThread *> expiredThreads;
QList<QueuePage *> queue;
QWaitCondition noActiveThreads;
QString objectName;
int expiryTimeout = 30000;
int requestedMaxThreadCount = QThread::idealThreadCount(); // don't use this directly
int reservedThreads = 0;
int activeThreads = 0;
uint stackSize = 0;
QThread::Priority threadPriority = QThread::InheritPriority;
};
QT_END_NAMESPACE
#endif