1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtCore module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qeventloop.h"
44 #include "qabstracteventdispatcher.h"
45 #include "qcoreapplication.h"
46 #include "qcoreapplication_p.h"
47 #include "qelapsedtimer.h"
49 #include "qobject_p.h"
50 #include "qeventloop_p.h"
51 #include <private/qthread_p.h>
57 \brief The QEventLoop class provides a means of entering and leaving an event loop.
59 At any time, you can create a QEventLoop object and call exec()
60 on it to start a local event loop. From within the event loop,
61 calling exit() will force exec() to return.
63 \sa QAbstractEventDispatcher
67 \enum QEventLoop::ProcessEventsFlag
69 This enum controls the types of events processed by the
70 processEvents() functions.
72 \value AllEvents All events. Note that
73 \l{QEvent::DeferredDelete}{DeferredDelete} events are processed
74 specially. See QObject::deleteLater() for more details.
76 \value ExcludeUserInputEvents Do not process user input events,
77 such as ButtonPress and KeyPress. Note that the events are not
78 discarded; they will be delivered the next time processEvents() is
79 called without the ExcludeUserInputEvents flag.
81 \value ExcludeSocketNotifiers Do not process socket notifier
82 events. Note that the events are not discarded; they will be
83 delivered the next time processEvents() is called without the
84 ExcludeSocketNotifiers flag.
86 \value WaitForMoreEvents Wait for events if no pending events are
89 \omitvalue X11ExcludeTimers
90 \omitvalue EventLoopExec
97 Constructs an event loop object with the given \a parent.
99 QEventLoop::QEventLoop(QObject *parent)
100 : QObject(*new QEventLoopPrivate, parent)
103 if (!QCoreApplication::instance()) {
104 qWarning("QEventLoop: Cannot be used without QApplication");
105 } else if (!d->threadData->eventDispatcher) {
106 QThreadPrivate::createEventDispatcher(d->threadData);
111 Destroys the event loop object.
113 QEventLoop::~QEventLoop()
118 Processes pending events that match \a flags until there are no
119 more events to process. Returns true if pending events were handled;
120 otherwise returns false.
122 This function is especially useful if you have a long running
123 operation and want to show its progress without allowing user
124 input; i.e. by using the \l ExcludeUserInputEvents flag.
126 This function is simply a wrapper for
127 QAbstractEventDispatcher::processEvents(). See the documentation
128 for that function for details.
130 bool QEventLoop::processEvents(ProcessEventsFlags flags)
133 if (!d->threadData->eventDispatcher)
135 return d->threadData->eventDispatcher->processEvents(flags);
139 Enters the main event loop and waits until exit() is called.
140 Returns the value that was passed to exit().
142 If \a flags are specified, only events of the types allowed by
143 the \a flags will be processed.
145 It is necessary to call this function to start event handling. The
146 main event loop receives events from the window system and
147 dispatches these to the application widgets.
149 Generally speaking, no user interaction can take place before
150 calling exec(). As a special case, modal widgets like QMessageBox
151 can be used before calling exec(), because modal widgets
152 use their own local event loop.
154 To make your application perform idle processing (i.e. executing a
155 special function whenever there are no pending events), use a
156 QTimer with 0 timeout. More sophisticated idle processing schemes
157 can be achieved using processEvents().
159 \sa QApplication::quit(), exit(), processEvents()
161 int QEventLoop::exec(ProcessEventsFlags flags)
164 //we need to protect from race condition with QThread::exit
165 QMutexLocker locker(&static_cast<QThreadPrivate *>(QObjectPrivate::get(d->threadData->thread))->mutex);
166 if (d->threadData->quitNow)
170 qWarning("QEventLoop::exec: instance %p has already called exec()", this);
174 struct LoopReference {
175 QEventLoopPrivate *d;
176 QMutexLocker &locker;
178 bool exceptionCaught;
179 LoopReference(QEventLoopPrivate *d, QMutexLocker &locker) : d(d), locker(locker), exceptionCaught(true)
183 ++d->threadData->loopLevel;
184 d->threadData->eventLoops.push(d->q_func());
190 if (exceptionCaught) {
191 qWarning("Qt has caught an exception thrown from an event handler. Throwing\n"
192 "exceptions from an event handler is not supported in Qt. You must\n"
193 "reimplement QApplication::notify() and catch all exceptions there.\n");
196 QEventLoop *eventLoop = d->threadData->eventLoops.pop();
197 Q_ASSERT_X(eventLoop == d->q_func(), "QEventLoop::exec()", "internal error");
198 Q_UNUSED(eventLoop); // --release warning
200 --d->threadData->loopLevel;
203 LoopReference ref(d, locker);
205 // remove posted quit events when entering a new event loop
206 QCoreApplication *app = QCoreApplication::instance();
207 if (app && app->thread() == thread())
208 QCoreApplication::removePostedEvents(app, QEvent::Quit);
211 processEvents(flags | WaitForMoreEvents | EventLoopExec);
213 ref.exceptionCaught = false;
214 return d->returnCode;
218 Process pending events that match \a flags for a maximum of \a
219 maxTime milliseconds, or until there are no more events to
220 process, whichever is shorter.
221 This function is especially useful if you have a long running
222 operation and want to show its progress without allowing user
223 input, i.e. by using the \l ExcludeUserInputEvents flag.
227 \o This function does not process events continuously; it
228 returns after all available events are processed.
229 \o Specifying the \l WaitForMoreEvents flag makes no sense
233 void QEventLoop::processEvents(ProcessEventsFlags flags, int maxTime)
236 if (!d->threadData->eventDispatcher)
241 while (processEvents(flags & ~WaitForMoreEvents)) {
242 if (start.elapsed() > maxTime)
248 Tells the event loop to exit with a return code.
250 After this function has been called, the event loop returns from
251 the call to exec(). The exec() function returns \a returnCode.
253 By convention, a \a returnCode of 0 means success, and any non-zero
254 value indicates an error.
256 Note that unlike the C library function of the same name, this
257 function \e does return to the caller -- it is event processing that
260 \sa QCoreApplication::quit(), quit(), exec()
262 void QEventLoop::exit(int returnCode)
265 if (!d->threadData->eventDispatcher)
268 d->returnCode = returnCode;
270 d->threadData->eventDispatcher->interrupt();
274 Returns true if the event loop is running; otherwise returns
275 false. The event loop is considered running from the time when
276 exec() is called until exit() is called.
280 bool QEventLoop::isRunning() const
282 Q_D(const QEventLoop);
287 Wakes up the event loop.
289 \sa QAbstractEventDispatcher::wakeUp()
291 void QEventLoop::wakeUp()
294 if (!d->threadData->eventDispatcher)
296 d->threadData->eventDispatcher->wakeUp();
300 bool QEventLoop::event(QEvent *event)
302 if (event->type() == QEvent::Quit) {
306 return QObject::event(event);
311 Tells the event loop to exit normally.
315 \sa QCoreApplication::quit(), exit()
317 void QEventLoop::quit()
321 class QEventLoopLockerPrivate
324 explicit QEventLoopLockerPrivate(QEventLoopPrivate *loop)
325 : loop(loop), thread(0), app(0)
330 explicit QEventLoopLockerPrivate(QThreadPrivate *thread)
331 : loop(0), thread(thread), app(0)
336 explicit QEventLoopLockerPrivate(QCoreApplicationPrivate *app)
337 : loop(0), thread(0), app(app)
342 ~QEventLoopLockerPrivate()
353 QEventLoopPrivate *loop;
354 QThreadPrivate *thread;
355 QCoreApplicationPrivate *app;
359 \class QEventLoopLocker
360 \brief The QEventLoopLocker class provides a means to quit an event loop when it is no longer needed.
362 The QEventLoopLocker operates on particular objects - either a QCoreApplication
363 instance or a QEventLoop instance.
365 This makes it possible to, for example, run a batch of jobs with an event loop
366 and exit that event loop after the last job is finished. That is accomplished
367 by keeping a QEventLoopLocker with each job instance.
369 The variant which operates on QCoreApplication makes it possible to finish
370 asynchronously running jobs after the last gui window has been closed. This
371 can be useful for example for running a job which uploads data to a network.
373 \sa QEventLoop, QCoreApplication
377 Creates an event locker operating on the \p app.
379 The application will quit when there are no more QEventLoopLockers operating on it.
381 \sa QCoreApplication::quit(), QCoreApplication::isQuitLockEnabled()
383 QEventLoopLocker::QEventLoopLocker()
384 : d_ptr(new QEventLoopLockerPrivate(static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(QCoreApplication::instance()))))
390 Creates an event locker operating on the \p app.
392 This particular QEventLoop will quit when there are no more QEventLoopLockers operating on it.
394 \sa QEventLoop::quit()
396 QEventLoopLocker::QEventLoopLocker(QEventLoop *loop)
397 : d_ptr(new QEventLoopLockerPrivate(static_cast<QEventLoopPrivate*>(QObjectPrivate::get(loop))))
402 QEventLoopLocker::QEventLoopLocker(QThread *thread)
403 : d_ptr(new QEventLoopLockerPrivate(static_cast<QThreadPrivate*>(QObjectPrivate::get(thread))))
409 Destroys this event loop locker object
411 QEventLoopLocker::~QEventLoopLocker()