kernel/qeventloop.cpp

Source codeSwitch to Preprocessed file
LineSource CodeCoverage
1/**************************************************************************** -
2** -
3** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -
4** Contact: http://www.qt-project.org/legal -
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 Digia. For licensing terms and -
14** conditions see http://qt.digia.com/licensing. For further information -
15** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software -
20** Foundation and appearing in the file LICENSE.LGPL included in the -
21** packaging of this file. Please review the following information to -
22** ensure the GNU Lesser General Public License version 2.1 requirements -
23** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -
24** -
25** In addition, as a special exception, Digia gives you certain additional -
26** rights. These rights are described in the Digia Qt LGPL Exception -
27** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -
28** -
29** GNU General Public License Usage -
30** Alternatively, this file may be used under the terms of the GNU -
31** General Public License version 3.0 as published by the Free Software -
32** Foundation and appearing in the file LICENSE.GPL included in the -
33** packaging of this file. Please review the following information to -
34** ensure the GNU General Public License version 3.0 requirements will be -
35** met: http://www.gnu.org/copyleft/gpl.html. -
36** -
37** -
38** $QT_END_LICENSE$ -
39** -
40****************************************************************************/ -
41 -
42#include "qeventloop.h" -
43 -
44#include "qabstracteventdispatcher.h" -
45#include "qcoreapplication.h" -
46#include "qcoreapplication_p.h" -
47#include "qelapsedtimer.h" -
48 -
49#include "qobject_p.h" -
50#include "qeventloop_p.h" -
51#include <private/qthread_p.h> -
52 -
53QT_BEGIN_NAMESPACE -
54 -
55/*! -
56 \class QEventLoop -
57 \inmodule QtCore -
58 \brief The QEventLoop class provides a means of entering and leaving an event loop. -
59 -
60 At any time, you can create a QEventLoop object and call exec() -
61 on it to start a local event loop. From within the event loop, -
62 calling exit() will force exec() to return. -
63 -
64 \sa QAbstractEventDispatcher -
65*/ -
66 -
67/*! -
68 \enum QEventLoop::ProcessEventsFlag -
69 -
70 This enum controls the types of events processed by the -
71 processEvents() functions. -
72 -
73 \value AllEvents All events. Note that -
74 \l{QEvent::DeferredDelete}{DeferredDelete} events are processed -
75 specially. See QObject::deleteLater() for more details. -
76 -
77 \value ExcludeUserInputEvents Do not process user input events, -
78 such as ButtonPress and KeyPress. Note that the events are not -
79 discarded; they will be delivered the next time processEvents() is -
80 called without the ExcludeUserInputEvents flag. -
81 -
82 \value ExcludeSocketNotifiers Do not process socket notifier -
83 events. Note that the events are not discarded; they will be -
84 delivered the next time processEvents() is called without the -
85 ExcludeSocketNotifiers flag. -
86 -
87 \value WaitForMoreEvents Wait for events if no pending events are -
88 available. -
89 -
90 \omitvalue X11ExcludeTimers -
91 \omitvalue EventLoopExec -
92 \omitvalue DialogExec -
93 -
94 \sa processEvents() -
95*/ -
96 -
97/*! -
98 Constructs an event loop object with the given \a parent. -
99*/ -
100QEventLoop::QEventLoop(QObject *parent) -
101 : QObject(*new QEventLoopPrivate, parent) -
102{ -
103 Q_D(QEventLoop);
executed (the execution status of this line is deduced): QEventLoopPrivate * const d = d_func();
-
104 if (!QCoreApplication::instance()) {
partially evaluated: !QCoreApplication::instance()
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:2677
0-2677
105 qWarning("QEventLoop: Cannot be used without QApplication");
never executed (the execution status of this line is deduced): QMessageLogger("kernel/qeventloop.cpp", 105, __PRETTY_FUNCTION__).warning("QEventLoop: Cannot be used without QApplication");
-
106 } else if (!d->threadData->eventDispatcher) {
never executed: }
evaluated: !d->threadData->eventDispatcher
TRUEFALSE
yes
Evaluation Count:2
yes
Evaluation Count:2678
0-2678
107 QThreadPrivate::createEventDispatcher(d->threadData);
executed (the execution status of this line is deduced): QThreadPrivate::createEventDispatcher(d->threadData);
-
108 }
executed: }
Execution Count:2
2
109} -
110 -
111/*! -
112 Destroys the event loop object. -
113*/ -
114QEventLoop::~QEventLoop() -
115{ } -
116 -
117 -
118/*! -
119 Processes pending events that match \a flags until there are no -
120 more events to process. Returns true if pending events were handled; -
121 otherwise returns false. -
122 -
123 This function is especially useful if you have a long running -
124 operation and want to show its progress without allowing user -
125 input; i.e. by using the \l ExcludeUserInputEvents flag. -
126 -
127 This function is simply a wrapper for -
128 QAbstractEventDispatcher::processEvents(). See the documentation -
129 for that function for details. -
130*/ -
131bool QEventLoop::processEvents(ProcessEventsFlags flags) -
132{ -
133 Q_D(QEventLoop);
executed (the execution status of this line is deduced): QEventLoopPrivate * const d = d_func();
-
134 if (!d->threadData->eventDispatcher)
partially evaluated: !d->threadData->eventDispatcher
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:60448
0-60448
135 return false;
never executed: return false;
0
136 return d->threadData->eventDispatcher->processEvents(flags);
executed: return d->threadData->eventDispatcher->processEvents(flags);
Execution Count:60446
60446
137} -
138 -
139/*! -
140 Enters the main event loop and waits until exit() is called. -
141 Returns the value that was passed to exit(). -
142 -
143 If \a flags are specified, only events of the types allowed by -
144 the \a flags will be processed. -
145 -
146 It is necessary to call this function to start event handling. The -
147 main event loop receives events from the window system and -
148 dispatches these to the application widgets. -
149 -
150 Generally speaking, no user interaction can take place before -
151 calling exec(). As a special case, modal widgets like QMessageBox -
152 can be used before calling exec(), because modal widgets -
153 use their own local event loop. -
154 -
155 To make your application perform idle processing (i.e. executing a -
156 special function whenever there are no pending events), use a -
157 QTimer with 0 timeout. More sophisticated idle processing schemes -
158 can be achieved using processEvents(). -
159 -
160 \sa QCoreApplication::quit(), exit(), processEvents() -
161*/ -
162int QEventLoop::exec(ProcessEventsFlags flags) -
163{ -
164 Q_D(QEventLoop);
executed (the execution status of this line is deduced): QEventLoopPrivate * const d = d_func();
-
165 //we need to protect from race condition with QThread::exit -
166 QMutexLocker locker(&static_cast<QThreadPrivate *>(QObjectPrivate::get(d->threadData->thread))->mutex);
executed (the execution status of this line is deduced): QMutexLocker locker(&static_cast<QThreadPrivate *>(QObjectPrivate::get(d->threadData->thread))->mutex);
-
167 if (d->threadData->quitNow)
evaluated: d->threadData->quitNow
TRUEFALSE
yes
Evaluation Count:8
yes
Evaluation Count:2699
8-2699
168 return -1;
executed: return -1;
Execution Count:8
8
169 -
170 if (d->inExec) {
evaluated: d->inExec
TRUEFALSE
yes
Evaluation Count:1
yes
Evaluation Count:2698
1-2698
171 qWarning("QEventLoop::exec: instance %p has already called exec()", this);
executed (the execution status of this line is deduced): QMessageLogger("kernel/qeventloop.cpp", 171, __PRETTY_FUNCTION__).warning("QEventLoop::exec: instance %p has already called exec()", this);
-
172 return -1;
executed: return -1;
Execution Count:1
1
173 } -
174 -
175 struct LoopReference {
executed (the execution status of this line is deduced): struct LoopReference {
-
176 QEventLoopPrivate *d;
executed (the execution status of this line is deduced): QEventLoopPrivate *d;
-
177 QMutexLocker &locker;
executed (the execution status of this line is deduced): QMutexLocker &locker;
-
178
executed (the execution status of this line is deduced):
-
179 bool exceptionCaught;
executed (the execution status of this line is deduced): bool exceptionCaught;
-
180 LoopReference(QEventLoopPrivate *d, QMutexLocker &locker) : d(d), locker(locker), exceptionCaught(true)
executed (the execution status of this line is deduced): LoopReference(QEventLoopPrivate *d, QMutexLocker &locker) : d(d), locker(locker), exceptionCaught(true)
-
181 {
executed (the execution status of this line is deduced): {
-
182 d->inExec = true;
executed (the execution status of this line is deduced): d->inExec = true;
-
183 d->exit = false;
executed (the execution status of this line is deduced): d->exit = false;
-
184 ++d->threadData->loopLevel;
executed (the execution status of this line is deduced): ++d->threadData->loopLevel;
-
185 d->threadData->eventLoops.push(d->q_func());
executed (the execution status of this line is deduced): d->threadData->eventLoops.push(d->q_func());
-
186 locker.unlock();
executed (the execution status of this line is deduced): locker.unlock();
-
187 }
executed: }
Execution Count:2698
2698
188
executed (the execution status of this line is deduced):
-
189 ~LoopReference()
executed (the execution status of this line is deduced): ~LoopReference()
-
190 {
executed (the execution status of this line is deduced): {
-
191 if (exceptionCaught) {
partially evaluated: exceptionCaught
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:2699
0-2699
192 qWarning("Qt has caught an exception thrown from an event handler. Throwing\n"
executed (the execution status of this line is deduced): QMessageLogger("kernel/qeventloop.cpp", 192, __PRETTY_FUNCTION__).warning("Qt has caught an exception thrown from an event handler. Throwing\n"
-
193 "exceptions from an event handler is not supported in Qt. You must\n"
executed (the execution status of this line is deduced): "exceptions from an event handler is not supported in Qt. You must\n"
-
194 "reimplement QApplication::notify() and catch all exceptions there.\n");
executed (the execution status of this line is deduced): "reimplement QApplication::notify() and catch all exceptions there.\n");
-
195 }
never executed: }
0
196 locker.relock();
executed (the execution status of this line is deduced): locker.relock();
-
197 QEventLoop *eventLoop = d->threadData->eventLoops.pop();
executed (the execution status of this line is deduced): QEventLoop *eventLoop = d->threadData->eventLoops.pop();
-
198 Q_ASSERT_X(eventLoop == d->q_func(), "QEventLoop::exec()", "internal error");
executed (the execution status of this line is deduced): qt_noop();
-
199 Q_UNUSED(eventLoop); // --release warning
executed (the execution status of this line is deduced): (void)eventLoop;;
-
200 d->inExec = false;
executed (the execution status of this line is deduced): d->inExec = false;
-
201 --d->threadData->loopLevel;
executed (the execution status of this line is deduced): --d->threadData->loopLevel;
-
202 }
executed: }
Execution Count:2699
2699
203 };
executed (the execution status of this line is deduced): };
-
204 LoopReference ref(d, locker);
executed (the execution status of this line is deduced): LoopReference ref(d, locker);
-
205 -
206 // remove posted quit events when entering a new event loop -
207 QCoreApplication *app = QCoreApplication::instance();
executed (the execution status of this line is deduced): QCoreApplication *app = QCoreApplication::instance();
-
208 if (app && app->thread() == thread())
partially evaluated: app
TRUEFALSE
yes
Evaluation Count:2698
no
Evaluation Count:0
evaluated: app->thread() == thread()
TRUEFALSE
yes
Evaluation Count:1990
yes
Evaluation Count:708
0-2698
209 QCoreApplication::removePostedEvents(app, QEvent::Quit);
executed: QCoreApplication::removePostedEvents(app, QEvent::Quit);
Execution Count:1990
1990
210 -
211 while (!d->exit)
evaluated: !d->exit
TRUEFALSE
yes
Evaluation Count:60439
yes
Evaluation Count:2699
2699-60439
212 processEvents(flags | WaitForMoreEvents | EventLoopExec);
executed: processEvents(flags | WaitForMoreEvents | EventLoopExec);
Execution Count:60438
60438
213 -
214 ref.exceptionCaught = false;
executed (the execution status of this line is deduced): ref.exceptionCaught = false;
-
215 return d->returnCode;
executed: return d->returnCode;
Execution Count:2699
2699
216} -
217 -
218/*! -
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. -
225 -
226 \b{Notes:} -
227 \list -
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 -
231 and will be ignored. -
232 \endlist -
233*/ -
234void QEventLoop::processEvents(ProcessEventsFlags flags, int maxTime) -
235{ -
236 Q_D(QEventLoop);
never executed (the execution status of this line is deduced): QEventLoopPrivate * const d = d_func();
-
237 if (!d->threadData->eventDispatcher)
never evaluated: !d->threadData->eventDispatcher
0
238 return;
never executed: return;
0
239 -
240 QElapsedTimer start;
never executed (the execution status of this line is deduced): QElapsedTimer start;
-
241 start.start();
never executed (the execution status of this line is deduced): start.start();
-
242 while (processEvents(flags & ~WaitForMoreEvents)) {
never evaluated: processEvents(flags & ~WaitForMoreEvents)
0
243 if (start.elapsed() > maxTime)
never evaluated: start.elapsed() > maxTime
0
244 break;
never executed: break;
0
245 }
never executed: }
0
246}
never executed: }
0
247 -
248/*! -
249 Tells the event loop to exit with a return code. -
250 -
251 After this function has been called, the event loop returns from -
252 the call to exec(). The exec() function returns \a returnCode. -
253 -
254 By convention, a \a returnCode of 0 means success, and any non-zero -
255 value indicates an error. -
256 -
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 -
259 stops. -
260 -
261 \sa QCoreApplication::quit(), quit(), exec() -
262*/ -
263void QEventLoop::exit(int returnCode) -
264{ -
265 Q_D(QEventLoop);
executed (the execution status of this line is deduced): QEventLoopPrivate * const d = d_func();
-
266 if (!d->threadData->eventDispatcher)
partially evaluated: !d->threadData->eventDispatcher
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:2709
0-2709
267 return;
never executed: return;
0
268 -
269 d->returnCode = returnCode;
executed (the execution status of this line is deduced): d->returnCode = returnCode;
-
270 d->exit = true;
executed (the execution status of this line is deduced): d->exit = true;
-
271 d->threadData->eventDispatcher->interrupt();
executed (the execution status of this line is deduced): d->threadData->eventDispatcher->interrupt();
-
272}
executed: }
Execution Count:2709
2709
273 -
274/*! -
275 Returns 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. -
278 -
279 \sa exec(), exit() -
280 */ -
281bool QEventLoop::isRunning() const -
282{ -
283 Q_D(const QEventLoop);
executed (the execution status of this line is deduced): const QEventLoopPrivate * const d = d_func();
-
284 return !d->exit;
executed: return !d->exit;
Execution Count:8
8
285} -
286 -
287/*! -
288 Wakes up the event loop. -
289 -
290 \sa QAbstractEventDispatcher::wakeUp() -
291*/ -
292void QEventLoop::wakeUp() -
293{ -
294 Q_D(QEventLoop);
executed (the execution status of this line is deduced): QEventLoopPrivate * const d = d_func();
-
295 if (!d->threadData->eventDispatcher)
partially evaluated: !d->threadData->eventDispatcher
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:1
0-1
296 return;
never executed: return;
0
297 d->threadData->eventDispatcher->wakeUp();
executed (the execution status of this line is deduced): d->threadData->eventDispatcher->wakeUp();
-
298}
executed: }
Execution Count:1
1
299 -
300 -
301/*! -
302 \reimp -
303*/ -
304bool QEventLoop::event(QEvent *event) -
305{ -
306 if (event->type() == QEvent::Quit) {
evaluated: event->type() == QEvent::Quit
TRUEFALSE
yes
Evaluation Count:2
yes
Evaluation Count:163
2-163
307 quit();
executed (the execution status of this line is deduced): quit();
-
308 return true;
executed: return true;
Execution Count:2
2
309 } else { -
310 return QObject::event(event);
executed: return QObject::event(event);
Execution Count:163
163
311 } -
312} -
313 -
314/*! -
315 Tells the event loop to exit normally. -
316 -
317 Same as exit(0). -
318 -
319 \sa QCoreApplication::quit(), exit() -
320*/ -
321void QEventLoop::quit() -
322{ exit(0); }
executed: exit(0);
Execution Count:380
380
323 -
324 -
325class QEventLoopLockerPrivate -
326{ -
327public: -
328 explicit QEventLoopLockerPrivate(QEventLoopPrivate *loop) -
329 : loop(loop), type(EventLoop) -
330 { -
331 loop->ref();
executed (the execution status of this line is deduced): loop->ref();
-
332 }
executed: }
Execution Count:11
11
333 -
334 explicit QEventLoopLockerPrivate(QThreadPrivate *thread) -
335 : thread(thread), type(Thread) -
336 { -
337 thread->ref();
executed (the execution status of this line is deduced): thread->ref();
-
338 }
executed: }
Execution Count:2
2
339 -
340 explicit QEventLoopLockerPrivate(QCoreApplicationPrivate *app) -
341 : app(app), type(Application) -
342 { -
343 app->ref();
executed (the execution status of this line is deduced): app->ref();
-
344 }
executed: }
Execution Count:6
6
345 -
346 ~QEventLoopLockerPrivate() -
347 { -
348 switch (type) -
349 { -
350 case EventLoop: -
351 loop->deref();
executed (the execution status of this line is deduced): loop->deref();
-
352 break;
executed: break;
Execution Count:11
11
353 case Thread: -
354 thread->deref();
executed (the execution status of this line is deduced): thread->deref();
-
355 break;
executed: break;
Execution Count:1
1
356 default: -
357 app->deref();
executed (the execution status of this line is deduced): app->deref();
-
358 break;
executed: break;
Execution Count:6
6
359 } -
360 }
executed: }
Execution Count:18
18
361 -
362private: -
363 union { -
364 QEventLoopPrivate * loop; -
365 QThreadPrivate * thread; -
366 QCoreApplicationPrivate * app; -
367 }; -
368 enum Type { -
369 EventLoop, -
370 Thread, -
371 Application -
372 }; -
373 const Type type; -
374}; -
375 -
376/*! -
377 \class QEventLoopLocker -
378 \inmodule QtCore -
379 \brief The QEventLoopLocker class provides a means to quit an event loop when it is no longer needed. -
380 \since 5.0 -
381 -
382 The QEventLoopLocker operates on particular objects - either a QCoreApplication -
383 instance, a QEventLoop instance or a QThread instance. -
384 -
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. -
388 -
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. -
392 -
393 \sa QEventLoop, QCoreApplication -
394*/ -
395 -
396/*! -
397 Creates an event locker operating on the QCoreApplication. -
398 -
399 The application will quit when there are no more QEventLoopLockers operating on it. -
400 -
401 \sa QCoreApplication::quit(), QCoreApplication::isQuitLockEnabled() -
402 */ -
403QEventLoopLocker::QEventLoopLocker() -
404 : d_ptr(new QEventLoopLockerPrivate(static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(QCoreApplication::instance())))) -
405{ -
406 -
407}
executed: }
Execution Count:6
6
408 -
409/*! -
410 Creates an event locker operating on the \a loop. -
411 -
412 This particular QEventLoop will quit when there are no more QEventLoopLockers operating on it. -
413 -
414 \sa QEventLoop::quit() -
415 */ -
416QEventLoopLocker::QEventLoopLocker(QEventLoop *loop) -
417 : d_ptr(new QEventLoopLockerPrivate(static_cast<QEventLoopPrivate*>(QObjectPrivate::get(loop)))) -
418{ -
419 -
420}
executed: }
Execution Count:11
11
421 -
422/*! -
423 Creates an event locker operating on the \a thread. -
424 -
425 This particular QThread will quit when there are no more QEventLoopLockers operating on it. -
426 -
427 \sa QThread::quit() -
428 */ -
429QEventLoopLocker::QEventLoopLocker(QThread *thread) -
430 : d_ptr(new QEventLoopLockerPrivate(static_cast<QThreadPrivate*>(QObjectPrivate::get(thread)))) -
431{ -
432 -
433}
executed: }
Execution Count:2
2
434 -
435/*! -
436 Destroys this event loop locker object -
437 */ -
438QEventLoopLocker::~QEventLoopLocker() -
439{ -
440 delete d_ptr;
executed (the execution status of this line is deduced): delete d_ptr;
-
441}
executed: }
Execution Count:18
18
442 -
443QT_END_NAMESPACE -
444 -
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial