Fix glib event loop threading

pull/2/head
Timothy Pearson 13 years ago
parent 9bff9eeefc
commit a7865cf691

@ -84,49 +84,49 @@ struct QSockNotGPollFD
class QEventLoopPrivate class QEventLoopPrivate
{ {
public: public:
QEventLoopPrivate() QEventLoopPrivate()
{ {
reset(); reset();
} }
void reset() { void reset() {
looplevel = 0; looplevel = 0;
quitcode = 0; quitcode = 0;
quitnow = FALSE; quitnow = FALSE;
exitloop = FALSE; exitloop = FALSE;
shortcut = FALSE; shortcut = FALSE;
singletoolkit = TRUE; singletoolkit = TRUE;
} }
int looplevel; int looplevel;
int quitcode; int quitcode;
unsigned int quitnow : 1; unsigned int quitnow : 1;
unsigned int exitloop : 1; unsigned int exitloop : 1;
unsigned int shortcut : 1; unsigned int shortcut : 1;
#if defined(Q_WS_X11) #if defined(Q_WS_X11)
int xfd; int xfd;
GPollFD x_gPollFD; GPollFD x_gPollFD;
#endif // Q_WS_X11 #endif // Q_WS_X11
int thread_pipe[2]; int thread_pipe[2];
GPollFD threadPipe_gPollFD; GPollFD threadPipe_gPollFD;
QPtrList<QSockNotGPollFD> sn_list;
QPtrList<QSockNotGPollFD> sn_list;
// pending socket notifiers list // pending socket notifiers list
QPtrList<QSockNotGPollFD> sn_pending_list; QPtrList<QSockNotGPollFD> sn_pending_list;
// store flags for one iteration // store flags for one iteration
uint pev_flags; uint pev_flags;
// My GSource // My GSource
GSource * gSource; GSource * gSource;
bool singletoolkit; bool singletoolkit;
// main context
GMainContext *ctx;
}; };
#endif // QEVENTLOOP_GLIB_P_H #endif // QEVENTLOOP_GLIB_P_H

@ -48,6 +48,7 @@
#if defined(QT_THREAD_SUPPORT) #if defined(QT_THREAD_SUPPORT)
# include "qmutex.h" # include "qmutex.h"
# include "qthread.h"
#endif // QT_THREAD_SUPPORT #endif // QT_THREAD_SUPPORT
#include <errno.h> #include <errno.h>
@ -79,7 +80,7 @@ static GSourceFuncs qt_gsource_funcs = {
// forward main loop callbacks to QEventLoop methods! // forward main loop callbacks to QEventLoop methods!
static gboolean qt_gsource_prepare ( GSource *source, static gboolean qt_gsource_prepare ( GSource *source,
gint *timeout ) gint *timeout )
{ {
QtGSource * qtGSource; QtGSource * qtGSource;
qtGSource = (QtGSource*) source; qtGSource = (QtGSource*) source;
@ -97,9 +98,18 @@ static gboolean qt_gsource_dispatch ( GSource *source,
{ {
Q_UNUSED(callback); Q_UNUSED(callback);
Q_UNUSED(user_data); Q_UNUSED(user_data);
QtGSource * qtGSource = (QtGSource*) source; 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) // initialize ProcessEventFlags (all events & wait for more)
d->pev_flags = AllEvents | WaitForMore; d->pev_flags = AllEvents | WaitForMore;
// initialize the common parts of the event loop // initialize the common parts of the event loop
if (pipe( d->thread_pipe ) < 0) { if (pipe( d->thread_pipe ) < 0) {
// Error! // Error!
@ -185,35 +195,33 @@ void QEventLoop::init()
d->xfd = XConnectionNumber( QPaintDevice::x11AppDisplay() ); 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 // new GSource
QtGSource * qtGSource = (QtGSource*) g_source_new(&qt_gsource_funcs, sizeof(QtGSource)); QtGSource * qtGSource = (QtGSource*) g_source_new(&qt_gsource_funcs, sizeof(QtGSource));
g_source_set_can_recurse ((GSource*)qtGSource, TRUE); g_source_set_can_recurse ((GSource*)qtGSource, TRUE);
qtGSource->qeventLoop = this; qtGSource->qeventLoop = this;
// init main loop and attach gsource // init main loop and attach gsource
#ifdef DEBUG_QT_GLIBMAINLOOP #ifdef DEBUG_QT_GLIBMAINLOOP
printf("inside init(1)\n"); printf("inside init(1)\n");
#endif #endif
g_main_loop_new (NULL, 1); g_main_loop_new (d->ctx, 1);
g_source_attach( (GSource*)qtGSource, d->ctx );
g_source_attach( (GSource*)qtGSource, NULL );
d->gSource = (GSource*) qtGSource; d->gSource = (GSource*) qtGSource;
// poll for X11 events // poll for X11 events
if ( qt_is_gui_used && QApplication::isGuiThread() ) { if ( qt_is_gui_used && QApplication::isGuiThread() ) {
d->x_gPollFD.fd = d->xfd; d->x_gPollFD.fd = d->xfd;
d->x_gPollFD.events = G_IO_IN | G_IO_HUP; 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 // poll thread-pipe
d->threadPipe_gPollFD.fd = d->thread_pipe[0]; d->threadPipe_gPollFD.fd = d->thread_pipe[0];
d->threadPipe_gPollFD.events = G_IO_IN | G_IO_HUP; 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[0] );
close( d->thread_pipe[1] ); close( d->thread_pipe[1] );
cleanupTimers(); cleanupTimers();
// cleanup the X11 parts of the event loop // cleanup the X11 parts of the event loop
d->xfd = -1; d->xfd = -1;
// unref the main context
g_main_context_unref(d->ctx);
// todo: destroy gsource // todo: destroy gsource
} }
@ -251,7 +262,7 @@ bool QEventLoop::processEvents( ProcessEventsFlags flags )
d->pev_flags = 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; 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 ) for ( it = qt_preselect_handler->begin(); it != end; ++it )
(**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 #ifdef DEBUG_QT_GLIBMAINLOOP
printf("inside gsourcePrepare(2.1) canwait=%d\n", canWait); printf("inside gsourcePrepare(2.1) canwait=%d\n", canWait);
#endif #endif
// do we have to dispatch events? // do we have to dispatch events?
if (hasPendingEvents()) { if (hasPendingEvents()) {
*timeout = 0; // no time to stay in poll *timeout = 0; // no time to stay in poll
#ifdef DEBUG_QT_GLIBMAINLOOP
#ifdef DEBUG_QT_GLIBMAINLOOP printf("inside gsourcePrepare(3a)\n");
printf("inside gsourcePrepare(3a)\n"); #endif
#endif
return FALSE; return FALSE;
} }
// stay in poll until something happens? // stay in poll until something happens?
if (!tm) { // fixme if (!tm) { // fixme
*timeout = -1; // wait forever *timeout = -1; // wait forever
#ifdef DEBUG_QT_GLIBMAINLOOP #ifdef DEBUG_QT_GLIBMAINLOOP
printf("inside gsourcePrepare(3b) timeout=%d \n", *timeout); printf("inside gsourcePrepare(3b) timeout=%d \n", *timeout);
#endif #endif
return FALSE; return FALSE;
} }
// else timeout >=0 // else timeout >=0
*timeout = tm->tv_sec * 1000 + tm->tv_usec/1000; *timeout = tm->tv_sec * 1000 + tm->tv_usec/1000;
#ifdef DEBUG_QT_GLIBMAINLOOP #ifdef DEBUG_QT_GLIBMAINLOOP
@ -529,7 +530,7 @@ bool QEventLoop::gsourceDispatch(GSource *gs) {
QMutexLocker locker( QApplication::qt_mutex ); QMutexLocker locker( QApplication::qt_mutex );
#endif #endif
#if defined(QT_THREAD_SUPPORT) #if defined(QT_THREAD_SUPPORT)
locker.mutex()->lock(); if (locker.mutex()) locker.mutex()->lock();
#endif #endif
int nevents=0; int nevents=0;
@ -598,13 +599,13 @@ bool QEventLoop::gsourceDispatch(GSource *gs) {
qt_reset_color_avail(); qt_reset_color_avail();
#if defined(QT_THREAD_SUPPORT) #if defined(QT_THREAD_SUPPORT)
locker.mutex()->unlock(); if (locker.mutex()) locker.mutex()->unlock();
#endif #endif
processX11Events(); processX11Events();
} }
else { else {
#if defined(QT_THREAD_SUPPORT) #if defined(QT_THREAD_SUPPORT)
locker.mutex()->unlock(); if (locker.mutex()) locker.mutex()->unlock();
#endif #endif
} }

Loading…
Cancel
Save