Make QEventDispatcherCoreFoundaton work on secondary threads
We were using CFRunLoopGetMain() everywhere. Get the correct run loop using CFRunLoopGetCurrent() during initialization, and store it. Event dispatcher initialization must now be delayed until after the constructor has run, since event dispatchers may be created on the main thread and then moved to the target thread. Initialize on first call to processEvents() where the current thread will be the correct thread. Use the stored m_runLoop instead of CFRunLoopGetMain(). This is required for wakeUp() and interrupt() which may be called from another thread. Change-Id: I6fffcfd4394899c4a12f241c42781979aaf99d5e Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
parent
489ae6db3c
commit
a09c8b0ee6
@ -86,7 +86,7 @@ CFRunLoopSourceRef qt_mac_add_socket_to_runloop(const CFSocketRef socket)
|
|||||||
if (!loopSource)
|
if (!loopSource)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
CFRunLoopAddSource(CFRunLoopGetMain(), loopSource, kCFRunLoopCommonModes);
|
CFRunLoopAddSource(CFRunLoopGetCurrent(), loopSource, kCFRunLoopCommonModes);
|
||||||
return loopSource;
|
return loopSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ CFRunLoopSourceRef qt_mac_add_socket_to_runloop(const CFSocketRef socket)
|
|||||||
void qt_mac_remove_socket_from_runloop(const CFSocketRef socket, CFRunLoopSourceRef runloop)
|
void qt_mac_remove_socket_from_runloop(const CFSocketRef socket, CFRunLoopSourceRef runloop)
|
||||||
{
|
{
|
||||||
Q_ASSERT(runloop);
|
Q_ASSERT(runloop);
|
||||||
CFRunLoopRemoveSource(CFRunLoopGetMain(), runloop, kCFRunLoopCommonModes);
|
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), runloop, kCFRunLoopCommonModes);
|
||||||
CFSocketDisableCallBacks(socket, kCFSocketReadCallBack);
|
CFSocketDisableCallBacks(socket, kCFSocketReadCallBack);
|
||||||
CFSocketDisableCallBacks(socket, kCFSocketWriteCallBack);
|
CFSocketDisableCallBacks(socket, kCFSocketWriteCallBack);
|
||||||
}
|
}
|
||||||
@ -188,7 +188,7 @@ void QCFSocketNotifier::registerSocketNotifier(QSocketNotifier *notifier)
|
|||||||
enableNotifiersObserver = CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopBeforeSources,
|
enableNotifiersObserver = CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopBeforeSources,
|
||||||
true, 0, enableSocketNotifiers, &context);
|
true, 0, enableSocketNotifiers, &context);
|
||||||
Q_ASSERT(enableNotifiersObserver);
|
Q_ASSERT(enableNotifiersObserver);
|
||||||
CFRunLoopAddObserver(CFRunLoopGetMain(), enableNotifiersObserver, kCFRunLoopCommonModes);
|
CFRunLoopAddObserver(CFRunLoopGetCurrent(), enableNotifiersObserver, kCFRunLoopCommonModes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,8 +209,16 @@ QEventDispatcherCoreFoundation::QEventDispatcherCoreFoundation(QObject *parent)
|
|||||||
, m_blockedRunLoopTimer(0)
|
, m_blockedRunLoopTimer(0)
|
||||||
, m_overdueTimerScheduled(false)
|
, m_overdueTimerScheduled(false)
|
||||||
{
|
{
|
||||||
m_cfSocketNotifier.setHostEventDispatcher(this);
|
}
|
||||||
|
|
||||||
|
void QEventDispatcherCoreFoundation::startingUp()
|
||||||
|
{
|
||||||
|
// The following code must run on the event dispatcher thread, so that
|
||||||
|
// CFRunLoopGetCurrent() returns the correct run loop.
|
||||||
|
Q_ASSERT(QThread::currentThread() == thread());
|
||||||
|
|
||||||
|
m_runLoop = QCFType<CFRunLoopRef>::constructFromGet(CFRunLoopGetCurrent());
|
||||||
|
m_cfSocketNotifier.setHostEventDispatcher(this);
|
||||||
m_postedEventsRunLoopSource.addToMode(kCFRunLoopCommonModes);
|
m_postedEventsRunLoopSource.addToMode(kCFRunLoopCommonModes);
|
||||||
m_runLoopActivityObserver.addToMode(kCFRunLoopCommonModes);
|
m_runLoopActivityObserver.addToMode(kCFRunLoopCommonModes);
|
||||||
}
|
}
|
||||||
@ -252,6 +260,7 @@ QEventLoop *QEventDispatcherCoreFoundation::currentEventLoop() const
|
|||||||
bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlags flags)
|
bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlags flags)
|
||||||
{
|
{
|
||||||
QT_APPLE_SCOPED_LOG_ACTIVITY(lcEventDispatcher().isDebugEnabled(), "processEvents");
|
QT_APPLE_SCOPED_LOG_ACTIVITY(lcEventDispatcher().isDebugEnabled(), "processEvents");
|
||||||
|
|
||||||
bool eventsProcessed = false;
|
bool eventsProcessed = false;
|
||||||
|
|
||||||
if (flags & (QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers))
|
if (flags & (QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers))
|
||||||
@ -413,7 +422,8 @@ bool QEventDispatcherCoreFoundation::processPostedEvents()
|
|||||||
|
|
||||||
m_processEvents.processedPostedEvents = true;
|
m_processEvents.processedPostedEvents = true;
|
||||||
|
|
||||||
qCDebug(lcEventDispatcher) << "Sending posted events for" << m_processEvents.flags;
|
qCDebug(lcEventDispatcher) << "Sending posted events for"
|
||||||
|
<< QEventLoop::ProcessEventsFlags(m_processEvents.flags.load());
|
||||||
QCoreApplication::sendPostedEvents();
|
QCoreApplication::sendPostedEvents();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -496,7 +506,7 @@ bool QEventDispatcherCoreFoundation::hasPendingEvents()
|
|||||||
// 'maybeHasPendingEvents' in our case.
|
// 'maybeHasPendingEvents' in our case.
|
||||||
|
|
||||||
extern uint qGlobalPostedEventsCount();
|
extern uint qGlobalPostedEventsCount();
|
||||||
return qGlobalPostedEventsCount() || !CFRunLoopIsWaiting(CFRunLoopGetMain());
|
return qGlobalPostedEventsCount() || !CFRunLoopIsWaiting(m_runLoop);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QEventDispatcherCoreFoundation::wakeUp()
|
void QEventDispatcherCoreFoundation::wakeUp()
|
||||||
@ -516,7 +526,8 @@ void QEventDispatcherCoreFoundation::wakeUp()
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_postedEventsRunLoopSource.signal();
|
m_postedEventsRunLoopSource.signal();
|
||||||
CFRunLoopWakeUp(CFRunLoopGetMain());
|
if (m_runLoop)
|
||||||
|
CFRunLoopWakeUp(m_runLoop);
|
||||||
|
|
||||||
qCDebug(lcEventDispatcher) << "Signaled posted event run-loop source";
|
qCDebug(lcEventDispatcher) << "Signaled posted event run-loop source";
|
||||||
}
|
}
|
||||||
@ -525,7 +536,7 @@ void QEventDispatcherCoreFoundation::interrupt()
|
|||||||
{
|
{
|
||||||
qCDebug(lcEventDispatcher) << "Marking current processEvent as interrupted";
|
qCDebug(lcEventDispatcher) << "Marking current processEvent as interrupted";
|
||||||
m_processEvents.wasInterrupted = true;
|
m_processEvents.wasInterrupted = true;
|
||||||
CFRunLoopStop(CFRunLoopGetMain());
|
CFRunLoopStop(m_runLoop);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QEventDispatcherCoreFoundation::flush()
|
void QEventDispatcherCoreFoundation::flush()
|
||||||
@ -620,7 +631,7 @@ void QEventDispatcherCoreFoundation::updateTimers()
|
|||||||
processTimers(timer);
|
processTimers(timer);
|
||||||
});
|
});
|
||||||
|
|
||||||
CFRunLoopAddTimer(CFRunLoopGetMain(), m_runLoopTimer, kCFRunLoopCommonModes);
|
CFRunLoopAddTimer(m_runLoop, m_runLoopTimer, kCFRunLoopCommonModes);
|
||||||
qCDebug(lcEventDispatcherTimers) << "Created new CFRunLoopTimer" << m_runLoopTimer;
|
qCDebug(lcEventDispatcherTimers) << "Created new CFRunLoopTimer" << m_runLoopTimer;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -208,6 +208,7 @@ class Q_CORE_EXPORT QEventDispatcherCoreFoundation : public QAbstractEventDispat
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
explicit QEventDispatcherCoreFoundation(QObject *parent = 0);
|
explicit QEventDispatcherCoreFoundation(QObject *parent = 0);
|
||||||
|
void startingUp() override;
|
||||||
~QEventDispatcherCoreFoundation();
|
~QEventDispatcherCoreFoundation();
|
||||||
|
|
||||||
bool processEvents(QEventLoop::ProcessEventsFlags flags) override;
|
bool processEvents(QEventLoop::ProcessEventsFlags flags) override;
|
||||||
@ -239,11 +240,11 @@ protected:
|
|||||||
, processedPostedEvents(false), processedTimers(false)
|
, processedPostedEvents(false), processedTimers(false)
|
||||||
, deferredWakeUp(false), deferredUpdateTimers(false) {}
|
, deferredWakeUp(false), deferredUpdateTimers(false) {}
|
||||||
|
|
||||||
QEventLoop::ProcessEventsFlags flags;
|
QAtomicInt flags;
|
||||||
bool wasInterrupted;
|
QAtomicInteger<char> wasInterrupted;
|
||||||
bool processedPostedEvents;
|
QAtomicInteger<char> processedPostedEvents;
|
||||||
bool processedTimers;
|
QAtomicInteger<char> processedTimers;
|
||||||
bool deferredWakeUp;
|
QAtomicInteger<char> deferredWakeUp;
|
||||||
bool deferredUpdateTimers;
|
bool deferredUpdateTimers;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -258,6 +259,7 @@ private:
|
|||||||
QTimerInfoList m_timerInfoList;
|
QTimerInfoList m_timerInfoList;
|
||||||
CFRunLoopTimerRef m_runLoopTimer;
|
CFRunLoopTimerRef m_runLoopTimer;
|
||||||
CFRunLoopTimerRef m_blockedRunLoopTimer;
|
CFRunLoopTimerRef m_blockedRunLoopTimer;
|
||||||
|
QCFType<CFRunLoopRef> m_runLoop;
|
||||||
bool m_overdueTimerScheduled;
|
bool m_overdueTimerScheduled;
|
||||||
|
|
||||||
QCFSocketNotifier m_cfSocketNotifier;
|
QCFSocketNotifier m_cfSocketNotifier;
|
||||||
|
@ -471,8 +471,9 @@ bool QIOSEventDispatcher::processPostedEvents()
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
QT_APPLE_SCOPED_LOG_ACTIVITY(lcEventDispatcher().isDebugEnabled(), "sendWindowSystemEvents");
|
QT_APPLE_SCOPED_LOG_ACTIVITY(lcEventDispatcher().isDebugEnabled(), "sendWindowSystemEvents");
|
||||||
qCDebug(lcEventDispatcher) << "Sending window system events for" << m_processEvents.flags;
|
QEventLoop::ProcessEventsFlags flags = QEventLoop::ProcessEventsFlags(m_processEvents.flags.load());
|
||||||
QWindowSystemInterface::sendWindowSystemEvents(m_processEvents.flags);
|
qCDebug(lcEventDispatcher) << "Sending window system events for" << flags;
|
||||||
|
QWindowSystemInterface::sendWindowSystemEvents(flags);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user