summaryrefslogtreecommitdiffstats
path: root/src/kernel/qapplication.cpp
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2012-12-06 16:47:27 -0600
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2012-12-06 16:47:27 -0600
commit78125ea2f051107b84fdc0354acdedb7885308ee (patch)
treec162d7f55467f81a01e2e669ce297acce06b3947 /src/kernel/qapplication.cpp
parent7aa5ac7f0e76c5b87e4ca837b75b3edd522a3372 (diff)
downloadqt3-78125ea2f051107b84fdc0354acdedb7885308ee.tar.gz
qt3-78125ea2f051107b84fdc0354acdedb7885308ee.zip
Add real threading support, including per-thread event loops, to QThread
Diffstat (limited to 'src/kernel/qapplication.cpp')
-rw-r--r--src/kernel/qapplication.cpp124
1 files changed, 110 insertions, 14 deletions
diff --git a/src/kernel/qapplication.cpp b/src/kernel/qapplication.cpp
index 51aa247..a9c9fb8 100644
--- a/src/kernel/qapplication.cpp
+++ b/src/kernel/qapplication.cpp
@@ -68,6 +68,7 @@
#if defined(QT_THREAD_SUPPORT)
# include "qmutex.h"
# include "qthread.h"
+# include <private/qthreadinstance_p.h>
#endif // QT_THREAD_SUPPORT
#include <stdlib.h>
@@ -383,7 +384,25 @@ Q_EXPORT Qt::HANDLE qt_get_application_thread_id()
}
#endif // QT_THREAD_SUPPORT
+#ifndef QT_THREAD_SUPPORT
QEventLoop *QApplication::eventloop = 0; // application event loop
+#endif
+
+#ifdef QT_THREAD_SUPPORT
+QEventLoop* QApplication::currentEventLoop() {
+ QThread* thread = QThread::currentThreadObject();
+ if (thread) {
+ if (thread->d) {
+ return thread->d->eventLoop;
+ }
+ }
+ return NULL;
+}
+#else
+QEventLoop* QApplication::currentEventLoop() {
+ return QApplication::eventloop;
+}
+#endif
#ifndef QT_NO_ACCEL
extern bool qt_dispatchAccelEvent( QWidget*, QKeyEvent* ); // def in qaccel.cpp
@@ -516,6 +535,41 @@ QClipboard *qt_clipboard = 0; // global clipboard object
#endif
QWidgetList * qt_modal_stack=0; // stack of modal widgets
+#ifdef QT_THREAD_SUPPORT
+// thread wrapper for the main() thread
+class QCoreApplicationThread : public QThread
+{
+public:
+ inline QCoreApplicationThread()
+ {
+ QThreadInstance::setCurrentThread(this);
+
+ // thread should be running and not finished for the lifetime
+ // of the application (even if QCoreApplication goes away)
+ d->running = true;
+ d->finished = false;
+ d->eventLoop = NULL;
+ }
+ inline ~QCoreApplicationThread()
+ {
+ // avoid warning from QThread
+ d->running = false;
+ }
+private:
+ inline void run()
+ {
+ // this function should never be called, it is implemented
+ // only so that we can instantiate the object
+ qFatal("QCoreApplicationThread: internal error");
+ }
+};
+
+static QCoreApplicationThread qt_main_thread;
+static QThread *mainThread() { return &qt_main_thread; }
+#else
+static QThread* mainThread() { return QThread::currentThread(); }
+#endif
+
// Definitions for posted events
struct QPostEvent {
QPostEvent( QObject *r, QEvent *e ): receiver( r ), event( e ) {}
@@ -818,8 +872,8 @@ void QApplication::construct( int &argc, char **argv, Type type )
initialize( argc, argv );
if ( qt_is_gui_used )
qt_maxWindowRect = desktop()->rect();
- if ( eventloop )
- eventloop->appStartingUp();
+ if ( currentEventLoop() )
+ currentEventLoop()->appStartingUp();
}
/*!
@@ -874,8 +928,8 @@ QApplication::QApplication( Display* dpy, HANDLE visual, HANDLE colormap )
if ( qt_is_gui_used )
qt_maxWindowRect = desktop()->rect();
- if ( eventloop )
- eventloop->appStartingUp();
+ if ( currentEventLoop() )
+ currentEventLoop()->appStartingUp();
}
/*!
@@ -916,13 +970,26 @@ QApplication::QApplication(Display *dpy, int argc, char **argv,
if ( qt_is_gui_used )
qt_maxWindowRect = desktop()->rect();
- if ( eventloop )
- eventloop->appStartingUp();
+ if ( currentEventLoop() )
+ currentEventLoop()->appStartingUp();
}
#endif // Q_WS_X11
+#ifdef QT_THREAD_SUPPORT
+QThread* QApplication::guiThread() {
+ return mainThread();
+}
+
+bool QApplication::isGuiThread() {
+ return (QThread::currentThreadObject() == guiThread());
+}
+#else
+bool QApplication::isGuiThread() {
+ return true;
+}
+#endif
void QApplication::init_precmdline()
{
@@ -1030,8 +1097,8 @@ QApplication::~QApplication()
}
#endif
- if ( eventloop )
- eventloop->appClosingDown();
+ if ( currentEventLoop() )
+ currentEventLoop()->appClosingDown();
if ( postRList ) {
QVFuncList::Iterator it = postRList->begin();
while ( it != postRList->end() ) { // call post routines
@@ -2698,8 +2765,20 @@ bool QApplication::internalNotify( QObject *receiver, QEvent * e)
}
- if (!handled)
+ if (!handled) {
+#if defined(QT_THREAD_SUPPORT)
+ bool locked = QApplication::qt_mutex->locked();
+ if (locked) {
+ QApplication::qt_mutex->unlock();
+ }
+#endif
consumed = receiver->event( e );
+#if defined(QT_THREAD_SUPPORT)
+ if (locked) {
+ QApplication::qt_mutex->lock();
+ }
+#endif
+ }
e->spont = FALSE;
return consumed;
}
@@ -2793,9 +2872,10 @@ void QApplication::processOneEvent()
*/
QEventLoop *QApplication::eventLoop()
{
- if ( !eventloop && !is_app_closing )
+ if ( !currentEventLoop() && !is_app_closing ) {
(void) new QEventLoop( qApp, "default event loop" );
- return eventloop;
+ }
+ return currentEventLoop();
}
@@ -3263,8 +3343,23 @@ void QApplication::postEvent( QObject *receiver, QEvent *event )
l->append( pe );
globalPostedEvents->append( pe );
- if (eventloop)
- eventloop->wakeUp();
+#ifdef QT_THREAD_SUPPORT
+ if ( event->type() == QEvent::MetaCall ) {
+ // Wake up the receiver thread event loop
+ QThread* thread = receiver->contextThreadObject();
+ if (thread) {
+ if (thread->d) {
+ if (thread->d->eventLoop) {
+ thread->d->eventLoop->wakeUp();
+ }
+ }
+ }
+ return;
+ }
+#endif
+
+ if (currentEventLoop())
+ currentEventLoop()->wakeUp();
}
@@ -3326,7 +3421,8 @@ void QApplication::sendPostedEvents( QObject *receiver, int event_type )
&& ( receiver == 0 // we send to all receivers
|| receiver == pe->receiver ) // we send to THAT receiver
&& ( event_type == 0 // we send all types
- || event_type == pe->event->type() ) ) { // we send THAT type
+ || event_type == pe->event->type() ) // we send THAT type
+ && ( (!pe->receiver) || (pe->receiver->contextThreadObject() == QThread::currentThreadObject()) ) ) { // only send if active thread is receiver object owning thread
// first, we diddle the event so that we can deliver
// it, and that noone will try to touch it later.
pe->event->posted = FALSE;