From 002cd1d5b972005fb074863fc4a621f9ad3ce81f Mon Sep 17 00:00:00 2001 From: Mat Sutcliffe Date: Tue, 28 Sep 2021 18:34:25 +0100 Subject: [PATCH] Issue #11 Improve CEventLoop API --- src/blackcore/application.cpp | 9 ++-- src/blackcore/db/backgrounddataupdater.cpp | 3 +- src/blackmisc/eventloop.h | 58 ++++++++++------------ src/blackmisc/network/networkutils.cpp | 9 ++-- 4 files changed, 38 insertions(+), 41 deletions(-) diff --git a/src/blackcore/application.cpp b/src/blackcore/application.cpp index 8a966ba21..9065c75de 100644 --- a/src/blackcore/application.cpp +++ b/src/blackcore/application.cpp @@ -426,11 +426,12 @@ namespace BlackCore CStatusMessageList CApplication::waitForSetup(int timeoutMs) { if (!m_setupReader) { return CStatusMessage(this).error(u"No setup reader"); } - CEventLoop::processEventsUntil(this, &CApplication::setupHandlingCompleted, timeoutMs, [this] + CEventLoop eventLoop; + eventLoop.stopWhen(this, &CApplication::setupHandlingCompleted); + if (!m_setupReader->isSetupAvailable()) { - // init, if this is true event queue is not started - return m_setupReader->isSetupAvailable(); - }); + eventLoop.exec(timeoutMs); + } // setup handling completed with success or failure, or we run into time out CStatusMessageList msgs; diff --git a/src/blackcore/db/backgrounddataupdater.cpp b/src/blackcore/db/backgrounddataupdater.cpp index b11cfdd6d..a9364128a 100644 --- a/src/blackcore/db/backgrounddataupdater.cpp +++ b/src/blackcore/db/backgrounddataupdater.cpp @@ -152,7 +152,8 @@ namespace BlackCore::Db { // just give the system some time to relax, consolidation is time consuming if (!this->doWorkCheck()) { return; } - CEventLoop::processEventsFor(1000); + CEventLoop eventLoop; + eventLoop.exec(1000); } } } diff --git a/src/blackmisc/eventloop.h b/src/blackmisc/eventloop.h index 83209e05f..686d0ec34 100644 --- a/src/blackmisc/eventloop.h +++ b/src/blackmisc/eventloop.h @@ -25,47 +25,41 @@ namespace BlackMisc class CEventLoop { public: - //! Deleted constructor - CEventLoop() = delete; - - //! Wait for the given time, while processing events. - static void processEventsFor(int timeoutMs) - { - QEventLoop eventLoop; - QTimer::singleShot(timeoutMs, &eventLoop, &QEventLoop::quit); - eventLoop.exec(); - } - - //! Block, but keep processing events, until sender emits the signal or the timeout expires. - //! Return true if the signal was emitted, false if the timeout expired. + //! Event loop will stop if the given signal is received. template - static bool processEventsUntil(const T *sender, F signal, int timeoutMs) + void stopWhen(const T *sender, F signal) { - return processEventsUntil(sender, signal, timeoutMs, [] {}); + QObject::connect(sender, signal, &m_eventLoop, [this] { m_eventLoop.exit(GotSignal); }); } - //! Overloaded version that executes an initial function after connecting the signal. - //! If the function's return type is convertible to bool, and it evaluates to true, - //! then the waiting will immediately time out and return true. + //! Event loop will stop if the given signal is received and condition returns true. template - static bool processEventsUntil(const T *sender, F1 signal, int timeoutMs, F2 init) + void stopWhen(const T *sender, F1 signal, F2 &&condition) { - QEventLoop eventLoop; - bool result = false; - QObject::connect(sender, signal, &eventLoop, [ & ] + QObject::connect(sender, signal, &m_eventLoop, [this, condition = std::forward(condition)](auto &&... args) { - result = true; - eventLoop.quit(); + if (condition(std::forward(args)...)) { m_eventLoop.exit(GotSignal); } }); - if constexpr (std::is_void_v) { init(); } - else if (init()) { return true; } - if (timeoutMs > 0) - { - QTimer::singleShot(timeoutMs, &eventLoop, &QEventLoop::quit); - } - eventLoop.exec(); - return result; } + + //! Begin processing events until the timeout or stop condition occurs. + //! \return True if the signal was received, false if it timed out. + bool exec(int timeoutMs) + { + if (timeoutMs >= 0) + { + QTimer::singleShot(timeoutMs, &m_eventLoop, [this] { m_eventLoop.exit(TimedOut); }); + } + return m_eventLoop.exec() == GotSignal; + } + + private: + enum Result + { + GotSignal = 0, + TimedOut, + }; + QEventLoop m_eventLoop; }; } // ns diff --git a/src/blackmisc/network/networkutils.cpp b/src/blackmisc/network/networkutils.cpp index af0e865c1..1b9a3643f 100644 --- a/src/blackmisc/network/networkutils.cpp +++ b/src/blackmisc/network/networkutils.cpp @@ -81,10 +81,11 @@ namespace BlackMisc::Network QObject::connect(&socket, &QTcpSocket::connected, &mapper, qOverload<>(&QSignalMapper::map)); QObject::connect(&socket, qOverload(&QTcpSocket::error), &mapper, qOverload<>(&QSignalMapper::map)); mapper.setMapping(&socket, 0); - const bool timedOut = !CEventLoop::processEventsUntil(&mapper, qOverload(&QSignalMapper::mapped), timeoutMs, [&] - { - socket.connectToHost(hostAddress, static_cast(port)); - }); + + CEventLoop eventLoop; + eventLoop.stopWhen(&mapper, qOverload(&QSignalMapper::mapped)); + socket.connectToHost(hostAddress, static_cast(port)); + const bool timedOut = !eventLoop.exec(timeoutMs); if (socket.state() != QTcpSocket::ConnectedState) {