From 8ab6ad64f9a570a5529f77dd2e99175bf46995d0 Mon Sep 17 00:00:00 2001 From: Vasily Galkin Date: Wed, 6 May 2020 11:43:47 +0300 Subject: [PATCH 1/2] Remove unused IEventQueue::isEmpty() method to simplify code understanding Current code base don't use IEventQueue::isEmpty() method. Remove it to simplify IEventQueue API and to remove confusion with IEventQueueBuffer with same name. The IEventQueueBuffer::isEmpty() and all its implementations kept unchanged --- src/lib/base/EventQueue.cpp | 6 ------ src/lib/base/EventQueue.h | 1 - src/lib/base/IEventQueue.h | 7 ------- 3 files changed, 14 deletions(-) diff --git a/src/lib/base/EventQueue.cpp b/src/lib/base/EventQueue.cpp index fe8cff5d..e71ec247 100644 --- a/src/lib/base/EventQueue.cpp +++ b/src/lib/base/EventQueue.cpp @@ -436,12 +436,6 @@ EventQueue::removeHandlers(void* target) } } -bool -EventQueue::isEmpty() const -{ - return (m_buffer->isEmpty() && getNextTimerTimeout() != 0.0); -} - IEventJob* EventQueue::getHandler(Event::Type type, void* target) const { diff --git a/src/lib/base/EventQueue.h b/src/lib/base/EventQueue.h index 0a2179be..b20d493b 100644 --- a/src/lib/base/EventQueue.h +++ b/src/lib/base/EventQueue.h @@ -58,7 +58,6 @@ public: virtual void removeHandlers(void* target); virtual Event::Type registerTypeOnce(Event::Type& type, const char* name); - virtual bool isEmpty() const; virtual IEventJob* getHandler(Event::Type type, void* target) const; virtual const char* getTypeName(Event::Type type); virtual Event::Type diff --git a/src/lib/base/IEventQueue.h b/src/lib/base/IEventQueue.h index cd4f0b3c..70399d36 100644 --- a/src/lib/base/IEventQueue.h +++ b/src/lib/base/IEventQueue.h @@ -189,13 +189,6 @@ public: //! @name accessors //@{ - //! Test if queue is empty - /*! - Returns true iff the queue has no events in it, including timer - events. - */ - virtual bool isEmpty() const = 0; - //! Get an event handler /*! Finds and returns the event handler for the \p type, \p target pair From 95f2a840be42b7fb92317a14d04f4dd047405660 Mon Sep 17 00:00:00 2001 From: Vasily Galkin Date: Wed, 6 May 2020 14:16:45 +0300 Subject: [PATCH 2/2] Windows 8+: make waiting for messages correspond to emptiness check Fixes high cpu usage spikes on win10. When queue was containing messages of only non-QS_POSTMESSAGE type the "while (m_buffer->isEmpty())" busy-looped in EventQueue::getEvent since isEmpty was true (checked only QS_POSTMESSAGE message type), but waitForEvent returned immediately (checked more message types). Investigation shows that the difference was introduced in https://github.com/debauchee/barrier/commit/dbfb04a6e to fix a problem with bad behaviour of GetQueueStatus Researching showed that a similar problem was fixed in Qt, and the solution was "pass different flags to GetQueueStatus depending on version of windows" https://bugreports.qt.io/browse/QTBUG-29097 So this patch makes changes to a barrier non-GUI core similar to Qt fix. --- src/lib/platform/MSWindowsEventQueueBuffer.cpp | 16 ++++++++++++---- src/lib/platform/MSWindowsEventQueueBuffer.h | 1 + 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/lib/platform/MSWindowsEventQueueBuffer.cpp b/src/lib/platform/MSWindowsEventQueueBuffer.cpp index f6de1573..31113676 100644 --- a/src/lib/platform/MSWindowsEventQueueBuffer.cpp +++ b/src/lib/platform/MSWindowsEventQueueBuffer.cpp @@ -21,6 +21,7 @@ #include "arch/win32/ArchMiscWindows.h" #include "mt/Thread.h" #include "base/IEventQueue.h" +#include // // EventQueueTimer @@ -48,6 +49,15 @@ MSWindowsEventQueueBuffer::MSWindowsEventQueueBuffer(IEventQueue* events) : // make sure this thread has a message queue MSG dummy; PeekMessage(&dummy, NULL, WM_USER, WM_USER, PM_NOREMOVE); + + m_os_supported_message_types = QS_ALLINPUT; + if (!IsWindows8OrGreater()) + { + // don't use QS_POINTER, QS_TOUCH + // because they can cause GetQueueStatus() to always return 0 and we miss events + // since those flags are confusing Windows 7. See QTBUG-29097 for related info + m_os_supported_message_types &= ~(QS_TOUCH | QS_POINTER); + } } MSWindowsEventQueueBuffer::~MSWindowsEventQueueBuffer() @@ -79,7 +89,7 @@ MSWindowsEventQueueBuffer::waitForEvent(double timeout) // cancellation but that's okay because we're run in the main // thread and we never cancel that thread. HANDLE dummy[1]; - MsgWaitForMultipleObjects(0, dummy, FALSE, t, QS_ALLINPUT); + MsgWaitForMultipleObjects(0, dummy, FALSE, t, m_os_supported_message_types); } IEventQueueBuffer::Type @@ -128,9 +138,7 @@ MSWindowsEventQueueBuffer::addEvent(UInt32 dataID) bool MSWindowsEventQueueBuffer::isEmpty() const { - // don't use QS_POINTER, QS_TOUCH, or any meta-flags that include them (like QS_ALLINPUT) - // because they can cause GetQueueStatus() to always return 0 and we miss events - return (HIWORD(GetQueueStatus(QS_POSTMESSAGE)) == 0); + return (HIWORD(GetQueueStatus(m_os_supported_message_types)) == 0); } EventQueueTimer* diff --git a/src/lib/platform/MSWindowsEventQueueBuffer.h b/src/lib/platform/MSWindowsEventQueueBuffer.h index 6a0f9f90..bc9bde1f 100644 --- a/src/lib/platform/MSWindowsEventQueueBuffer.h +++ b/src/lib/platform/MSWindowsEventQueueBuffer.h @@ -47,4 +47,5 @@ private: MSG m_event; UINT m_daemonQuit; IEventQueue* m_events; + UINT m_os_supported_message_types; };