1 /*
2     SPDX-FileCopyrightText: 2009 Nokia Corporation and /or its subsidiary(-ies).
3     Contact: Qt Software Information (qt-info@nokia.com)
4 
5     This file is part of the QtCore module of the Qt Toolkit.
6 
7     $QT_BEGIN_LICENSE:LGPL$
8     Commercial Usage
9     Licensees holding valid Qt Commercial licenses may use this file in
10     accordance with the Qt Commercial License Agreement provided with the
11     Software or, alternatively, in accordance with the terms contained in
12     a written agreement between you and Nokia.
13 
14     GNU Lesser General Public License Usage
15     Alternatively, this file may be used under the terms of the GNU Lesser
16     General Public License version 2.1 as published by the Free Software
17     Foundation and appearing in the file LICENSE.LGPL included in the
18     packaging of this file.  Please review the following information to
19     ensure the GNU Lesser General Public License version 2.1 requirements
20     will be met: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
21 
22     In addition, as a special exception, Nokia gives you certain
23     additional rights. These rights are described in the Nokia Qt LGPL
24     Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
25     package.
26 
27     GNU General Public License Usage
28     Alternatively, this file may be used under the terms of the GNU
29     General Public License version 3.0 as published by the Free Software
30     Foundation and appearing in the file LICENSE.GPL included in the
31     packaging of this file.  Please review the following information to
32     ensure the GNU General Public License version 3.0 requirements will be
33     met: https://www.gnu.org/licenses/gpl-3.0.html.
34 
35     If you are unsure which license is appropriate for your use, please
36     contact the sales department at qt-sales@nokia.com.
37     $QT_END_LICENSE$
38 
39 */
40 
41 #ifndef QTHREAD_P_H
42 #define QTHREAD_P_H
43 
44 //
45 //  W A R N I N G
46 //  -------------
47 //
48 // This file is not part of the Qt API.  It exists purely as an
49 // implementation detail.  This header file may change from version to
50 // version without notice, or even be removed.
51 //
52 // We mean it.
53 //
54 //
55 
56 #include "qplatformdefs.h"
57 #include "QtCore/qthread.h"
58 #include "QtCore/QtCore/QMutex"
59 #include "QtCore/qstack.h"
60 #include "QtCore/QtCore/QWaitCondition"
61 #include "QtCore/QtCore/QMap"
62 #include "private/qobject_p.h"
63 
64 QT_BEGIN_NAMESPACE
65 
66 class QAbstractEventDispatcher;
67 class QEventLoop;
68 
69 class QPostEvent
70 {
71 public:
72     QObject *receiver;
73     QEvent *event;
74     int priority;
QPostEvent()75     inline QPostEvent()
76         : receiver(0), event(0), priority(0)
77     { }
QPostEvent(QObject * r,QEvent * e,int p)78     inline QPostEvent(QObject *r, QEvent *e, int p)
79         : receiver(r), event(e), priority(p)
80     { }
81 };
82 inline bool operator<(int priority, const QPostEvent &pe)
83 {
84     return pe.priority < priority;
85 }
86 inline bool operator<(const QPostEvent &pe, int priority)
87 {
88     return priority < pe.priority;
89 }
90 
91 class QPostEventList : public QList<QPostEvent>
92 {
93 public:
94     // recursion == recursion count for sendPostedEvents()
95     int recursion;
96 
97     // sendOffset == the current event to start sending
98     int startOffset;
99     // insertionOffset == set by sendPostedEvents to tell postEvent() where to start insertions
100     int insertionOffset;
101 
102     QMutex mutex;
103 
QPostEventList()104     inline QPostEventList()
105         : QList<QPostEvent>(), recursion(0), startOffset(0), insertionOffset(0)
106     { }
107 };
108 
109 class Q_CORE_EXPORT QThreadData
110 {
111     QAtomicInt _ref;
112 
113 public:
114     QThreadData(int initialRefCount = 1);
115     ~QThreadData();
116 
117     static QThreadData *current();
118     static QThreadData *get2(QThread *thread);
119 
120     void ref();
121     void deref();
122 
123     QThread *thread;
124     bool quitNow;
125     int loopLevel;
126     QAbstractEventDispatcher *eventDispatcher;
127     QStack<QEventLoop *> eventLoops;
128     QPostEventList postEventList;
129     bool canWait;
130     QMap<int, void *> tls;
131 
132     QMutex mutex;
133 };
134 
135 #ifndef QT_NO_THREAD
136 class QThreadPrivate : public QObjectPrivate
137 {
138     Q_DECLARE_PUBLIC(QThread)
139 
140 public:
141     QThreadPrivate(QThreadData *d = 0);
142     ~QThreadPrivate();
143 
144     mutable QMutex mutex;
145 
146     bool running;
147     bool finished;
148     bool terminated;
149 
150     uint stackSize;
151     QThread::Priority priority;
152 
153     static QThread *threadForId(int id);
154 
155 #ifdef Q_OS_UNIX
156     pthread_t thread_id;
157     QWaitCondition thread_done;
158 
159     static void *start(void *arg);
160     static void finish(void *arg);
161 #endif
162 
163 #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
164     HANDLE handle;
165     unsigned int id;
166     int waiters;
167     bool terminationEnabled, terminatePending;
168 
169     static unsigned int __stdcall start(void *);
170     static void finish(void *, bool lockAnyway=true);
171 #endif // Q_OS_WIN32
172 
173     QThreadData *data;
174 
175     static void createEventDispatcher(QThreadData *data);
176 };
177 
178 // thread wrapper for the main() thread
179 class QAdoptedThread : public QThread
180 {
181     Q_DECLARE_PRIVATE(QThread)
182 
183 public:
184     QAdoptedThread(QThreadData *data = 0);
185     ~QAdoptedThread();
186     void init();
187 
188     static QThread *createThreadForAdoption();
189 private:
190     void run();
191 };
192 
193 #else // QT_NO_THREAD
194 
195 class QThreadPrivate : public QObjectPrivate
196 {
197 public:
QThreadPrivate()198     QThreadPrivate() : data(QThreadData::current()) {}
~QThreadPrivate()199     ~QThreadPrivate() { }
200 
201     QThreadData *data;
202 
setCurrentThread(QThread *)203     static void setCurrentThread(QThread*) {}
threadForId(int)204     static QThread *threadForId(int) { return QThread::currentThread(); }
205     static void createEventDispatcher(QThreadData *data);
206 
207     Q_DECLARE_PUBLIC(QThread)
208 };
209 
210 #endif // QT_NO_THREAD
211 
212 QT_END_NAMESPACE
213 
214 #endif // QTHREAD_P_H
215