Update spec to build Qt 5.0
[profile/ivi/qtbase.git] / src / corelib / kernel / qeventloop.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 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
53 QT_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 */
100 QEventLoop::QEventLoop(QObject *parent)
101     : QObject(*new QEventLoopPrivate, parent)
102 {
103     Q_D(QEventLoop);
104     if (!QCoreApplication::instance()) {
105         qWarning("QEventLoop: Cannot be used without QApplication");
106     } else if (!d->threadData->eventDispatcher) {
107         QThreadPrivate::createEventDispatcher(d->threadData);
108     }
109 }
110
111 /*!
112     Destroys the event loop object.
113 */
114 QEventLoop::~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 */
131 bool QEventLoop::processEvents(ProcessEventsFlags flags)
132 {
133     Q_D(QEventLoop);
134     if (!d->threadData->eventDispatcher)
135         return false;
136     return d->threadData->eventDispatcher->processEvents(flags);
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 */
162 int QEventLoop::exec(ProcessEventsFlags flags)
163 {
164     Q_D(QEventLoop);
165     //we need to protect from race condition with QThread::exit
166     QMutexLocker locker(&static_cast<QThreadPrivate *>(QObjectPrivate::get(d->threadData->thread))->mutex);
167     if (d->threadData->quitNow)
168         return -1;
169
170     if (d->inExec) {
171         qWarning("QEventLoop::exec: instance %p has already called exec()", this);
172         return -1;
173     }
174
175     struct LoopReference {
176         QEventLoopPrivate *d;
177         QMutexLocker &locker;
178
179         bool exceptionCaught;
180         LoopReference(QEventLoopPrivate *d, QMutexLocker &locker) : d(d), locker(locker), exceptionCaught(true)
181         {
182             d->inExec = true;
183             d->exit = false;
184             ++d->threadData->loopLevel;
185             d->threadData->eventLoops.push(d->q_func());
186             locker.unlock();
187         }
188
189         ~LoopReference()
190         {
191             if (exceptionCaught) {
192                 qWarning("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"
194                          "reimplement QApplication::notify() and catch all exceptions there.\n");
195             }
196             locker.relock();
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
200             d->inExec = false;
201             --d->threadData->loopLevel;
202         }
203     };
204     LoopReference ref(d, locker);
205
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);
210
211     while (!d->exit)
212         processEvents(flags | WaitForMoreEvents | EventLoopExec);
213
214     ref.exceptionCaught = false;
215     return d->returnCode;
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 */
234 void QEventLoop::processEvents(ProcessEventsFlags flags, int maxTime)
235 {
236     Q_D(QEventLoop);
237     if (!d->threadData->eventDispatcher)
238         return;
239
240     QElapsedTimer start;
241     start.start();
242     while (processEvents(flags & ~WaitForMoreEvents)) {
243         if (start.elapsed() > maxTime)
244             break;
245     }
246 }
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 */
263 void QEventLoop::exit(int returnCode)
264 {
265     Q_D(QEventLoop);
266     if (!d->threadData->eventDispatcher)
267         return;
268
269     d->returnCode = returnCode;
270     d->exit = true;
271     d->threadData->eventDispatcher->interrupt();
272 }
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  */
281 bool QEventLoop::isRunning() const
282 {
283     Q_D(const QEventLoop);
284     return !d->exit;
285 }
286
287 /*!
288     Wakes up the event loop.
289
290     \sa QAbstractEventDispatcher::wakeUp()
291 */
292 void QEventLoop::wakeUp()
293 {
294     Q_D(QEventLoop);
295     if (!d->threadData->eventDispatcher)
296         return;
297     d->threadData->eventDispatcher->wakeUp();
298 }
299
300
301 /*!
302     \reimp
303 */
304 bool QEventLoop::event(QEvent *event)
305 {
306     if (event->type() == QEvent::Quit) {
307         quit();
308         return true;
309     } else {
310         return QObject::event(event);
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 */
321 void QEventLoop::quit()
322 { exit(0); }
323
324
325 class QEventLoopLockerPrivate
326 {
327 public:
328     explicit QEventLoopLockerPrivate(QEventLoopPrivate *loop)
329       : loop(loop), type(EventLoop)
330     {
331         loop->ref();
332     }
333
334     explicit QEventLoopLockerPrivate(QThreadPrivate *thread)
335       : thread(thread), type(Thread)
336     {
337         thread->ref();
338     }
339
340     explicit QEventLoopLockerPrivate(QCoreApplicationPrivate *app)
341       : app(app), type(Application)
342     {
343         app->ref();
344     }
345
346     ~QEventLoopLockerPrivate()
347     {
348         switch (type)
349         {
350         case EventLoop:
351             loop->deref();
352             break;
353         case Thread:
354             thread->deref();
355             break;
356         default:
357             app->deref();
358             break;
359         }
360     }
361
362 private:
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  */
403 QEventLoopLocker::QEventLoopLocker()
404   : d_ptr(new QEventLoopLockerPrivate(static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(QCoreApplication::instance()))))
405 {
406
407 }
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  */
416 QEventLoopLocker::QEventLoopLocker(QEventLoop *loop)
417   : d_ptr(new QEventLoopLockerPrivate(static_cast<QEventLoopPrivate*>(QObjectPrivate::get(loop))))
418 {
419
420 }
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  */
429 QEventLoopLocker::QEventLoopLocker(QThread *thread)
430   : d_ptr(new QEventLoopLockerPrivate(static_cast<QThreadPrivate*>(QObjectPrivate::get(thread))))
431 {
432
433 }
434
435 /*!
436     Destroys this event loop locker object
437  */
438 QEventLoopLocker::~QEventLoopLocker()
439 {
440     delete d_ptr;
441 }
442
443 QT_END_NAMESPACE