--- a/src/QuailEventLoop.cpp Wed Sep 18 14:04:25 2013 +0100
+++ b/src/QuailEventLoop.cpp Thu Sep 19 16:09:24 2013 +0100
@@ -20,8 +20,10 @@
#include "QuailEventLoop.h"
@@ -39,21 +41,38 @@
static guint nextSourceId = 0;
static QMap<guint, QQuailSourceInfo*> m_sources;
+//static QThread *quailThread = new QThread(); QQuailTimer::QQuailTimer(guint sourceId, GSourceFunc func, gpointer data)
- : QTimer(), sourceId(sourceId), func(func), userData(data)
+ : sourceId(sourceId), func(func), userData(data), t(0) - connect(this, SIGNAL(timeout()),
+ qDebug() << "QQuailTimer::QQuailTimer.1"; + qDebug() << "QQuailTimer::update()"; qQuailSourceRemove(sourceId);
+QQuailTimer::start(int msec) + qDebug() << "QQuailTimer::start.1"; + t = mainWin->getNewTimer(); + connect(t, SIGNAL(timeout()), QQuailInputNotifier::QQuailInputNotifier(int fd,
PurpleInputCondition cond,
PurpleInputFunction func,
@@ -115,6 +134,7 @@
info->handle = nextSourceId++;
info->timer = new QQuailTimer(info->handle, func, data);
+ //info->timer->moveToThread(quailThread); info->timer->start(interval);
m_sources.insert(info->handle, info);
@@ -205,3 +225,4 @@
--- a/src/QuailWinGlibEventLoop.cpp Wed Sep 18 14:04:25 2013 +0100
+++ b/src/QuailWinGlibEventLoop.cpp Thu Sep 19 16:09:24 2013 +0100
@@ -2,6 +2,18 @@
#include <QCoreApplication>
+#include "qsystemlibrary.h" +#include <QWinEventNotifier> +#include <QElapsedTimer> +#include "quailtimerinfolist.h" struct GPollFDWithQSocketNotifier
@@ -200,19 +212,21 @@
static gboolean postEventSourcePrepare(GSource *s, gint *timeout)
- QThreadData *data = QThreadData::current();
+// QThreadData *data = QThreadData::current();
- const bool canWait = data->canWaitLocked();
- *timeout = canWait ? -1 : 0;
+// const bool canWait = data->canWaitLocked(); +// *timeout = canWait ? -1 : 0; GPostEventSource *source = reinterpret_cast<GPostEventSource *>(s);
- || (source->serialNumber.load() != source->lastSerialNumber));
+// || (source->serialNumber.load() != source->lastSerialNumber)); + return source->serialNumber.load() != source->lastSerialNumber; static gboolean postEventSourceCheck(GSource *source)
@@ -479,7 +493,9 @@
static bool triedResolve = false;
- QMutexLocker locker(QMutexPool::globalInstanceGet(&triedResolve));
+ //QMutexLocker locker(QMutexPool::globalInstanceGet(&triedResolve)); + triedResolve = locker.tryLock(); @@ -500,17 +516,21 @@
-QuailEventDispatcherWinGlib::QuailEventDispatcherWinGlib(GMainContext *context = 0, QObject parent = 0)
- : mainContext(context), threadId(GetCurrentThreadId()), interruptFlag(false), internalHwnd(0), getMessageHook(0),
- serialNumber(0), lastSerialNumber(0), sendPostedEventsWindowsTimerId(0), wakeUps(0)
+QuailEventDispatcherWinGlib::QuailEventDispatcherWinGlib(QObject *parent) + : QAbstractEventDispatcher(parent), mainContext(0), + threadId(GetCurrentThreadId()), interruptFlag(false), + internalHwnd(0), getMessageHook(0), + serialNumber(0), lastSerialNumber(0), + sendPostedEventsWindowsTimerId(0), wakeUps(0) + qDebug() << "QuailEventDispatcherWinGlib"; #if GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION < 32
if (qEnvironmentVariableIsEmpty("QT_NO_THREADED_GLIB")) {
static QBasicMutex mutex;
QMutexLocker locker(&mutex);
- if (!g_thread_supported())
+// if (!g_thread_supported()) @@ -580,7 +600,7 @@
void QuailEventDispatcherWinGlib::activateEventNotifier(QWinEventNotifier * wen)
QEvent event(QEvent::WinEventAct);
- QCoreApplication::sendEvent(wen, &event);
+ QCoreApplication::sendEvent((QObject*)wen, &event); // This function is called by a workerthread
@@ -620,7 +640,8 @@
QuailEventDispatcherWinGlib *d = 0;
if (message == WM_QT_SOCKETNOTIFIER) {
// socket notifier message
@@ -685,7 +706,8 @@
- QuailEventDispatcherWinGlib *d = q->d_func();
+ //QuailEventDispatcherWinGlib *d = q->d_func(); + QuailEventDispatcherWinGlib *d = q; const int localSerialNumber = d->serialNumber.load();
if (HIWORD(GetQueueStatus(QS_TIMER | QS_INPUT | QS_RAWINPUT)) == 0) {
// no more input or timer events in the message queue, we can allow posted events to be sent normally now
@@ -768,9 +790,11 @@
void QuailEventDispatcherWinGlib::registerTimer(WinTimerInfo *t)
+ qDebug() << "QuailEventDispatcherWinGlib::registerTimer"; - Q_Q(QuailEventDispatcherWinGlib);
+ //Q_Q(QuailEventDispatcherWinGlib); + QuailEventDispatcherWinGlib *q = this; uint interval = t->interval;
@@ -790,7 +814,7 @@
ok = SetTimer(internalHwnd, t->timerId, interval, 0);
- t->timeout = qt_msectime() + interval;
+ t->timeout = QDateTime::currentMSecsSinceEpoch() + interval; qErrnoWarning("QuailEventDispatcherWinGlib::registerTimer: Failed to create a timer");
@@ -799,10 +823,12 @@
void QuailEventDispatcherWinGlib::unregisterTimer(WinTimerInfo *t)
- QCoreApplicationPrivate::removePostedTimerEvent(t->dispatcher, t->timerId);
+ //QCoreApplicationPrivate::removePostedTimerEvent(t->dispatcher, t->timerId); + QCoreApplication::removePostedEvents(t->dispatcher, t->timerId); } else if (t->fastTimerId != 0) {
qtimeKillEvent(t->fastTimerId);
- QCoreApplicationPrivate::removePostedTimerEvent(t->dispatcher, t->timerId);
+ //QCoreApplicationPrivate::removePostedTimerEvent(t->dispatcher, t->timerId); + QCoreApplication::removePostedEvents(t->dispatcher, t->timerId); } else if (internalHwnd) {
KillTimer(internalHwnd, t->timerId);
@@ -839,12 +865,13 @@
// BoundsChecker may emit a warning for WSAAsyncSelect when sn_event == 0
// This is a BoundsChecker bug and not a Qt bug
- WSAAsyncSelect(socket, internalHwnd, sn_event ? int(WM_QT_SOCKETNOTIFIER) : 0, sn_event);
+ //WSAAsyncSelect(socket, internalHwnd, sn_event ? int(WM_QT_SOCKETNOTIFIER) : 0, sn_event); void QuailEventDispatcherWinGlib::createInternalHwnd()
- Q_D(QuailEventDispatcherWinGlib);
+ //QuailEventDispatcherWinGlib *d = this; + QuailEventDispatcherWinGlib *d = this; Q_ASSERT(!d->internalHwnd);
@@ -876,7 +903,9 @@
bool QuailEventDispatcherWinGlib::processEvents(QEventLoop::ProcessEventsFlags flags)
- Q_D(QuailEventDispatcherWinGlib);
+ qDebug() << "QuailEventDispatcherWinGlib::processEvents"; + //QuailEventDispatcherWinGlib *d = this; + QuailEventDispatcherWinGlib *d = this; @@ -1025,6 +1054,7 @@
void QuailEventDispatcherWinGlib::registerSocketNotifier(QSocketNotifier *notifier)
+ qDebug() << "QuailEventDispatcherWinGlib::registerSocketNotifier"; int sockfd = notifier->socket();
int type = notifier->type();
@@ -1038,7 +1068,8 @@
- Q_D(QuailEventDispatcherWinGlib);
+ //QuailEventDispatcherWinGlib *d = this; + QuailEventDispatcherWinGlib *d = this; QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except };
QSNDict *dict = sn_vec[type];
@@ -1063,6 +1094,7 @@
void QuailEventDispatcherWinGlib::unregisterSocketNotifier(QSocketNotifier *notifier)
+ qDebug() << "QuailEventDispatcherWinGlib::unregisterSocketNotifier"; int sockfd = notifier->socket();
int type = notifier->type();
@@ -1076,7 +1108,7 @@
- Q_D(QuailEventDispatcherWinGlib);
+ QuailEventDispatcherWinGlib *d = this; QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except };
QSNDict *dict = sn_vec[type];
QSockNot *sn = dict->value(sockfd);
@@ -1092,6 +1124,7 @@
void QuailEventDispatcherWinGlib::registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object)
+ qDebug() << "QuailEventDispatcherWinGlib::registerTimer.GLIB'ed"; if (timerId < 1 || interval < 0 || !object) {
qWarning("QuailEventDispatcherWinGlib::registerTimer: invalid arguments");
@@ -1100,7 +1133,7 @@
- Q_D(QuailEventDispatcherWinGlib);
+ QuailEventDispatcherWinGlib *d = this; WinTimerInfo *t = new WinTimerInfo;
@@ -1120,6 +1153,7 @@
bool QuailEventDispatcherWinGlib::unregisterTimer(int timerId)
+ qDebug() << "QuailEventDispatcherWinGlib::unregisterTimer"; qWarning("QuailEventDispatcherWinGlib::unregisterTimer: invalid argument");
@@ -1130,7 +1164,7 @@
- Q_D(QuailEventDispatcherWinGlib);
+ QuailEventDispatcherWinGlib *d = this; if (d->timerVec.isEmpty() || timerId <= 0)
@@ -1146,6 +1180,7 @@
bool QuailEventDispatcherWinGlib::unregisterTimers(QObject *object)
+ qDebug() << "QuailEventDispatcherWinGlib::unregisterTimer"; qWarning("QuailEventDispatcherWinGlib::unregisterTimers: invalid argument");
@@ -1156,7 +1191,7 @@
- Q_D(QuailEventDispatcherWinGlib);
+ QuailEventDispatcherWinGlib *d = this; if (d->timerVec.isEmpty())
register WinTimerInfo *t;
@@ -1175,12 +1210,13 @@
QList<QuailEventDispatcherWinGlib::TimerInfo>
QuailEventDispatcherWinGlib::registeredTimers(QObject *object) const
+ qDebug() << "QuailEventDispatcherWinGlib::registeredTimers"; qWarning("QuailEventDispatcherWinGlib:registeredTimers: invalid argument");
return QList<TimerInfo>();
- Q_D(const QuailEventDispatcherWinGlib);
+ const QuailEventDispatcherWinGlib *d = this; for (int i = 0; i < d->timerVec.size(); ++i) {
const WinTimerInfo *t = d->timerVec.at(i);
@@ -1192,6 +1228,7 @@
bool QuailEventDispatcherWinGlib::registerEventNotifier(QWinEventNotifier *notifier)
+ qDebug() << "QuailEventDispatcherWinGlib::registerEventNotifier"; qWarning("QWinEventNotifier: Internal error");
@@ -1200,7 +1237,7 @@
- Q_D(QuailEventDispatcherWinGlib);
+ QuailEventDispatcherWinGlib *d = this; if (d->winEventNotifierList.contains(notifier))
@@ -1215,6 +1252,7 @@
void QuailEventDispatcherWinGlib::unregisterEventNotifier(QWinEventNotifier *notifier)
+ qDebug() << "QuailEventDispatcherWinGlib::unregisterEventNotifier"; qWarning("QWinEventNotifier: Internal error");
@@ -1223,7 +1261,7 @@
- Q_D(QuailEventDispatcherWinGlib);
+ QuailEventDispatcherWinGlib *d = this; int i = d->winEventNotifierList.indexOf(notifier);
@@ -1232,7 +1270,7 @@
void QuailEventDispatcherWinGlib::activateEventNotifiers()
- Q_D(QuailEventDispatcherWinGlib);
+ QuailEventDispatcherWinGlib *d = this; //### this could break if events are removed/added in the activation
for (int i=0; i<d->winEventNotifierList.count(); i++) {
@@ -1254,12 +1292,12 @@
- Q_D(QuailEventDispatcherWinGlib);
+ QuailEventDispatcherWinGlib *d = this; if (d->timerVec.isEmpty())
- quint64 currentTime = qt_msectime();
+ quint64 currentTime = QDateTime::currentMSecsSinceEpoch (); register WinTimerInfo *t;
for (int i=0; i<d->timerVec.size(); i++) {
@@ -1283,7 +1321,7 @@
void QuailEventDispatcherWinGlib::wakeUp()
- Q_D(QuailEventDispatcherWinGlib);
+ QuailEventDispatcherWinGlib *d = this; if (d->internalHwnd && d->wakeUps.testAndSetAcquire(0, 1)) {
// post a WM_QT_SENDPOSTEDEVENTS to this thread if there isn't one already pending
@@ -1293,7 +1331,7 @@
void QuailEventDispatcherWinGlib::interrupt()
- Q_D(QuailEventDispatcherWinGlib);
+ QuailEventDispatcherWinGlib *d = this; @@ -1306,7 +1344,7 @@
void QuailEventDispatcherWinGlib::closingDown()
- Q_D(QuailEventDispatcherWinGlib);
+ QuailEventDispatcherWinGlib *d = this; // clean up any socketnotifiers
while (!d->sn_read.isEmpty())
@@ -1331,7 +1369,8 @@
bool QuailEventDispatcherWinGlib::event(QEvent *e)
- Q_D(QuailEventDispatcherWinGlib);
+ qDebug() << "QuailEventDispatcherWinGlib::event"; + QuailEventDispatcherWinGlib *d = this; if (e->type() == QEvent::ZeroTimerEvent) {
QZeroTimerEvent *zte = static_cast<QZeroTimerEvent*>(e);
WinTimerInfo *t = d->timerDict.value(zte->timerId());
@@ -1361,6 +1400,62 @@
void QuailEventDispatcherWinGlib::sendPostedEvents()
- Q_D(QuailEventDispatcherWinGlib);
- QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData);
+ //QuailEventDispatcherWinGlib *d = this; + //QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData); + QCoreApplication::sendPostedEvents(); +QThreadData::QThreadData(int initialRefCount) + : _ref(initialRefCount), thread(0), threadId(0), + quitNow(false), loopLevel(0), eventDispatcher(0), canWait(true), isAdopted(false) + // fprintf(stderr, "QThreadData %p created\n", this); +QThreadData::~QThreadData() + Q_ASSERT(_ref.load() == 0); + // In the odd case that Qt is running on a secondary thread, the main + // thread instance will have been dereffed asunder because of the deref in + // QThreadData::current() and the deref in the pthread_destroy. To avoid + // crashing during QCoreApplicationData's global static cleanup we need to + // safeguard the main thread here.. This fix is a bit crude, but it solves +// if (this->thread == QCoreApplication::thread()) { +// //QCoreApplication::thread() = 0; +// QThreadData::clearCurrentThreadData(); + for (int i = 0; i < postEventList.size(); ++i) { + const QPostEvent &pe = postEventList.at(i); + //--pe.receiver->d_func()->postedEvents; + pe.event->posted = false; + // fprintf(stderr, "QThreadData %p destroyed\n", this); + Q_ASSERT(_ref.load() != 0); +void QThreadData::deref() --- a/src/QuailWinGlibEventLoop.h Wed Sep 18 14:04:25 2013 +0100
+++ b/src/QuailWinGlibEventLoop.h Thu Sep 19 16:09:24 2013 +0100
@@ -2,15 +2,18 @@
#define QUAILWINGLIBEVENTLOOP_H
#include "QtCore/qt_windows.h"
-#include "QtCore/qcoreevent.h"
+//#include "QtCore/qcoreevent.h" #include <QAbstractEventDispatcher>
+#include <QCoreApplication> +#include <QSocketNotifier> typedef struct _GMainContext GMainContext;
-class QWinEventNotifier;
-class QuailEventDispatcherWinGlibPrivate;
LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp);
@@ -49,13 +52,169 @@
typedef QList<WinTimerInfo*> WinTimerVec; // vector of TimerInfo structs
typedef QHash<int, WinTimerInfo*> WinTimerDict; // fast dict of timers
+ : receiver(0), event(0), priority(0) + inline QPostEvent(QObject *r, QEvent *e, int p) + : receiver(r), event(e), priority(p) +inline bool operator<(const QPostEvent &first, const QPostEvent &second) + return first.priority > second.priority; +// This class holds the list of posted events. +// The list has to be kept sorted by priority +class QPostEventList : public QVector<QPostEvent> + // recursion == recursion count for sendPostedEvents() + // sendOffset == the current event to start sending + // insertionOffset == set by sendPostedEvents to tell postEvent() where to start insertions + inline QPostEventList() + : QVector<QPostEvent>(), recursion(0), startOffset(0), insertionOffset(0) + void addEvent(const QPostEvent &ev) { + int priority = ev.priority; + last().priority >= priority || + insertionOffset >= size()) { + // optimization: we can simply append if the last event in + // the queue has higher or equal priority + // insert event in descending priority order, using upper + // bound for a given priority (to ensure proper ordering + // of events with the same priority) + QPostEventList::iterator at = std::upper_bound(begin() + insertionOffset, end(), ev); + //hides because they do not keep that list sorted. addEvent must be used + using QVector<QPostEvent>::append; + using QVector<QPostEvent>::insert; +class QThreadPrivate : public QObject + QThreadPrivate(QThreadData *d = 0); + void setPriority(QThread::Priority prio); + QAtomicInt quitLockRef; + bool isInFinish; //when in QThreadPrivate::finish + QThread::Priority priority; + static QThread *threadForId(int id); + QWaitCondition thread_done; + static void *start(void *arg); + static void finish(void *); + static unsigned int __stdcall start(void *); + static void finish(void *, bool lockAnyway=true); + bool terminationEnabled, terminatePending; + static void createEventDispatcher(QThreadData *data); + if (!quitLockRef.deref() && running) { + QCoreApplication::instance()->postEvent(this, new QEvent(QEvent::Quit)); + QThreadData(int initialRefCount = 1); + static QThreadData *current(); + static void clearCurrentThreadData(); +// static QThreadData *get2(QThread *thread) +// { Q_ASSERT_X(thread != 0, "QThread", "internal error"); return thread->d_func()->data; } + inline bool hasEventDispatcher() const + { return eventDispatcher.load() != 0; } + QMutexLocker locker(&postEventList.mutex); + QAtomicPointer<QAbstractEventDispatcher> eventDispatcher; + QStack<QEventLoop *> eventLoops; + QPostEventList postEventList; class QuailEventDispatcherWinGlib : public QAbstractEventDispatcher
void createInternalHwnd();
- explicit QuailEventDispatcherWinGlib(GMainContext *context = 0, QObject *parent = 0);
+ QuailEventDispatcherWinGlib(QObject *parent = 0); ~QuailEventDispatcherWinGlib();
bool QT_ENSURE_STACK_ALIGNED_FOR_SSE processEvents(QEventLoop::ProcessEventsFlags flags);