1
/****************************************************************************
3
** Copyright (C) 2016 The Qt Company Ltd.
4
** Contact: https://www.qt.io/licensing/
6
** This file is part of the QtCore module of the Qt Toolkit.
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.
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.
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.
38
****************************************************************************/
40
#include "qeventloop.h"
42
#include "qabstracteventdispatcher.h"
43
#include "qcoreapplication.h"
44
#include "qcoreapplication_p.h"
45
#include "qelapsedtimer.h"
47
#include "qobject_p.h"
48
#include "qeventloop_p.h"
49
#include <private/qthread_p.h>
56
\brief The QEventLoop class provides a means of entering and leaving an event loop.
58
At any time, you can create a QEventLoop object and call exec()
59
on it to start a local event loop. From within the event loop,
60
calling exit() will force exec() to return.
62
\sa QAbstractEventDispatcher
66
\enum QEventLoop::ProcessEventsFlag
68
This enum controls the types of events processed by the
69
processEvents() functions.
71
\value AllEvents All events. Note that
72
\l{QEvent::DeferredDelete}{DeferredDelete} events are processed
73
specially. See QObject::deleteLater() for more details.
75
\value ExcludeUserInputEvents Do not process user input events,
76
such as ButtonPress and KeyPress. Note that the events are not
77
discarded; they will be delivered the next time processEvents() is
78
called without the ExcludeUserInputEvents flag.
80
\value ExcludeSocketNotifiers Do not process socket notifier
81
events. Note that the events are not discarded; they will be
82
delivered the next time processEvents() is called without the
83
ExcludeSocketNotifiers flag.
85
\value WaitForMoreEvents Wait for events if no pending events are
88
\omitvalue X11ExcludeTimers
89
\omitvalue EventLoopExec
96
Constructs an event loop object with the given \a parent.
98
QEventLoop::QEventLoop(QObject *parent)
99
: QObject(*new QEventLoopPrivate, parent)
102
if (!QCoreApplication::instance() && QCoreApplicationPrivate::threadRequiresCoreApplication()) {
103
qWarning("QEventLoop: Cannot be used without QApplication");
104
} else if (!d->threadData->eventDispatcher.load()) {
105
QThreadPrivate::createEventDispatcher(d->threadData);
110
Destroys the event loop object.
112
QEventLoop::~QEventLoop()
117
Processes pending events that match \a flags until there are no
118
more events to process. Returns \c true if pending events were handled;
119
otherwise returns \c false.
121
This function is especially useful if you have a long running
122
operation and want to show its progress without allowing user
123
input; i.e. by using the \l ExcludeUserInputEvents flag.
125
This function is simply a wrapper for
126
QAbstractEventDispatcher::processEvents(). See the documentation
127
for that function for details.
129
bool QEventLoop::processEvents(ProcessEventsFlags flags)
132
if (!d->threadData->eventDispatcher.load())
134
return d->threadData->eventDispatcher.load()->processEvents(flags);
138
Enters the main event loop and waits until exit() is called.
139
Returns the value that was passed to exit().
141
If \a flags are specified, only events of the types allowed by
142
the \a flags will be processed.
144
It is necessary to call this function to start event handling. The
145
main event loop receives events from the window system and
146
dispatches these to the application widgets.
148
Generally speaking, no user interaction can take place before
149
calling exec(). As a special case, modal widgets like QMessageBox
150
can be used before calling exec(), because modal widgets
151
use their own local event loop.
153
To make your application perform idle processing (i.e. executing a
154
special function whenever there are no pending events), use a
155
QTimer with 0 timeout. More sophisticated idle processing schemes
156
can be achieved using processEvents().
158
\sa QCoreApplication::quit(), exit(), processEvents()
160
int QEventLoop::exec(ProcessEventsFlags flags)
163
//we need to protect from race condition with QThread::exit
164
QMutexLocker locker(&static_cast<QThreadPrivate *>(QObjectPrivate::get(d->threadData->thread))->mutex);
165
if (d->threadData->quitNow)
169
qWarning("QEventLoop::exec: instance %p has already called exec()", this);
173
struct LoopReference {
174
QEventLoopPrivate *d;
175
QMutexLocker &locker;
177
bool exceptionCaught;
178
LoopReference(QEventLoopPrivate *d, QMutexLocker &locker) : d(d), locker(locker), exceptionCaught(true)
181
d->exit.storeRelease(false);
182
++d->threadData->loopLevel;
183
d->threadData->eventLoops.push(d->q_func());
189
if (exceptionCaught) {
190
qWarning("Qt has caught an exception thrown from an event handler. Throwing\n"
191
"exceptions from an event handler is not supported in Qt.\n"
192
"You must not let any exception whatsoever propagate through Qt code.\n"
193
"If that is not possible, in Qt 5 you must at least reimplement\n"
194
"QCoreApplication::notify() and catch all exceptions there.\n");
197
QEventLoop *eventLoop = d->threadData->eventLoops.pop();
198
Q_ASSERT_X(eventLoop == d->q_func(), "QEventLoop::exec()", "internal error");
199
Q_UNUSED(eventLoop); // --release warning
201
--d->threadData->loopLevel;
204
LoopReference ref(d, locker);
206
// remove posted quit events when entering a new event loop
207
QCoreApplication *app = QCoreApplication::instance();
208
if (app && app->thread() == thread())
209
QCoreApplication::removePostedEvents(app, QEvent::Quit);
211
while (!d->exit.loadAcquire())
212
processEvents(flags | WaitForMoreEvents | EventLoopExec);
214
ref.exceptionCaught = false;
215
return d->returnCode.load();
219
Process pending events that match \a flags for a maximum of \a
220
maxTime milliseconds, or until there are no more events to
221
process, whichever is shorter.
222
This function is especially useful if you have a long running
223
operation and want to show its progress without allowing user
224
input, i.e. by using the \l ExcludeUserInputEvents flag.
228
\li This function does not process events continuously; it
229
returns after all available events are processed.
230
\li Specifying the \l WaitForMoreEvents flag makes no sense
234
void QEventLoop::processEvents(ProcessEventsFlags flags, int maxTime)
237
if (!d->threadData->eventDispatcher.load())
242
while (processEvents(flags & ~WaitForMoreEvents)) {
243
if (start.elapsed() > maxTime)
249
Tells the event loop to exit with a return code.
251
After this function has been called, the event loop returns from
252
the call to exec(). The exec() function returns \a returnCode.
254
By convention, a \a returnCode of 0 means success, and any non-zero
255
value indicates an error.
257
Note that unlike the C library function of the same name, this
258
function \e does return to the caller -- it is event processing that
261
\sa QCoreApplication::quit(), quit(), exec()
263
void QEventLoop::exit(int returnCode)
266
if (!d->threadData->eventDispatcher.load())
269
d->returnCode.store(returnCode);
270
d->exit.storeRelease(true);
271
d->threadData->eventDispatcher.load()->interrupt();
275
Returns \c true if the event loop is running; otherwise returns
276
false. The event loop is considered running from the time when
277
exec() is called until exit() is called.
281
bool QEventLoop::isRunning() const
283
Q_D(const QEventLoop);
284
return !d->exit.loadAcquire();
288
Wakes up the event loop.
290
\sa QAbstractEventDispatcher::wakeUp()
292
void QEventLoop::wakeUp()
295
if (!d->threadData->eventDispatcher.load())
297
d->threadData->eventDispatcher.load()->wakeUp();
304
bool QEventLoop::event(QEvent *event)
306
if (event->type() == QEvent::Quit) {
310
return QObject::event(event);
315
Tells the event loop to exit normally.
319
\sa QCoreApplication::quit(), exit()
321
void QEventLoop::quit()
325
class QEventLoopLockerPrivate
328
explicit QEventLoopLockerPrivate(QEventLoopPrivate *loop)
329
: loop(loop), type(EventLoop)
334
explicit QEventLoopLockerPrivate(QThreadPrivate *thread)
335
: thread(thread), type(Thread)
340
explicit QEventLoopLockerPrivate(QCoreApplicationPrivate *app)
341
: app(app), type(Application)
346
~QEventLoopLockerPrivate()
364
QEventLoopPrivate * loop;
365
QThreadPrivate * thread;
366
QCoreApplicationPrivate * app;
377
\class QEventLoopLocker
379
\brief The QEventLoopLocker class provides a means to quit an event loop when it is no longer needed.
382
The QEventLoopLocker operates on particular objects - either a QCoreApplication
383
instance, a QEventLoop instance or a QThread instance.
385
This makes it possible to, for example, run a batch of jobs with an event loop
386
and exit that event loop after the last job is finished. That is accomplished
387
by keeping a QEventLoopLocker with each job instance.
389
The variant which operates on QCoreApplication makes it possible to finish
390
asynchronously running jobs after the last gui window has been closed. This
391
can be useful for example for running a job which uploads data to a network.
393
\sa QEventLoop, QCoreApplication
397
Creates an event locker operating on the QCoreApplication.
399
The application will quit when there are no more QEventLoopLockers operating on it.
401
\sa QCoreApplication::quit(), QCoreApplication::isQuitLockEnabled()
403
QEventLoopLocker::QEventLoopLocker()
404
: d_ptr(new QEventLoopLockerPrivate(static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(QCoreApplication::instance()))))
410
Creates an event locker operating on the \a loop.
412
This particular QEventLoop will quit when there are no more QEventLoopLockers operating on it.
414
\sa QEventLoop::quit()
416
QEventLoopLocker::QEventLoopLocker(QEventLoop *loop)
417
: d_ptr(new QEventLoopLockerPrivate(static_cast<QEventLoopPrivate*>(QObjectPrivate::get(loop))))
423
Creates an event locker operating on the \a thread.
425
This particular QThread will quit when there are no more QEventLoopLockers operating on it.
429
QEventLoopLocker::QEventLoopLocker(QThread *thread)
430
: d_ptr(new QEventLoopLockerPrivate(static_cast<QThreadPrivate*>(QObjectPrivate::get(thread))))
436
Destroys this event loop locker object
438
QEventLoopLocker::~QEventLoopLocker()