Files
qt5-legatus-legacy/Lts/Common/LtsUtils/LtsUtilsCore/await.h
T
2026-08-13 18:33:10 +02:00

125 lines
3.4 KiB
C++
Executable File

#pragma once
/**
* @RDE_HEADER@
* Function which waits (QEventLoop) for a success signal or a cancelation signal, optionally with a timeout
* Useful for blocking on async things
* $Id: connection.h 45834 2019-03-01 12:56:15Z ehrlicher $
* $HeadURL: svn://192.168.133.21/TDS/branches/product/features/swp_2023_devel/Lts/Common/LtsUtils/LtsUtilsCore/connection.h $
* $Author: ehrlicher $
*
* Created by Mike Wille, ESZS, 2024-03-03
*/
#include <QObject>
#include <QTimer>
#include <QEventLoop>
#include <memory>
namespace LtsUtils
{
template <typename Func>
void addConnect(QEventLoop &x, bool &success, const typename QtPrivate::FunctionPointer<Func>::Object *sender, Func signal, bool isSuccess)
{
if (isSuccess)
{
QObject::connect(sender, signal, &x, [&success]()
{
//fprintf(stderr, "await: success!\n");
success = true;
});
}
QObject::connect(sender, signal, &x, &QEventLoop::quit, Qt::QueuedConnection);
}
template <typename Func, typename... Connect>
void addConnect(QEventLoop &x, bool &success, const typename QtPrivate::FunctionPointer<Func>::Object *sender, Func signal, bool isSuccess, Connect... connects)
{
addConnect(x, success, sender, signal, isSuccess);
addConnect(x, success, connects...);
}
template <typename... Connect> // a 'Connect' consists of a Qt sender, a Qt signal and a bool if this signal is a signal for success or for failure.
void await(Connect... connects) noexcept(false)
{
QEventLoop x;
bool success = false;
addConnect(x, success, connects...);
// fprintf(stderr, "await: now waiting...\n");
x.exec();
// fprintf(stderr, "await: done! success? %d\n", success);
if (!success)
{
// fprintf(stderr, "await: !success - throwing error!\n");
throw std::runtime_error("Failed.");
}
}
template <typename... Connect>
void awaitTimeout(const int timeoutMs, Connect... connects) noexcept(false)
{
std::unique_ptr<QTimer> t(new QTimer);
bool timeout = false;
if (timeoutMs > -1)
{
t->setInterval(timeoutMs);
t->setSingleShot(true);
QObject::connect(t.get(), &QTimer::timeout, t.get(), [&timeout](){ fprintf(stderr, "awaitTimeout: timed out!\n"); timeout = true; });
t->start();
}
await(t.get(), &QTimer::timeout, false, connects...); // throws
// fprintf(stderr, "awaitTimeout: done waiting - timeout? %d\n", timeout);
if (timeout)
{
// fprintf(stderr, "await: timed out - throwing error!\n");
throw std::runtime_error("Timeout.");
}
}
//// non-looping version of the classic wait stdlib function which enters the event loop to prevent the application from hanging
//void waitEventLoop(const int timeoutMs);
//{
// try
// {
// awaitTimeout(timeoutMs);
// }
// catch(...){}
//}
// 2024.11.29 Norbert Thoden
// awaitWithCancelationSignal scheint unter Windows nicth zu funktioneren.
// Siehe auch GUEZE-3155 Replay auf ABT nicht funktional
// deprecated, do not use
template <typename Func1, typename Func2>
void awaitWithCancelationSignal(const typename QtPrivate::FunctionPointer<Func1>::Object *sender1, Func1 signal1,
const typename QtPrivate::FunctionPointer<Func2>::Object *sender2, Func2 signal2,
const int timeoutMs = 0) noexcept(false)
{
if (timeoutMs > 0)
{
awaitTimeout(timeoutMs,
sender1, signal1, true,
sender2, signal2, false);
return;
}
await(sender1, signal1, true,
sender2, signal2, false);
}
} // namespace LtsUtils