125 lines
3.4 KiB
C++
Executable File
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
|