2021-01-27 21:59:31 +03:00
|
|
|
/*
|
2024-12-30 22:44:47 +01:00
|
|
|
* Copyright (C) 2018-2025 QuasarApp.
|
2021-01-27 21:59:31 +03:00
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2021-03-23 23:02:28 +03:00
|
|
|
#include "abstractnode.h"
|
2020-11-29 23:31:55 +03:00
|
|
|
#include "async.h"
|
|
|
|
|
|
|
|
#include <QCoreApplication>
|
|
|
|
#include <QDateTime>
|
2020-12-06 20:12:34 +03:00
|
|
|
#include <QThread>
|
2020-12-16 23:02:59 +03:00
|
|
|
#include <QDebug>
|
2021-03-23 19:20:29 +03:00
|
|
|
#include <quasarapp.h>
|
2021-11-01 13:39:01 +03:00
|
|
|
#include <thread>
|
|
|
|
#include <chrono>
|
2022-01-20 17:12:59 +03:00
|
|
|
#include <qaglobalutils.h>
|
2020-11-29 23:31:55 +03:00
|
|
|
|
|
|
|
// 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; \
|
|
|
|
|
2021-11-01 13:39:01 +03:00
|
|
|
|
|
|
|
#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; \
|
|
|
|
|
2020-11-29 23:31:55 +03:00
|
|
|
namespace QH {
|
2021-03-23 19:20:29 +03:00
|
|
|
Async::Async(QThread *thread, QObject *ptr):
|
2020-11-29 23:31:55 +03:00
|
|
|
QObject(ptr) {
|
|
|
|
|
2021-03-23 19:20:29 +03:00
|
|
|
threadAnalize(thread);
|
|
|
|
moveToThread(thread);
|
|
|
|
}
|
|
|
|
|
|
|
|
Async::~Async() {
|
|
|
|
|
2020-11-29 23:31:55 +03:00
|
|
|
}
|
|
|
|
|
2020-12-06 20:12:34 +03:00
|
|
|
void Async::asyncHandler(Job job,
|
2021-03-23 19:20:29 +03:00
|
|
|
bool *endOfWork,
|
|
|
|
bool *resultOfWork) const {
|
2020-11-29 23:31:55 +03:00
|
|
|
|
|
|
|
bool result = job();
|
|
|
|
|
2020-12-17 17:31:26 +03:00
|
|
|
if (endOfWork && resultOfWork)
|
2020-11-29 23:31:55 +03:00
|
|
|
*resultOfWork = result;
|
|
|
|
|
|
|
|
if (endOfWork) {
|
|
|
|
*endOfWork = true;
|
|
|
|
}
|
2021-03-23 19:20:29 +03:00
|
|
|
}
|
2020-12-06 20:12:34 +03:00
|
|
|
|
2021-03-23 19:20:29 +03:00
|
|
|
void Async::threadAnalize(QThread *thread) {
|
2021-03-24 10:47:03 +03:00
|
|
|
QThread * mainThread = AbstractNode::mainThreadID();
|
2021-03-23 23:02:28 +03:00
|
|
|
|
2021-03-24 10:45:13 +03:00
|
|
|
debug_assert((mainThread != thread) && thread, "You try create async object into main thread");
|
2020-11-29 23:31:55 +03:00
|
|
|
}
|
|
|
|
|
2021-11-01 13:39:01 +03:00
|
|
|
bool Async::waitFor(bool *condition, int timeout, bool freaze) const {
|
2020-11-29 23:31:55 +03:00
|
|
|
if (!condition)
|
|
|
|
return false;
|
|
|
|
|
2021-11-01 13:39:01 +03:00
|
|
|
if (freaze) {
|
|
|
|
freazePrivate(*condition, timeout)
|
|
|
|
} else {
|
|
|
|
waitPrivate(*condition, timeout)
|
|
|
|
}
|
2020-11-29 23:31:55 +03:00
|
|
|
}
|
|
|
|
|
2021-11-01 13:39:01 +03:00
|
|
|
bool Async::asyncLauncher(const Async::Job &job, bool await, bool freaze) const {
|
2021-03-24 10:39:04 +03:00
|
|
|
|
2020-12-06 20:12:34 +03:00
|
|
|
if (QThread::currentThread() == thread()) {
|
|
|
|
return job();
|
|
|
|
}
|
|
|
|
|
2021-03-24 10:39:04 +03:00
|
|
|
if (!thread()->isRunning()) {
|
|
|
|
|
2025-01-03 17:39:38 +01:00
|
|
|
qCritical() << "The work threand of the async object is not running";
|
2021-03-24 10:39:04 +03:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-12-17 17:31:26 +03:00
|
|
|
if (!await) {
|
2021-02-19 18:59:00 +03:00
|
|
|
return QMetaObject::invokeMethod(const_cast<Async*>(this),
|
2021-01-13 17:31:44 +03:00
|
|
|
"asyncHandler",
|
|
|
|
Qt::QueuedConnection,
|
|
|
|
Q_ARG(QH::Async::Job, job));
|
2020-12-17 17:31:26 +03:00
|
|
|
}
|
|
|
|
|
2020-12-06 20:12:34 +03:00
|
|
|
bool workOfEnd = false, workResult = false;
|
|
|
|
|
2021-02-19 18:59:00 +03:00
|
|
|
bool invockeResult = QMetaObject::invokeMethod(const_cast<Async*>(this),
|
2020-12-06 20:12:34 +03:00
|
|
|
"asyncHandler",
|
|
|
|
Qt::QueuedConnection,
|
|
|
|
Q_ARG(QH::Async::Job, job),
|
2021-03-02 19:33:11 +03:00
|
|
|
Q_ARG(bool*, &workOfEnd),
|
|
|
|
Q_ARG(bool*, &workResult));
|
2020-12-06 20:12:34 +03:00
|
|
|
|
|
|
|
|
|
|
|
if (!invockeResult)
|
|
|
|
return false;
|
|
|
|
|
2021-11-01 13:39:01 +03:00
|
|
|
if (!waitFor(&workOfEnd, WAIT_TIME, freaze)) {
|
2020-12-06 20:12:34 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return workResult;
|
|
|
|
}
|
|
|
|
|
2021-11-01 13:39:01 +03:00
|
|
|
bool Async::waitFor(const std::function<bool ()> &condition, int timeout, bool freaze) const {
|
|
|
|
if (freaze) {
|
|
|
|
freazePrivate(condition(), timeout)
|
|
|
|
} else {
|
|
|
|
waitPrivate(condition(), timeout)
|
|
|
|
}
|
|
|
|
|
2020-11-29 23:31:55 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|