1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QTHREADPOOL_P_H
41#define QTHREADPOOL_P_H
42
43//
44// W A R N I N G
45// -------------
46//
47// This file is not part of the Qt API. It exists purely as an
48// implementation detail. This header file may change from version to
49// version without notice, or even be removed.
50//
51// We mean it.
52//
53//
54
55#include "QtCore/qmutex.h"
56#include "QtCore/qthread.h"
57#include "QtCore/qwaitcondition.h"
58#include "QtCore/qset.h"
59#include "QtCore/qqueue.h"
60#include "private/qobject_p.h"
61
62QT_REQUIRE_CONFIG(thread);
63
64QT_BEGIN_NAMESPACE
65
66class QDeadlineTimer;
67
68class QueuePage {
69public:
70 enum {
71 MaxPageSize = 256
72 };
73
74 QueuePage(QRunnable *runnable, int pri)
75 : m_priority(pri)
76 {
77 push(runnable);
78 }
79
80 bool isFull() {
81 return m_lastIndex >= MaxPageSize - 1;
82 }
83
84 bool isFinished() {
85 return m_firstIndex > m_lastIndex;
86 }
87
88 void push(QRunnable *runnable) {
89 Q_ASSERT(runnable != nullptr);
90 Q_ASSERT(!isFull());
91 m_lastIndex += 1;
92 m_entries[m_lastIndex] = runnable;
93 }
94
95 void skipToNextOrEnd() {
96 while (!isFinished() && m_entries[m_firstIndex] == nullptr) {
97 m_firstIndex += 1;
98 }
99 }
100
101 QRunnable *first() {
102 Q_ASSERT(!isFinished());
103 QRunnable *runnable = m_entries[m_firstIndex];
104 Q_ASSERT(runnable);
105 return runnable;
106 }
107
108 QRunnable *pop() {
109 Q_ASSERT(!isFinished());
110 QRunnable *runnable = first();
111 Q_ASSERT(runnable);
112
113 // clear the entry although this should not be necessary
114 m_entries[m_firstIndex] = nullptr;
115 m_firstIndex += 1;
116
117 // make sure the next runnable returned by first() is not a nullptr
118 skipToNextOrEnd();
119
120 return runnable;
121 }
122
123 bool tryTake(QRunnable *runnable) {
124 Q_ASSERT(!isFinished());
125 for (int i = m_firstIndex; i <= m_lastIndex; i++) {
126 if (m_entries[i] == runnable) {
127 m_entries[i] = nullptr;
128 if (i == m_firstIndex) {
129 // make sure first() does not return a nullptr
130 skipToNextOrEnd();
131 }
132 return true;
133 }
134 }
135 return false;
136 }
137
138 int priority() const {
139 return m_priority;
140 }
141
142private:
143 int m_priority = 0;
144 int m_firstIndex = 0;
145 int m_lastIndex = -1;
146 QRunnable *m_entries[MaxPageSize];
147};
148
149class QThreadPoolThread;
150class Q_CORE_EXPORT QThreadPoolPrivate : public QObjectPrivate
151{
152 Q_DECLARE_PUBLIC(QThreadPool)
153 friend class QThreadPoolThread;
154
155public:
156 QThreadPoolPrivate();
157
158 bool tryStart(QRunnable *task);
159 void enqueueTask(QRunnable *task, int priority = 0);
160 int activeThreadCount() const;
161
162 void tryToStartMoreThreads();
163 bool tooManyThreadsActive() const;
164
165 void startThread(QRunnable *runnable = nullptr);
166 void reset();
167 bool waitForDone(int msecs);
168 bool waitForDone(const QDeadlineTimer &timer);
169 void clear();
170 void stealAndRunRunnable(QRunnable *runnable);
171 void deletePageIfFinished(QueuePage *page);
172
173 mutable QMutex mutex;
174 QSet<QThreadPoolThread *> allThreads;
175 QQueue<QThreadPoolThread *> waitingThreads;
176 QQueue<QThreadPoolThread *> expiredThreads;
177 QVector<QueuePage*> queue;
178 QWaitCondition noActiveThreads;
179
180 int expiryTimeout = 30000;
181 int maxThreadCount = QThread::idealThreadCount();
182 int reservedThreads = 0;
183 int activeThreads = 0;
184 uint stackSize = 0;
185};
186
187QT_END_NAMESPACE
188
189#endif
190

source code of qtbase/src/corelib/thread/qthreadpool_p.h