summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimothy Pearson <[email protected]>2012-12-07 20:06:25 -0600
committerTimothy Pearson <[email protected]>2012-12-07 20:06:25 -0600
commita7865cf6918fc3457d0141522e791a92bcf62810 (patch)
tree6cd840a44b85c401b4640be655ac536cb3d1ffa9
parent9bff9eeefc262c8509b2db7c1120f6001d65e64c (diff)
downloadqt3-a7865cf6918fc3457d0141522e791a92bcf62810.tar.gz
qt3-a7865cf6918fc3457d0141522e791a92bcf62810.zip
Fix glib event loop threading
-rw-r--r--src/kernel/qeventloop_glib_p.h58
-rw-r--r--src/kernel/qeventloop_x11_glib.cpp81
2 files changed, 70 insertions, 69 deletions
diff --git a/src/kernel/qeventloop_glib_p.h b/src/kernel/qeventloop_glib_p.h
index 7de324d..ef0e6ac 100644
--- a/src/kernel/qeventloop_glib_p.h
+++ b/src/kernel/qeventloop_glib_p.h
@@ -84,49 +84,49 @@ struct QSockNotGPollFD
class QEventLoopPrivate
{
public:
- QEventLoopPrivate()
- {
- reset();
- }
-
- void reset() {
- looplevel = 0;
- quitcode = 0;
- quitnow = FALSE;
- exitloop = FALSE;
- shortcut = FALSE;
- singletoolkit = TRUE;
- }
-
- int looplevel;
- int quitcode;
- unsigned int quitnow : 1;
- unsigned int exitloop : 1;
- unsigned int shortcut : 1;
+ QEventLoopPrivate()
+ {
+ reset();
+ }
+
+ void reset() {
+ looplevel = 0;
+ quitcode = 0;
+ quitnow = FALSE;
+ exitloop = FALSE;
+ shortcut = FALSE;
+ singletoolkit = TRUE;
+ }
+
+ int looplevel;
+ int quitcode;
+ unsigned int quitnow : 1;
+ unsigned int exitloop : 1;
+ unsigned int shortcut : 1;
#if defined(Q_WS_X11)
- int xfd;
+ int xfd;
GPollFD x_gPollFD;
#endif // Q_WS_X11
- int thread_pipe[2];
-
+ int thread_pipe[2];
GPollFD threadPipe_gPollFD;
-
- QPtrList<QSockNotGPollFD> sn_list;
- // pending socket notifiers list
- QPtrList<QSockNotGPollFD> sn_pending_list;
-
+ QPtrList<QSockNotGPollFD> sn_list;
+
+ // pending socket notifiers list
+ QPtrList<QSockNotGPollFD> sn_pending_list;
+
// store flags for one iteration
uint pev_flags;
-
+
// My GSource
-
GSource * gSource;
bool singletoolkit;
+ // main context
+ GMainContext *ctx;
};
#endif // QEVENTLOOP_GLIB_P_H
diff --git a/src/kernel/qeventloop_x11_glib.cpp b/src/kernel/qeventloop_x11_glib.cpp
index 0d2275e..771428b 100644
--- a/src/kernel/qeventloop_x11_glib.cpp
+++ b/src/kernel/qeventloop_x11_glib.cpp
@@ -48,6 +48,7 @@
#if defined(QT_THREAD_SUPPORT)
# include "qmutex.h"
+# include "qthread.h"
#endif // QT_THREAD_SUPPORT
#include <errno.h>
@@ -79,7 +80,7 @@ static GSourceFuncs qt_gsource_funcs = {
// forward main loop callbacks to QEventLoop methods!
static gboolean qt_gsource_prepare ( GSource *source,
- gint *timeout )
+ gint *timeout )
{
QtGSource * qtGSource;
qtGSource = (QtGSource*) source;
@@ -97,9 +98,18 @@ static gboolean qt_gsource_dispatch ( GSource *source,
{
Q_UNUSED(callback);
Q_UNUSED(user_data);
-
+
QtGSource * qtGSource = (QtGSource*) source;
- return qtGSource->qeventLoop->gsourceDispatch(source);
+ QEventLoop* candidateEventLoop = qtGSource->qeventLoop;
+ QEventLoop* activeThreadEventLoop = QApplication::eventLoop();
+
+ if (candidateEventLoop == activeThreadEventLoop) {
+ return candidateEventLoop->gsourceDispatch(source);
+ }
+ else {
+ // Dispatch failed
+ return FALSE;
+ }
}
@@ -171,7 +181,7 @@ void QEventLoop::init()
{
// initialize ProcessEventFlags (all events & wait for more)
d->pev_flags = AllEvents | WaitForMore;
-
+
// initialize the common parts of the event loop
if (pipe( d->thread_pipe ) < 0) {
// Error!
@@ -185,35 +195,33 @@ void QEventLoop::init()
d->xfd = XConnectionNumber( QPaintDevice::x11AppDisplay() );
}
+ // new main context for thread
+ d->ctx = g_main_context_new();
+ g_main_context_push_thread_default(d->ctx);
+
// new GSource
QtGSource * qtGSource = (QtGSource*) g_source_new(&qt_gsource_funcs, sizeof(QtGSource));
-
g_source_set_can_recurse ((GSource*)qtGSource, TRUE);
-
qtGSource->qeventLoop = this;
- // init main loop and attach gsource
+ // init main loop and attach gsource
#ifdef DEBUG_QT_GLIBMAINLOOP
printf("inside init(1)\n");
#endif
- g_main_loop_new (NULL, 1);
-
- g_source_attach( (GSource*)qtGSource, NULL );
-
+ g_main_loop_new (d->ctx, 1);
+ g_source_attach( (GSource*)qtGSource, d->ctx );
d->gSource = (GSource*) qtGSource;
-
+
// poll for X11 events
-
if ( qt_is_gui_used && QApplication::isGuiThread() ) {
d->x_gPollFD.fd = d->xfd;
d->x_gPollFD.events = G_IO_IN | G_IO_HUP;
- g_source_add_poll(d->gSource, &d->x_gPollFD);
+ g_source_add_poll(d->gSource, &d->x_gPollFD);
}
// poll thread-pipe
-
d->threadPipe_gPollFD.fd = d->thread_pipe[0];
d->threadPipe_gPollFD.events = G_IO_IN | G_IO_HUP;
@@ -231,10 +239,13 @@ void QEventLoop::cleanup()
close( d->thread_pipe[0] );
close( d->thread_pipe[1] );
cleanupTimers();
-
+
// cleanup the X11 parts of the event loop
d->xfd = -1;
-
+
+ // unref the main context
+ g_main_context_unref(d->ctx);
+
// todo: destroy gsource
}
@@ -251,7 +262,7 @@ bool QEventLoop::processEvents( ProcessEventsFlags flags )
d->pev_flags = flags;
- rval = g_main_context_iteration(NULL, flags & WaitForMore ? TRUE : FALSE);
+ rval = g_main_context_iteration(d->ctx, flags & WaitForMore ? TRUE : FALSE);
d->pev_flags = save_flags;
@@ -411,40 +422,30 @@ bool QEventLoop::gsourcePrepare(GSource *gs, int * timeout)
for ( it = qt_preselect_handler->begin(); it != end; ++it )
(**it)();
}
-
- // unlock the GUI mutex and select. when we return from this function, there is
- // something for us to do
-#if defined(QT_THREAD_SUPPORT)
- locker.mutex()->unlock();
-#endif
-
+
#ifdef DEBUG_QT_GLIBMAINLOOP
printf("inside gsourcePrepare(2.1) canwait=%d\n", canWait);
#endif
// do we have to dispatch events?
- if (hasPendingEvents()) {
+ if (hasPendingEvents()) {
*timeout = 0; // no time to stay in poll
-
- #ifdef DEBUG_QT_GLIBMAINLOOP
- printf("inside gsourcePrepare(3a)\n");
- #endif
-
+#ifdef DEBUG_QT_GLIBMAINLOOP
+ printf("inside gsourcePrepare(3a)\n");
+#endif
return FALSE;
}
// stay in poll until something happens?
if (!tm) { // fixme
*timeout = -1; // wait forever
- #ifdef DEBUG_QT_GLIBMAINLOOP
- printf("inside gsourcePrepare(3b) timeout=%d \n", *timeout);
- #endif
-
-
+#ifdef DEBUG_QT_GLIBMAINLOOP
+ printf("inside gsourcePrepare(3b) timeout=%d \n", *timeout);
+#endif
return FALSE;
}
- // else timeout >=0
+ // else timeout >=0
*timeout = tm->tv_sec * 1000 + tm->tv_usec/1000;
#ifdef DEBUG_QT_GLIBMAINLOOP
@@ -529,7 +530,7 @@ bool QEventLoop::gsourceDispatch(GSource *gs) {
QMutexLocker locker( QApplication::qt_mutex );
#endif
#if defined(QT_THREAD_SUPPORT)
- locker.mutex()->lock();
+ if (locker.mutex()) locker.mutex()->lock();
#endif
int nevents=0;
@@ -598,13 +599,13 @@ bool QEventLoop::gsourceDispatch(GSource *gs) {
qt_reset_color_avail();
#if defined(QT_THREAD_SUPPORT)
- locker.mutex()->unlock();
+ if (locker.mutex()) locker.mutex()->unlock();
#endif
processX11Events();
}
else {
#if defined(QT_THREAD_SUPPORT)
- locker.mutex()->unlock();
+ if (locker.mutex()) locker.mutex()->unlock();
#endif
}