summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qcoreapplication.cpp
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@nokia.com>2011-06-23 14:11:50 +0200
committerQt by Nokia <qt-info@nokia.com>2011-07-11 12:43:52 +0200
commitf9035587b98ac5dc9491e642b8ec84470ec03f0e (patch)
treef91962125963ee91ff6d13fa029606966b00a272 /src/corelib/kernel/qcoreapplication.cpp
parent915ec02cadcd6e3ca423968a094a97ad417783a1 (diff)
Replace try/catch blocks in favour of destructors in the event loop.
This has two direct benefits: 1) compiles regardless of -fno-exceptions: no need for #ifndef QT_NO_EXCEPTIONS or QT_TRY/QT_CATCH 2) no QT_RETHROW either, which means the backtrace of an application crashing due to an uncaught exception will include the actual throw point. Change-Id: I18e5500e121bfa81431ef16699df96d962794f0e Reviewed-on: http://codereview.qt.nokia.com/663 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Olivier Goffart <olivier.goffart@nokia.com>
Diffstat (limited to 'src/corelib/kernel/qcoreapplication.cpp')
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp101
1 files changed, 56 insertions, 45 deletions
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index 5f11b10ec5..2458f9649e 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -816,7 +816,16 @@ bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event)
// call overhead.
QObjectPrivate *d = receiver->d_func();
QThreadData *threadData = d->threadData;
- ++threadData->loopLevel;
+
+ // Exception-safety without try/catch
+ struct Incrementer {
+ int &variable;
+ inline Incrementer(int &variable) : variable(variable)
+ { ++variable; }
+ inline ~Incrementer()
+ { --variable; }
+ };
+ Incrementer inc(threadData->loopLevel);
#ifdef QT_JAMBI_BUILD
int deleteWatch = 0;
@@ -827,12 +836,7 @@ bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event)
#endif
bool returnValue;
- QT_TRY {
- returnValue = notify(receiver, event);
- } QT_CATCH (...) {
- --threadData->loopLevel;
- QT_RETHROW;
- }
+ returnValue = notify(receiver, event);
#ifdef QT_JAMBI_BUILD
// Restore the previous state if the object was not deleted..
@@ -841,7 +845,6 @@ bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event)
}
QObjectPrivate::resetDeleteWatch(d, oldDeleteWatch, deleteWatch);
#endif
- --threadData->loopLevel;
return returnValue;
}
@@ -1384,6 +1387,40 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type
int &i = (!event_type && !receiver) ? data->postEventList.startOffset : startOffset;
data->postEventList.insertionOffset = data->postEventList.size();
+ // Exception-safe cleaning up without the need for a try/catch block
+ struct CleanUp {
+ QObject *receiver;
+ int event_type;
+ QThreadData *data;
+ bool exceptionCaught;
+
+ inline CleanUp(QObject *receiver, int event_type, QThreadData *data) :
+ receiver(receiver), event_type(event_type), data(data), exceptionCaught(true)
+ {}
+ inline ~CleanUp()
+ {
+ if (exceptionCaught) {
+ // since we were interrupted, we need another pass to make sure we clean everything up
+ data->canWait = false;
+ }
+
+ --data->postEventList.recursion;
+ if (!data->postEventList.recursion && !data->canWait && data->eventDispatcher)
+ data->eventDispatcher->wakeUp();
+
+ // clear the global list, i.e. remove everything that was
+ // delivered.
+ if (!event_type && !receiver && data->postEventList.startOffset >= 0) {
+ const QPostEventList::iterator it = data->postEventList.begin();
+ data->postEventList.erase(it, it + data->postEventList.startOffset);
+ data->postEventList.insertionOffset -= data->postEventList.startOffset;
+ Q_ASSERT(data->postEventList.insertionOffset >= 0);
+ data->postEventList.startOffset = 0;
+ }
+ }
+ };
+ CleanUp cleanup(receiver, event_type, data);
+
while (i < data->postEventList.size()) {
// avoid live-lock
if (i >= data->postEventList.insertionOffset)
@@ -1422,7 +1459,7 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type
// first, we diddle the event so that we can deliver
// it, and that no one will try to touch it later.
pe.event->posted = false;
- QEvent * e = pe.event;
+ QScopedPointer<QEvent> e(pe.event);
QObject * r = pe.receiver;
--r->d_func()->postedEvents;
@@ -1432,49 +1469,23 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type
// for the next event.
const_cast<QPostEvent &>(pe).event = 0;
- locker.unlock();
- // after all that work, it's time to deliver the event.
-#ifdef QT_NO_EXCEPTIONS
- QCoreApplication::sendEvent(r, e);
-#else
- try {
- QCoreApplication::sendEvent(r, e);
- } catch (...) {
- delete e;
- locker.relock();
-
- // since we were interrupted, we need another pass to make sure we clean everything up
- data->canWait = false;
-
- // uglehack: copied from below
- --data->postEventList.recursion;
- if (!data->postEventList.recursion && !data->canWait && data->eventDispatcher)
- data->eventDispatcher->wakeUp();
- throw; // rethrow
- }
-#endif
+ struct MutexUnlocker
+ {
+ QMutexLocker &m;
+ MutexUnlocker(QMutexLocker &m) : m(m) { m.unlock(); }
+ ~MutexUnlocker() { m.relock(); }
+ };
+ MutexUnlocker unlocker(locker);
- delete e;
- locker.relock();
+ // after all that work, it's time to deliver the event.
+ QCoreApplication::sendEvent(r, e.data());
// careful when adding anything below this point - the
// sendEvent() call might invalidate any invariants this
// function depends on.
}
- --data->postEventList.recursion;
- if (!data->postEventList.recursion && !data->canWait && data->eventDispatcher)
- data->eventDispatcher->wakeUp();
-
- // clear the global list, i.e. remove everything that was
- // delivered.
- if (!event_type && !receiver && data->postEventList.startOffset >= 0) {
- const QPostEventList::iterator it = data->postEventList.begin();
- data->postEventList.erase(it, it + data->postEventList.startOffset);
- data->postEventList.insertionOffset -= data->postEventList.startOffset;
- Q_ASSERT(data->postEventList.insertionOffset >= 0);
- data->postEventList.startOffset = 0;
- }
+ cleanup.exceptionCaught = false;
}
/*!