Optimize QEventDispatcherWinRT::runOnMainThread()

- use std::make_shared instead of QSharedPointer
  - two memory allocations saved
- co-locate semaphore and HRESULT object in a single State object
  - one more memory allocation saved
- pass the shared_ptr<State> by value into the runnable
  - two more memory allocations saved

Not only is the new code much faster, it's also much more readable.

Also use QSemaphoreReleaser, just in case the delegate should throw.

Change-Id: Ib99b9da86984d440d10b72e3071aa88099e24a1f
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
Marc Mutz 2019-09-04 19:30:08 +02:00
parent 6f4bc3942d
commit 236d4637b2

View File

@ -44,12 +44,13 @@
#include <QtCore/QHash>
#include <QtCore/QMutex>
#include <QtCore/QSemaphore>
#include <QtCore/QSharedPointer>
#include <QtCore/qfunctions_winrt.h>
#include <private/qabstracteventdispatcher_p.h>
#include <private/qcoreapplication_p.h>
#include <functional>
#include <memory>
#include <wrl.h>
#include <windows.foundation.h>
#include <windows.system.threading.h>
@ -300,19 +301,19 @@ HRESULT QEventDispatcherWinRT::runOnMainThread(const std::function<HRESULT()> &d
if (QThread::currentThread() == QCoreApplication::instance()->thread())
return delegate();
auto semaphore = QSharedPointer<QSemaphore>(new QSemaphore);
auto ptrSemaphore = new QSharedPointer<QSemaphore>(semaphore);
auto result = QSharedPointer<HRESULT>(new HRESULT);
auto ptrResult = new QSharedPointer<HRESULT>(result);
struct State {
QSemaphore semaphore;
HRESULT result;
};
QMetaObject::invokeMethod(QCoreApplication::instance(), [delegate, ptrSemaphore, ptrResult]() {
**ptrResult = delegate();
delete ptrResult;
(*ptrSemaphore)->release();
delete ptrSemaphore;
const auto state = std::make_shared<State>();
QMetaObject::invokeMethod(QCoreApplication::instance(), [delegate, state]() {
const QSemaphoreReleaser releaser{state->semaphore};
state->result = delegate();
}, nullptr);
return semaphore->tryAcquire(1, timeout) ? *result : E_FAIL;
return state->semaphore.tryAcquire(1, timeout) ? state->result : E_FAIL;
}
bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)