Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
DISCONTINUED:openSUSE:11.2
libqt4-sql-plugins
glib-eventloop-regression.diff
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File glib-eventloop-regression.diff of Package libqt4-sql-plugins
commit d0d0fdb8e46351b4ab8492de31e5363ef6662b57 Author: Bradley T. Hughes <bradley.hughes@nokia.com> Date: Wed Sep 23 13:51:17 2009 +0200 Fix regressions in qeventloop, qtimer, and qsocketnotifier autotests Commit ed375675d4a4f6fd63edeb242e23c87b3de4be6f triggers a behavior in Glib's mainloop implementation where some event sources are not "serviced" every iteration of the mainloop context. This breaks an invariant that many tests relied on, so we need to solve the problem. The invariant is that a newly added timer that would normally fire on the next pass of the event loop (liker a zero timer) SHOULD actually fire. We do this by registering 2 timer event sources with Glib's mainloop: one normal priority source and one idle priority source. The idle priority source is the one that will send events most of the time, with the normal priority one taking over only when processEvents() is called manually. Task-number: QT-877 Reviewed-by: jbache Reviewed-by: thiago Reviewed-by: denis diff --git a/src/corelib/kernel/qeventdispatcher_glib.cpp b/src/corelib/kernel/qeventdispatcher_glib.cpp index 6e457f4..665b73e 100644 --- a/src/corelib/kernel/qeventdispatcher_glib.cpp +++ b/src/corelib/kernel/qeventdispatcher_glib.cpp @@ -127,16 +127,11 @@ struct GTimerSource GSource source; QTimerInfoList timerList; QEventLoop::ProcessEventsFlags processEventsFlags; + bool runWithIdlePriority; }; -static gboolean timerSourcePrepare(GSource *source, gint *timeout) +static gboolean timerSourcePrepareHelper(GTimerSource *src, gint *timeout) { - gint dummy; - if (!timeout) - timeout = &dummy; - - GTimerSource *src = reinterpret_cast<GTimerSource *>(source); - timeval tv = { 0l, 0l }; if (!(src->processEventsFlags & QEventLoop::X11ExcludeTimers) && src->timerList.timerWait(tv)) *timeout = (tv.tv_sec * 1000) + (tv.tv_usec / 1000); @@ -146,10 +141,8 @@ static gboolean timerSourcePrepare(GSource *source, gint *timeout) return (*timeout == 0); } -static gboolean timerSourceCheck(GSource *source) +static gboolean timerSourceCheckHelper(GTimerSource *src) { - GTimerSource *src = reinterpret_cast<GTimerSource *>(source); - if (src->timerList.isEmpty() || (src->processEventsFlags & QEventLoop::X11ExcludeTimers)) return false; @@ -160,9 +153,35 @@ static gboolean timerSourceCheck(GSource *source) return true; } +static gboolean timerSourcePrepare(GSource *source, gint *timeout) +{ + gint dummy; + if (!timeout) + timeout = &dummy; + + GTimerSource *src = reinterpret_cast<GTimerSource *>(source); + if (src->runWithIdlePriority) { + if (timeout) + *timeout = -1; + return false; + } + + return timerSourcePrepareHelper(src, timeout); +} + +static gboolean timerSourceCheck(GSource *source) +{ + GTimerSource *src = reinterpret_cast<GTimerSource *>(source); + if (src->runWithIdlePriority) + return false; + return timerSourceCheckHelper(src); +} + static gboolean timerSourceDispatch(GSource *source, GSourceFunc, gpointer) { - (void) reinterpret_cast<GTimerSource *>(source)->timerList.activateTimers(); + GTimerSource *timerSource = reinterpret_cast<GTimerSource *>(source); + timerSource->runWithIdlePriority = true; + (void) timerSource->timerList.activateTimers(); return true; // ??? don't remove, right again? } @@ -175,6 +194,53 @@ static GSourceFuncs timerSourceFuncs = { NULL }; +struct GIdleTimerSource +{ + GSource source; + GTimerSource *timerSource; +}; + +static gboolean idleTimerSourcePrepare(GSource *source, gint *timeout) +{ + GIdleTimerSource *idleTimerSource = reinterpret_cast<GIdleTimerSource *>(source); + GTimerSource *timerSource = idleTimerSource->timerSource; + if (!timerSource->runWithIdlePriority) { + // Yield to the normal priority timer source + if (timeout) + *timeout = -1; + return false; + } + + return timerSourcePrepareHelper(timerSource, timeout); +} + +static gboolean idleTimerSourceCheck(GSource *source) +{ + GIdleTimerSource *idleTimerSource = reinterpret_cast<GIdleTimerSource *>(source); + GTimerSource *timerSource = idleTimerSource->timerSource; + if (!timerSource->runWithIdlePriority) { + // Yield to the normal priority timer source + return false; + } + return timerSourceCheckHelper(timerSource); +} + +static gboolean idleTimerSourceDispatch(GSource *source, GSourceFunc, gpointer) +{ + GTimerSource *timerSource = reinterpret_cast<GIdleTimerSource *>(source)->timerSource; + (void) timerSourceDispatch(&timerSource->source, 0, 0); + return true; +} + +static GSourceFuncs idleTimerSourceFuncs = { + idleTimerSourcePrepare, + idleTimerSourceCheck, + idleTimerSourceDispatch, + NULL, + NULL, + NULL +}; + struct GPostEventSource { GSource source; @@ -235,14 +301,15 @@ QEventDispatcherGlibPrivate::QEventDispatcherGlibPrivate(GMainContext *context) g_main_context_ref(mainContext); } else { QCoreApplication *app = QCoreApplication::instance(); - if (app && QThread::currentThread() == app->thread()) { - mainContext = g_main_context_default(); - g_main_context_ref(mainContext); - } else { - mainContext = g_main_context_new(); - } + if (app && QThread::currentThread() == app->thread()) { + mainContext = g_main_context_default(); + g_main_context_ref(mainContext); + } else { + mainContext = g_main_context_new(); + } } + // setup post event source postEventSource = reinterpret_cast<GPostEventSource *>(g_source_new(&postEventSourceFuncs, sizeof(GPostEventSource))); postEventSource->serialNumber = 1; @@ -257,14 +324,21 @@ QEventDispatcherGlibPrivate::QEventDispatcherGlibPrivate(GMainContext *context) g_source_set_can_recurse(&socketNotifierSource->source, true); g_source_attach(&socketNotifierSource->source, mainContext); - // setup timerSource + // setup normal and idle timer sources timerSource = reinterpret_cast<GTimerSource *>(g_source_new(&timerSourceFuncs, sizeof(GTimerSource))); (void) new (&timerSource->timerList) QTimerInfoList(); timerSource->processEventsFlags = QEventLoop::AllEvents; + timerSource->runWithIdlePriority = false; g_source_set_can_recurse(&timerSource->source, true); - g_source_set_priority(&timerSource->source, G_PRIORITY_DEFAULT_IDLE); g_source_attach(&timerSource->source, mainContext); + + idleTimerSource = reinterpret_cast<GIdleTimerSource *>(g_source_new(&idleTimerSourceFuncs, + sizeof(GIdleTimerSource))); + idleTimerSource->timerSource = timerSource; + g_source_set_can_recurse(&idleTimerSource->source, true); + g_source_set_priority(&idleTimerSource->source, G_PRIORITY_DEFAULT_IDLE); + g_source_attach(&idleTimerSource->source, mainContext); } QEventDispatcherGlib::QEventDispatcherGlib(QObject *parent) @@ -272,12 +346,9 @@ QEventDispatcherGlib::QEventDispatcherGlib(QObject *parent) { } -QEventDispatcherGlib::QEventDispatcherGlib(GMainContext *mainContext, - QObject *parent) - : QAbstractEventDispatcher(*(new QEventDispatcherGlibPrivate(mainContext)), - parent) -{ -} +QEventDispatcherGlib::QEventDispatcherGlib(GMainContext *mainContext, QObject *parent) + : QAbstractEventDispatcher(*(new QEventDispatcherGlibPrivate(mainContext)), parent) +{ } QEventDispatcherGlib::~QEventDispatcherGlib() { @@ -289,6 +360,9 @@ QEventDispatcherGlib::~QEventDispatcherGlib() g_source_destroy(&d->timerSource->source); g_source_unref(&d->timerSource->source); d->timerSource = 0; + g_source_destroy(&d->idleTimerSource->source); + g_source_unref(&d->idleTimerSource->source); + d->idleTimerSource = 0; // destroy socket notifier source for (int i = 0; i < d->socketNotifierSource->pollfds.count(); ++i) { @@ -324,11 +398,16 @@ bool QEventDispatcherGlib::processEvents(QEventLoop::ProcessEventsFlags flags) // tell postEventSourcePrepare() and timerSource about any new flags QEventLoop::ProcessEventsFlags savedFlags = d->timerSource->processEventsFlags; d->timerSource->processEventsFlags = flags; - + + if (!(flags & QEventLoop::EventLoopExec)) { + // force timers to be sent at normal priority + d->timerSource->runWithIdlePriority = false; + } + bool result = g_main_context_iteration(d->mainContext, canWait); while (!result && canWait) result = g_main_context_iteration(d->mainContext, canWait); - + d->timerSource->processEventsFlags = savedFlags; if (canWait) diff --git a/src/corelib/kernel/qeventdispatcher_glib_p.h b/src/corelib/kernel/qeventdispatcher_glib_p.h index 8dbc44d..6a4e726 100644 --- a/src/corelib/kernel/qeventdispatcher_glib_p.h +++ b/src/corelib/kernel/qeventdispatcher_glib_p.h @@ -98,6 +98,7 @@ protected: struct GPostEventSource; struct GSocketNotifierSource; struct GTimerSource; +struct GIdleTimerSource; class Q_CORE_EXPORT QEventDispatcherGlibPrivate : public QAbstractEventDispatcherPrivate { @@ -108,6 +109,7 @@ public: GPostEventSource *postEventSource; GSocketNotifierSource *socketNotifierSource; GTimerSource *timerSource; + GIdleTimerSource *idleTimerSource; }; QT_END_NAMESPACE diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp index a912971..5a0afb8 100644 --- a/src/corelib/kernel/qeventdispatcher_unix.cpp +++ b/src/corelib/kernel/qeventdispatcher_unix.cpp @@ -446,10 +446,10 @@ bool QTimerInfoList::timerWait(timeval &tm) // Find first waiting timer not already active QTimerInfo *t = 0; for (QTimerInfoList::const_iterator it = constBegin(); it != constEnd(); ++it) { - if (!(*it)->inTimerEvent) { - t = *it; - break; - } + if (!(*it)->inTimerEvent) { + t = *it; + break; + } } if (!t)
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor