From 63f625fe4ee6435cc4b010bd94def8113b5b932f Mon Sep 17 00:00:00 2001 From: Roland Winklmeier Date: Fri, 10 Feb 2017 11:17:44 +0100 Subject: [PATCH] CEventLoop - swift's custom event loop --- src/blackmisc/eventloop.h | 92 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 src/blackmisc/eventloop.h diff --git a/src/blackmisc/eventloop.h b/src/blackmisc/eventloop.h new file mode 100644 index 000000000..9db181f49 --- /dev/null +++ b/src/blackmisc/eventloop.h @@ -0,0 +1,92 @@ +/* Copyright (C) 2017 + * swift project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +//! \file + +#ifndef BLACKMISC_EVENTLOOP_H +#define BLACKMISC_EVENTLOOP_H + +#include "blackmisc/blackmiscexport.h" + +#include +#include +#include + +namespace BlackMisc +{ + /*! + * Utility class which blocks until a signal is emitted or timeout reached + */ + 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. + template + static bool processEventsUntil(const T *sender, F signal, int timeoutMs) + { + return processEventsUntil(sender, signal, timeoutMs, [] {}); + } + + //! 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. + template + #ifdef Q_CC_MINGW + __attribute__((noinline)) // work around an apparent GCC 5.3 PE/COFF codegen bug + #endif + static bool processEventsUntil(const T *sender, F1 signal, int timeoutMs, F2 init) + { + QEventLoop eventLoop; + bool result = false; + QObject::connect(sender, signal, &eventLoop, [ & ] + { + result = true; + eventLoop.quit(); + }); + if (checkInit(init)) + { + return true; + } + if (timeoutMs > 0) + { + QTimer::singleShot(timeoutMs, &eventLoop, &QEventLoop::quit); + } + eventLoop.exec(); + return result; + } + + private: + template + static bool checkInit(F init, std::enable_if_t::value, int> = 0) + { + init(); + return false; + } + + template + static bool checkInit(F init, std::enable_if_t::value, int> = 0) + { + return init(); + } + }; +} // ns + +#endif // guard