Heart/src/public/async.cpp
2025-01-03 17:39:38 +01:00

130 lines
3.4 KiB
C++

/*
* Copyright (C) 2018-2025 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "abstractnode.h"
#include "async.h"
#include <QCoreApplication>
#include <QDateTime>
#include <QThread>
#include <QDebug>
#include <quasarapp.h>
#include <thread>
#include <chrono>
#include <qaglobalutils.h>
// Private implementation of waitFor functions.
#define waitPrivate(CONDITION, TIMEOUT) \
auto curmsec = QDateTime::currentMSecsSinceEpoch() + TIMEOUT; \
while (curmsec > QDateTime::currentMSecsSinceEpoch() && !CONDITION) { \
QCoreApplication::processEvents(); \
} \
QCoreApplication::processEvents(); \
return CONDITION; \
#define freazePrivate(CONDITION, TIMEOUT) \
auto curmsec = QDateTime::currentMSecsSinceEpoch() + TIMEOUT; \
while (curmsec > QDateTime::currentMSecsSinceEpoch() && !CONDITION) { \
std::this_thread::sleep_for(std::chrono::microseconds(1)); \
} \
return CONDITION; \
namespace QH {
Async::Async(QThread *thread, QObject *ptr):
QObject(ptr) {
threadAnalize(thread);
moveToThread(thread);
}
Async::~Async() {
}
void Async::asyncHandler(Job job,
bool *endOfWork,
bool *resultOfWork) const {
bool result = job();
if (endOfWork && resultOfWork)
*resultOfWork = result;
if (endOfWork) {
*endOfWork = true;
}
}
void Async::threadAnalize(QThread *thread) {
QThread * mainThread = AbstractNode::mainThreadID();
debug_assert((mainThread != thread) && thread, "You try create async object into main thread");
}
bool Async::waitFor(bool *condition, int timeout, bool freaze) const {
if (!condition)
return false;
if (freaze) {
freazePrivate(*condition, timeout)
} else {
waitPrivate(*condition, timeout)
}
}
bool Async::asyncLauncher(const Async::Job &job, bool await, bool freaze) const {
if (QThread::currentThread() == thread()) {
return job();
}
if (!thread()->isRunning()) {
qCritical() << "The work threand of the async object is not running";
return false;
}
if (!await) {
return QMetaObject::invokeMethod(const_cast<Async*>(this),
"asyncHandler",
Qt::QueuedConnection,
Q_ARG(QH::Async::Job, job));
}
bool workOfEnd = false, workResult = false;
bool invockeResult = QMetaObject::invokeMethod(const_cast<Async*>(this),
"asyncHandler",
Qt::QueuedConnection,
Q_ARG(QH::Async::Job, job),
Q_ARG(bool*, &workOfEnd),
Q_ARG(bool*, &workResult));
if (!invockeResult)
return false;
if (!waitFor(&workOfEnd, WAIT_TIME, freaze)) {
return false;
}
return workResult;
}
bool Async::waitFor(const std::function<bool ()> &condition, int timeout, bool freaze) const {
if (freaze) {
freazePrivate(condition(), timeout)
} else {
waitPrivate(condition(), timeout)
}
}
}